Properly handle temporaries that are created in a AsmStmt.

Previously the temporaries would get destroyed before the asm call.

llvm-svn: 118001
This commit is contained in:
Argyrios Kyrtzidis 2010-11-02 02:33:08 +00:00
parent 315d2cab27
commit 3050d9bdb8
5 changed files with 43 additions and 14 deletions

View File

@ -2342,10 +2342,12 @@ public:
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
Stmt *MaybeCreateCXXStmtWithTemporaries(Stmt *SubStmt);
ExprResult MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr);
FullExpr CreateFullExpr(Expr *SubExpr);
ExprResult ActOnFinishFullExpr(Expr *Expr);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);

View File

@ -188,6 +188,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
<< Attr.Range;
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
Res = Actions.ActOnFinishFullStmt(Res.get());
if (msAsm) return move(Res);
SemiError = "asm";
break;
@ -1458,7 +1459,6 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
SkipUntil(tok::r_paren);
return true;
}
Res = Actions.MakeFullExpr(Res.get()).release();
Exprs.push_back(Res.release());
// Eat the comma and continue parsing if it exists.
if (Tok.isNot(tok::comma)) return false;

View File

@ -3016,6 +3016,26 @@ FullExpr Sema::CreateFullExpr(Expr *SubExpr) {
return E;
}
Stmt *Sema::MaybeCreateCXXStmtWithTemporaries(Stmt *SubStmt) {
assert(SubStmt && "sub statement can't be null!");
unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
assert(ExprTemporaries.size() >= FirstTemporary);
if (ExprTemporaries.size() == FirstTemporary)
return SubStmt;
// FIXME: In order to attach the temporaries, wrap the statement into
// a StmtExpr; currently this is only used for asm statements.
// This is hacky, either create a new CXXStmtWithTemporaries statement or
// a new AsmStmtWithTemporaries.
CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1,
SourceLocation(),
SourceLocation());
Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
SourceLocation());
return MaybeCreateCXXExprWithTemporaries(E);
}
ExprResult
Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, ParsedType &ObjectType,
@ -3398,3 +3418,9 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
CheckImplicitConversions(FullExpr);
return MaybeCreateCXXExprWithTemporaries(FullExpr);
}
StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
if (!FullStmt) return StmtError();
return MaybeCreateCXXStmtWithTemporaries(FullStmt);
}

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s
struct A
{
~A();
};
int foo(A);
void bar(A &a)
{
// CHECK: call void asm
asm("" : : "r"(foo(a)) ); // rdar://8540491
// CHECK: call void @_ZN1AD1Ev
}

View File

@ -1,13 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct A
{
~A();
};
int foo(A);
void bar()
{
A a;
asm("" : : "r"(foo(a)) ); // rdar://8540491
}