javed.absar created this revision.
Herald added a subscriber: aemerson.

This patch adds support for a '#pragma clang section' directive in clang.
 An RFC was sent out earlier by my colleague  James Molloy:
 http://lists.llvm.org/pipermail/cfe-dev/2017-March/053100.html

      

Purpose:

  The purpose of this is to provide to developers a means to specify 
section-names
  for global variables, functions and static variables, using #pragma 
directives.
  This will provide a migration path towards clang for developers in the 
embedded
  and automotive domain. For example, AUTOSAR, an automotive standard, mandates
  the use of a #pragma in header files to determine in which sections 
initialized
  and uninitialized data get put into.
  This feature is implemented in our legacy ARM Compiler 5 toolchain and GCC 
forks
  used across the automotive space that have this feature implemented compatible
  with the ARM Compiler 5 implementation. The documentation is here:
  
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124985290.html


User-Visible Behavior:

  The developer can specify section names as:
    #pragma clang section bss="myBSS" data="myData" rodata="myRodata" 
text="myText"
  
  The developer can "unspecify" a section name with empty string e.g.
    #pragma clang section bss="" data="" text="" rodata=""
  
  1. The pragma applies to all global variable, statics and function 
declarations
  from the pragma to the end of the translation unit.    
  2. The pragma clang section is enabled automatically, without need of any 
flags.    
  3. This feature is only defined to work sensibly for ELF targets.    
  4. If section name is specified through _attribute_((section("myname"))), then
  the attribute name gains precedence over any applicable section name via 
pragma directives.    
  5. Global variables, including - basic types, arrays, struct - that are 
initialized to zero
   e.g. int x = 0; will be placed in the named bss section, if one is present.  
  
  6. The section type using '#pragma clang section' approach does not does NOT
  try to infer section-kind from the name.
  For example, assigning a section ".bss.mysec" does NOT mean it will be placed 
in BSS.


Design:

  The decision about which section-kind applies to each global is not taken by 
this
  implementation but is purely inquired from the default back-end 
implementation in LLVM.
  Once the section-kind is known, appropriate section name as specified by the 
user
  using pragma directive, is applied to that global.
  Note that this is more effective approach than choosing the section name in 
the front-end
  when optimisation passes have not been run and the final proper section is 
not known.    

There is a llvm corresponding patch with this patch.


https://reviews.llvm.org/D33412

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/CodeGen/CGDecl.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/Parse/ParsePragma.cpp
  lib/Sema/SemaAttr.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeGenCXX/clang-sections-tentative.c
  test/CodeGenCXX/clang-sections.cpp
  test/Sema/pragma-clang-section.c

