diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -472,6 +472,9 @@ /// Whether to emit unused static constants. CODEGENOPT(KeepStaticConsts, 1, 0) +/// Whether to emit all static variables. +CODEGENOPT(KeepStaticVariables, 1, 0) + /// Whether to follow the AAPCS enforcing at least one read before storing to a volatile bitfield CODEGENOPT(ForceAAPCSBitfieldLoad, 1, 0) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1697,6 +1697,10 @@ CodeGenOpts<"KeepStaticConsts">, DefaultFalse, PosFlag, NegFlag, BothFlags<[NoXarchOption], " static const variables if unused">>; +defm keep_static_variables : BoolFOption<"keep-static-variables", + CodeGenOpts<"KeepStaticVariables">, DefaultFalse, + PosFlag, NegFlag, + BothFlags<[NoXarchOption], " static variables if unused">>; defm fixed_point : BoolFOption<"fixed-point", LangOpts<"FixedPoint">, DefaultFalse, PosFlag, NegFlag, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2198,11 +2198,15 @@ if (D && D->hasAttr()) addUsedOrCompilerUsedGlobal(GV); - if (CodeGenOpts.KeepStaticConsts && D && isa(D)) { + if ((CodeGenOpts.KeepStaticConsts || CodeGenOpts.KeepStaticVariables) && D && + isa(D)) { const auto *VD = cast(D); - if (VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - addUsedOrCompilerUsedGlobal(GV); + if (VD->getStorageDuration() == SD_Static) { + if (CodeGenOpts.KeepStaticVariables) + addUsedOrCompilerUsedGlobal(GV); + else if (CodeGenOpts.KeepStaticConsts && VD->getType().isConstQualified()) + addUsedOrCompilerUsedGlobal(GV); + } } } @@ -3084,11 +3088,14 @@ if (LangOpts.EmitAllDecls) return true; - if (CodeGenOpts.KeepStaticConsts) { + if (CodeGenOpts.KeepStaticConsts || CodeGenOpts.KeepStaticVariables) { const auto *VD = dyn_cast(Global); - if (VD && VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - return true; + if (VD && VD->getStorageDuration() == SD_Static) { + if (CodeGenOpts.KeepStaticVariables) + return true; + else if (CodeGenOpts.KeepStaticConsts && VD->getType().isConstQualified()) + return true; + } } return getContext().DeclMustBeEmitted(Global); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7294,6 +7294,8 @@ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_consts, options::OPT_fno_keep_static_consts); + Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_variables, + options::OPT_fno_keep_static_variables); Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers, options::OPT_fno_complete_member_pointers); Args.addOptOutFlag(CmdArgs, options::OPT_fcxx_static_destructors, diff --git a/clang/test/CodeGen/keep-static-variables.cpp b/clang/test/CodeGen/keep-static-variables.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/keep-static-variables.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fkeep-static-variables -emit-llvm %s -o - -triple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-ELF +// RUN: %clang_cc1 -fkeep-static-variables -emit-llvm %s -o - -triple=powerpc64-ibm-aix-xcoff | FileCheck %s --check-prefixes=CHECK,CHECK-NON-ELF + +// CHECK: @_ZL2g1 = internal global i32 0, align 4 +// CHECK: @_ZL2g2 = internal global i32 1, align 4 +// CHECK: @_ZL2g3 = internal global i32 0, align 4 +// CHECK: @_ZL2g4 = internal global i32 2, align 4 +// CHECK-ELF: @llvm.compiler.used = appending global [4 x ptr] [ptr @_ZL2g1, ptr @_ZL2g2, ptr @_ZL2g3, ptr @_ZL2g4], section "llvm.metadata" +// CHECK-NON-ELF: @llvm.used = appending global [4 x ptr] [ptr @_ZL2g1, ptr @_ZL2g2, ptr @_ZL2g3, ptr @_ZL2g4], section "llvm.metadata" + +static int g1; +static int g2 = 1; +static int g3; +static int g4 = 2; + +int test1() { + g1 = 3; + return g1; +} + +int test2() { + return g2; +}