aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
5 files changed, 278 insertions, 61 deletions
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();