Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -308,6 +308,8 @@ LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0, "unsigned fixed point types having one extra padding bit") +BENIGN_LANGOPT(KeepStaticConsts , 1, 0, "keep static const variables even if unused") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -893,7 +893,8 @@ def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">, Group, Flags<[CC1Option]>, HelpText<"Disable support for int128_t type">; - +def fkeep_static_consts : Flag<["-"], "fkeep-static-consts">, Group, Flags<[CC1Option]>, + HelpText<"Keep static const variables even if unused">; def ffixed_point : Flag<["-"], "ffixed-point">, Group, Flags<[CC1Option]>, HelpText<"Enable fixed point types">; def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group, Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -9741,6 +9741,14 @@ if (D->hasAttr() || D->hasAttr()) return true; + // Emit static constants even if they are not used if KeepStaticConsts is set. + if (LangOpts.KeepStaticConsts) { + const auto *VD = dyn_cast(D); + if (VD && VD->getType().isConstQualified() && + VD->getStorageClass() == SC_Static) + return true; + } + if (const auto *FD = dyn_cast(D)) { // Forward declarations aren't required. if (!FD->doesThisDeclarationHaveABody()) Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1350,6 +1350,12 @@ if (D && D->hasAttr()) addUsedGlobal(GV); + + if (LangOpts.KeepStaticConsts && D && isa(D)) { + const auto *VD = cast(D); + if (VD->getType().isConstQualified() && VD->getStorageClass() == SC_Static) + addUsedGlobal(GV); + } } bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3996,6 +3996,7 @@ Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); Args.AddLastArg(CmdArgs, options::OPT_femulated_tls, options::OPT_fno_emulated_tls); + Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts); // AltiVec-like language extensions aren't relevant for assembling. if (!isa(JA) || Output.getType() != types::TY_PP_Asm) Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2485,6 +2485,7 @@ Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns) | Opts.NativeHalfArgsAndReturns; Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); + Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts); // __declspec is enabled by default for the PS4 by the driver, and also // enabled for Microsoft Extensions or Borland Extensions, here. Index: test/CodeGen/keep-static-consts.cpp =================================================================== --- /dev/null +++ test/CodeGen/keep-static-consts.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fkeep-static-consts -emit-llvm %s -o - -triple=x86_64-unknown-linux-gnu | FileCheck %s + +// CHECK: @_ZL7srcvers = internal constant [4 x i8] c"xyz\00", align 1 +// CHECK: @llvm.used = appending global [1 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_ZL7srcvers, i32 0, i32 0)], section "llvm.metadata" +static const char srcvers[] = "xyz"; +extern const int b = 1;