parent
14491abe48
commit
a42ab8f3d5
|
@ -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); }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue