Handle temporaries in default arguments.

llvm-svn: 73462
This commit is contained in:
Anders Carlsson 2009-06-16 03:37:31 +00:00
parent 14491abe48
commit a42ab8f3d5
9 changed files with 59 additions and 17 deletions

View File

@ -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); }

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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

View File

@ -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();
}