Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 10aad44

Browse files
committed
Fix the rest of PR9316 along with some other bugs spotted by inspection.
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
1 parent b43e8ad commit 10aad44

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

lib/AST/Decl.cpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
708708
// external linkage.
709709
if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
710710
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
711-
if (Function->isInAnonymousNamespace())
711+
if (Function->isInAnonymousNamespace() && !Function->isExternC())
712712
return LinkageInfo::uniqueExternal();
713713

714714
LinkageInfo LV;
@@ -729,7 +729,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
729729
if (const VarDecl *Var = dyn_cast<VarDecl>(D))
730730
if (Var->getStorageClass() == SC_Extern ||
731731
Var->getStorageClass() == SC_PrivateExtern) {
732-
if (Var->isInAnonymousNamespace())
732+
if (Var->isInAnonymousNamespace() && !Var->isExternC())
733733
return LinkageInfo::uniqueExternal();
734734

735735
LinkageInfo LV;
@@ -1041,17 +1041,18 @@ bool VarDecl::isExternC() const {
10411041
getStorageClass() != SC_Static) ||
10421042
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
10431043

1044-
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
1045-
DC = DC->getParent()) {
1044+
const DeclContext *DC = getDeclContext();
1045+
if (DC->isFunctionOrMethod())
1046+
return false;
1047+
1048+
for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
10461049
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
10471050
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
10481051
return getStorageClass() != SC_Static;
10491052

10501053
break;
10511054
}
10521055

1053-
if (DC->isFunctionOrMethod())
1054-
return false;
10551056
}
10561057

10571058
return false;
@@ -1367,18 +1368,18 @@ bool FunctionDecl::isExternC() const {
13671368
if (!Context.getLangOptions().CPlusPlus)
13681369
return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
13691370

1370-
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
1371-
DC = DC->getParent()) {
1371+
const DeclContext *DC = getDeclContext();
1372+
if (DC->isRecord())
1373+
return false;
1374+
1375+
for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
13721376
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
13731377
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
13741378
return getStorageClass() != SC_Static &&
13751379
!getAttr<OverloadableAttr>();
13761380

13771381
break;
13781382
}
1379-
1380-
if (DC->isRecord())
1381-
break;
13821383
}
13831384

13841385
return isMain();

test/SemaCXX/linkage.cpp

+24-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// compared against the earlier cached value. If we had a way of
44
// testing linkage directly in Sema, that would be better.
55

6-
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
6+
// RUN: %clang_cc1 -Werror -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
77

88
// PR8926
99
namespace test0 {
@@ -69,5 +69,28 @@ namespace {
6969
extern "C" void test4(void) {}
7070
}
7171

72+
// PR9316: Ensure that even non-namespace-scope function declarations in
73+
// a C declaration context respect that over the anonymous namespace.
74+
extern "C" {
75+
namespace {
76+
struct X {
77+
int f() {
78+
extern int g();
79+
extern int a;
80+
81+
// Test both for mangling in the code generation and warnings from use
82+
// of internal, undefined names via -Werror.
83+
// CHECK: call i32 @g(
84+
// CHECK: load i32* @a,
85+
return g() + a;
86+
}
87+
};
88+
}
89+
// Force the above function to be emitted by codegen.
90+
int test(X& x) {
91+
return x.f();
92+
}
93+
}
94+
7295
// CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
7396
// CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(

0 commit comments

Comments
 (0)