r193200 - Treat aliases as definitions.

Rafael Espindola rafael.espindola at gmail.com
Tue Oct 22 14:39:04 PDT 2013


Author: rafael
Date: Tue Oct 22 16:39:03 2013
New Revision: 193200

URL: http://llvm.org/viewvc/llvm-project?rev=193200&view=rev
Log:
Treat aliases as definitions.

This fixes pr17639.

Before this patch clang would consider

void foo(void) __attribute((alias("__foo")));

a declaration. It now correctly handles it as a definition.

Initial patch by Alp Toker. I added support for variables.

Added:
    cfe/trunk/test/Sema/alias-redefinition.c
    cfe/trunk/test/Sema/pragma-weak.c
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CodeGen/pragma-weak.c

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Oct 22 16:39:03 2013
@@ -173,7 +173,7 @@ def AddressSpace : TypeAttr {
   let Args = [IntArgument<"AddressSpace">];
 }
 
-def Alias : InheritableAttr {
+def Alias : Attr {
   let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">];
   let Args = [StringArgument<"Aliasee">];
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 22 16:39:03 2013
@@ -3500,6 +3500,10 @@ def warn_missing_variable_declarations :
   "no previous extern declaration for non-static variable %0">,
   InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
 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_definition_of_implicitly_declared_member : Error<
   "definition of implicitly declared %select{default constructor|copy "
   "constructor|move constructor|copy assignment operator|move assignment "

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 22 16:39:03 2013
@@ -1539,7 +1539,9 @@ public:
 
   void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
                                        SourceLocation LocAfterDecls);
-  void CheckForFunctionRedefinition(FunctionDecl *FD);
+  void CheckForFunctionRedefinition(FunctionDecl *FD,
+                                    const FunctionDecl *EffectiveDefinition =
+                                        0);
   Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
   Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
   void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Oct 22 16:39:03 2013
@@ -1762,6 +1762,9 @@ VarDecl::DefinitionKind VarDecl::isThisD
   if (hasInit())
     return Definition;
 
+  if (hasAttr<AliasAttr>())
+    return Definition;
+
   // A variable template specialization (other than a static data member
   // template or an explicit specialization) is a declaration until we
   // instantiate its initializer.
@@ -2223,7 +2226,8 @@ bool FunctionDecl::hasTrivialBody() cons
 
 bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
   for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
-    if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed) {
+    if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed ||
+        I->hasAttr<AliasAttr>()) {
       Definition = I->IsDeleted ? I->getCanonicalDecl() : *I;
       return true;
     }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Oct 22 16:39:03 2013
@@ -1996,11 +1996,15 @@ static bool mergeDeclAttribute(Sema &S,
 static const Decl *getDefinition(const Decl *D) {
   if (const TagDecl *TD = dyn_cast<TagDecl>(D))
     return TD->getDefinition();
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
-    return VD->getDefinition();
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    const VarDecl *Def = VD->getDefinition();
+    if (Def)
+      return Def;
+    return VD->getActingDefinition();
+  }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     const FunctionDecl* Def;
-    if (FD->hasBody(Def))
+    if (FD->isDefined(Def))
       return Def;
   }
   return NULL;
@@ -2029,6 +2033,32 @@ static void checkNewAttributesAfterDef(S
   AttrVec &NewAttributes = New->getAttrs();
   for (unsigned I = 0, E = NewAttributes.size(); I != E;) {
     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();
+      }
+      ++I;
+      continue;
+    }
+
+    if (const VarDecl *VD = dyn_cast<VarDecl>(Def)) {
+      // Tentative definitions are only interesting for the alias check above.
+      if (VD->isThisDeclarationADefinition() != VarDecl::Definition) {
+        ++I;
+        continue;
+      }
+    }
+
     if (hasAttribute(Def, NewAttribute->getKind())) {
       ++I;
       continue; // regular attr merging will take care of validating this.
@@ -8819,6 +8849,18 @@ 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.
@@ -9323,12 +9365,17 @@ static bool ShouldWarnAboutMissingProtot
   return MissingPrototype;
 }
 
