]> granicus.if.org Git - clang/commitdiff
Move the check that gives functions with unique-external types unique-external
authorJohn McCall <rjmccall@apple.com>
Thu, 10 Feb 2011 06:50:24 +0000 (06:50 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 10 Feb 2011 06:50:24 +0000 (06:50 +0000)
linkage into Decl.cpp.  Disable this logic for extern "C" functions, because
the operative rule there is weaker.  Fixes rdar://problem/8898466

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125268 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/AST/Decl.cpp
test/SemaCXX/linkage.cpp
test/SemaCXX/warn-unused-filescoped.cpp

index d6c89c947ce927a74918def125cf5ddfe994f72d..6b2674325866e70a0df6afa43d7fff2c552c491d 100644 (file)
@@ -5859,10 +5859,6 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
   GVALinkage External = GVA_StrongExternal;
 
   Linkage L = FD->getLinkage();
-  if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
-      FD->getType()->getLinkage() == UniqueExternalLinkage)
-    L = UniqueExternalLinkage;
-  
   switch (L) {
   case NoLinkage:
   case InternalLinkage:
index 11614df500350c1c6d569639881e1f656c7e2071..9aeb04fa448852f832ffb04188c4ecfbc02170f1 100644 (file)
@@ -392,6 +392,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
       }
     }
 
+    // In C++, then if the type of the function uses a type with
+    // unique-external linkage, it's not legally usable from outside
+    // this translation unit.  However, we should use the C linkage
+    // rules instead for extern "C" declarations.
+    if (Context.getLangOptions().CPlusPlus && !Function->isExternC() &&
+        Function->getType()->getLinkage() == UniqueExternalLinkage)
+      return LinkageInfo::uniqueExternal();
+
     if (FunctionTemplateSpecializationInfo *SpecInfo
                                = Function->getTemplateSpecializationInfo()) {
       LV.merge(getLVForDecl(SpecInfo->getTemplate(),
@@ -512,6 +520,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
     return LinkageInfo::uniqueExternal();
 
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+    // If the type of the function uses a type with unique-external
+    // linkage, it's not legally usable from outside this translation unit.
+    if (MD->getType()->getLinkage() == UniqueExternalLinkage)
+      return LinkageInfo::uniqueExternal();
+
     TemplateSpecializationKind TSK = TSK_Undeclared;
 
     // If this is a method template specialization, use the linkage for
index fb21f94e92e6efe3f54788ecf1671d0f7eb012cb..ba56318fbd68caaa691aceeebd5eacd321330e2f 100644 (file)
@@ -53,5 +53,16 @@ namespace test2 {
   }
 }
 
+namespace test3 {
+  namespace { struct A {}; }
+
+  // CHECK: define internal void @_ZN5test34testENS_12_GLOBAL__N_11AE(
+  void test(A a) {}
+  void force() { test(A()); }
+
+  // CHECK: define void @test3(
+  extern "C" void test3(A a) {}
+}
+
 // CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
 // CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(
index 628075ac04dded2de87da352b40f0a31f86ee8f7..c32acb0b48be90e57db39661f074b2efb95fe213 100644 (file)
@@ -66,7 +66,15 @@ namespace PR8841 {
   template <typename T> void template_test(X<T> x) {
     (void)(x == x);
   }
-  void test(X<int> x) {
+  void test() {
+    X<int> x;
     template_test(x);
   }
 }
+
+namespace test4 {
+  namespace { struct A {}; }
+
+  void test(A a); // expected-warning {{unused function}}
+  extern "C" void test4(A a);
+}