]> granicus.if.org Git - clang/commitdiff
Fix the rest of PR9316 along with some other bugs spotted by inspection.
authorChandler Carruth <chandlerc@gmail.com>
Fri, 25 Feb 2011 00:05:02 +0000 (00:05 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Fri, 25 Feb 2011 00:05:02 +0000 (00:05 +0000)
I tried to add test cases for these, but I can't because variables
aren't warned on the way functions are and the codegen layer appears to
use different logic for determining that 'a' and 'g' in the test case
should receive C mangling. I've included the test so that if we ever
switch the codegen layer to use these functions, we won't regress due to
latent bugs.

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

lib/AST/Decl.cpp
test/SemaCXX/linkage.cpp

index b482a0329942b0d05f7d682e7f168b3710150601..c0300c50cd9d7cd5c48888f01db3ba59a0b69ebe 100644 (file)
@@ -708,7 +708,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
   //   external linkage.
   if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
     if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
-      if (Function->isInAnonymousNamespace())
+      if (Function->isInAnonymousNamespace() && !Function->isExternC())
         return LinkageInfo::uniqueExternal();
 
       LinkageInfo LV;
@@ -729,7 +729,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
     if (const VarDecl *Var = dyn_cast<VarDecl>(D))
       if (Var->getStorageClass() == SC_Extern ||
           Var->getStorageClass() == SC_PrivateExtern) {
-        if (Var->isInAnonymousNamespace())
+        if (Var->isInAnonymousNamespace() && !Var->isExternC())
           return LinkageInfo::uniqueExternal();
 
         LinkageInfo LV;
@@ -1041,8 +1041,11 @@ bool VarDecl::isExternC() const {
             getStorageClass() != SC_Static) ||
       (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
 
-  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
-       DC = DC->getParent()) {
+  const DeclContext *DC = getDeclContext();
+  if (DC->isFunctionOrMethod())
+    return false;
+
+  for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
     if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
       if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
         return getStorageClass() != SC_Static;
@@ -1050,8 +1053,6 @@ bool VarDecl::isExternC() const {
       break;
     }
 
-    if (DC->isFunctionOrMethod())
-      return false;
   }
 
   return false;
@@ -1367,8 +1368,11 @@ bool FunctionDecl::isExternC() const {
   if (!Context.getLangOptions().CPlusPlus)
     return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
 
-  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
-       DC = DC->getParent()) {
+  const DeclContext *DC = getDeclContext();
+  if (DC->isRecord())
+    return false;
+
+  for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
     if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
       if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
         return getStorageClass() != SC_Static &&
@@ -1376,9 +1380,6 @@ bool FunctionDecl::isExternC() const {
 
       break;
     }
-    
-    if (DC->isRecord())
-      break;
   }
 
   return isMain();
index b93a310b00f743ca5ebcc21705dc0497d9c98ed1..6b73d596e01ba226b4fee941d8f22e66bc1d8140 100644 (file)
@@ -3,7 +3,7 @@
 // compared against the earlier cached value.  If we had a way of
 // testing linkage directly in Sema, that would be better.
 
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -Werror -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
 
 // PR8926
 namespace test0 {
@@ -69,5 +69,28 @@ namespace {
   extern "C" void test4(void) {}
 }
 
+// PR9316: Ensure that even non-namespace-scope function declarations in
+// a C declaration context respect that over the anonymous namespace.
+extern "C" {
+  namespace {
+    struct X {
+      int f() {
+        extern int g();
+        extern int a;
+
+        // Test both for mangling in the code generation and warnings from use
+        // of internal, undefined names via -Werror.
+        // CHECK: call i32 @g(
+        // CHECK: load i32* @a,
+        return g() + a;
+      }
+    };
+  }
+  // Force the above function to be emitted by codegen.
+  int test(X& x) {
+    return x.f();
+  }
+}
+
 // CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
 // CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(