[clang] 955d7c3 - [clang] Add support for #pragma strict_gs_check

David Majnemer via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 19 13:09:43 PDT 2022


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
+


        


More information about the cfe-commits mailing list