Emit section information for extern variables.
authorErich Keane <erich.keane@intel.com>
Tue, 26 Sep 2017 23:42:34 +0000 (23:42 +0000)
committerErich Keane <erich.keane@intel.com>
Tue, 26 Sep 2017 23:42:34 +0000 (23:42 +0000)
Currently, if _attribute_((section())) is used for extern variables,
section information is not emitted in generated IR when the variables are used.
This is expected since sections are not generated for external linkage objects.
However NiosII requires this information as it uses special GP-relative accesses
for any objects that use attribute section (.sdata). GCC keeps this attribute in
  middle-end.

This change emits the section information for all targets.

Patch By: Elizabeth Andrews

Differential Revision:https://reviews.llvm.org/D36487

llvm-svn: 314262

clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Sema/SemaDecl.cpp
clang/test/Sema/attr-section.c

index 1420dab..0b3c9fe 100644 (file)
@@ -2620,6 +2620,8 @@ def err_attribute_section_invalid_for_target : Error<
   "argument to 'section' attribute is not valid for this target: %0">;
 def warn_mismatched_section : Warning<
   "section does not match previous declaration">, InGroup<Section>;
+def warn_attribute_section_on_redeclaration : Warning<
+  "section attribute is specified on redeclared variable">, InGroup<Section>;
 
 def err_anonymous_property: Error<
   "anonymous property is not supported">;
index 03a3e36..89185c8 100644 (file)
@@ -2432,6 +2432,12 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
       EmitGlobalVarDefinition(D);
     }
 
+    // Emit section information for extern variables.
+    if (D->hasExternalStorage()) {
+      if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+        GV->setSection(SA->getName());
+    }
+
     // Handle XCore specific ABI requirements.
     if (getTriple().getArch() == llvm::Triple::xcore &&
         D->getLanguageLinkage() == CLanguageLinkage &&
index 33f02c5..c99dbd9 100644 (file)
@@ -2607,6 +2607,16 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
     }
   }
 
+  // This redeclaration adds a section attribute.
+  if (New->hasAttr<SectionAttr>() && !Old->hasAttr<SectionAttr>()) {
+    if (auto *VD = dyn_cast<VarDecl>(New)) {
+      if (VD->isThisDeclarationADefinition() != VarDecl::Definition) {
+        Diag(New->getLocation(), diag::warn_attribute_section_on_redeclaration);
+        Diag(Old->getLocation(), diag::note_previous_declaration);
+      }
+    }
+  }
+
   if (!Old->hasAttrs())
     return;
 
index c64b10d..2fb4dbd 100644 (file)
@@ -19,3 +19,7 @@ void __attribute__((section("foo,zed"))) test2(void); // expected-note {{previou
 void __attribute__((section("bar,zed"))) test2(void) {} // expected-warning {{section does not match previous declaration}}
 
 enum __attribute__((section("NEAR,x"))) e { one }; // expected-error {{'section' attribute only applies to functions, methods, properties, and global variables}}
+
+extern int a; // expected-note {{previous declaration is here}}
+int *b = &a;
+extern int a __attribute__((section("foo,zed"))); // expected-warning {{section attribute is specified on redeclared variable}}