diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 105 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/Linkage.h | 9 |
3 files changed, 68 insertions, 54 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 diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index a9c5ab2cc1d..ef54ad5ec85 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1691,10 +1691,16 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // to emit that last part of the prefix here. if (Decl *Context = Lambda->getLambdaContextDecl()) { if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && - Context->getDeclContext()->isRecord()) { + !isa<ParmVarDecl>(Context)) { + // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a + // reasonable mangling here. if (const IdentifierInfo *Name = cast<NamedDecl>(Context)->getIdentifier()) { mangleSourceName(Name); + const TemplateArgumentList *TemplateArgs = nullptr; + if (const TemplateDecl *TD = + isTemplate(cast<NamedDecl>(Context), TemplateArgs)) + mangleTemplateArgs(*TemplateArgs); Out << 'M'; } } diff --git a/clang/lib/AST/Linkage.h b/clang/lib/AST/Linkage.h index b577901f3a0..e6489c7ef2b 100644 --- a/clang/lib/AST/Linkage.h +++ b/clang/lib/AST/Linkage.h @@ -117,10 +117,12 @@ class LinkageComputer { LVComputationKind computation); LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - LVComputationKind computation); + LVComputationKind computation, + bool IgnoreVarTypeLinkage); LinkageInfo getLVForClassMember(const NamedDecl *D, - LVComputationKind computation); + LVComputationKind computation, + bool IgnoreVarTypeLinkage); LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, LVComputationKind computation); @@ -135,7 +137,8 @@ class LinkageComputer { public: LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation); + LVComputationKind computation, + bool IgnoreVarTypeLinkage = false); LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); |