Sema: Variable definitions cannot be __attribute__((alias))
authorDavid Majnemer <david.majnemer@gmail.com>
Mon, 19 Jan 2015 09:00:28 +0000 (09:00 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Mon, 19 Jan 2015 09:00:28 +0000 (09:00 +0000)
Things that are OK:
  extern int var1 __attribute((alias("v1")));
  static int var2 __attribute((alias("v2")));

Things that are not OK:
  int var3 __attribute((alias("v3")));
  extern int var4 __attribute((alias("v4"))) = 4;

We choose to accpet:
  struct S { static int var5 __attribute((alias("v5"))); };

  This code causes assertion failues in GCC 4.8 and ICC 13.0.1, we have
  no reason to reject it.

This partially fixes PR22217.

llvm-svn: 226436

clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/Misc/ast-dump-attr.cpp
clang/test/Sema/alias-redefinition.c

index 8437461..8323c8f 100644 (file)
@@ -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];
 }
 
index 5b5528e..5509b03 100644 (file)
@@ -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 "
index 9aa1d9c..da59fb5 100644 (file)
@@ -2219,18 +2219,8 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
     const Attr *NewAttribute = NewAttributes[I];
 
     if (isa<AliasAttr>(NewAttribute)) {
-      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
-        S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
-      else {
-        VarDecl *VD = cast<VarDecl>(New);
-        unsigned Diag = cast<VarDecl>(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<FunctionDecl>(New);
+      S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(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<WeakRefAttr>();
+      ND.dropAttr<AliasAttr>();
+    }
+  }
+
+  if (auto *VD = dyn_cast<VarDecl>(&ND)) {
+    if (VD->hasInit()) {
+      if (const auto *Attr = VD->getAttr<AliasAttr>()) {
+        assert(VD->isThisDeclarationADefinition() &&
+               !VD->isExternallyVisible() && "Broken AliasAttr handled late!");
+        S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD;
+        VD->dropAttr<AliasAttr>();
+      }
     }
   }
 
@@ -9617,18 +9619,6 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
     }
   }
 
-  if (!VD->isInvalidDecl() &&
-      VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) {
-    if (const VarDecl *Def = VD->getDefinition()) {
-      if (Def->hasAttr<AliasAttr>()) {
-        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.
index 17a849e..8837bbd 100644 (file)
@@ -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<FunctionDecl>(D)) {
+    if (FD->isThisDeclarationADefinition()) {
+      S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD;
+      return;
+    }
+  } else {
+    const auto *VD = cast<VarDecl>(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,
index 446f0fa..ed6d1f5 100644 (file)
@@ -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"
 
index 6c6ebf8..9f9930d 100644 (file)
@@ -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}}