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

Commit dd94e04

Browse files
committedSep 22, 2017
DR1113: anonymous namespaces formally give their contents internal linkage.
This doesn't affect our code generation in any material way -- we already give such declarations internal linkage from a codegen perspective -- but it has some subtle effects on code validity. We suppress the 'L' (internal linkage) marker for mangled names in anonymous namespaces, because it is redundant (the information is already carried by the namespace); this deviates from GCC's behavior if a variable or function in an anonymous namespace is redundantly declared 'static' (where GCC does include the 'L'), but GCC's behavior is incoherent because such a declaration can be validly declared with or without the 'static'. We still deviate from the standard in one regard here: extern "C" declarations in anonymous namespaces are still granted external linkage. Changing those does not appear to have been an intentional consequence of the standard change in DR1113. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314037 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 945869e commit dd94e04

File tree

7 files changed

+69
-10
lines changed

7 files changed

+69
-10
lines changed
 

‎lib/AST/Decl.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -619,16 +619,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
619619
if (D->isInAnonymousNamespace()) {
620620
const auto *Var = dyn_cast<VarDecl>(D);
621621
const auto *Func = dyn_cast<FunctionDecl>(D);
622-
// FIXME: In C++11 onwards, anonymous namespaces should give decls
623-
// within them (including those inside extern "C" contexts) internal
624-
// linkage, not unique external linkage:
622+
// FIXME: The check for extern "C" here is not justified by the standard
623+
// wording, but we retain it from the pre-DR1113 model to avoid breaking
624+
// code.
625625
//
626626
// C++11 [basic.link]p4:
627627
// An unnamed namespace or a namespace declared directly or indirectly
628628
// within an unnamed namespace has internal linkage.
629629
if ((!Var || !isFirstInExternCContext(Var)) &&
630630
(!Func || !isFirstInExternCContext(Func)))
631-
return LinkageInfo::uniqueExternal();
631+
return getInternalLinkageFor(D);
632632
}
633633

634634
// Set up the defaults.
@@ -1130,7 +1130,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
11301130
if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
11311131
if (Function->isInAnonymousNamespace() &&
11321132
!Function->isInExternCContext())
1133-
return LinkageInfo::uniqueExternal();
1133+
return getInternalLinkageFor(Function);
11341134

11351135
// This is a "void f();" which got merged with a file static.
11361136
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
@@ -1153,7 +1153,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
11531153
if (const auto *Var = dyn_cast<VarDecl>(D)) {
11541154
if (Var->hasExternalStorage()) {
11551155
if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
1156-
return LinkageInfo::uniqueExternal();
1156+
return getInternalLinkageFor(Var);
11571157

11581158
LinkageInfo LV;
11591159
if (Var->getStorageClass() == SC_PrivateExtern)

‎lib/AST/ItaniumMangle.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -1287,9 +1287,15 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
12871287
//
12881288
// void test() { extern void foo(); }
12891289
// static void foo();
1290+
//
1291+
// Don't bother with the L marker for names in anonymous namespaces; the
1292+
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
1293+
// matches GCC anyway, because GCC does not treat anonymous namespaces as
1294+
// implying internal linkage.
12901295
if (ND && ND->getFormalLinkage() == InternalLinkage &&
12911296
!ND->isExternallyVisible() &&
1292-
getEffectiveDeclContext(ND)->isFileContext())
1297+
getEffectiveDeclContext(ND)->isFileContext() &&
1298+
!ND->isInAnonymousNamespace())
12931299
Out << 'L';
12941300

12951301
auto *FD = dyn_cast<FunctionDecl>(ND);

‎test/CXX/basic/basic.link/p8.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ void use_visible_no_linkage() {
5252
visible_no_linkage3(); // expected-note {{used here}}
5353
}
5454

55+
namespace {
56+
struct InternalLinkage {};
57+
}
58+
InternalLinkage internal_linkage(); // expected-error {{used but not defined}}
59+
void use_internal_linkage() {
60+
internal_linkage(); // expected-note {{used here}}
61+
}
5562

5663
extern inline int not_defined; // expected-error {{not defined}}
5764
extern inline int defined_after_use;

‎test/CXX/drs/dr11xx.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
2+
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
3+
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
4+
// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
5+
// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
6+
7+
namespace dr1113 { // dr1113: partial
8+
namespace named {
9+
extern int a; // expected-note {{previous}}
10+
static int a; // expected-error {{static declaration of 'a' follows non-static}}
11+
}
12+
namespace {
13+
extern int a;
14+
static int a; // ok, both declarations have internal linkage
15+
int b = a;
16+
}
17+
18+
// FIXME: Per DR1113 and DR4, this is ill-formed due to ambiguity: the second
19+
// 'f' has internal linkage, and so does not have C language linkage, so is
20+
// not a redeclaration of the first 'f'.
21+
//
22+
// To avoid a breaking change here, Clang ignores the "internal linkage" effect
23+
// of anonymous namespaces on declarations declared within an 'extern "C"'
24+
// linkage-specification.
25+
extern "C" void f();
26+
namespace {
27+
extern "C" void f();
28+
}
29+
void g() { f(); }
30+
}

‎test/CodeGenCXX/anonymous-namespaces.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ int f();
66

77
namespace {
88
// CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0
9-
// CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
9+
// CHECK-1: @_ZN12_GLOBAL__N_11cE = internal global i32 0
10+
// CHECK-1: @_ZN12_GLOBAL__N_12c2E = internal global i32 0
1011
// CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
1112
// CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0
1213
int a = 0;
@@ -15,6 +16,12 @@ namespace {
1516

1617
static int c = f();
1718

19+
// Note, we can't use an 'L' mangling for c or c2 (like GCC does) based on
20+
// the 'static' specifier, because the variable can be redeclared without it.
21+
extern int c2;
22+
int g() { return c2; }
23+
static int c2 = f();
24+
1825
class D {
1926
static int d;
2027
};

‎test/SemaCXX/linkage2.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,10 @@ namespace test13 {
143143
}
144144

145145
namespace test14 {
146+
// Anonymous namespace implies internal linkage, so 'static' has no effect.
146147
namespace {
147-
void a(void); // expected-note {{previous declaration is here}}
148-
static void a(void) {} // expected-error {{static declaration of 'a' follows non-static declaration}}
148+
void a(void);
149+
static void a(void) {}
149150
}
150151
}
151152

‎test/SemaCXX/undefined-internal.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,21 @@ namespace OverloadUse {
187187
void f();
188188
void f(int); // expected-warning {{function 'OverloadUse::(anonymous namespace)::f' has internal linkage but is not defined}}
189189
void f(int, int); // expected-warning {{function 'OverloadUse::(anonymous namespace)::f' has internal linkage but is not defined}}
190+
#if __cplusplus < 201103L
191+
// expected-note@-3 {{here}}
192+
// expected-note@-3 {{here}}
193+
#endif
190194
}
191195
template<void x()> void t() { x(); }
192196
template<void x(int)> void t(int*) { x(10); }
193197
template<void x(int, int)> void t(int*, int*) {}
194198
void g(int n) {
195199
t<f>(&n); // expected-note {{used here}}
196200
t<f>(&n, &n); // expected-note {{used here}}
201+
#if __cplusplus < 201103L
202+
// expected-warning@-3 {{non-type template argument referring to function 'f' with internal linkage}}
203+
// expected-warning@-3 {{non-type template argument referring to function 'f' with internal linkage}}
204+
#endif
197205
}
198206
}
199207

0 commit comments

Comments
 (0)
This repository has been archived.