Re-implement caching for the linkage calculation of declarations.
My previous attempt at solving the compile-time problem with many redeclarations of the same entity cached both linkage and visibility, while this patch only tackles linkage. There are several reasons for this difference: - Linkage is a language concept, and is evaluated many times during semantic analysis and codegen, while visibility is only a code-generation concept that is evaluated only once per (unique) declaration. Hence, we *must* optimize linkage calculations but don't need to optimize visibility computation. - Once we know the linkage of a declaration, subsequent redeclarations can't change that linkage. Hence, cache invalidation is far simpler than for visibility, where a later redeclaration can completely change the visibility. - We have 3 spare bits in Decl to store the linkage cache, so the cache doesn't increase the size of declarations. With the visibility+linkage cache, NamedDecl got larger. llvm-svn: 121023
This commit is contained in:
parent
9bc2677b8c
commit
bf62d647de
|
@ -264,7 +264,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Determine what kind of linkage this entity has.
|
/// \brief Determine what kind of linkage this entity has.
|
||||||
Linkage getLinkage() const { return getLinkageAndVisibility().linkage(); }
|
Linkage getLinkage() const;
|
||||||
|
|
||||||
/// \brief Determines the visibility of this entity.
|
/// \brief Determines the visibility of this entity.
|
||||||
Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
|
Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
|
||||||
|
@ -272,6 +272,10 @@ public:
|
||||||
/// \brief Determines the linkage and visibility of this entity.
|
/// \brief Determines the linkage and visibility of this entity.
|
||||||
LinkageInfo getLinkageAndVisibility() const;
|
LinkageInfo getLinkageAndVisibility() const;
|
||||||
|
|
||||||
|
/// \brief Clear the linkage cache in response to a change
|
||||||
|
/// to the declaration.
|
||||||
|
void ClearLinkageCache() { HasCachedLinkage = 0; }
|
||||||
|
|
||||||
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
|
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
|
||||||
/// the underlying named decl.
|
/// the underlying named decl.
|
||||||
NamedDecl *getUnderlyingDecl();
|
NamedDecl *getUnderlyingDecl();
|
||||||
|
@ -625,6 +629,8 @@ private:
|
||||||
bool NRVOVariable : 1;
|
bool NRVOVariable : 1;
|
||||||
|
|
||||||
friend class StmtIteratorBase;
|
friend class StmtIteratorBase;
|
||||||
|
friend class ASTDeclReader;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||||
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
|
QualType T, TypeSourceInfo *TInfo, StorageClass SC,
|
||||||
|
@ -660,10 +666,7 @@ public:
|
||||||
StorageClass getStorageClassAsWritten() const {
|
StorageClass getStorageClassAsWritten() const {
|
||||||
return (StorageClass) SClassAsWritten;
|
return (StorageClass) SClassAsWritten;
|
||||||
}
|
}
|
||||||
void setStorageClass(StorageClass SC) {
|
void setStorageClass(StorageClass SC);
|
||||||
assert(isLegalForVariable(SC));
|
|
||||||
SClass = SC;
|
|
||||||
}
|
|
||||||
void setStorageClassAsWritten(StorageClass SC) {
|
void setStorageClassAsWritten(StorageClass SC) {
|
||||||
assert(isLegalForVariable(SC));
|
assert(isLegalForVariable(SC));
|
||||||
SClassAsWritten = SC;
|
SClassAsWritten = SC;
|
||||||
|
@ -1478,10 +1481,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageClass getStorageClass() const { return StorageClass(SClass); }
|
StorageClass getStorageClass() const { return StorageClass(SClass); }
|
||||||
void setStorageClass(StorageClass SC) {
|
void setStorageClass(StorageClass SC);
|
||||||
assert(isLegalForFunction(SC));
|
|
||||||
SClass = SC;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageClass getStorageClassAsWritten() const {
|
StorageClass getStorageClassAsWritten() const {
|
||||||
return StorageClass(SClassAsWritten);
|
return StorageClass(SClassAsWritten);
|
||||||
|
@ -2558,6 +2558,32 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||||
return DB;
|
return DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename decl_type>
|
||||||
|
void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
|
||||||
|
// Note: This routine is implemented here because we need both NamedDecl
|
||||||
|
// and Redeclarable to be defined.
|
||||||
|
|
||||||
|
decl_type *First;
|
||||||
|
|
||||||
|
if (PrevDecl) {
|
||||||
|
// Point to previous. Make sure that this is actually the most recent
|
||||||
|
// redeclaration, or we can build invalid chains. If the most recent
|
||||||
|
// redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
|
||||||
|
RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
|
||||||
|
PrevDecl->getMostRecentDeclaration()));
|
||||||
|
First = PrevDecl->getFirstDeclaration();
|
||||||
|
assert(First->RedeclLink.NextIsLatest() && "Expected first");
|
||||||
|
} else {
|
||||||
|
// Make this first.
|
||||||
|
First = static_cast<decl_type*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First one will point to this one as latest.
|
||||||
|
First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
|
||||||
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this)))
|
||||||
|
ND->ClearLinkageCache();
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -198,7 +198,7 @@ private:
|
||||||
return DeclCtx.get<DeclContext*>();
|
return DeclCtx.get<DeclContext*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loc - The location that this decl.
|
/// Loc - The location of this decl.
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
|
|
||||||
/// DeclKind - This indicates which class this is.
|
/// DeclKind - This indicates which class this is.
|
||||||
|
@ -231,8 +231,19 @@ protected:
|
||||||
unsigned ChangedAfterLoad : 1;
|
unsigned ChangedAfterLoad : 1;
|
||||||
|
|
||||||
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
|
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
|
||||||
unsigned IdentifierNamespace : 15;
|
unsigned IdentifierNamespace : 12;
|
||||||
|
|
||||||
|
/// \brief Whether the \c CachedLinkage field is active.
|
||||||
|
///
|
||||||
|
/// This field is only valid for NamedDecls subclasses.
|
||||||
|
mutable unsigned HasCachedLinkage : 1;
|
||||||
|
|
||||||
|
/// \brief If \c HasCachedLinkage, the linkage of this declaration.
|
||||||
|
///
|
||||||
|
/// This field is only valid for NamedDecls subclasses.
|
||||||
|
mutable unsigned CachedLinkage : 2;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckAccessDeclContext() const;
|
void CheckAccessDeclContext() const;
|
||||||
|
|
||||||
|
@ -243,7 +254,9 @@ protected:
|
||||||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||||
HasAttrs(false), Implicit(false), Used(false),
|
HasAttrs(false), Implicit(false), Used(false),
|
||||||
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
||||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
|
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||||
|
HasCachedLinkage(0)
|
||||||
|
{
|
||||||
if (Decl::CollectingStats()) add(DK);
|
if (Decl::CollectingStats()) add(DK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +264,9 @@ protected:
|
||||||
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
|
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
|
||||||
HasAttrs(false), Implicit(false), Used(false),
|
HasAttrs(false), Implicit(false), Used(false),
|
||||||
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
||||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
|
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||||
|
HasCachedLinkage(0)
|
||||||
|
{
|
||||||
if (Decl::CollectingStats()) add(DK);
|
if (Decl::CollectingStats()) add(DK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,25 +109,7 @@ public:
|
||||||
|
|
||||||
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
|
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
|
||||||
/// first and only declaration.
|
/// first and only declaration.
|
||||||
void setPreviousDeclaration(decl_type *PrevDecl) {
|
void setPreviousDeclaration(decl_type *PrevDecl);
|
||||||
decl_type *First;
|
|
||||||
|
|
||||||
if (PrevDecl) {
|
|
||||||
// Point to previous. Make sure that this is actually the most recent
|
|
||||||
// redeclaration, or we can build invalid chains. If the most recent
|
|
||||||
// redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
|
|
||||||
RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
|
|
||||||
PrevDecl->getMostRecentDeclaration()));
|
|
||||||
First = PrevDecl->getFirstDeclaration();
|
|
||||||
assert(First->RedeclLink.NextIsLatest() && "Expected first");
|
|
||||||
} else {
|
|
||||||
// Make this first.
|
|
||||||
First = static_cast<decl_type*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First one will point to this one as latest.
|
|
||||||
First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Iterates through all the redeclarations of the same decl.
|
/// \brief Iterates through all the redeclarations of the same decl.
|
||||||
class redecl_iterator {
|
class redecl_iterator {
|
||||||
|
|
|
@ -85,6 +85,15 @@ struct LVFlags {
|
||||||
ConsiderVisibilityAttributes(true) {
|
ConsiderVisibilityAttributes(true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Returns a set of flags that is only useful for computing the
|
||||||
|
/// linkage, not the visibility, of a declaration.
|
||||||
|
static LVFlags CreateOnlyDeclLinkage() {
|
||||||
|
LVFlags F;
|
||||||
|
F.ConsiderGlobalVisibility = false;
|
||||||
|
F.ConsiderVisibilityAttributes = false;
|
||||||
|
return F;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a set of flags, otherwise based on these, which ignores
|
/// Returns a set of flags, otherwise based on these, which ignores
|
||||||
/// off all sources of visibility except template arguments.
|
/// off all sources of visibility except template arguments.
|
||||||
LVFlags onlyTemplateVisibility() const {
|
LVFlags onlyTemplateVisibility() const {
|
||||||
|
@ -119,10 +128,14 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) {
|
||||||
return LV;
|
return LV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getLVForDecl - Get the linkage and visibility for the given declaration.
|
||||||
|
static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F);
|
||||||
|
|
||||||
/// \brief Get the most restrictive linkage for the types and
|
/// \brief Get the most restrictive linkage for the types and
|
||||||
/// declarations in the given template argument list.
|
/// declarations in the given template argument list.
|
||||||
static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
|
static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
|
||||||
unsigned NumArgs) {
|
unsigned NumArgs,
|
||||||
|
LVFlags &F) {
|
||||||
LVPair LV(ExternalLinkage, DefaultVisibility);
|
LVPair LV(ExternalLinkage, DefaultVisibility);
|
||||||
|
|
||||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||||
|
@ -140,21 +153,24 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
|
||||||
// The decl can validly be null as the representation of nullptr
|
// The decl can validly be null as the representation of nullptr
|
||||||
// arguments, valid only in C++0x.
|
// arguments, valid only in C++0x.
|
||||||
if (Decl *D = Args[I].getAsDecl()) {
|
if (Decl *D = Args[I].getAsDecl()) {
|
||||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||||
LV = merge(LV, ND->getLinkageAndVisibility());
|
LinkageInfo LI = getLVForDecl(ND, F);
|
||||||
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
|
LV = merge(LV, LVPair(LI.linkage(), LI.visibility()));
|
||||||
LV = merge(LV, VD->getLinkageAndVisibility());
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TemplateArgument::Template:
|
case TemplateArgument::Template:
|
||||||
if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
|
if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl()){
|
||||||
LV = merge(LV, Template->getLinkageAndVisibility());
|
LinkageInfo LI = getLVForDecl(Template, F);
|
||||||
|
LV = merge(LV, LVPair(LI.linkage(), LI.visibility()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TemplateArgument::Pack:
|
case TemplateArgument::Pack:
|
||||||
LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
|
LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
|
||||||
Args[I].pack_size()));
|
Args[I].pack_size(),
|
||||||
|
F));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,14 +179,11 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
static LVPair
|
static LVPair
|
||||||
getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) {
|
getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
|
||||||
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size());
|
LVFlags &F) {
|
||||||
|
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getLVForDecl - Get the cached linkage and visibility for the given
|
|
||||||
/// declaration.
|
|
||||||
static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F);
|
|
||||||
|
|
||||||
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
|
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
|
||||||
"Not a name having namespace scope");
|
"Not a name having namespace scope");
|
||||||
|
@ -296,7 +309,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
// is visible, or if the prior declaration specifies no
|
// is visible, or if the prior declaration specifies no
|
||||||
// linkage, then the identifier has external linkage.
|
// linkage, then the identifier has external linkage.
|
||||||
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
|
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
|
||||||
LinkageInfo PrevLV = PrevVar->getLinkageAndVisibility();
|
LinkageInfo PrevLV = getLVForDecl(PrevVar, F);
|
||||||
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
||||||
LV.mergeVisibility(PrevLV);
|
LV.mergeVisibility(PrevLV);
|
||||||
}
|
}
|
||||||
|
@ -331,7 +344,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
// is visible, or if the prior declaration specifies no
|
// is visible, or if the prior declaration specifies no
|
||||||
// linkage, then the identifier has external linkage.
|
// linkage, then the identifier has external linkage.
|
||||||
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
|
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
|
||||||
LinkageInfo PrevLV = PrevFunc->getLinkageAndVisibility();
|
LinkageInfo PrevLV = getLVForDecl(PrevFunc, F);
|
||||||
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
||||||
LV.mergeVisibility(PrevLV);
|
LV.mergeVisibility(PrevLV);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +355,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
LV.merge(getLVForDecl(SpecInfo->getTemplate(),
|
LV.merge(getLVForDecl(SpecInfo->getTemplate(),
|
||||||
F.onlyTemplateVisibility()));
|
F.onlyTemplateVisibility()));
|
||||||
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
|
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
|
||||||
LV.merge(getLVForTemplateArgumentList(TemplateArgs));
|
LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - a named class (Clause 9), or an unnamed class defined in a
|
// - a named class (Clause 9), or an unnamed class defined in a
|
||||||
|
@ -366,7 +379,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
|
|
||||||
// The arguments at which the template was instantiated.
|
// The arguments at which the template was instantiated.
|
||||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||||
LV.merge(getLVForTemplateArgumentList(TemplateArgs));
|
LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider -fvisibility unless the type has C linkage.
|
// Consider -fvisibility unless the type has C linkage.
|
||||||
|
@ -377,8 +390,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
|
||||||
|
|
||||||
// - an enumerator belonging to an enumeration with external linkage;
|
// - an enumerator belonging to an enumeration with external linkage;
|
||||||
} else if (isa<EnumConstantDecl>(D)) {
|
} else if (isa<EnumConstantDecl>(D)) {
|
||||||
LinkageInfo EnumLV =
|
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), F);
|
||||||
cast<NamedDecl>(D->getDeclContext())->getLinkageAndVisibility();
|
|
||||||
if (!isExternalLinkage(EnumLV.linkage()))
|
if (!isExternalLinkage(EnumLV.linkage()))
|
||||||
return LinkageInfo::none();
|
return LinkageInfo::none();
|
||||||
LV.merge(EnumLV);
|
LV.merge(EnumLV);
|
||||||
|
@ -464,7 +476,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
|
||||||
// the template parameters and arguments.
|
// the template parameters and arguments.
|
||||||
if (FunctionTemplateSpecializationInfo *Spec
|
if (FunctionTemplateSpecializationInfo *Spec
|
||||||
= MD->getTemplateSpecializationInfo()) {
|
= MD->getTemplateSpecializationInfo()) {
|
||||||
LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments));
|
LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F));
|
||||||
LV.merge(getLVForTemplateParameterList(
|
LV.merge(getLVForTemplateParameterList(
|
||||||
Spec->getTemplate()->getTemplateParameters()));
|
Spec->getTemplate()->getTemplateParameters()));
|
||||||
|
|
||||||
|
@ -499,7 +511,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
|
||||||
= dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
|
= dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
|
||||||
// Merge template argument/parameter information for member
|
// Merge template argument/parameter information for member
|
||||||
// class template specializations.
|
// class template specializations.
|
||||||
LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs()));
|
LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));
|
||||||
LV.merge(getLVForTemplateParameterList(
|
LV.merge(getLVForTemplateParameterList(
|
||||||
Spec->getSpecializedTemplate()->getTemplateParameters()));
|
Spec->getSpecializedTemplate()->getTemplateParameters()));
|
||||||
}
|
}
|
||||||
|
@ -525,8 +537,27 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
|
||||||
return LV;
|
return LV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Linkage NamedDecl::getLinkage() const {
|
||||||
|
if (HasCachedLinkage) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(CachedLinkage == getLVForDecl(this,
|
||||||
|
LVFlags::CreateOnlyDeclLinkage()).linkage());
|
||||||
|
#endif
|
||||||
|
return Linkage(CachedLinkage);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedLinkage = getLVForDecl(this,
|
||||||
|
LVFlags::CreateOnlyDeclLinkage()).linkage();
|
||||||
|
HasCachedLinkage = 1;
|
||||||
|
return Linkage(CachedLinkage);
|
||||||
|
}
|
||||||
|
|
||||||
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
|
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
|
||||||
return getLVForDecl(this, LVFlags());
|
LinkageInfo LI = getLVForDecl(this, LVFlags());
|
||||||
|
assert(!HasCachedLinkage || (CachedLinkage == LI.linkage()));
|
||||||
|
HasCachedLinkage = 1;
|
||||||
|
CachedLinkage = LI.linkage();
|
||||||
|
return LI;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
|
static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
|
||||||
|
@ -581,11 +612,13 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
|
||||||
return LinkageInfo::uniqueExternal();
|
return LinkageInfo::uniqueExternal();
|
||||||
|
|
||||||
LinkageInfo LV;
|
LinkageInfo LV;
|
||||||
if (const VisibilityAttr *VA = GetExplicitVisibility(Function))
|
if (Flags.ConsiderVisibilityAttributes) {
|
||||||
LV.setVisibility(GetVisibilityFromAttr(VA));
|
if (const VisibilityAttr *VA = GetExplicitVisibility(Function))
|
||||||
|
LV.setVisibility(GetVisibilityFromAttr(VA));
|
||||||
|
}
|
||||||
|
|
||||||
if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
|
if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
|
||||||
LinkageInfo PrevLV = Prev->getLinkageAndVisibility();
|
LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
|
||||||
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
||||||
LV.mergeVisibility(PrevLV);
|
LV.mergeVisibility(PrevLV);
|
||||||
}
|
}
|
||||||
|
@ -602,11 +635,13 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
|
||||||
LinkageInfo LV;
|
LinkageInfo LV;
|
||||||
if (Var->getStorageClass() == SC_PrivateExtern)
|
if (Var->getStorageClass() == SC_PrivateExtern)
|
||||||
LV.setVisibility(HiddenVisibility);
|
LV.setVisibility(HiddenVisibility);
|
||||||
else if (const VisibilityAttr *VA = GetExplicitVisibility(Var))
|
else if (Flags.ConsiderVisibilityAttributes) {
|
||||||
LV.setVisibility(GetVisibilityFromAttr(VA));
|
if (const VisibilityAttr *VA = GetExplicitVisibility(Var))
|
||||||
|
LV.setVisibility(GetVisibilityFromAttr(VA));
|
||||||
|
}
|
||||||
|
|
||||||
if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
|
if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
|
||||||
LinkageInfo PrevLV = Prev->getLinkageAndVisibility();
|
LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
|
||||||
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
|
||||||
LV.mergeVisibility(PrevLV);
|
LV.mergeVisibility(PrevLV);
|
||||||
}
|
}
|
||||||
|
@ -878,6 +913,14 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||||
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
|
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VarDecl::setStorageClass(StorageClass SC) {
|
||||||
|
assert(isLegalForVariable(SC));
|
||||||
|
if (getStorageClass() != SC)
|
||||||
|
ClearLinkageCache();
|
||||||
|
|
||||||
|
SClass = SC;
|
||||||
|
}
|
||||||
|
|
||||||
SourceLocation VarDecl::getInnerLocStart() const {
|
SourceLocation VarDecl::getInnerLocStart() const {
|
||||||
SourceLocation Start = getTypeSpecStartLoc();
|
SourceLocation Start = getTypeSpecStartLoc();
|
||||||
if (Start.isInvalid())
|
if (Start.isInvalid())
|
||||||
|
@ -1277,6 +1320,14 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() {
|
||||||
return getFirstDeclaration();
|
return getFirstDeclaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunctionDecl::setStorageClass(StorageClass SC) {
|
||||||
|
assert(isLegalForFunction(SC));
|
||||||
|
if (getStorageClass() != SC)
|
||||||
|
ClearLinkageCache();
|
||||||
|
|
||||||
|
SClass = SC;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Returns a value indicating whether this function
|
/// \brief Returns a value indicating whether this function
|
||||||
/// corresponds to a builtin function.
|
/// corresponds to a builtin function.
|
||||||
///
|
///
|
||||||
|
@ -1787,6 +1838,7 @@ void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {
|
||||||
TypedefDeclOrQualifier = TDD;
|
TypedefDeclOrQualifier = TDD;
|
||||||
if (TypeForDecl)
|
if (TypeForDecl)
|
||||||
TypeForDecl->ClearLinkageCache();
|
TypeForDecl->ClearLinkageCache();
|
||||||
|
ClearLinkageCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagDecl::startDefinition() {
|
void TagDecl::startDefinition() {
|
||||||
|
|
|
@ -384,7 +384,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||||
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
|
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
|
||||||
// after everything else is read.
|
// after everything else is read.
|
||||||
|
|
||||||
FD->setStorageClass((StorageClass)Record[Idx++]);
|
FD->SClass = (StorageClass)Record[Idx++];
|
||||||
FD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
|
FD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
|
||||||
FD->setInlineSpecified(Record[Idx++]);
|
FD->setInlineSpecified(Record[Idx++]);
|
||||||
FD->setVirtualAsWritten(Record[Idx++]);
|
FD->setVirtualAsWritten(Record[Idx++]);
|
||||||
|
@ -651,7 +651,7 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
|
||||||
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
|
void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
|
||||||
VisitDeclaratorDecl(VD);
|
VisitDeclaratorDecl(VD);
|
||||||
VisitRedeclarable(VD);
|
VisitRedeclarable(VD);
|
||||||
VD->setStorageClass((StorageClass)Record[Idx++]);
|
VD->SClass = (StorageClass)Record[Idx++];
|
||||||
VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
|
VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
|
||||||
VD->setThreadSpecified(Record[Idx++]);
|
VD->setThreadSpecified(Record[Idx++]);
|
||||||
VD->setCXXDirectInitializer(Record[Idx++]);
|
VD->setCXXDirectInitializer(Record[Idx++]);
|
||||||
|
|
Loading…
Reference in New Issue