Index: test/Sema/pragma-clang-section.c
===================================================================
--- /dev/null
+++ test/Sema/pragma-clang-section.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple arm-none-eabi
+#pragma clang section bss="mybss.1" data="mydata.1" rodata="myrodata.1" text="mytext.1"
+#pragma clang section bss="" data="" rodata="" text=""
+#pragma clang section
+
+#pragma clang section dss="mybss.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+#pragma clang section deta="mydata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+#pragma clang section rodeta="rodata.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+#pragma clang section taxt="text.2" // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+
+#pragma clang section section bss="mybss.2"  // expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+
+#pragma clang section bss "mybss.2"   // expected-error {{expected '=' following '#pragma clang section bss'}}
+#pragma clang section data "mydata.2"   // expected-error {{expected '=' following '#pragma clang section data'}}
+#pragma clang section rodata "myrodata.2"   // expected-error {{expected '=' following '#pragma clang section rodata'}}
+#pragma clang section bss="" data="" rodata="" text="" more //expected-error {{expected one of [bss|data|rodata|text] section kind in '#pragma clang section'}}
+int a;
Index: test/CodeGenCXX/clang-sections.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/clang-sections.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
+// Test that global variables, statics and functions are attached section-attributes
+// as per '#pragma clang section' directives.
+
+extern "C" {
+// test with names for each section
+#pragma clang section bss="my_bss.1" data="my_data.1" rodata="my_rodata.1"
+#pragma clang section text="my_text.1"
+int a;      // my_bss.1
+int b = 1;  // my_data.1
+int c[4];   // my_bss.1
+short d[5] = {0}; // my_bss.1
+short e[6] = {0, 0, 1}; // my_data.1
+extern const int f;
+const int f = 2;  // my_rodata.1
+int foo(void) {   // my_text.1
+  return b;
+}
+static int g[2]; // my_bss.1
+#pragma clang section bss=""
+int h; // default - .bss
+#pragma clang section data=""  bss="my_bss.2" text="my_text.2"
+int i = 0; // my_bss.2
+extern const int j;
+const int j = 4; // default - .rodata
+int k; // my_bss.2
+extern int zoo(int *x, int *y);
+int goo(void) {  // my_text.2
+  static int lstat_h;  // my_bss.2
+  return zoo(g, &lstat_h);
+}
+#pragma clang section rodata="my_rodata.2" data="my_data.2"
+int l = 5; // my_data.2
+extern const int m;
+const int m = 6; // my_rodata.2
+#pragma clang section rodata="" data="" bss="" text=""
+int n; // default
+int o = 6; // default
+extern const int p;
+const int p = 7; // default
+int hoo(void) {
+  return b;
+}
+}
+//CHECK: @a = global i32 0, align 4 #0
+//CHECK: @b = global i32 1, align 4 #0
+//CHECK: @c = global [4 x i32] zeroinitializer, align 4 #0
+//CHECK: @d = global [5 x i16] zeroinitializer, align 2 #0
+//CHECK: @e = global [6 x i16] [i16 0, i16 0, i16 1, i16 0, i16 0, i16 0], align 2 #0
+//CHECK: @f = constant i32 2, align 4 #0
+
+//CHECK: @h = global i32 0, align 4 #1
+//CHECK: @i = global i32 0, align 4 #2
+//CHECK: @j = constant i32 4, align 4 #2
+//CHECK: @k = global i32 0, align 4 #2
+//CHECK: @_ZZ3gooE7lstat_h = internal global i32 0, align 4 #2
+//CHECK: @_ZL1g = internal global [2 x i32] zeroinitializer, align 4 #0
+
+//CHECK: @l = global i32 5, align 4 #3
+//CHECK: @m = constant i32 6, align 4 #3
+
+//CHECK: @n = global i32 0, align 4
+//CHECK: @o = global i32 6, align 4
+//CHECK: @p = constant i32 7, align 4
+
+//CHECK: define i32 @foo() #4 {
+//CHECK: define i32 @goo() #5 {
+//CHECK: declare i32 @zoo(i32*, i32*) #6
+//CHECK: define i32 @hoo() #7 {
+
+//CHECK: attributes #0 = { "bss-section"="my_bss.1" "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
+//CHECK: attributes #1 = { "data-section"="my_data.1" "rodata-section"="my_rodata.1" }
+//CHECK: attributes #2 = { "bss-section"="my_bss.2" "rodata-section"="my_rodata.1" }
+//CHECK: attributes #3 = { "bss-section"="my_bss.2" "data-section"="my_data.2" "rodata-section"="my_rodata.2" }
+//CHECK: attributes #4 = { {{.*"implicit-section-name"="my_text.1".*}} }
+//CHECK: attributes #5 = { {{.*"implicit-section-name"="my_text.2".*}} }
+//CHECK-NOT: attributes #6 = { {{.*"implicit-section-name".*}} }
+//CHECK-NOT: attributes #7 = { {{.*"implicit-section-name".*}} }
Index: test/CodeGenCXX/clang-sections-tentative.c
===================================================================
--- /dev/null
+++ test/CodeGenCXX/clang-sections-tentative.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -x c -emit-llvm -triple arm-none-eabi -o - %s | FileCheck %s
+
+// Test that section attributes are attached to C tentative definitions as per
+// '#pragma clang section' directives.
+
+#pragma clang section bss = ".bss.1"
+int x; // bss.1
+
+#pragma clang section bss = ""
+int x; // stays in .bss.1
+int y; // not assigned a section attribute
+int z; // not assigned a section attribute
+
+#pragma clang section bss = ".bss.2"
+int x; // stays in .bss.1
+int y; // .bss.2
+
+// Test the same for `const` declarations.
+#pragma clang section rodata = ".rodata.1"
+const int cx; // rodata.1
+
+#pragma clang section rodata = ""
+const int cx; // stays in .rodata.1
+const int cy; // not assigned a section attribute
+const int cz; // not assigned a rodata section attribute
+
+#pragma clang section rodata = ".rodata.2"
+const int cx; // stays in .rodata.1
+const int cy; // .rodata.2
+
+// CHECK: @x = global i32 0, align 4 #0
+// CHECK: @y = global i32 0, align 4 #1
+// CHECK: @z = common global i32 0, align 4
+// CHECK: @cx = constant i32 0, align 4 #2
+// CHECK: @cy = constant i32 0, align 4 #3
+// CHECK: @cz = constant i32 0, align 4 #1
+
+// CHECK: attributes #0 = { "bss-section"=".bss.1" }
+// CHECK: attributes #1 = { "bss-section"=".bss.2" }
+// CHECK: attributes #2 = { "bss-section"=".bss.2" "rodata-section"=".rodata.1" }
+// CHECK: attributes #3 = { "bss-section"=".bss.2" "rodata-section"=".rodata.2" }
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -8650,6 +8650,14 @@
     NewFD->setInvalidDecl();
   }
 
