[cfe-commits] r95216 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/Type.h include/clang/Basic/Linkage.h include/clang/Basic/Specifiers.h lib/AST/Decl.cpp lib/AST/Type.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/Mangle.cpp lib/Sema/SemaTemplate.cpp test/CodeGenCXX/internal-linkage.cpp test/SemaTemplate/instantiate-decl-init.cpp
Douglas Gregor
dgregor at apple.com
Wed Feb 3 01:33:46 PST 2010
Author: dgregor
Date: Wed Feb 3 03:33:45 2010
New Revision: 95216
URL: http://llvm.org/viewvc/llvm-project?rev=95216&view=rev
Log:
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.
Added:
cfe/trunk/include/clang/Basic/Linkage.h (with props)
cfe/trunk/test/CodeGenCXX/internal-linkage.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/Specifiers.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaTemplate/instantiate-decl-init.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Feb 3 03:33:45 2010
@@ -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 @@
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;
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Feb 3 03:33:45 2010
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
ID.AddPointer(Pointee.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == BlockPointer;
}
@@ -1203,6 +1215,8 @@
ID.AddBoolean(SpelledAsLValue);
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == LValueReference ||
T->getTypeClass() == RValueReference;
@@ -1277,6 +1291,8 @@
ID.AddPointer(Class);
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == MemberPointer;
}
@@ -1328,6 +1344,8 @@
}
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 @@
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 @@
ID.AddPointer(ResultType.getAsOpaquePtr());
}
+ virtual Linkage getLinkage() const;
+
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto;
}
@@ -1856,6 +1879,8 @@
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 @@
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 @@
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 @@
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);
Added: cfe/trunk/include/clang/Basic/Linkage.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Linkage.h?rev=95216&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/Linkage.h (added)
+++ cfe/trunk/include/clang/Basic/Linkage.h Wed Feb 3 03:33:45 2010
@@ -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
Propchange: cfe/trunk/include/clang/Basic/Linkage.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/include/clang/Basic/Linkage.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/include/clang/Basic/Linkage.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/include/clang/Basic/Specifiers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Specifiers.h (original)
+++ cfe/trunk/include/clang/Basic/Specifiers.h Wed Feb 3 03:33:45 2010
@@ -77,6 +77,7 @@
AS_private,
AS_none
};
-}
+
+} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Feb 3 03:33:45 2010
@@ -47,7 +47,72 @@
// 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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
return L;
+ if (Function->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
return ExternalLinkage;
}
@@ -235,6 +346,9 @@
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
+ if (Var->isInAnonymousNamespace())
+ return UniqueExternalLinkage;
+
return ExternalLinkage;
}
}
@@ -242,7 +356,7 @@
// C++ [basic.link]p6:
// Names not covered by these rules have no linkage.
return NoLinkage;
-}
+ }
std::string NamedDecl::getQualifiedNameAsString() const {
return getQualifiedNameAsString(getASTContext().getLangOptions());
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Feb 3 03:33:45 2010
@@ -1049,3 +1049,79 @@
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;
+}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Feb 3 03:33:45 2010
@@ -255,34 +255,40 @@
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 @@
// 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 @@
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 @@
// 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;
}
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Wed Feb 3 03:33:45 2010
@@ -178,8 +178,7 @@
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 @@
// 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';
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Feb 3 03:33:45 2010
@@ -2336,7 +2336,7 @@
// 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 @@
}
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();
Added: cfe/trunk/test/CodeGenCXX/internal-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/internal-linkage.cpp?rev=95216&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/internal-linkage.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/internal-linkage.cpp Wed Feb 3 03:33:45 2010
@@ -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;
+
Propchange: cfe/trunk/test/CodeGenCXX/internal-linkage.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CodeGenCXX/internal-linkage.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CodeGenCXX/internal-linkage.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/test/SemaTemplate/instantiate-decl-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-decl-init.cpp?rev=95216&r1=95215&r2=95216&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-decl-init.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-decl-init.cpp Wed Feb 3 03:33:45 2010
@@ -20,3 +20,17 @@
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>();
More information about the cfe-commits
mailing list