From: Nick Lewycky Date: Fri, 11 Dec 2015 21:28:55 +0000 (+0000) Subject: Error on redeclaring with a conflicting asm label and on redeclaring with an asm... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7271e6a3578dfaa990ae26affd3efeac43cdee87;p=clang Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled the file but with different behaviour. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@255371 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f1a8c279dc..c008888f74 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4259,6 +4259,9 @@ def err_tag_definition_of_typedef : Error< def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; +def err_different_asm_label : Error<"conflicting asm label">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index af5fdc95c9..6a61ac0e44 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2379,9 +2379,24 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, if (!Old->hasAttrs() && !New->hasAttrs()) return; - // attributes declared post-definition are currently ignored + // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); + if (AsmLabelAttr *NewA = New->getAttr()) { + if (AsmLabelAttr *OldA = Old->getAttr()) { + if (OldA->getLabel() != NewA->getLabel()) { + // This redeclaration changes __asm__ label. + Diag(New->getLocation(), diag::err_different_asm_label); + Diag(OldA->getLocation(), diag::note_previous_declaration); + } + } else if (Old->isUsed()) { + // This redeclaration adds an __asm__ label to a declaration that has + // already been ODR-used. + Diag(New->getLocation(), diag::err_late_asm_label_name) + << isa(Old) << New->getAttr()->getRange(); + } + } + if (!Old->hasAttrs()) return; diff --git a/test/Sema/asm-label.c b/test/Sema/asm-label.c new file mode 100644 index 0000000000..87cda2f533 --- /dev/null +++ b/test/Sema/asm-label.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -verify %s + +void f(); +void f() __asm__("fish"); +void g(); + +void f() { + g(); +} +void g() __asm__("gold"); // expected-error{{cannot apply asm label to function after its first use}} + +void h() __asm__("hose"); // expected-note{{previous declaration is here}} +void h() __asm__("hair"); // expected-error{{conflicting asm label}} + +int x; +int x __asm__("xenon"); +int y; + +int test() { return y; } + +int y __asm__("yacht"); // expected-error{{cannot apply asm label to variable after its first use}} + +int z __asm__("zebra"); // expected-note{{previous declaration is here}} +int z __asm__("zooms"); // expected-error{{conflicting asm label}} + + +// No diagnostics on the following. +void __real_readlink() __asm("readlink"); +void readlink() __asm("__protected_readlink"); +void readlink() { __real_readlink(); }