+  // Apply an implicit SectionAttr if '#pragma clang section text' is active
+  if (PragmaClangTextSection.Valid && D.isFunctionDefinition() &&
+      !NewFD->hasAttr<SectionAttr>()) {
+    NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context,
+                                                 PragmaClangTextSection.SectionName,
+                                                 PragmaClangTextSection.PragmaLocation));
+  }
+
   // Apply an implicit SectionAttr if #pragma code_seg is active.
   if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
       !NewFD->hasAttr<SectionAttr>()) {
@@ -11163,6 +11171,23 @@
   if (!VD)
     return;
 
+  // Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active
+  if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() &&
+      !inTemplateInstantiation() && !VD->hasAttr<SectionAttr>()) {
+    if (PragmaClangBSSSection.Valid)
+      VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context,
+                                                            PragmaClangBSSSection.SectionName,
+                                                            PragmaClangBSSSection.PragmaLocation));
+    if (PragmaClangDataSection.Valid)
+      VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context,
+                                                             PragmaClangDataSection.SectionName,
+                                                             PragmaClangDataSection.PragmaLocation));
+    if (PragmaClangRodataSection.Valid)
+      VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context,
+                                                               PragmaClangRodataSection.SectionName,
+                                                               PragmaClangRodataSection.PragmaLocation));
+  }
+
   if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
     for (auto *BD : DD->bindings()) {
       FinalizeDeclaration(BD);
Index: lib/Sema/SemaAttr.cpp
===================================================================
--- lib/Sema/SemaAttr.cpp
+++ lib/Sema/SemaAttr.cpp
@@ -126,6 +126,36 @@
   PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
 }
 
+void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
+                                   PragmaClangSectionKind SecKind, StringRef SecName) {
+  PragmaClangSection *CSec;
+  switch (SecKind) {
+    case PragmaClangSectionKind::PCSK_BSS:
+      CSec = &PragmaClangBSSSection;
+      break;
+    case PragmaClangSectionKind::PCSK_Data:
+      CSec = &PragmaClangDataSection;
+      break;
+    case PragmaClangSectionKind::PCSK_Rodata:
+      CSec = &PragmaClangRodataSection;
+      break;
+    case PragmaClangSectionKind::PCSK_Text:
+      CSec = &PragmaClangTextSection;
+      break;
+    default:
+      llvm_unreachable("invalid clang section kind");
+  }
+
+  if (Action == PragmaClangSectionAction::PCSA_Clear) {
+    CSec->Valid = false;
+    return;
+  }
+
+  CSec->Valid = true;
+  CSec->SectionName = SecName;
+  CSec->PragmaLocation = PragmaLoc;
+}
+
 void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
                            StringRef SlotLabel, Expr *alignment) {
   Expr *Alignment = static_cast<Expr *>(alignment);
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -49,6 +49,15 @@
                     Token &FirstToken) override;
 };
 
