forked from OSchip/llvm-project
Introduce reference counting for statements and expressions, using it
to allow sharing of nodes. Simplifies some aspects of template instantiation, and fixes both PR3444 and <rdar://problem/6757457>. llvm-svn: 78450
This commit is contained in:
parent
b94284b5e2
commit
2c742024ff
|
@ -67,6 +67,15 @@ protected:
|
|||
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
|
||||
|
||||
public:
|
||||
/// \brief Increases the reference count for this expression.
|
||||
///
|
||||
/// Invoke the Retain() operation when this expression
|
||||
/// is being shared by another owner.
|
||||
Expr *Retain() {
|
||||
Stmt::Retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
QualType getType() const { return TR; }
|
||||
void setType(QualType t) {
|
||||
// In C++, the type of an expression is always adjusted so that it
|
||||
|
|
|
@ -105,7 +105,11 @@ public:
|
|||
#include "clang/AST/StmtNodes.def"
|
||||
};
|
||||
private:
|
||||
const StmtClass sClass;
|
||||
/// \brief The statement class.
|
||||
const unsigned sClass : 8;
|
||||
|
||||
/// \brief The reference count for this statement.
|
||||
unsigned RefCount : 24;
|
||||
|
||||
// Make vanilla 'new' and 'delete' illegal for Stmts.
|
||||
protected:
|
||||
|
@ -151,7 +155,7 @@ protected:
|
|||
void DestroyChildren(ASTContext& Ctx);
|
||||
|
||||
/// \brief Construct an empty statement.
|
||||
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) {
|
||||
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
|
||||
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
|
||||
}
|
||||
|
||||
|
@ -163,15 +167,27 @@ protected:
|
|||
virtual void DoDestroy(ASTContext &Ctx);
|
||||
|
||||
public:
|
||||
Stmt(StmtClass SC) : sClass(SC) {
|
||||
Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
|
||||
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
|
||||
}
|
||||
virtual ~Stmt() {}
|
||||
|
||||
/// \brief Destroy the current statement and its children.
|
||||
void Destroy(ASTContext &Ctx) { DoDestroy(Ctx); }
|
||||
void Destroy(ASTContext &Ctx) {
|
||||
if (--RefCount == 0)
|
||||
DoDestroy(Ctx);
|
||||
}
|
||||
|
||||
StmtClass getStmtClass() const { return sClass; }
|
||||
/// \brief Increases the reference count for this statement.
|
||||
///
|
||||
/// Invoke the Retain() operation when this statement or expression
|
||||
/// is being shared by another owner.
|
||||
Stmt *Retain() {
|
||||
++RefCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
StmtClass getStmtClass() const { return (StmtClass)sClass; }
|
||||
const char *getStmtClassName() const;
|
||||
|
||||
/// SourceLocation tokens are not useful in isolation - they are low level
|
||||
|
@ -643,6 +659,10 @@ class SwitchStmt : public Stmt {
|
|||
// This points to a linked list of case and default statements.
|
||||
SwitchCase *FirstCase;
|
||||
SourceLocation SwitchLoc;
|
||||
|
||||
protected:
|
||||
virtual void DoDestroy(ASTContext &Ctx);
|
||||
|
||||
public:
|
||||
SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
|
||||
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
|
||||
|
@ -661,6 +681,11 @@ public:
|
|||
Stmt *getBody() { return SubExprs[BODY]; }
|
||||
void setBody(Stmt *S) { SubExprs[BODY] = S; }
|
||||
SwitchCase *getSwitchCaseList() { return FirstCase; }
|
||||
|
||||
/// \brief Set the case list for this switch statement.
|
||||
///
|
||||
/// The caller is responsible for incrementing the retain counts on
|
||||
/// all of the SwitchCase statements in this list.
|
||||
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
|
||||
|
||||
SourceLocation getSwitchLoc() const { return SwitchLoc; }
|
||||
|
@ -672,6 +697,7 @@ public:
|
|||
}
|
||||
void addSwitchCase(SwitchCase *SC) {
|
||||
assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
|
||||
SC->Retain();
|
||||
SC->setNextSwitchCase(FirstCase);
|
||||
FirstCase = SC;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
|
|||
}
|
||||
|
||||
const char *Stmt::getStmtClassName() const {
|
||||
return getStmtInfoTableEntry(sClass).Name;
|
||||
return getStmtInfoTableEntry((StmtClass)sClass).Name;
|
||||
}
|
||||
|
||||
void Stmt::DestroyChildren(ASTContext &C) {
|
||||
|
@ -104,6 +104,20 @@ BreakStmt* BreakStmt::Clone(ASTContext &C) const {
|
|||
return new (C) BreakStmt(BreakLoc);
|
||||
}
|
||||
|
||||
void SwitchStmt::DoDestroy(ASTContext &Ctx) {
|
||||
// Destroy the SwitchCase statements in this switch. In the normal
|
||||
// case, this loop will merely decrement the reference counts from
|
||||
// the Retain() calls in addSwitchCase();
|
||||
SwitchCase *SC = FirstCase;
|
||||
while (SC) {
|
||||
SwitchCase *Next = SC->getNextSwitchCase();
|
||||
SC->Destroy(Ctx);
|
||||
SC = Next;
|
||||
}
|
||||
|
||||
Stmt::DoDestroy(Ctx);
|
||||
}
|
||||
|
||||
void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
|
||||
if (this->Body)
|
||||
C.Deallocate(Body);
|
||||
|
|
|
@ -194,6 +194,10 @@ unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
|
|||
PrevSC->setNextSwitchCase(SC);
|
||||
else
|
||||
S->setSwitchCaseList(SC);
|
||||
|
||||
// Retain this SwitchCase, since SwitchStmt::addSwitchCase() would
|
||||
// normally retain it (but we aren't calling addSwitchCase).
|
||||
SC->Retain();
|
||||
PrevSC = SC;
|
||||
}
|
||||
return 2;
|
||||
|
|
|
@ -2821,14 +2821,6 @@ public:
|
|||
|
||||
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
|
||||
|
||||
// Simple function for cloning expressions.
|
||||
template<typename T>
|
||||
OwningExprResult Clone(T *E) {
|
||||
assert(!E->isValueDependent() && !E->isTypeDependent() &&
|
||||
"expression is value or type dependent!");
|
||||
return Owned(E->Clone(Context));
|
||||
}
|
||||
|
||||
// Objective-C declarations.
|
||||
virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
|
|
|
@ -222,7 +222,8 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
|||
if (InstantiatedAssertExpr.isInvalid())
|
||||
return 0;
|
||||
|
||||
OwningExprResult Message = SemaRef.Clone(D->getMessage());
|
||||
OwningExprResult Message(SemaRef, D->getMessage());
|
||||
D->getMessage()->Retain();
|
||||
Decl *StaticAssert
|
||||
= SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
|
||||
move(InstantiatedAssertExpr),
|
||||
|
|
|
@ -57,53 +57,53 @@ Sema::OwningExprResult TemplateExprInstantiator::VisitExpr(Expr *E) {
|
|||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitPredefinedExpr(PredefinedExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitFloatingLiteral(FloatingLiteral *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitStringLiteral(StringLiteral *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCharacterLiteral(CharacterLiteral *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitImaginaryLiteral(ImaginaryLiteral *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitGNUNullExpr(GNUNullExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
|
||||
UnresolvedFunctionNameExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -706,7 +706,8 @@ TemplateExprInstantiator::VisitImplicitValueInitExpr(
|
|||
ImplicitValueInitExpr *E) {
|
||||
assert(!E->isTypeDependent() && !E->isValueDependent() &&
|
||||
"ImplicitValueInitExprs are never dependent");
|
||||
return SemaRef.Clone(E);
|
||||
E->Retain();
|
||||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -1110,7 +1111,7 @@ TemplateExprInstantiator::VisitCXXFunctionalCastExpr(
|
|||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
|
||||
return SemaRef.Clone(E);
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -1289,7 +1290,7 @@ TemplateExprInstantiator::VisitCXXUnresolvedMemberExpr(
|
|||
//----------------------------------------------------------------------------
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCStringLiteral(ObjCStringLiteral *E) {
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -1314,12 +1315,12 @@ TemplateExprInstantiator::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
|||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
return SemaRef.Owned(E->Retain());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
|
Loading…
Reference in New Issue