diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2017-08-09 04:02:49 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2017-08-09 04:02:49 +0000 |
commit | 99db3ea6902a3bf86cde37866ba8afd55bada30e (patch) | |
tree | 109a594d25cb08690b43c747c400f70f80b802ae /clang/lib/AST/Decl.cpp | |
parent | c06b35c97e65e673530293db1d6931a06cd98396 (diff) | |
download | bcm5719-llvm-99db3ea6902a3bf86cde37866ba8afd55bada30e.tar.gz bcm5719-llvm-99db3ea6902a3bf86cde37866ba8afd55bada30e.zip |
[AST] Move visibility computations into a class; NFC
This is patch 1 in a 2 patch series that aims to fix PR29160. Its goal
is to cache decl visibility/linkage for the duration of each
visibility+linkage query.
The simplest way I can see to do this is to put the visibility
calculation code that needs to (transitively) access this cache into a
class, which is what this patch does. Actual caching will come in patch
2. (Another way would be to keep the cache in ASTContext + manually
invalidate it or something, but that felt way too subtle to me.)
Caching visibility results across multiple queries seems a bit tricky,
since the user can add visibility attributes ~whenever they want, and
these attributes can apparently have far-reaching effects (e.g. class
visibility extends to its members, ...). Because a cache that's dropped
at the end of each top-level query seems to work nearly as well and
doesn't require any eviction logic, I opted for that design.
llvm-svn: 310436
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 187 |
1 files changed, 73 insertions, 114 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index a80306bf5b4..317b493ad6b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Decl.h" +#include "Linkage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" @@ -99,38 +100,6 @@ TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) // and 'matcher' is a type only matters when looking for attributes // and settings from the immediate context. -const static unsigned IgnoreExplicitVisibilityBit = 2; -const static unsigned IgnoreAllVisibilityBit = 4; - -/// Kinds of LV computation. The linkage side of the computation is -/// always the same, but different things can change how visibility is -/// computed. -enum LVComputationKind { - /// Do an LV computation for, ultimately, a type. - /// Visibility may be restricted by type visibility settings and - /// the visibility of template arguments. - LVForType = NamedDecl::VisibilityForType, - - /// Do an LV computation for, ultimately, a non-type declaration. - /// Visibility may be restricted by value visibility settings and - /// the visibility of template arguments. - LVForValue = NamedDecl::VisibilityForValue, - - /// Do an LV computation for, ultimately, a type that already has - /// some sort of explicit visibility. Visibility may only be - /// restricted by the visibility of template arguments. - LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit), - - /// Do an LV computation for, ultimately, a non-type declaration - /// that already has some sort of explicit visibility. Visibility - /// may only be restricted by the visibility of template arguments. - LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit), - - /// Do an LV computation when we only care about the linkage. - LVForLinkageOnly = - LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit -}; - /// Does this computation kind permit us to consider additional /// visibility settings from attributes and the like? static bool hasExplicitVisibilityAlready(LVComputationKind computation) { @@ -219,8 +188,8 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, return None; } -static LinkageInfo -getLVForType(const Type &T, LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForType(const Type &T, + LVComputationKind computation) { if (computation == LVForLinkageOnly) return LinkageInfo(T.getLinkage(), DefaultVisibility, true); return T.getLinkageAndVisibility(); @@ -229,9 +198,8 @@ getLVForType(const Type &T, LVComputationKind computation) { /// \brief Get the most restrictive linkage for the types in the given /// template parameter list. For visibility purposes, template /// parameters are part of the signature of a template. -static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *Params, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForTemplateParameterList( + const TemplateParameterList *Params, LVComputationKind computation) { LinkageInfo LV; for (const NamedDecl *P : *Params) { // Template type parameters are the most common and never @@ -283,10 +251,6 @@ getLVForTemplateParameterList(const TemplateParameterList *Params, return LV; } -/// getLVForDecl - Get the linkage and visibility for the given declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation); - static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { const Decl *Ret = nullptr; const DeclContext *DC = D->getDeclContext(); @@ -303,8 +267,9 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { /// /// Note that we don't take an LVComputationKind because we always /// want to honor the visibility of template arguments in the same way. -static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation) { LinkageInfo LV; for (const TemplateArgument &Arg : Args) { @@ -346,9 +311,9 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, return LV; } -static LinkageInfo -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVComputationKind computation) { return getLVForTemplateArgumentList(TArgs.asArray(), computation); } @@ -371,10 +336,10 @@ static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, /// LVForValue. /// /// \param[out] LV the computation to use for the parent -static void -mergeTemplateLV(LinkageInfo &LV, const FunctionDecl *fn, - const FunctionTemplateSpecializationInfo *specInfo, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(fn, specInfo); @@ -449,9 +414,9 @@ static bool shouldConsiderTemplateVisibility( /// Merge in template-related linkage and visibility for the given /// class template specialization. -static void mergeTemplateLV(LinkageInfo &LV, - const ClassTemplateSpecializationDecl *spec, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); // Merge information from the template parameters, but ignore @@ -501,9 +466,9 @@ static bool shouldConsiderTemplateVisibility( /// Merge in template-related linkage and visibility for the given /// variable template specialization. As usual, follow class template /// specialization logic up to initialization. -static void mergeTemplateLV(LinkageInfo &LV, - const VarTemplateSpecializationDecl *spec, - LVComputationKind computation) { +void LinkageComputer::mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); // Merge information from the template parameters, but ignore @@ -603,8 +568,9 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { return LinkageInfo::external(); } -static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, + LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -883,8 +849,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, return LV; } -static LinkageInfo getLVForClassMember(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo +LinkageComputer::getLVForClassMember(const NamedDecl *D, + LVComputationKind computation) { // 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 @@ -1041,15 +1008,13 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, void NamedDecl::anchor() { } -static LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation); - bool NamedDecl::isLinkageValid() const { if (!hasCachedLinkage()) return true; - return computeLVForDecl(this, LVForLinkageOnly).getLinkage() == - getCachedLinkage(); + Linkage L = + LinkageComputer{}.computeLVForDecl(this, LVForLinkageOnly).getLinkage(); + return L == getCachedLinkage(); } ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { @@ -1068,13 +1033,11 @@ ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { Linkage NamedDecl::getLinkageInternal() const { // We don't care about visibility here, so ask for the cheapest // possible visibility analysis. - return getLVForDecl(this, LVForLinkageOnly).getLinkage(); + return LinkageComputer{}.getLVForDecl(this, LVForLinkageOnly).getLinkage(); } LinkageInfo NamedDecl::getLinkageAndVisibility() const { - LVComputationKind computation = - (usesTypeVisibility(this) ? LVForType : LVForValue); - return getLVForDecl(this, computation); + return LinkageComputer{}.getDeclLinkageAndVisibility(this); } static Optional<Visibility> @@ -1152,8 +1115,9 @@ NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { return getExplicitVisibilityAux(this, kind, false); } -static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, + Decl *ContextDecl, + LVComputationKind computation) { // This lambda has its linkage/visibility determined by its owner. if (ContextDecl) { if (isa<ParmVarDecl>(ContextDecl)) @@ -1170,8 +1134,8 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, return LinkageInfo::external(); } -static LinkageInfo getLVForLocalDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation) { if (const auto *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && !Function->isInExternCContext()) @@ -1264,8 +1228,8 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) { return Ret; } -static LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation) { +LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, + LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) return getInternalLinkageFor(D); @@ -1384,56 +1348,51 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, return LinkageInfo::none(); } -namespace clang { -class LinkageComputer { -public: - static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation) { - // Internal_linkage attribute overrides other considerations. - if (D->hasAttr<InternalLinkageAttr>()) - return getInternalLinkageFor(D); +/// getLVForDecl - Get the linkage and visibility for the given declaration. +LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return getInternalLinkageFor(D); - if (computation == LVForLinkageOnly && D->hasCachedLinkage()) - return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); + if (computation == LVForLinkageOnly && D->hasCachedLinkage()) + return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); - LinkageInfo LV = computeLVForDecl(D, computation); - if (D->hasCachedLinkage()) - assert(D->getCachedLinkage() == LV.getLinkage()); + LinkageInfo LV = computeLVForDecl(D, computation); + if (D->hasCachedLinkage()) + assert(D->getCachedLinkage() == LV.getLinkage()); - D->setCachedLinkage(LV.getLinkage()); + D->setCachedLinkage(LV.getLinkage()); #ifndef NDEBUG - // In C (because of gnu inline) and in c++ with microsoft extensions an - // static can follow an extern, so we can have two decls with different - // linkages. - const LangOptions &Opts = D->getASTContext().getLangOpts(); - if (!Opts.CPlusPlus || Opts.MicrosoftExt) - return LV; + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = D->getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return LV; - // We have just computed the linkage for this decl. By induction we know - // that all other computed linkages match, check that the one we just - // computed also does. - NamedDecl *Old = nullptr; - for (auto I : D->redecls()) { - auto *T = cast<NamedDecl>(I); - if (T == D) - continue; - if (!T->isInvalidDecl() && T->hasCachedLinkage()) { - Old = T; - break; - } + // We have just computed the linkage for this decl. By induction we know + // that all other computed linkages match, check that the one we just + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + auto *T = cast<NamedDecl>(I); + if (T == D) + continue; + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { + Old = T; + break; } - assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); + } + assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); #endif - return LV; - } -}; + return LV; } -static LinkageInfo getLVForDecl(const NamedDecl *D, - LVComputationKind computation) { - return clang::LinkageComputer::getLVForDecl(D, computation); +LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { + return getLVForDecl(D, usesTypeVisibility(D) ? LVForType : LVForValue); } void NamedDecl::printName(raw_ostream &os) const { |