[cfe-commits] r111012 - in /cfe/trunk: lib/AST/Decl.cpp test/CodeGenCXX/anonymous-namespaces.cpp

John McCall rjmccall at apple.com
Fri Aug 13 01:35:11 PDT 2010


Author: rjmccall
Date: Fri Aug 13 03:35:10 2010
New Revision: 111012

URL: http://llvm.org/viewvc/llvm-project?rev=111012&view=rev
Log:
Properly give unique-external linkage to members of member templates
instantiated with unique-external parameters.


Modified:
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=111012&r1=111011&r2=111012&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Aug 13 03:35:10 2010
@@ -97,6 +97,12 @@
   return L;
 }
 
+static Linkage
+getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) {
+  return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(), 
+                                           TArgs.flat_size());
+}
+
 static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
   assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
          "Not a name having namespace scope");
@@ -219,10 +225,7 @@
                                = Function->getTemplateSpecializationInfo()) {
       Linkage L = SpecInfo->getTemplate()->getLinkage();
       const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
-      L = minLinkage(L, 
-                     getLinkageForTemplateArgumentList(
-                                          TemplateArgs.getFlatArgumentList(), 
-                                          TemplateArgs.flat_size()));
+      L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs));
       return L;
     }
 
@@ -245,9 +248,7 @@
       if (const ClassTemplateSpecializationDecl *Spec
             = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
         const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
-        Linkage L = getLinkageForTemplateArgumentList(
-                                          TemplateArgs.getFlatArgumentList(),
-                                                 TemplateArgs.flat_size());
+        Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
         return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
       }
 
@@ -279,6 +280,47 @@
   return NoLinkage;
 }
 
+static Linkage getLinkageForClassMember(const NamedDecl *D) {
+  if (!(isa<CXXMethodDecl>(D) ||
+        isa<VarDecl>(D) ||
+        (isa<TagDecl>(D) &&
+         (D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
+    return NoLinkage;
+
+  // Class members only have linkage if their class has external linkage.
+  Linkage L = cast<RecordDecl>(D->getDeclContext())->getLinkage();
+  if (!isExternalLinkage(L)) return NoLinkage;
+
+  // If the class already has unique-external linkage, we can't improve.
+  if (L == UniqueExternalLinkage) return UniqueExternalLinkage;
+
+  // If this is a method template specialization, use the linkage for
+  // the template parameters and arguments.
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+    if (FunctionTemplateSpecializationInfo *SpecInfo
+           = MD->getTemplateSpecializationInfo()) {
+      Linkage ArgLinkage =
+        getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments);
+      Linkage ParamLinkage =
+        getLinkageForTemplateParameterList(
+                           SpecInfo->getTemplate()->getTemplateParameters());
+      return minLinkage(ArgLinkage, ParamLinkage);
+    }
+
+  // Similarly for member class template specializations.
+  } else if (const ClassTemplateSpecializationDecl *Spec
+               = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    Linkage ArgLinkage =
+      getLinkageForTemplateArgumentList(Spec->getTemplateArgs());
+    Linkage ParamLinkage =
+      getLinkageForTemplateParameterList(
+                    Spec->getSpecializedTemplate()->getTemplateParameters());
+    return minLinkage(ArgLinkage, ParamLinkage);
+  }
+
+  return ExternalLinkage;
+}
+
 Linkage NamedDecl::getLinkage() const {
 
   // Objective-C: treat all Objective-C declarations as having external
@@ -314,14 +356,8 @@
   //   that the class or enumeration has the typedef name for linkage
   //   purposes (7.1.3), has external linkage if the name of the class
   //   has external linkage.
-  if (getDeclContext()->isRecord() &&
-      (isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
-       (isa<TagDecl>(this) &&
-        (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
-    Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
-    if (isExternalLinkage(L))
-      return L;
-  }
+  if (getDeclContext()->isRecord())
+    return getLinkageForClassMember(this);
 
   // C++ [basic.link]p6:
   //   The name of a function declared in block scope and the name of

Modified: cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp?rev=111012&r1=111011&r2=111012&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/anonymous-namespaces.cpp Fri Aug 13 03:35:10 2010
@@ -1,12 +1,14 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t
+// RUN: FileCheck %s -check-prefix=1 < %t
+// RUN: FileCheck %s -check-prefix=2 < %t
 
 int f();
 
 namespace {
-  // CHECK: @_ZN12_GLOBAL__N_11bE = internal global i32 0
-  // CHECK: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
-  // CHECK: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
-  // CHECK: @_ZN12_GLOBAL__N_11aE = internal global i32 0
+  // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0
+  // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
+  // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
+  // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0
   int a = 0;
 
   int b = f();
@@ -20,18 +22,18 @@
   int D::d = f();
 
   // Check for generation of a VTT with internal linkage
-  // CHECK: @_ZTSN12_GLOBAL__N_11X1EE = internal constant
+  // CHECK-1: @_ZTSN12_GLOBAL__N_11X1EE = internal constant
   struct X { 
     struct EBase { };
     struct E : public virtual EBase { virtual ~E() {} };
   };
 
-  // CHECK: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
+  // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
   int foo() {
     return 32;
   }
 
-  // CHECK: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
+  // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
   namespace A {
     int foo() {
       return 45;
@@ -44,3 +46,23 @@
 }
 
 void test_XE() { throw X::E(); }
+
+// Miscompile on llvmc plugins.
+namespace test2 {
+  struct A {
+    template <class T> struct B {
+      static void foo() {}
+    };
+  };
+  namespace {
+    struct C;
+  }
+
+  // CHECK-2: define void @_ZN5test24testEv()
+  // CHECK-2:   call void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
+  void test() {
+    A::B<C>::foo();
+  }
+
+  // CHECK-2: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
+}





More information about the cfe-commits mailing list