aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-08-08 01:41:12 +0000
committerDouglas Gregor <dgregor@apple.com>2009-08-08 01:41:12 +0000
commit43d9d9243329b1b75d1a6efdad9f16d6fb386b8e (patch)
treed788e8c42f7e7838e8a707e93e0bbb307197f9a7
parent80e4b9e0e87064a824d72b6ff89074206ecced58 (diff)
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>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78450 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h9
-rw-r--r--include/clang/AST/Stmt.h36
-rw-r--r--lib/AST/Stmt.cpp16
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp4
-rw-r--r--lib/Sema/Sema.h8
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp31
7 files changed, 77 insertions, 30 deletions
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<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;
}
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<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,
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