diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 843746111463..8323c8f2b2ac 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -345,6 +345,8 @@ def AddressSpace : TypeAttr { def Alias : Attr { let Spellings = [GCC<"alias">]; let Args = [StringArgument<"Aliasee">]; + let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag, + "ExpectedFunctionGlobalVarMethodOrProperty">; let Documentation = [Undocumented]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5b5528e4f764..5509b03ab225 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3902,10 +3902,8 @@ def warn_missing_variable_declarations : Warning< def err_static_data_member_reinitialization : Error<"static data member %0 already has an initializer">; def err_redefinition : Error<"redefinition of %0">; -def err_alias_after_tentative : - Error<"alias definition of %0 after tentative definition">; -def err_tentative_after_alias : - Error<"tentative definition of %0 after alias definition">; +def err_alias_is_definition : + Error<"definition %0 cannot also be an alias">; def err_definition_of_implicitly_declared_member : Error< "definition of implicitly declared %select{default constructor|copy " "constructor|move constructor|copy assignment operator|move assignment " diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9aa1d9ca83c8..da59fb577323 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2219,18 +2219,8 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { const Attr *NewAttribute = NewAttributes[I]; if (isa(NewAttribute)) { - if (FunctionDecl *FD = dyn_cast(New)) - S.CheckForFunctionRedefinition(FD, cast(Def)); - else { - VarDecl *VD = cast(New); - unsigned Diag = cast(Def)->isThisDeclarationADefinition() == - VarDecl::TentativeDefinition - ? diag::err_alias_after_tentative - : diag::err_redefinition; - S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); - S.Diag(Def->getLocation(), diag::note_previous_definition); - VD->setInvalidDecl(); - } + FunctionDecl *FD = cast(New); + S.CheckForFunctionRedefinition(FD, cast(Def)); ++I; continue; } @@ -5103,6 +5093,18 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { if (ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); ND.dropAttr(); + ND.dropAttr(); + } + } + + if (auto *VD = dyn_cast(&ND)) { + if (VD->hasInit()) { + if (const auto *Attr = VD->getAttr()) { + assert(VD->isThisDeclarationADefinition() && + !VD->isExternallyVisible() && "Broken AliasAttr handled late!"); + S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD; + VD->dropAttr(); + } } } @@ -9617,18 +9619,6 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { } } - if (!VD->isInvalidDecl() && - VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) { - if (const VarDecl *Def = VD->getDefinition()) { - if (Def->hasAttr()) { - Diag(VD->getLocation(), diag::err_tentative_after_alias) - << VD->getDeclName(); - Diag(Def->getLocation(), diag::note_previous_definition); - VD->setInvalidDecl(); - } - } - } - const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 17a849ea7af0..8837bbdb2bc4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1492,6 +1492,20 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } + // Aliases should be on declarations, not definitions. + if (const auto *FD = dyn_cast(D)) { + if (FD->isThisDeclarationADefinition()) { + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD; + return; + } + } else { + const auto *VD = cast(D); + if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD; + return; + } + } + // FIXME: check if target symbol exists in current file D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, diff --git a/clang/test/Misc/ast-dump-attr.cpp b/clang/test/Misc/ast-dump-attr.cpp index 446f0fa692f9..ed6d1f5781da 100644 --- a/clang/test/Misc/ast-dump-attr.cpp +++ b/clang/test/Misc/ast-dump-attr.cpp @@ -79,7 +79,7 @@ void TestInt(void) __attribute__((constructor(123))); // CHECK: FunctionDecl{{.*}}TestInt // CHECK-NEXT: ConstructorAttr{{.*}} 123 -int TestString __attribute__((alias("alias1"))); +static int TestString __attribute__((alias("alias1"))); // CHECK: VarDecl{{.*}}TestString // CHECK-NEXT: AliasAttr{{.*}} "alias1" diff --git a/clang/test/Sema/alias-redefinition.c b/clang/test/Sema/alias-redefinition.c index 6c6ebf80250b..9f9930dc2a97 100644 --- a/clang/test/Sema/alias-redefinition.c +++ b/clang/test/Sema/alias-redefinition.c @@ -23,22 +23,5 @@ void fun4(void); void f5() {} void __attribute((alias("f5"))) fun5(void) {} // expected-error {{redefinition of 'fun5'}} // expected-note {{previous definition}} -int v1; -int var1 __attribute((alias("v1"))); // expected-note {{previous definition}} -int var1 __attribute((alias("v1"))); // expected-error {{redefinition of 'var1'}} - -int v2; -int var2 = 2; // expected-note {{previous definition}} -int var2 __attribute((alias("v2"))); // expected-error {{redefinition of 'var2'}} - -int v3; -int var3 __attribute((alias("v3"))); // expected-note {{previous definition}} -int var3 = 2; // expected-error {{redefinition of 'var3'}} - -int v4; -int var4; // expected-note {{previous definition}} -int var4 __attribute((alias("v4"))); // expected-error {{alias definition of 'var4' after tentative definition}} - -int v5; -int var5 __attribute((alias("v5"))); // expected-note {{previous definition}} -int var5; // expected-error {{tentative definition of 'var5' after alias definition}} +int var1 __attribute((alias("v1"))); // expected-error {{definition 'var1' cannot also be an alias}} +static int var2 __attribute((alias("v2"))) = 2; // expected-error {{definition 'var2' cannot also be an alias}}