+struct PragmaClangSectionHandler : public PragmaHandler {
+  explicit PragmaClangSectionHandler(Sema &S)
+             : PragmaHandler("section"), Actions(S) {}
+  void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+                    Token &FirstToken) override;
+private:
+  Sema &Actions;
+};
+
 struct PragmaMSStructHandler : public PragmaHandler {
   explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
   void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
@@ -224,6 +233,9 @@
   FPContractHandler.reset(new PragmaFPContractHandler());
   PP.AddPragmaHandler("STDC", FPContractHandler.get());
 
+  PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
+  PP.AddPragmaHandler("clang", PCSectionHandler.get());
+
   if (getLangOpts().OpenCL) {
     OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
     PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
@@ -323,6 +335,9 @@
     MSCommentHandler.reset();
   }
 
+  PP.RemovePragmaHandler("clang", PCSectionHandler.get());
+  PCSectionHandler.reset();
+
   if (getLangOpts().MicrosoftExt) {
     PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
     MSDetectMismatchHandler.reset();
@@ -1614,6 +1629,51 @@
   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
 }
 
+// #pragma clang section bss="abc" data="" rodata="def" text=""
+void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
+             PragmaIntroducerKind Introducer, Token &FirstToken) {
+
+  Token Tok;
+  auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
+
+  PP.Lex(Tok); // eat 'section'
+  while (Tok.isNot(tok::eod)) {
+    if (Tok.isNot(tok::identifier)) {
+      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
+      return;
+    }
+
+    const IdentifierInfo *SecType = Tok.getIdentifierInfo();
+    if (SecType->isStr("bss"))
+      SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
+    else if (SecType->isStr("data"))
+      SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
+    else if (SecType->isStr("rodata"))
+      SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
+    else if (SecType->isStr("text"))
+      SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
+    else {
+      PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
+      return;
+    }
+
+    PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
+    if (Tok.isNot(tok::equal)) {
+      PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
+      return;
+    }
+
+    std::string SecName;
+    if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
+      return;
+
+    Actions.ActOnPragmaClangSection(Tok.getLocation(),
+      (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
+                       Sema::PragmaClangSectionAction::PCSA_Clear),
+       SecKind, SecName);
+  }
+}
+
 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1012,9 +1012,25 @@
                                           llvm::GlobalObject *GO) {
   SetCommonAttributes(D, GO);
 
-  if (D)
+  if (D) {
+    if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) {
+      if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>())
+        GV->addAttribute("bss-section", SA->getName());
+      if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>())
+        GV->addAttribute("data-section", SA->getName());
+      if (auto *SA = D->getAttr<PragmaClangRodataSectionAttr>())
+        GV->addAttribute("rodata-section", SA->getName());
+    }
+
+    if (auto *F = dyn_cast<llvm::Function>(GO)) {
+      if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
+       if (!D->getAttr<SectionAttr>())
+         F->addFnAttr("implicit-section-name", SA->getName());
+    }
+
     if (const SectionAttr *SA = D->getAttr<SectionAttr>())
       GO->setSection(SA->getName());
+  }
 
   getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
 }
@@ -1113,6 +1129,10 @@
 
   setLinkageAndVisibilityForGV(F, FD);
 
+  if (FD->getAttr<PragmaClangTextSectionAttr>()) {
+    F->addFnAttr("implicit-section-name");
+  }
+
   if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
     F->setSection(SA->getName());
 
@@ -2788,6 +2808,14 @@
   if (D->hasAttr<SectionAttr>())
     return true;
 
+  // A variable cannot be both common and exist in a section.
+  // We dont try to determine which is the right section in the front-end.
+  // If no specialized section name is applicable, it will resort to default.
+  if (D->hasAttr<PragmaClangBSSSectionAttr>() ||
+      D->hasAttr<PragmaClangDataSectionAttr>() ||
+      D->hasAttr<PragmaClangRodataSectionAttr>())
+    return true;
+
   // Thread local vars aren't considered common linkage.
   if (D->getTLSKind())
     return true;
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -406,6 +406,13 @@
   if (D.hasAttr<AnnotateAttr>())
     CGM.AddGlobalAnnotations(&D, var);
 
+  if (auto *SA = D.getAttr<PragmaClangBSSSectionAttr>())
+    var->addAttribute("bss-section", SA->getName());
+  if (auto *SA = D.getAttr<PragmaClangDataSectionAttr>())
+    var->addAttribute("data-section", SA->getName());
+  if (auto *SA = D.getAttr<PragmaClangRodataSectionAttr>())
+    var->addAttribute("rodata-section", SA->getName());
+
   if (const SectionAttr *SA = D.getAttr<SectionAttr>())
     var->setSection(SA->getName());
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -336,6 +336,35 @@
   /// \brief Source location for newly created implicit MSInheritanceAttrs
   SourceLocation ImplicitMSInheritanceAttrLoc;
 
