diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -57,7 +57,7 @@ using RoundingMode = llvm::RoundingMode; enum GCMode { NonGC, GCOnly, HybridGC }; - enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; + enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq, SSPUnspecified }; // Automatic variables live on the stack, and when trivial they're usually // uninitialized because it's undefined behavior to use them without diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -309,7 +309,7 @@ "apply global symbol visibility to external declarations without an explicit visibility") BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition") BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") -ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, +ENUM_LANGOPT(StackProtector, StackProtectorMode, 3, SSPUnspecified, "stack protector mode") ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized, "trivial automatic variable initialization") diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -385,7 +385,7 @@ /// this tool chain. virtual LangOptions::StackProtectorMode GetDefaultStackProtectorLevel(bool KernelOrKext) const { - return LangOptions::SSPOff; + return LangOptions::SSPUnspecified; } /// Get the default trivial automatic variable initialization. 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 @@ -2994,8 +2994,8 @@ if (EffectiveTriple.isNVPTX()) return; - // -stack-protector=0 is default. - LangOptions::StackProtectorMode StackProtectorLevel = LangOptions::SSPOff; + LangOptions::StackProtectorMode StackProtectorLevel = + LangOptions::SSPUnspecified; LangOptions::StackProtectorMode DefaultStackProtectorLevel = TC.GetDefaultStackProtectorLevel(KernelOrKext); @@ -3004,8 +3004,11 @@ options::OPT_fstack_protector_strong, options::OPT_fstack_protector)) { if (A->getOption().matches(options::OPT_fstack_protector)) - StackProtectorLevel = - std::max<>(LangOptions::SSPOn, DefaultStackProtectorLevel); + if (DefaultStackProtectorLevel == LangOptions::SSPUnspecified) + StackProtectorLevel = LangOptions::SSPOn; + else + StackProtectorLevel = + std::max<>(LangOptions::SSPOn, DefaultStackProtectorLevel); else if (A->getOption().matches(options::OPT_fstack_protector_strong)) StackProtectorLevel = LangOptions::SSPStrong; else if (A->getOption().matches(options::OPT_fstack_protector_all)) @@ -3014,7 +3017,7 @@ StackProtectorLevel = DefaultStackProtectorLevel; } - if (StackProtectorLevel) { + if (StackProtectorLevel != LangOptions::SSPUnspecified) { CmdArgs.push_back("-stack-protector"); CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel))); } diff --git a/clang/lib/Driver/ToolChains/CrossWindows.h b/clang/lib/Driver/ToolChains/CrossWindows.h --- a/clang/lib/Driver/ToolChains/CrossWindows.h +++ b/clang/lib/Driver/ToolChains/CrossWindows.h @@ -62,7 +62,7 @@ LangOptions::StackProtectorMode GetDefaultStackProtectorLevel(bool KernelOrKext) const override { - return LangOptions::SSPOff; + return LangOptions::SSPUnspecified; } void diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -503,7 +503,7 @@ else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext) return LangOptions::SSPOn; - return LangOptions::SSPOff; + return LangOptions::SSPUnspecified; } void CheckObjCARC() const override; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3379,7 +3379,7 @@ Opts.RetainCommentsFromSystemHeaders = Args.hasArg(OPT_fretain_comments_from_system_headers); - unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); + unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, UINT_MAX, Diags); switch (SSP) { default: Diags.Report(diag::err_drv_invalid_value) @@ -3389,6 +3389,9 @@ case 1: Opts.setStackProtector(LangOptions::SSPOn); break; case 2: Opts.setStackProtector(LangOptions::SSPStrong); break; case 3: Opts.setStackProtector(LangOptions::SSPReq); break; + case UINT_MAX: + Opts.setStackProtector(LangOptions::SSPUnspecified); + break; } if (Arg *A = Args.getLastArg(OPT_ftrivial_auto_var_init)) { diff --git a/clang/test/CodeGen/stack-protector.c b/clang/test/CodeGen/stack-protector.c --- a/clang/test/CodeGen/stack-protector.c +++ b/clang/test/CodeGen/stack-protector.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 0 | FileCheck -check-prefix=DEF -check-prefix=NOSSP %s +// RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 0 | FileCheck -check-prefix=DEF-NOSSP -check-prefix=NOSSP %s // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 1 | FileCheck -check-prefix=DEF -check-prefix=SSP %s // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 2 | FileCheck -check-prefix=DEF -check-prefix=SSPSTRONG %s // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 3 | FileCheck -check-prefix=DEF -check-prefix=SSPREQ %s @@ -16,6 +16,7 @@ char *strcpy(char *s1, const char *s2); // DEF: define {{.*}}void @test1(i8* %msg) #[[A:.*]] { +// DEF-NOSSP: define {{.*}}void @test1(i8* %msg) #[[B:.*]] { void test1(const char *msg) { char a[strlen(msg) + 1]; strcpy(a, msg); @@ -23,6 +24,7 @@ } // DEF: define {{.*}}void @test2(i8* %msg) #[[B:.*]] { +// DEF-NOSSP: define {{.*}}void @test2(i8* %msg) #[[B:.*]] { __attribute__((no_stack_protector)) void test2(const char *msg) { char a[strlen(msg) + 1];