diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-02-03 09:33:45 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-02-03 09:33:45 +0000 |
commit | 0b6bc8bd7a1d2a7d7478d13d78cff94cacad61fc (patch) | |
tree | 411606af7c58db02b6f15df5197c7656a852fe44 | |
parent | e20d3c1f86a8ff8b1980d42ea1e59d585d703bb7 (diff) |
When a function or variable somehow depends on a type or declaration
that is in an anonymous namespace, give that function or variable
internal linkage.
This change models an oddity of the C++ standard, where names declared
in an anonymous namespace have external linkage but, because anonymous
namespace are really "uniquely-named" namespaces, the names cannot be
referenced from other translation units. That means that they have
external linkage for semantic analysis, but the only sensible
implementation for code generation is to give them internal
linkage. We now model this notion via the UniqueExternalLinkage
linkage type. There are several changes here:
- Extended NamedDecl::getLinkage() to produce UniqueExternalLinkage
when the declaration is in an anonymous namespace.
- Added Type::getLinkage() to determine the linkage of a type, which
is defined as the minimum linkage of the types (when we're dealing
with a compound type that is not a struct/class/union).
- Extended NamedDecl::getLinkage() to consider the linkage of the
template arguments and template parameters of function template
specializations and class template specializations.
- Taught code generation to rely on NamedDecl::getLinkage() when
determining the linkage of variables and functions, also
considering the linkage of the types of those variables and
functions (C++ only). Map UniqueExternalLinkage to internal
linkage, taking out the explicit checks for
isInAnonymousNamespace().
This fixes much of PR5792, which, as discovered by Anders Carlsson, is
actually the reason behind the pass-manager assertion that causes the
majority of clang-on-clang regression test failures. With this fix,
Clang-built-Clang+LLVM passes 88% of its regression tests (up from
67%). The specific numbers are:
LLVM:
Expected Passes : 4006
Expected Failures : 32
Unsupported Tests : 40
Unexpected Failures: 736
Clang:
Expected Passes : 1903
Expected Failures : 14
Unexpected Failures: 75
Overall:
Expected Passes : 5909
Expected Failures : 46
Unsupported Tests : 40
Unexpected Failures: 811
Still to do:
- Improve testing
- Check whether we should allow the presence of types with
InternalLinkage (in addition to UniqueExternalLinkage) given
variables/functions internal linkage in C++, as mentioned in
PR5792.
- Determine how expensive the getLinkage() calls are in practice;
consider caching the result in NamedDecl.
- Assess the feasibility of Chris's idea in comment #1 of PR5792.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95216 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 18 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 31 | ||||
-rw-r--r-- | include/clang/Basic/Linkage.h | 57 | ||||
-rw-r--r-- | include/clang/Basic/Specifiers.h | 3 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 164 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 76 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 90 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | test/CodeGenCXX/internal-linkage.cpp | 19 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-decl-init.cpp | 14 |
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>(); |