diff options
-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>(); |