aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-06-16 03:37:31 +0000
committerAnders Carlsson <andersca@mac.com>2009-06-16 03:37:31 +0000
commitf54741e6465692d3bdbae974ac3beeeab92e4a95 (patch)
tree1b7100f044e74fc9da1164e514b784b5285b5850
parent76e4ce42a30cee4dc40ce7c6014874fbc4f9baa7 (diff)
Handle temporaries in default arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73462 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ExprCXX.h11
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/CodeGen/CGCXXTemp.cpp5
-rw-r--r--lib/Sema/Sema.h4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp15
-rw-r--r--lib/Sema/SemaExprCXX.cpp7
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp5
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp15
9 files changed, 59 insertions, 17 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index e44ccca0bd..f9f5da1291 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1023,17 +1023,16 @@ class CXXExprWithTemporaries : public Expr {
CXXTemporary **Temps;
unsigned NumTemps;
- bool DestroyTemps;
+ bool ShouldDestroyTemps;
CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
- unsigned NumTemps, bool DestroyTemps);
+ unsigned NumTemps, bool ShouldDestroyTemps);
~CXXExprWithTemporaries();
public:
static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
- CXXTemporary **Temps,
- unsigned NumTemps,
- bool DestroyTems);
+ CXXTemporary **Temps, unsigned NumTemps,
+ bool ShouldDestroyTemporaries);
void Destroy(ASTContext &C);
unsigned getNumTemporaries() const { return NumTemps; }
@@ -1046,6 +1045,8 @@ public:
return Temps[i];
}
+ bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; }
+
void removeLastTemporary() { NumTemps--; }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 8fd66a2981..18c0f77ab2 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -306,10 +306,11 @@ void CXXConstructExpr::Destroy(ASTContext &C) {
CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXTemporary **temps,
unsigned numtemps,
- bool destroytemps)
+ bool shoulddestroytemps)
: Expr(CXXExprWithTemporariesClass, subexpr->getType(),
subexpr->isTypeDependent(), subexpr->isValueDependent()),
- SubExpr(subexpr), Temps(0), NumTemps(numtemps), DestroyTemps(destroytemps) {
+ SubExpr(subexpr), Temps(0), NumTemps(numtemps),
+ ShouldDestroyTemps(shoulddestroytemps) {
if (NumTemps > 0) {
Temps = new CXXTemporary*[NumTemps];
for (unsigned i = 0; i < NumTemps; ++i)
@@ -321,9 +322,9 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps){
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps,
- DestroyTemps);
+ ShouldDestroyTemps);
}
void CXXExprWithTemporaries::Destroy(ASTContext &C) {
diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp
index 141726a649..a6e6d11505 100644
--- a/lib/CodeGen/CGCXXTemp.cpp
+++ b/lib/CodeGen/CGCXXTemp.cpp
@@ -85,6 +85,11 @@ RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool isAggLocVolatile) {
+ // If we shouldn't destroy the temporaries, just emit the
+ // child expression.
+ if (!E->shouldDestroyTemporaries())
+ return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
+
// Keep track of the current cleanup stack depth.
size_t CleanupStackDepth = CleanupEntries.size();
(void) CleanupStackDepth;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 34513e7d58..28fb918fef 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1661,8 +1661,8 @@ public:
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
- Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps = true);
+ Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
+ bool ShouldDestroyTemporaries);
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8f64e78c52..70057a34df 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -147,8 +147,11 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
return;
}
+ DefaultArgPtr = MaybeCreateCXXExprWithTemporaries(DefaultArg.take(),
+ /*DestroyTemps=*/false);
+
// Okay: add the default argument to the parameter
- Param->setDefaultArg(DefaultArg.take());
+ Param->setDefaultArg(DefaultArgPtr);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c01c812be6..c0469416e4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2491,8 +2491,21 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)],
diag::note_default_argument_declared_here);
+ } else {
+ Expr *DefaultExpr = FDecl->getParamDecl(i)->getDefaultArg();
+
+ // If the default expression creates temporaries, we need to
+ // push them to the current stack of expression temporaries so they'll
+ // be properly destroyed.
+ if (CXXExprWithTemporaries *E
+ = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) {
+ assert(!E->shouldDestroyTemporaries() &&
+ "Can't destroy temporaries in a default argument expr!");
+ for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I)
+ ExprTemporaries.push_back(E->getTemporary(I));
+ }
}
-
+
// We already type-checked the argument, so we know it works.
Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i));
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ed4ac555ad..7353efbae7 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1589,7 +1589,7 @@ Expr *Sema::RemoveOutermostTemporaryBinding(Expr *E) {
}
Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps) {
assert(SubExpr && "sub expression can't be null!");
if (ExprTemporaries.empty())
@@ -1598,7 +1598,7 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr,
&ExprTemporaries[0],
ExprTemporaries.size(),
- DestroyTemps);
+ ShouldDestroyTemps);
ExprTemporaries.clear();
return E;
@@ -1607,7 +1607,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)
- FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
+ FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr,
+ /*ShouldDestroyTemps=*/true);
return Owned(FullExpr);
}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 3c67f2ad0d..bf19701d6b 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -1165,7 +1165,10 @@ TemplateExprInstantiator::VisitCXXExprWithTemporaries(
if (SubExpr.isInvalid())
return SemaRef.ExprError();
- return SemaRef.ActOnFinishFullExpr(move(SubExpr));
+ Expr *Temp =
+ SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
+ E->shouldDestroyTemporaries());
+ return SemaRef.Owned(Temp);
}
Sema::OwningExprResult
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
new file mode 100644
index 0000000000..2dcf773346
--- /dev/null
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 &&
+
+struct T {
+ T();
+ ~T();
+};
+
+void f(const T& t = T());
+
+void g() {
+ // RUN: grep "call void @_ZN1TC1Ev" %t | count 2 &&
+ // RUN: grep "call void @_ZN1TD1Ev" %t | count 2
+ f();
+ f();
+}