Author: David Majnemer Date: 2022-09-19T20:07:14Z New Revision: 955d7c39ff74868a28c848a0462ff41be972043e
URL: https://github.com/llvm/llvm-project/commit/955d7c39ff74868a28c848a0462ff41be972043e DIFF: https://github.com/llvm/llvm-project/commit/955d7c39ff74868a28c848a0462ff41be972043e.diff LOG: [clang] Add support for #pragma strict_gs_check Added: clang/test/CodeGenCXX/pragma-strict_gs_check.cpp Modified: clang/include/clang/Basic/AttrDocs.td clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/Parse/ParsePragma.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaDecl.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index ee9deef0dde1..0238b3877120 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4454,8 +4454,8 @@ def NoStackProtectorDocs : Documentation { let Category = DocCatFunction; let Heading = "no_stack_protector, safebuffers"; let Content = [{ -Clang supports the ``__attribute__((no_stack_protector))`` and Microsoft style -``__declspec(safebuffers)`` attribute which disables +Clang supports the GNU style ``__attribute__((no_stack_protector))`` and Microsoft +style ``__declspec(safebuffers)`` attribute which disables the stack protector on the specified function. This attribute is useful for selectively disabling the stack protector on some functions when building with ``-fstack-protector`` compiler option. diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 690a56bf6614..273af97ef241 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -194,6 +194,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> MSConstSeg; std::unique_ptr<PragmaHandler> MSCodeSeg; std::unique_ptr<PragmaHandler> MSSection; + std::unique_ptr<PragmaHandler> MSStrictGuardStackCheck; std::unique_ptr<PragmaHandler> MSRuntimeChecks; std::unique_ptr<PragmaHandler> MSIntrinsic; std::unique_ptr<PragmaHandler> MSFunction; @@ -725,6 +726,8 @@ class Parser : public CodeCompletionHandler { SourceLocation PragmaLocation); bool HandlePragmaMSInitSeg(StringRef PragmaName, SourceLocation PragmaLocation); + bool HandlePragmaMSStrictGuardStackCheck(StringRef PragmaName, + SourceLocation PragmaLocation); bool HandlePragmaMSFunction(StringRef PragmaName, SourceLocation PragmaLocation); bool HandlePragmaMSAllocText(StringRef PragmaName, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f1a4c8d914c0..6dd656e29559 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -691,6 +691,9 @@ class Sema final { PragmaStack<StringLiteral *> ConstSegStack; PragmaStack<StringLiteral *> CodeSegStack; + // #pragma strict_gs_check. + PragmaStack<bool> StrictGuardStackCheckStack; + // This stack tracks the current state of Sema.CurFPFeatures. PragmaStack<FPOptionsOverride> FpPragmaStack; FPOptionsOverride CurFPFeatureOverrides() { @@ -10295,6 +10298,12 @@ class Sema final { SourceLocation IncludeLoc); void DiagnoseUnterminatedPragmaAlignPack(); + /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma + /// strict_gs_check. + void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + bool Value); + /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 74fa70379858..123d94ee703f 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -449,6 +449,9 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSCodeSeg.get()); MSSection = std::make_unique<PragmaMSPragma>("section"); PP.AddPragmaHandler(MSSection.get()); + MSStrictGuardStackCheck = + std::make_unique<PragmaMSPragma>("strict_gs_check"); + PP.AddPragmaHandler(MSStrictGuardStackCheck.get()); MSFunction = std::make_unique<PragmaMSPragma>("function"); PP.AddPragmaHandler(MSFunction.get()); MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text"); @@ -567,6 +570,8 @@ void Parser::resetPragmaHandlers() { MSCodeSeg.reset(); PP.RemovePragmaHandler(MSSection.get()); MSSection.reset(); + PP.RemovePragmaHandler(MSStrictGuardStackCheck.get()); + MSStrictGuardStackCheck.reset(); PP.RemovePragmaHandler(MSFunction.get()); MSFunction.reset(); PP.RemovePragmaHandler(MSAllocText.get()); @@ -936,6 +941,7 @@ void Parser::HandlePragmaMSPragma() { .Case("code_seg", &Parser::HandlePragmaMSSegment) .Case("section", &Parser::HandlePragmaMSSection) .Case("init_seg", &Parser::HandlePragmaMSInitSeg) + .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck) .Case("function", &Parser::HandlePragmaMSFunction) .Case("alloc_text", &Parser::HandlePragmaMSAllocText) .Case("optimize", &Parser::HandlePragmaMSOptimize); @@ -1175,6 +1181,59 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, return true; } +// #pragma strict_gs_check(pop) +// #pragma strict_gs_check(push, "on" | "off") +// #pragma strict_gs_check("on" | "off") +bool Parser::HandlePragmaMSStrictGuardStackCheck( + StringRef PragmaName, SourceLocation PragmaLocation) { + if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, + PragmaName)) + return false; + + Sema::PragmaMsStackAction Action = Sema::PSK_Set; + if (Tok.is(tok::identifier)) { + StringRef PushPop = Tok.getIdentifierInfo()->getName(); + if (PushPop == "push") { + PP.Lex(Tok); + Action = Sema::PSK_Push; + if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc, + PragmaName)) + return false; + } else if (PushPop == "pop") { + PP.Lex(Tok); + Action = Sema::PSK_Pop; + } + } + + bool Value = false; + if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) { + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II && II->isStr("off")) { + PP.Lex(Tok); + Value = false; + } else if (II && II->isStr("on")) { + PP.Lex(Tok); + Value = true; + } else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) + << PragmaName; + return false; + } + } + + // Finish the pragma: ')' $ + if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, + PragmaName)) + return false; + + if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, + PragmaName)) + return false; + + Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value); + return true; +} + bool Parser::HandlePragmaMSAllocText(StringRef PragmaName, SourceLocation PragmaLocation) { Token FirstTok = Tok; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 7ccf6330b49b..9fdd5098e62d 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -195,9 +195,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, VtorDispStack(LangOpts.getVtorDispMode()), AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)), DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), - CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()), - CurInitSeg(nullptr), VisContext(nullptr), - PragmaAttributeCurrentTargetDecl(nullptr), + CodeSegStack(nullptr), StrictGuardStackCheckStack(false), + FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr), + VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr), IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index c997d018a406..47611aed7957 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -34,6 +34,7 @@ Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S, S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel); S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel); S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel); + S.StrictGuardStackCheckStack.SentinelAction(PSK_Push, SlotLabel); } } @@ -44,6 +45,7 @@ Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() { S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel); S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel); S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel); + S.StrictGuardStackCheckStack.SentinelAction(PSK_Pop, SlotLabel); } } @@ -774,6 +776,17 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); } +/// Called on well formed \#pragma strict_gs_check(). +void Sema::ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + bool Value) { + if (Action & PSK_Pop && StrictGuardStackCheckStack.Stack.empty()) + Diag(PragmaLocation, diag::warn_pragma_pop_failed) << "strict_gs_check" + << "stack empty"; + + StrictGuardStackCheckStack.Act(PragmaLocation, Action, StringRef(), Value); +} + /// Called on well formed \#pragma bss_seg(). void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags, StringLiteral *SegmentName) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index db0e2981aa82..0f567d91dc81 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9997,6 +9997,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->dropAttr<SectionAttr>(); } + // Apply an implicit StrictGuardStackCheckAttr if #pragma strict_gs_check is + // active. + if (StrictGuardStackCheckStack.CurrentValue && D.isFunctionDefinition() && + !NewFD->hasAttr<StrictGuardStackCheckAttr>()) + NewFD->addAttr(StrictGuardStackCheckAttr::CreateImplicit( + Context, PragmaClangTextSection.PragmaLocation, + AttributeCommonInfo::AS_Pragma)); + // Apply an implicit CodeSegAttr from class declspec or // apply an implicit SectionAttr from #pragma code_seg if active. if (!NewFD->hasAttr<CodeSegAttr>()) { diff --git a/clang/test/CodeGenCXX/pragma-strict_gs_check.cpp b/clang/test/CodeGenCXX/pragma-strict_gs_check.cpp new file mode 100644 index 000000000000..9cfab47692ad --- /dev/null +++ b/clang/test/CodeGenCXX/pragma-strict_gs_check.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -stack-protector 2 -emit-llvm -o - | FileCheck %s + +#pragma strict_gs_check(on) + +extern "C" void test0() { +} +// CHECK: define {{.*}} @test0() #[[ATTR_TEST0:[0-9]*]] { + + +// CHECK: attributes #[[ATTR_TEST0]] = {{.*}} sspstrong + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits