bool isCXXInstanceMember() const;
/// \brief Determine what kind of linkage this entity has.
- Linkage getLinkage() const;
+ /// This is not the linkage as defined by the standard or the codegen notion
+ /// of linkage. It is just an implementation detail that is used to compute
+ /// those.
+ Linkage getLinkageInternal() const;
+
+ /// \brief Get the linkage from a semantic point of view. Entities in
+ /// anonymous namespaces are external (in c++98).
+ Linkage getFormalLinkage() const {
+ Linkage L = getLinkageInternal();
+ if (L == UniqueExternalLinkage)
+ return ExternalLinkage;
+ return L;
+ }
/// \brief True if this decl has external linkage.
- bool hasExternalLinkage() const {
- return getLinkage() == ExternalLinkage;
+ bool hasExternalFormalLinkage() const {
+ return getFormalLinkage() == ExternalLinkage;
+ }
+ bool isExternallyVisible() const {
+ return getLinkageInternal() == ExternalLinkage;
}
/// \brief Determines the visibility of this entity.
GVA_ExplicitTemplateInstantiation
};
-/// \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.
inline Linkage minLinkage(Linkage L1, Linkage L2) {
return L1 < L2? L1 : L2;
// it will keep having external linkage. If it has internal linkage, we
// will not link it. Since it has no previous decls, it will remain
// with internal linkage.
- return !Old->isHidden() || New->hasExternalLinkage();
+ return !Old->isHidden() || New->isExternallyVisible();
}
public:
if (FD->getName() == "CFRetain" &&
FD->getNumParams() == 1 &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage()) {
+ FD->isExternallyVisible()) {
Expr *Arg = callE->getArg(0);
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
const Expr *sub = ICE->getSubExpr();
FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage())
+ FD->isExternallyVisible())
return true;
return false;
if (FD->isGlobal() &&
FD->getIdentifier() &&
FD->getParent()->isTranslationUnit() &&
- FD->hasExternalLinkage() &&
+ FD->isExternallyVisible() &&
ento::cocoa::isRefType(callE->getType(), "CF",
FD->getIdentifier()->getName())) {
StringRef fname = FD->getIdentifier()->getName();
E = E->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl()->getDeclContext()->isFileContext() &&
- DRE->getDecl()->hasExternalLinkage();
+ DRE->getDecl()->isExternallyVisible();
if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
return isGlobalVar(condOp->getTrueExpr()) &&
isGlobalVar(condOp->getFalseExpr());
}
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
- GVALinkage External = GVA_StrongExternal;
-
- Linkage L = FD->getLinkage();
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
+ if (!FD->isExternallyVisible())
return GVA_Internal;
-
- case ExternalLinkage:
- switch (FD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- External = GVA_StrongExternal;
- break;
- case TSK_ExplicitInstantiationDefinition:
- return GVA_ExplicitTemplateInstantiation;
+ GVALinkage External = GVA_StrongExternal;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = GVA_StrongExternal;
+ break;
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ImplicitInstantiation:
- External = GVA_TemplateInstantiation;
- break;
- }
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
+ External = GVA_TemplateInstantiation;
+ break;
}
if (!FD->isInlined())
}
GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ if (!VD->isExternallyVisible())
+ return GVA_Internal;
+
// If this is a static data member, compute the kind of template
// specialization. Otherwise, this variable is not part of a
// template.
if (VD->isStaticDataMember())
TSK = VD->getTemplateSpecializationKind();
- Linkage L = VD->getLinkage();
-
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return GVA_Internal;
+ switch (TSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return GVA_StrongExternal;
- case ExternalLinkage:
- switch (TSK) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- return GVA_StrongExternal;
+ case TSK_ExplicitInstantiationDeclaration:
+ llvm_unreachable("Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
- case TSK_ExplicitInstantiationDeclaration:
- llvm_unreachable("Variable should not be instantiated");
- // Fall through to treat this like any other instantiation.
-
- case TSK_ExplicitInstantiationDefinition:
- return GVA_ExplicitTemplateInstantiation;
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
- case TSK_ImplicitInstantiation:
- return GVA_TemplateInstantiation;
- }
+ case TSK_ImplicitInstantiation:
+ return GVA_TemplateInstantiation;
}
-
- llvm_unreachable("Invalid Linkage!");
}
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
void ASTContext::addUnnamedTag(const TagDecl *Tag) {
// FIXME: This mangling should be applied to function local classes too
if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
- !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage)
+ !isa<CXXRecordDecl>(Tag->getParent()) ||
+ !Tag->isExternallyVisible())
return;
std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
continue;
if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) {
- if (isExternalLinkage(FoundFunction->getLinkage()) &&
- isExternalLinkage(D->getLinkage())) {
+ if (FoundFunction->hasExternalFormalLinkage() &&
+ D->hasExternalFormalLinkage()) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundFunction->getType())) {
// FIXME: Actually try to merge the body and other attributes.
if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) {
// We have found a variable that we may need to merge with. Check it.
- if (isExternalLinkage(FoundVar->getLinkage()) &&
- isExternalLinkage(D->getLinkage())) {
+ if (FoundVar->hasExternalFormalLinkage() &&
+ D->hasExternalFormalLinkage()) {
if (Importer.IsStructurallyEquivalent(D->getType(),
FoundVar->getType())) {
MergeWithVar = FoundVar;
return false;
}
+static bool isExternalLinkage(Linkage L) {
+ return L == UniqueExternalLinkage || L == ExternalLinkage;
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
Linkage(CachedLinkage);
}
-Linkage NamedDecl::getLinkage() const {
+Linkage NamedDecl::getLinkageInternal() const {
if (HasCachedLinkage)
return Linkage(CachedLinkage);
}
bool NamedDecl::hasLinkage() const {
- return getLinkage() != NoLinkage;
+ return getLinkageInternal() != NoLinkage;
}
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
static LanguageLinkage getLanguageLinkageTemplate(const T &D) {
// C++ [dcl.link]p1: All function types, function names with external linkage,
// and variable names with external linkage have a language linkage.
- if (!isExternalLinkage(D.getLinkage()))
+ if (!D.hasExternalFormalLinkage())
return NoLanguageLinkage;
// Language linkage is a C++ concept, but saying that everything else in C has
if (DC->isFunctionOrMethod() && D->hasLinkage())
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = getEffectiveParentContext(DC);
- if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
+ if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage)
return false;
}
// static void foo();
// This naming convention is the same as that followed by GCC,
// though it shouldn't actually matter.
- if (ND && ND->getLinkage() == InternalLinkage &&
+ if (ND && ND->getFormalLinkage() == InternalLinkage &&
getEffectiveDeclContext(ND)->isFileContext())
Out << 'L';
// Variables at global scope with internal linkage are not mangled.
if (!FD) {
const DeclContext *DC = D->getDeclContext();
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
+ if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage)
return false;
}
// A class that is not externally visible doesn't have a key function. (Or
// at least, there's no point to assigning a key function to such a class;
// this doesn't affect the ABI.)
- if (RD->getLinkage() != ExternalLinkage)
+ if (!RD->isExternallyVisible())
return 0;
// Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6.
// - 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
- Linkage L = Tag->getLinkage();
+ Linkage L = Tag->getLinkageInternal();
bool IsLocalOrUnnamed =
Tag->getDeclContext()->isFunctionOrMethod() ||
!Tag->hasNameForLinkage();
return result;
}
case Type::ObjCInterface: {
- Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkage();
+ Linkage L = cast<ObjCInterfaceType>(T)->getDecl()->getLinkageInternal();
return CachedProperties(L, false);
}
case Type::ObjCObject:
/// Note that we only call this at the end of the translation unit.
llvm::GlobalVariable::LinkageTypes
CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
- if (RD->getLinkage() != ExternalLinkage)
+ if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
// We're at the end of the translation unit, so the current key
return;
// Must have internal linkage and an ordinary name.
- if (!D->getIdentifier() || D->getLinkage() != InternalLinkage)
+ if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage)
return;
// Must be in an extern "C" context. Entities declared directly within
// on their mangled names, if they're external.
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
- if (Features.CPlusPlus &&
- ETy->getDecl()->getLinkage() != ExternalLinkage)
+ if (Features.CPlusPlus && !ETy->getDecl()->isExternallyVisible())
return MetadataCache[Ty] = getChar();
// TODO: This is using the RTTI name. Is there a better way to get
if (D->getMostRecentDecl()->isUsed())
return true;
- if (D->hasExternalLinkage())
+ if (D->isExternallyVisible())
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
if (FD->isDefined())
continue;
- if (FD->hasExternalLinkage() &&
+ if (FD->isExternallyVisible() &&
!FD->getMostRecentDecl()->isInlined())
continue;
} else {
if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly)
continue;
- if (ND->hasExternalLinkage())
+ if (ND->isExternallyVisible())
continue;
}
I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
NamedDecl *ND = I->first;
- if (ND->getLinkage() != ExternalLinkage) {
+ if (!ND->isExternallyVisible()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
} else {
DC = DC->getParent();
}
- return !D->hasExternalLinkage();
+ return !D->isExternallyVisible();
}
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
if (!old->isHidden())
continue;
- if (old->getLinkage() != ExternalLinkage)
+ if (!old->isExternallyVisible())
filter.erase();
}
// storage classes.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
- isExternalLinkage(Old->getLinkage()) &&
+ Old->hasExternalFormalLinkage() &&
!New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
// [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
!New->isStaticDataMember() &&
- isExternalLinkage(Old->getLinkage())) {
+ Old->hasExternalFormalLinkage()) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
// 'weak' only applies to declarations with external linkage.
if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
- if (ND.getLinkage() != ExternalLinkage) {
+ if (!ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
ND.dropAttr<WeakAttr>();
}
}
if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
- if (ND.hasExternalLinkage()) {
+ if (ND.isExternallyVisible()) {
S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
ND.dropAttr<WeakRefAttr>();
}
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this function.
- if (!DC->isRecord() && NewFD->hasExternalLinkage())
+ if (!DC->isRecord() && NewFD->isExternallyVisible())
AddPushedVisibilityAttribute(NewFD);
// If there's a #pragma clang arc_cf_code_audited in scope, consider
// declared with no linkage (C99 6.2.2p6), the type for the
// object shall be complete.
if (!Type->isDependentType() && Var->isLocalVarDecl() &&
- !Var->getLinkage() && !Var->isInvalidDecl() &&
+ !Var->hasLinkage() && !Var->isInvalidDecl() &&
RequireCompleteType(Var->getLocation(), Type,
diag::err_typecheck_decl_incomplete_type))
Var->setInvalidDecl();
}
if (var->isThisDeclarationADefinition() &&
- var->hasExternalLinkage() &&
+ var->isExternallyVisible() &&
getDiagnostics().getDiagnosticLevel(
diag::warn_missing_variable_declarations,
var->getLocation())) {
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this variable.
- if (!DC->isRecord() && VD->hasExternalLinkage())
+ if (!DC->isRecord() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(VD);
if (VD->isFileVarDecl())
// ODR use before the definition. Avoid the expensive map lookup if this
// is the first declaration.
if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) {
- if (FD->getLinkage() != ExternalLinkage)
+ if (!FD->isExternallyVisible())
UndefinedButUsed.erase(FD);
else if (FD->isInlined() &&
(LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
// Optionally warn if we're emitting a weak vtable.
- if (Class->hasExternalLinkage() &&
+ if (Class->isExternallyVisible() &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = 0;
if (!KeyFunction ||
return;
if (!Current->isInlined())
return;
- if (Current->getLinkage() != ExternalLinkage)
+ if (!Current->isExternallyVisible())
return;
-
+
// Check if the decl has internal linkage.
- if (D->getLinkage() != InternalLinkage)
+ if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
// Keep track of used but undefined variables.
// FIXME: We shouldn't suppress this warning for static data members.
if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
- Var->getLinkage() != ExternalLinkage &&
+ !Var->isExternallyVisible() &&
!(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
}
// Address / reference template args must have external linkage in C++98.
- if (Entity->getLinkage() == InternalLinkage) {
+ if (Entity->getFormalLinkage() == InternalLinkage) {
S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_object_internal :
diag::ext_template_arg_object_internal)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
- } else if (Entity->getLinkage() == NoLinkage) {
+ } else if (!Entity->hasLinkage()) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_object_no_linkage)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
//prototyped/non-prototyped functions, etc.
if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
FunctionDecl *FuncY = cast<FunctionDecl>(Y);
- return (FuncX->getLinkage() == FuncY->getLinkage()) &&
+ return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType());
}
// Variables with the same type and linkage match.
if (VarDecl *VarX = dyn_cast<VarDecl>(X)) {
VarDecl *VarY = cast<VarDecl>(Y);
- return (VarX->getLinkage() == VarY->getLinkage()) &&
+ return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) &&
VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType());
}
Record.push_back(D->hasImplicitReturnZero());
Record.push_back(D->isConstexpr());
Record.push_back(D->HasSkippedBody);
- Record.push_back(D->getLinkage());
+ Record.push_back(D->getLinkageInternal());
Writer.AddSourceLocation(D->getLocEnd(), Record);
Record.push_back(D->getTemplatedKind());
Record.push_back(D->isCXXForRangeDecl());
Record.push_back(D->isARCPseudoStrong());
Record.push_back(D->isConstexpr());
- Record.push_back(D->getLinkage());
+ Record.push_back(D->getLinkageInternal());
if (D->getInit()) {
Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2));
// If this function is not externally visible, it is not a C library function.
// Note that we make an exception for inline functions, which may be
// declared in header files without external linkage.
- if (!FD->isInlined() && FD->getLinkage() != ExternalLinkage)
+ if (!FD->isInlined() && !FD->isExternallyVisible())
return false;
if (Name.empty())
const Decl *D = cxcursor::getCursorDecl(cursor);
if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
- switch (ND->getLinkage()) {
+ switch (ND->getLinkageInternal()) {
case NoLinkage: return CXLinkage_NoLinkage;
case InternalLinkage: return CXLinkage_Internal;
case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
}
static inline bool ShouldGenerateLocation(const NamedDecl *D) {
- return D->getLinkage() != ExternalLinkage;
+ return !D->isExternallyVisible();
}
void USRGenerator::VisitDeclContext(const DeclContext *DC) {
return false;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- switch (ND->getLinkage()) {
+ switch (ND->getFormalLinkage()) {
case NoLinkage:
case InternalLinkage:
return true;
case UniqueExternalLinkage:
+ llvm_unreachable("Not a sema linkage");
case ExternalLinkage:
return false;
}