+  /// \brief pragma clang section kind
+  enum PragmaClangSectionKind {
+    PCSK_Invalid      = 0,
+    PCSK_BSS          = 1,
+    PCSK_Data         = 2,
+    PCSK_Rodata       = 3,
+    PCSK_Text         = 4
+   };
+
+  enum PragmaClangSectionAction {
+    PCSA_Set     = 0,
+    PCSA_Clear   = 1
+  };
+
+  struct PragmaClangSection {
+    std::string SectionName;
+    bool Valid = false;
+    SourceLocation PragmaLocation;
+
+    void Act(SourceLocation PragmaLocation,
+             PragmaClangSectionAction Action,
+             StringLiteral* Name);
+   };
+
+   PragmaClangSection PragmaClangBSSSection;
+   PragmaClangSection PragmaClangDataSection;
+   PragmaClangSection PragmaClangRodataSection;
+   PragmaClangSection PragmaClangTextSection;
+
   enum PragmaMsStackAction {
     PSK_Reset     = 0x0,                // #pragma ()
     PSK_Set       = 0x1,                // #pragma (value)
@@ -8093,6 +8122,11 @@
     POAK_Reset    // #pragma options align=reset
   };
 
+  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
+  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
+                               PragmaClangSectionAction Action,
+                               PragmaClangSectionKind SecKind, StringRef SecName);
+
   /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
   void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
                                SourceLocation PragmaLoc);
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -166,6 +166,7 @@
   std::unique_ptr<PragmaHandler> FPContractHandler;
   std::unique_ptr<PragmaHandler> OpenCLExtensionHandler;
   std::unique_ptr<PragmaHandler> OpenMPHandler;
+  std::unique_ptr<PragmaHandler> PCSectionHandler;
   std::unique_ptr<PragmaHandler> MSCommentHandler;
   std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
   std::unique_ptr<PragmaHandler> MSPointersToMembers;
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -887,9 +887,18 @@
   "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
 def warn_pragma_expected_identifier : Warning<
   "expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
+
+// '#pragma clang section' related errors
+def err_pragma_expected_clang_section_name : Error<
+  "expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
+def err_pragma_clang_section_expected_equal : Error<
+  "expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
+def err_pragma_clang_section_expected_name_or_clear : Error<
+  "expected section name or '\"\"' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">;
 def warn_pragma_expected_section_name : Warning<
   "expected a string literal for the section name in '#pragma %0' - ignored">,
   InGroup<IgnoredPragmas>;
+
 def warn_pragma_expected_section_push_pop_or_name : Warning<
   "expected push, pop or a string literal for the section name in '#pragma %0' - ignored">,
   InGroup<IgnoredPragmas>;
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -1668,6 +1668,42 @@
   let Documentation = [SectionDocs];
 }
 
+def PragmaClangBSSSection : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Args = [StringArgument<"Name">];
+  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
+                             "ExpectedFunctionMethodOrGlobalVar">;
+  let Documentation = [Undocumented];
+}
+
+def PragmaClangDataSection : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Args = [StringArgument<"Name">];
+  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
+                             "ExpectedFunctionMethodOrGlobalVar">;
+  let Documentation = [Undocumented];
+}
+
+def PragmaClangRodataSection : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Args = [StringArgument<"Name">];
+  let Subjects = SubjectList<[GlobalVar], ErrorDiag,
+                             "ExpectedFunctionMethodOrGlobalVar">;
+  let Documentation = [Undocumented];
+}
+
+def PragmaClangTextSection : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let Args = [StringArgument<"Name">];
+  let Subjects = SubjectList<[Function], ErrorDiag,
+                             "ExpectedFunctionMethodOrGlobalVar">;
+  let Documentation = [Undocumented];
+}
+
 def Sentinel : InheritableAttr {
   let Spellings = [GCC<"sentinel">];
   let Args = [DefaultIntArgument<"Sentinel", 0>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to