diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | clang/test/Sema/attr-section.c | 4 |
4 files changed, 22 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1420dabf1e9..0b3c9fed6bd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 03a3e36b831..89185c89518 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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 && diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 33f02c5b7f4..c99dbd944b0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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; diff --git a/clang/test/Sema/attr-section.c b/clang/test/Sema/attr-section.c index c64b10d80ff..2fb4dbd6bfd 100644 --- a/clang/test/Sema/attr-section.c +++ b/clang/test/Sema/attr-section.c @@ -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}} |