-void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) {
+void
+Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
+                                   const FunctionDecl *EffectiveDefinition) {
   // Don't complain if we're in GNU89 mode and the previous definition
   // was an extern inline function.
-  const FunctionDecl *Definition;
-  if (!FD->isDefined(Definition) ||
-      canRedefineFunction(Definition, getLangOpts()))
+  const FunctionDecl *Definition = EffectiveDefinition;
+  if (!Definition)
+    if (!FD->isDefined(Definition))
+      return;
+
+  if (canRedefineFunction(Definition, getLangOpts()))
     return;
 
   if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&

Modified: cfe/trunk/test/CodeGen/pragma-weak.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pragma-weak.c?rev=193200&r1=193199&r2=193200&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/pragma-weak.c (original)
+++ cfe/trunk/test/CodeGen/pragma-weak.c Tue Oct 22 16:39:03 2013
@@ -7,8 +7,6 @@
 
 // CHECK-DAG: @both = alias void ()* @__both
 // CHECK-DAG: @both2 = alias void ()* @__both2
-// CHECK-DAG: @both3 = alias weak void ()* @__both3
-// CHECK-DAG: @a3 = alias weak void ()* @__a3
 // CHECK-DAG: @weakvar_alias = alias weak i32* @__weakvar_alias
 // CHECK-DAG: @foo = alias weak void ()* @__foo
 // CHECK-DAG: @foo2 = alias weak void ()* @__foo2
@@ -125,12 +123,6 @@ void both2(void) __attribute((alias("__b
 void __both2(void) {}
 // CHECK-LABEL: define void @__both2()
 
-void __both3(void);
-#pragma weak both3 = __both3 // first, wins
-void both3(void) __attribute((alias("__both3")));
-void __both3(void) {}
-// CHECK-LABEL: define void @__both3()
-
 ///////////// ensure that #pragma weak does not alter existing __attributes()
 
 void __a1(void) __attribute((noinline));
@@ -138,14 +130,6 @@ void __a1(void) __attribute((noinline));
 void __a1(void) {}
 // CHECK: define void @__a1() [[NI:#[0-9]+]]
 
-// attributes introduced BEFORE a combination of #pragma weak and alias()
-// hold...
-void __a3(void) __attribute((noinline));
-#pragma weak a3 = __a3
-void a3(void) __attribute((alias("__a3")));
-void __a3(void) {}
-// CHECK: define void @__a3() [[NI]]
-
 #pragma weak xxx = __xxx
 __attribute((pure,noinline,const)) void __xxx(void) { }
 // CHECK: void @__xxx() [[RN:#[0-9]+]]

Added: cfe/trunk/test/Sema/alias-redefinition.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/alias-redefinition.c?rev=193200&view=auto
==============================================================================
--- cfe/trunk/test/Sema/alias-redefinition.c (added)
+++ cfe/trunk/test/Sema/alias-redefinition.c Tue Oct 22 16:39:03 2013
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s
+
+void f0() {}
+void fun0(void) __attribute((alias("f0")));
+
+void f1() {}
+void fun1() {} // expected-note {{previous definition}}
+void fun1(void) __attribute((alias("f1"))); // expected-error {{redefinition of 'fun1'}}
+
+void f2() {}
+void fun2(void) __attribute((alias("f2"))); // expected-note {{previous definition}}
+void fun2() {} // expected-error {{redefinition of 'fun2'}}
+
+void f3() {}
+void fun3(void) __attribute((alias("f3"))); // expected-note {{previous definition}}
+void fun3(void) __attribute((alias("f3"))); // expected-error {{redefinition of 'fun3'}}
+
+void f4() {}
+void fun4(void) __attribute((alias("f4")));
+void fun4(void);
+
+// FIXME: We should produce a special case error for this.
+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}}

Added: cfe/trunk/test/Sema/pragma-weak.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pragma-weak.c?rev=193200&view=auto
==============================================================================
--- cfe/trunk/test/Sema/pragma-weak.c (added)
+++ cfe/trunk/test/Sema/pragma-weak.c Tue Oct 22 16:39:03 2013
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s
+
+void __both3(void);
+#pragma weak both3 = __both3 // expected-note {{previous definition}}
+void both3(void) __attribute((alias("__both3"))); // expected-error {{redefinition of 'both3'}}
+void __both3(void) {}
+
+void __a3(void) __attribute((noinline));
+#pragma weak a3 = __a3 // expected-note {{previous definition}}
+void a3(void) __attribute((alias("__a3"))); // expected-error {{redefinition of 'a3'}}
+void __a3(void) {}





More information about the cfe-commits mailing list