From: Douglas Gregor Date: Sat, 8 Aug 2009 01:41:12 +0000 (+0000) Subject: Introduce reference counting for statements and expressions, using it X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43d9d9243329b1b75d1a6efdad9f16d6fb386b8e;p=clang 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78450 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index fed58ba22b..d4b622ed04 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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 diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 239c6b5f43..5a4c93d695 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -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(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; } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 668f7ef57f..a0ef5a6428 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -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); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 6b97e610f5..3040a52260 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -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; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6094e6dae0..295607b739 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2821,14 +2821,6 @@ public: NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D); - // Simple function for cloning expressions. - template - 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, diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 021a6ad2ab..1c98fca6af 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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), diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 2e7ed1a632..1e97f5fcc4 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -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