mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Remove mutable data on TagType and InjectedClassNameType, by instead walking the declaration chain in search of a definition. This is necessary for a sane chained PCH implementation. No observable performance change on Carbon.h syntax-only, and bootstraps cleanly.
llvm-svn: 110051
This commit is contained in:
parent
9c6a39e862
commit
9d8854ec60
@ -1814,6 +1814,9 @@ private:
|
||||
/// it is a declaration ("struct foo;").
|
||||
bool IsDefinition : 1;
|
||||
|
||||
/// IsBeingDefined - True if this is currently being defined.
|
||||
bool IsBeingDefined : 1;
|
||||
|
||||
/// IsEmbeddedInDeclarator - True if this tag declaration is
|
||||
/// "embedded" (i.e., defined or declared for the very first time)
|
||||
/// in the syntax of a declarator.
|
||||
@ -1855,6 +1858,7 @@ protected:
|
||||
"EnumDecl not matched with TTK_Enum");
|
||||
TagDeclKind = TK;
|
||||
IsDefinition = false;
|
||||
IsBeingDefined = false;
|
||||
IsEmbeddedInDeclarator = false;
|
||||
setPreviousDeclaration(PrevDecl);
|
||||
}
|
||||
@ -1896,6 +1900,11 @@ public:
|
||||
return IsDefinition;
|
||||
}
|
||||
|
||||
/// isBeingDefined - Return true if this decl is currently being defined.
|
||||
bool isBeingDefined() const {
|
||||
return IsBeingDefined;
|
||||
}
|
||||
|
||||
bool isEmbeddedInDeclarator() const {
|
||||
return IsEmbeddedInDeclarator;
|
||||
}
|
||||
|
@ -2267,14 +2267,9 @@ public:
|
||||
};
|
||||
|
||||
class TagType : public Type {
|
||||
/// Stores the TagDecl associated with this type. The decl will
|
||||
/// point to the TagDecl that actually defines the entity (or is a
|
||||
/// definition in progress), if there is such a definition. The
|
||||
/// single-bit value will be non-zero when this tag is in the
|
||||
/// process of being defined.
|
||||
mutable llvm::PointerIntPair<TagDecl *, 1> decl;
|
||||
friend class ASTContext;
|
||||
friend class TagDecl;
|
||||
/// Stores the TagDecl associated with this type. The decl may point to any
|
||||
/// TagDecl that declares the entity.
|
||||
TagDecl * decl;
|
||||
|
||||
protected:
|
||||
TagType(TypeClass TC, const TagDecl *D, QualType can);
|
||||
@ -2282,12 +2277,11 @@ protected:
|
||||
virtual Linkage getLinkageImpl() const;
|
||||
|
||||
public:
|
||||
TagDecl *getDecl() const { return decl.getPointer(); }
|
||||
TagDecl *getDecl() const;
|
||||
|
||||
/// @brief Determines whether this type is in the process of being
|
||||
/// defined.
|
||||
bool isBeingDefined() const { return decl.getInt(); }
|
||||
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
|
||||
bool isBeingDefined() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
|
||||
@ -2580,7 +2574,6 @@ class InjectedClassNameType : public Type {
|
||||
QualType InjectedType;
|
||||
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
friend class TagDecl; // TagDecl mutilates the Decl
|
||||
friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not
|
||||
// currently suitable for PCH reading, too much
|
||||
// interdependencies.
|
||||
@ -2598,7 +2591,7 @@ public:
|
||||
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
|
||||
}
|
||||
|
||||
CXXRecordDecl *getDecl() const { return Decl; }
|
||||
CXXRecordDecl *getDecl() const;
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
@ -1534,14 +1534,7 @@ void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {
|
||||
}
|
||||
|
||||
void TagDecl::startDefinition() {
|
||||
if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
|
||||
TagT->decl.setPointer(this);
|
||||
TagT->decl.setInt(1);
|
||||
} else if (InjectedClassNameType *Injected
|
||||
= const_cast<InjectedClassNameType *>(
|
||||
TypeForDecl->getAs<InjectedClassNameType>())) {
|
||||
Injected->Decl = cast<CXXRecordDecl>(this);
|
||||
}
|
||||
IsBeingDefined = true;
|
||||
|
||||
if (isa<CXXRecordDecl>(this)) {
|
||||
CXXRecordDecl *D = cast<CXXRecordDecl>(this);
|
||||
@ -1558,17 +1551,7 @@ void TagDecl::completeDefinition() {
|
||||
"definition completed but not started");
|
||||
|
||||
IsDefinition = true;
|
||||
if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
|
||||
assert(TagT->decl.getPointer() == this &&
|
||||
"Attempt to redefine a tag definition?");
|
||||
TagT->decl.setInt(0);
|
||||
} else if (InjectedClassNameType *Injected
|
||||
= const_cast<InjectedClassNameType *>(
|
||||
TypeForDecl->getAs<InjectedClassNameType>())) {
|
||||
assert(Injected->Decl == this &&
|
||||
"Attempt to redefine a class template definition?");
|
||||
(void)Injected;
|
||||
}
|
||||
IsBeingDefined = false;
|
||||
}
|
||||
|
||||
TagDecl* TagDecl::getDefinition() const {
|
||||
|
@ -1072,7 +1072,30 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
|
||||
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
|
||||
: Type(TC, can, D->isDependentType()),
|
||||
decl(const_cast<TagDecl*>(D), 0) {}
|
||||
decl(const_cast<TagDecl*>(D)) {}
|
||||
|
||||
static TagDecl *getInterestingTagDecl(TagDecl *decl) {
|
||||
for (TagDecl::redecl_iterator I = decl->redecls_begin(),
|
||||
E = decl->redecls_end();
|
||||
I != E; ++I) {
|
||||
if (I->isDefinition() || I->isBeingDefined())
|
||||
return *I;
|
||||
}
|
||||
// If there's no definition (not even in progress), return what we have.
|
||||
return decl;
|
||||
}
|
||||
|
||||
TagDecl *TagType::getDecl() const {
|
||||
return getInterestingTagDecl(decl);
|
||||
}
|
||||
|
||||
bool TagType::isBeingDefined() const {
|
||||
return getDecl()->isBeingDefined();
|
||||
}
|
||||
|
||||
CXXRecordDecl *InjectedClassNameType::getDecl() const {
|
||||
return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
|
||||
}
|
||||
|
||||
bool RecordType::classof(const TagType *TT) {
|
||||
return isa<RecordDecl>(TT->getDecl());
|
||||
|
Loading…
Reference in New Issue
Block a user