aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h18
-rw-r--r--include/clang/AST/Type.h31
-rw-r--r--include/clang/Basic/Linkage.h57
-rw-r--r--include/clang/Basic/Specifiers.h3
-rw-r--r--lib/AST/Decl.cpp164
-rw-r--r--lib/AST/Type.cpp76
-rw-r--r--lib/CodeGen/CodeGenModule.cpp90
-rw-r--r--lib/CodeGen/Mangle.cpp5
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--test/CodeGenCXX/internal-linkage.cpp19
-rw-r--r--test/SemaTemplate/instantiate-decl-init.cpp14
11 files changed, 402 insertions, 79 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index dd83443c65..8166316fcc 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -19,6 +19,7 @@
#include "clang/AST/Redeclarable.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/Linkage.h"
namespace clang {
class CXXTemporary;
@@ -195,23 +196,6 @@ public:
return DC->isRecord();
}
- /// \brief Describes the different kinds of linkage
- /// (C++ [basic.link], C99 6.2.2) that an entity may have.
- enum Linkage {
- /// \brief No linkage, which means that the entity is unique and
- /// can only be referred to from within its scope.
- NoLinkage = 0,
-
- /// \brief Internal linkage, which indicates that the entity can
- /// be referred to from within the translation unit (but not other
- /// translation units).
- InternalLinkage,
-
- /// \brief External linkage, which indicates that the entity can
- /// be referred to from other translation units.
- ExternalLinkage
- };
-
/// \brief Determine what kind of linkage this entity has.
Linkage getLinkage() const;
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index b7b60df5ac..f53fd92106 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -16,6 +16,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Linkage.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
@@ -974,6 +975,9 @@ public:
const char *getTypeClassName() const;
+ /// \brief Determine the linkage of this type.
+ virtual Linkage getLinkage() const;
+
QualType getCanonicalTypeInternal() const { return CanonicalType; }
void dump() const;
static bool classof(const Type *) { return true; }
@@ -1062,6 +1066,8 @@ public:
return TypeKind >= Float && TypeKind <= LongDouble;
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
static bool classof(const BuiltinType *) { return true; }
};
@@ -1089,6 +1095,8 @@ public:
ID.AddPointer(Element.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
static bool classof(const ComplexType *) { return true; }
};
@@ -1116,6 +1124,8 @@ public:
ID.AddPointer(Pointee.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
static bool classof(const PointerType *) { return true; }
};
@@ -1146,6 +1156,8 @@ public:
ID.AddPointer(Pointee.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == BlockPointer;
}
@@ -1203,6 +1215,8 @@ public:
ID.AddBoolean(SpelledAsLValue);
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == LValueReference ||
T->getTypeClass() == RValueReference;
@@ -1277,6 +1291,8 @@ public:
ID.AddPointer(Class);
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == MemberPointer;
}
@@ -1328,6 +1344,8 @@ public:
}
unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray ||
T->getTypeClass() == VariableArray ||
@@ -1611,6 +1629,9 @@ public:
ID.AddInteger(NumElements);
ID.AddInteger(TypeClass);
}
+
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
}
@@ -1753,6 +1774,8 @@ public:
ID.AddPointer(ResultType.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto;
}
@@ -1856,6 +1879,8 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionProto;
}
@@ -2058,6 +2083,8 @@ public:
bool isBeingDefined() const { return decl.getInt(); }
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
}
@@ -2548,6 +2575,8 @@ public:
const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == ObjCInterface;
}
@@ -2628,6 +2657,8 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+ virtual Linkage getLinkage() const;
+
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
ObjCProtocolDecl **protocols, unsigned NumProtocols);
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
new file mode 100644
index 0000000000..de0de348d3
--- /dev/null
+++ b/include/clang/Basic/Linkage.h
@@ -0,0 +1,57 @@
+//===--- Linkage.h - Linkage enumeration and utilities ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Linkage enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_LINKAGE_H
+#define LLVM_CLANG_BASIC_LINKAGE_H
+
+namespace clang {
+
+/// \brief Describes the different kinds of linkage
+/// (C++ [basic.link], C99 6.2.2) that an entity may have.
+enum Linkage {
+ /// \brief No linkage, which means that the entity is unique and
+ /// can only be referred to from within its scope.
+ NoLinkage = 0,
+
+ /// \brief Internal linkage, which indicates that the entity can
+ /// be referred to from within the translation unit (but not other
+ /// translation units).
+ InternalLinkage,
+
+ /// \brief External linkage within a unique namespace. From the
+ /// langauge perspective, these entities have external
+ /// linkage. However, since they reside in an anonymous namespace,
+ /// their names are unique to this translation unit, which is
+ /// equivalent to having internal linkage from the code-generation
+ /// point of view.
+ UniqueExternalLinkage,
+
+ /// \brief External linkage, which indicates that the entity can
+ /// be referred to from other translation units.
+ ExternalLinkage
+};
+
+/// \brief Determine whether the given linkage is semantically
+/// external.
+inline bool isExternalLinkage(Linkage L) {
+ return L == UniqueExternalLinkage || L == ExternalLinkage;
+}
+
+/// \brief Compute the minimum linkage given two linages.
+static inline Linkage minLinkage(Linkage L1, Linkage L2) {
+ return L1 < L2? L1 : L2;
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_LINKAGE_H
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 4cace86dd1..9e54762add 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -77,6 +77,7 @@ namespace clang {
AS_private,
AS_none
};
-}
+
+} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a2cf73849d..c3e976a080 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -47,7 +47,72 @@ TypeLoc TypeSourceInfo::getTypeLoc() const {
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
-static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
+/// \brief Get the most restrictive linkage for the types in the given
+/// template parameter list.
+static Linkage
+getLinkageForTemplateParameterList(const TemplateParameterList *Params) {
+ Linkage L = ExternalLinkage;
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
+ if (!NTTP->getType()->isDependentType()) {
+ L = minLinkage(L, NTTP->getType()->getLinkage());
+ continue;
+ }
+
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(*P)) {
+ L = minLinkage(L,
+ getLinkageForTemplateParameterList(TTP->getTemplateParameters()));
+ }
+ }
+
+ return L;
+}
+
+/// \brief Get the most restrictive linkage for the types and
+/// declarations in the given template argument list.
+static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ Linkage L = ExternalLinkage;
+
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ switch (Args[I].getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Expression:
+ break;
+
+ case TemplateArgument::Type:
+ L = minLinkage(L, Args[I].getAsType()->getLinkage());
+ break;
+
+ case TemplateArgument::Declaration:
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
+ L = minLinkage(L, ND->getLinkage());
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(Args[I].getAsDecl()))
+ L = minLinkage(L, VD->getType()->getLinkage());
+ break;
+
+ case TemplateArgument::Template:
+ if (TemplateDecl *Template
+ = Args[I].getAsTemplate().getAsTemplateDecl())
+ L = minLinkage(L, Template->getLinkage());
+ break;
+
+ case TemplateArgument::Pack:
+ L = minLinkage(L,
+ getLinkageForTemplateArgumentList(Args[I].pack_begin(),
+ Args[I].pack_size()));
+ break;
+ }
+ }
+
+ return L;
+}
+
+static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -61,7 +126,7 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == VarDecl::Static)
- return NamedDecl::InternalLinkage;
+ return InternalLinkage;
// - an object or reference that is explicitly declared const
// and neither explicitly declared extern nor previously
@@ -75,13 +140,16 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
PrevVar && !FoundExtern;
PrevVar = PrevVar->getPreviousDeclaration())
- if (PrevVar->getLinkage() == NamedDecl::ExternalLinkage)
+ if (isExternalLinkage(PrevVar->getLinkage()))
FoundExtern = true;
if (!FoundExtern)
- return NamedDecl::InternalLinkage;
+ return InternalLinkage;
}
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
+ // C++ [temp]p4:
+ // A non-member function template can have internal linkage; any
+ // other template name shall have external linkage.
const FunctionDecl *Function = 0;
if (const FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(D))
@@ -91,11 +159,11 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// Explicitly declared static.
if (Function->getStorageClass() == FunctionDecl::Static)
- return NamedDecl::InternalLinkage;
+ return InternalLinkage;
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
- return NamedDecl::InternalLinkage;
+ return InternalLinkage;
}
// C++ [basic.link]p4:
@@ -118,7 +186,7 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
- if (NamedDecl::Linkage L = PrevVar->getLinkage())
+ if (Linkage L = PrevVar->getLinkage())
return L;
}
}
@@ -127,7 +195,10 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
- return NamedDecl::ExternalLinkage;
+ if (Var->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
+ return ExternalLinkage;
}
// - a function, unless it has internal linkage; or
@@ -151,12 +222,26 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
- if (NamedDecl::Linkage L = PrevFunc->getLinkage())
+ if (Linkage L = PrevFunc->getLinkage())
return L;
}
}
- return NamedDecl::ExternalLinkage;
+ if (Function->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = Function->getTemplateSpecializationInfo()) {
+ Linkage L = SpecInfo->getTemplate()->getLinkage();
+ const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
+ L = minLinkage(L,
+ getLinkageForTemplateArgumentList(
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size()));
+ return L;
+ }
+
+ return ExternalLinkage;
}
// - a named class (Clause 9), or an unnamed class defined in a
@@ -166,29 +251,50 @@ static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
if (const TagDecl *Tag = dyn_cast<TagDecl>(D))
- if (Tag->getDeclName() || Tag->getTypedefForAnonDecl())
- return NamedDecl::ExternalLinkage;
+ if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) {
+ if (Tag->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
+ // If this is a class template specialization, consider the
+ // linkage of the template and template arguments.
+ if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ Linkage L = getLinkageForTemplateArgumentList(
+ TemplateArgs.getFlatArgumentList(),
+ TemplateArgs.flat_size());
+ return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
+ }
+
+ return ExternalLinkage;
+ }
// - an enumerator belonging to an enumeration with external linkage;
- if (isa<EnumConstantDecl>(D))
- if (cast<NamedDecl>(D->getDeclContext())->getLinkage()
- == NamedDecl::ExternalLinkage)
- return NamedDecl::ExternalLinkage;
+ if (isa<EnumConstantDecl>(D)) {
+ Linkage L = cast<NamedDecl>(D->getDeclContext())->getLinkage();
+ if (isExternalLinkage(L))
+ return L;
+ }
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
- if (isa<TemplateDecl>(D))
- return NamedDecl::ExternalLinkage;
+ if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+ if (D->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
+ return getLinkageForTemplateParameterList(
+ Template->getTemplateParameters());
+ }
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
- return NamedDecl::ExternalLinkage;
+ return ExternalLinkage;
- return NamedDecl::NoLinkage;
+ return NoLinkage;
}
-NamedDecl::Linkage NamedDecl::getLinkage() const {
+Linkage NamedDecl::getLinkage() const {
// Handle linkage for namespace-scope names.
if (getDeclContext()->getLookupContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
@@ -204,9 +310,11 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
if (getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
(isa<TagDecl>(this) &&
- (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl()))) &&
- cast<RecordDecl>(getDeclContext())->getLinkage() == ExternalLinkage)
- return ExternalLinkage;
+ (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
+ Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
+ if (isExternalLinkage(L))
+ return L;
+ }
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@@ -225,6 +333,9 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
return L;
+ if (Function->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
return ExternalLinkage;
}
@@ -235,6 +346,9 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
+ if (Var->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
return ExternalLinkage;
}
}
@@ -242,7 +356,7 @@ NamedDecl::Linkage NamedDecl::getLinkage() const {
// C++ [basic.link]p6:
// Names not covered by these rules have no linkage.
return NoLinkage;
-}
+ }
std::string NamedDecl::getQualifiedNameAsString() const {
return getQualifiedNameAsString(getASTContext().getLangOptions());
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 504ffc5e4e..b3010d5e7b 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1049,3 +1049,79 @@ void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
else
Profile(ID, getDecl(), 0, 0);
}
+
+Linkage Type::getLinkage() const {
+ // C++ [basic.link]p8:
+ // Names not covered by these rules have no linkage.
+ if (this != CanonicalType.getTypePtr())
+ return CanonicalType->getLinkage();
+
+ return NoLinkage;
+}
+
+Linkage BuiltinType::getLinkage() const {
+ // C++ [basic.link]p8:
+ // A type is said to have linkage if and only if:
+ // - it is a fundamental type (3.9.1); or
+ return ExternalLinkage;
+}
+
+Linkage TagType::getLinkage() const {
+ // C++ [basic.link]p8:
+ // - it is a class or enumeration type that is named (or has a name for
+ // linkage purposes (7.1.3)) and the name has linkage; or
+ // - it is a specialization of a class template (14); or
+ return getDecl()->getLinkage();
+}
+
+// C++ [basic.link]p8:
+// - it is a compound type (3.9.2) other than a class or enumeration,
+// compounded exclusively from types that have linkage; or
+Linkage ComplexType::getLinkage() const {
+ return ElementType->getLinkage();
+}
+
+Linkage PointerType::getLinkage() const {
+ return PointeeType->getLinkage();
+}
+
+Linkage BlockPointerType::getLinkage() const {
+ return PointeeType->getLinkage();
+}
+
+Linkage ReferenceType::getLinkage() const {
+ return PointeeType->getLinkage();
+}
+
+Linkage MemberPointerType::getLinkage() const {
+ return minLinkage(Class->getLinkage(), PointeeType->getLinkage());
+}
+
+Linkage ArrayType::getLinkage() const {
+ return ElementType->getLinkage();
+}
+
+Linkage VectorType::getLinkage() const {
+ return ElementType->getLinkage();
+}
+
+Linkage FunctionNoProtoType::getLinkage() const {
+ return getResultType()->getLinkage();
+}
+
+Linkage FunctionProtoType::getLinkage() const {
+ Linkage L = getResultType()->getLinkage();
+ for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
+ A != AEnd; ++A)
+ L = minLinkage(L, (*A)->getLinkage());
+
+ return L;
+}
+
+Linkage ObjCInterfaceType::getLinkage() const {
+ return ExternalLinkage;
+}
+
+Linkage ObjCObjectPointerType::getLinkage() const {
+ return ExternalLinkage;
+}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 28a808bd83..c3f5443c47 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -255,34 +255,40 @@ void CodeGenModule::EmitAnnotations() {
static CodeGenModule::GVALinkage
GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
const LangOptions &Features) {
- // Everything located semantically within an anonymous namespace is
- // always internal.
- if (FD->isInAnonymousNamespace())
- return CodeGenModule::GVA_Internal;
+ CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
- // "static" functions get internal linkage.
- if (FD->getStorageClass() == FunctionDecl::Static && !isa<CXXMethodDecl>(FD))
- return CodeGenModule::GVA_Internal;
+ Linkage L = FD->getLinkage();
+ if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+ FD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
- // The kind of external linkage this function will have, if it is not
- // inline or static.
- CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
- if (Context.getLangOptions().CPlusPlus) {
- TemplateSpecializationKind TSK = FD->getTemplateSpecializationKind();
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return CodeGenModule::GVA_Internal;
- if (TSK == TSK_ExplicitInstantiationDefinition) {
- // If a function has been explicitly instantiated, then it should
- // always have strong external linkage.
+ case ExternalLinkage:
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = CodeGenModule::GVA_StrongExternal;
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ // FIXME: explicit instantiation definitions should use weak linkage
return CodeGenModule::GVA_StrongExternal;
- }
-
- if (TSK == TSK_ImplicitInstantiation)
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
External = CodeGenModule::GVA_TemplateInstantiation;
+ break;
+ }
}
if (!FD->isInlined())
return External;
-
+
if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.
@@ -581,13 +587,24 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Static data may be deferred, but out-of-line static data members
// cannot be.
- if (VD->getLinkage() == VarDecl::InternalLinkage ||
- VD->isInAnonymousNamespace()) {
+ Linkage L = VD->getLinkage();
+ if (L == ExternalLinkage && getContext().getLangOptions().CPlusPlus &&
+ VD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
// Initializer has side effects?
if (VD->getInit() && VD->getInit()->HasSideEffects(Context))
return false;
return !(VD->isStaticDataMember() && VD->isOutOfLine());
+
+ case ExternalLinkage:
+ break;
}
+
return false;
}
@@ -941,16 +958,30 @@ CodeGenModule::getVtableLinkage(const CXXRecordDecl *RD) {
static CodeGenModule::GVALinkage
GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
- // Everything located semantically within an anonymous namespace is
- // always internal.
- if (VD->isInAnonymousNamespace())
+ // If this is a static data member, compute the kind of template
+ // specialization. Otherwise, this variable is not part of a
+ // template.
+ TemplateSpecializationKind TSK = TSK_Undeclared;
+ if (VD->isStaticDataMember())
+ TSK = VD->getTemplateSpecializationKind();
+
+ Linkage L = VD->getLinkage();
+ if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+ VD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
return CodeGenModule::GVA_Internal;
- // Handle linkage for static data members.
- if (VD->isStaticDataMember()) {
- switch (VD->getTemplateSpecializationKind()) {
+ case ExternalLinkage:
+ switch (TSK) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
+
+ // FIXME: ExplicitInstantiationDefinition should be weak!
case TSK_ExplicitInstantiationDefinition:
return CodeGenModule::GVA_StrongExternal;
@@ -959,13 +990,10 @@ GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
// Fall through to treat this like any other instantiation.
case TSK_ImplicitInstantiation:
- return CodeGenModule::GVA_TemplateInstantiation;
+ return CodeGenModule::GVA_TemplateInstantiation;
}
}
- if (VD->getLinkage() == VarDecl::InternalLinkage)
- return CodeGenModule::GVA_Internal;
-
return CodeGenModule::GVA_StrongExternal;
}
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 4f84edd908..6326625bae 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -178,8 +178,7 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
if (isa<FunctionDecl>(DC) && D->hasLinkage())
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = DC->getParent();
- if (DC->isTranslationUnit() &&
- D->getLinkage() != NamedDecl::InternalLinkage)
+ if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
return false;
}
@@ -420,7 +419,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
// We must avoid conflicts between internally- and externally-
// linked names in the same TU. This naming convention is the
// same as that followed by GCC, though it shouldn't actually matter.
- if (ND->getLinkage() == NamedDecl::InternalLinkage &&
+ if (ND->getLinkage() == InternalLinkage &&
ND->getDeclContext()->isFileContext())
Out << 'L';
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 44b0d83b46..13cf783391 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2336,7 +2336,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
// Functions must have external linkage.
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
- if (Func->getLinkage() != NamedDecl::ExternalLinkage) {
+ if (!isExternalLinkage(Func->getLinkage())) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_function_not_extern)
<< Func << Arg->getSourceRange();
@@ -2351,7 +2351,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
}
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (Var->getLinkage() != NamedDecl::ExternalLinkage) {
+ if (!isExternalLinkage(Var->getLinkage())) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_object_not_extern)
<< Var << Arg->getSourceRange();
diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp
new file mode 100644
index 0000000000..1ae0f08f86
--- /dev/null
+++ b/test/CodeGenCXX/internal-linkage.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+struct Global { };
+template<typename T> struct X { };
+
+
+namespace {
+ struct Anon { };
+
+ // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global
+ Global anon0;
+}
+
+// CHECK: @anon1 = internal global
+Anon anon1;
+
+// CHECK: @anon2 = internal global
+X<Anon> anon2;
+
diff --git a/test/SemaTemplate/instantiate-decl-init.cpp b/test/SemaTemplate/instantiate-decl-init.cpp
index b0c2aa8afa..69c7721b51 100644
--- a/test/SemaTemplate/instantiate-decl-init.cpp
+++ b/test/SemaTemplate/instantiate-decl-init.cpp
@@ -20,3 +20,17 @@ void fn(T t, const arg& arg) {
void test() {
fn(1, arg());
}
+
+struct X0 { };
+
+struct X1 {
+ explicit X1(const X0 &x0 = X0());
+};
+
+template<typename T>
+void f0() {
+ X1 x1;
+}
+
+template void f0<int>();
+template void f0<float>();