summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp105
1 files changed, 55 insertions, 50 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a6036d1cbf8..7ca2bf2614a 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -554,7 +554,8 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
LinkageInfo
LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
- LVComputationKind computation) {
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -611,7 +612,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// - a data member of an anonymous union.
const VarDecl *VD = IFD->getVarDecl();
assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
- return getLVForNamespaceScopeDecl(VD, computation);
+ return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
}
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
@@ -700,7 +701,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
//
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
- if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
+ !IgnoreVarTypeLinkage) {
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
if (!isExternallyVisible(TypeLV.getLinkage()))
return LinkageInfo::uniqueExternal();
@@ -740,15 +742,9 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOpts().CPlusPlus &&
- !Function->isInExternCContext()) {
- // Only look at the type-as-written. If this function has an auto-deduced
- // return type, we can't compute the linkage of that type because it could
- // require looking at the linkage of this function, and we don't need this
- // for correctness because the type is not part of the function's
- // signature.
- // FIXME: This is a hack. We should be able to solve this circularity and
- // the one in getLVForClassMember for Functions some other way.
+ if (Context.getLangOpts().CPlusPlus && !Function->isInExternCContext()) {
+ // Only look at the type-as-written. Otherwise, deducing the return type
+ // of a function could change its linkage.
QualType TypeAsWritten = Function->getType();
if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
TypeAsWritten = TSI->getType();
@@ -831,7 +827,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
LinkageInfo
LinkageComputer::getLVForClassMember(const NamedDecl *D,
- LVComputationKind computation) {
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
// Only certain class members have linkage. Note that fields don't
// really have linkage, but it's convenient to say they do for the
// purposes of calculating linkage of pointer-to-data-member
@@ -889,22 +886,14 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
const NamedDecl *explicitSpecSuppressor = nullptr;
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- // If the type of the function uses a type that has non-externally-visible
- // linkage, it's not legally usable from outside this translation unit.
- // But only look at the type-as-written. If this function has an
- // auto-deduced return type, we can't compute the linkage of that type
- // because it could require looking at the linkage of this function, and we
- // don't need this for correctness because the type is not part of the
- // function's signature.
- // FIXME: This is a hack. We should be able to solve this circularity and
- // the one in getLVForNamespaceScopeDecl for Functions some other way.
- {
- QualType TypeAsWritten = MD->getType();
- if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
- TypeAsWritten = TSI->getType();
- if (!isExternallyVisible(TypeAsWritten->getLinkage()))
- return LinkageInfo::uniqueExternal();
- }
+ // Only look at the type-as-written. Otherwise, deducing the return type
+ // of a function could change its linkage.
+ QualType TypeAsWritten = MD->getType();
+ if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
+ TypeAsWritten = TSI->getType();
+ if (!isExternallyVisible(TypeAsWritten->getLinkage()))
+ return LinkageInfo::uniqueExternal();
+
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *spec
@@ -941,10 +930,14 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
// Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition.
- LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
- if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
- LV.mergeVisibility(typeLV);
- LV.mergeExternalVisibility(typeLV);
+ if (!IgnoreVarTypeLinkage) {
+ LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
+ // FIXME: If the type's linkage is not externally visible, we can
+ // give this static data member UniqueExternalLinkage.
+ if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
+ LV.mergeVisibility(typeLV);
+ LV.mergeExternalVisibility(typeLV);
+ }
if (isExplicitMemberSpecialization(VD)) {
explicitSpecSuppressor = VD;
@@ -1102,22 +1095,33 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
Decl *ContextDecl,
LVComputationKind computation) {
// This lambda has its linkage/visibility determined by its owner.
+ const NamedDecl *Owner;
+ if (!ContextDecl)
+ Owner = dyn_cast<NamedDecl>(DC);
+ else if (isa<ParmVarDecl>(ContextDecl))
+ Owner =
+ dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
+ else
+ Owner = cast<NamedDecl>(ContextDecl);
+
+ // FIXME: If there is no owner, the closure should have no linkage.
+ if (!Owner)
+ return LinkageInfo::external();
+
+ // If the owner has a deduced type, we need to skip querying the linkage and
+ // visibility of that type, because it might involve this closure type. The
+ // only effect of this is that we might give a lambda VisibleNoLinkage rather
+ // than NoLinkage when we don't strictly need to, which is benign.
+ auto *VD = dyn_cast<VarDecl>(Owner);
+ LinkageInfo OwnerLinkage =
+ VD && VD->getType()->getContainedDeducedType()
+ ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
+ : getLVForDecl(Owner, computation);
+
// FIXME: This is wrong. A lambda never formally has linkage; if this
- // calculation determines the lambda has external linkage, it should be
+ // calculation determines a lambda has external linkage, it should be
// downgraded to VisibleNoLinkage.
- if (ContextDecl) {
- if (isa<ParmVarDecl>(ContextDecl))
- DC = ContextDecl->getDeclContext()->getRedeclContext();
- else
- return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
- }
-
- if (const auto *ND = dyn_cast<NamedDecl>(DC))
- return getLVForDecl(ND, computation);
-
- // FIXME: We have a closure at TU scope with no context declaration. This
- // should probably have no linkage.
- return LinkageInfo::external();
+ return OwnerLinkage;
}
LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
@@ -1215,7 +1219,8 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) {
}
LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
- LVComputationKind computation) {
+ LVComputationKind computation,
+ bool IgnoreVarTypeLinkage) {
// Internal_linkage attribute overrides other considerations.
if (D->hasAttr<InternalLinkageAttr>())
return getInternalLinkageFor(D);
@@ -1303,7 +1308,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
// Handle linkage for namespace-scope names.
if (D->getDeclContext()->getRedeclContext()->isFileContext())
- return getLVForNamespaceScopeDecl(D, computation);
+ return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
@@ -1313,7 +1318,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (D->getDeclContext()->isRecord())
- return getLVForClassMember(D, computation);
+ return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
OpenPOWER on IntegriCloud