When variadic return stmt doesn't have a return value, invalidate the calculation of the last expr for evaluation.

In the same cases we still need to synthesize the setValueNoAlloc, to initialize
the cling::Value to void.
This commit is contained in:
Vassil Vassilev 2014-04-03 15:27:12 +02:00 committed by sftnight
parent 529088b816
commit d1a416ddc0
2 changed files with 34 additions and 22 deletions

View File

@ -87,16 +87,29 @@ namespace cling {
I != E; ++I) {
ReturnStmt* RS = dyn_cast<ReturnStmt>(**I);
if (RS) {
if (Expr* RetV = RS->getRetValue()) {
assert (RetV->getType()->isVoidType() && "Must be void type.");
// When we are handling a return stmt, the last expression must be the
// return stmt value. Ignore the calculation of the lastStmt because it
// might be wrong, in cases where the return is not in the end of the
// function.
lastExpr = RS->getRetValue();
if (lastExpr) {
assert (lastExpr->getType()->isVoidType() && "Must be void type.");
// Any return statement will have been "healed" by Sema
// to correspond to the original void return type of the
// wrapper, using a ImplicitCastExpr 'void' <ToVoid>.
// Remove that.
if (ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RetV)) {
if (ImplicitCastExpr* VoidCast
= dyn_cast<ImplicitCastExpr>(lastExpr)) {
lastExpr = VoidCast->getSubExpr();
}
}
// if no value assume void
else {
// We can't PushDeclContext, because we don't have scope.
Sema::ContextRAII pushedDC(*m_Sema, FD);
RS->setRetValue(SynthesizeSVRInit(0));
}
}
else
lastExpr = cast<Expr>(**I);
@ -151,11 +164,8 @@ namespace cling {
// if we had return stmt update to execute the SVR init, even if the
// wrapper returns void.
if (RS) {
Expr* retValue = RS->getRetValue();
if (!retValue)
RS->setRetValue(SVRInit);
else if (ImplicitCastExpr* VoidCast
= dyn_cast<ImplicitCastExpr>(retValue))
if (ImplicitCastExpr* VoidCast
= dyn_cast<ImplicitCastExpr>(RS->getRetValue()))
VoidCast->setSubExpr(SVRInit);
}
else
@ -174,10 +184,12 @@ namespace cling {
// Build a reference to Value* in the wrapper, should be
// the only argument of the wrapper.
SourceLocation locStart = (E) ? E->getLocStart() : FD->getLocStart();
SourceLocation locEnd = (E) ? E->getLocEnd() : FD->getLocEnd();
ExprResult wrapperSVRDRE
= m_Sema->BuildDeclRefExpr(FD->getParamDecl(0), m_Context->VoidPtrTy,
VK_RValue, E->getLocStart());
QualType ETy = E->getType();
VK_RValue, locStart);
QualType ETy = (E) ? E->getType() : m_Context->VoidTy;
QualType desugaredTy = ETy.getDesugaredType(*m_Context);
// The expr result is transported as reference, pointer, array, float etc
@ -206,18 +218,16 @@ namespace cling {
// We need to synthesize setValueNoAlloc(...), E, because we still need
// to run E.
Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc,
E->getLocStart(), CallArgs,
E->getLocEnd());
Call = m_Sema->CreateBuiltinBinOp(Call.get()->getLocStart(), BO_Comma,
Call.take(), E);
locStart, CallArgs, locEnd);
if (E)
Call = m_Sema->CreateBuiltinBinOp(locStart, BO_Comma, Call.take(), E);
}
else if (desugaredTy->isRecordType() || desugaredTy->isConstantArrayType()){
// 2) object types :
// call new (setValueWithAlloc(gCling, &SVR, ETy)) (E)
Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedWithAlloc,
E->getLocStart(), CallArgs,
E->getLocEnd());
locStart, CallArgs, locEnd);
Expr* placement = Call.take();
if (const ConstantArrayType* constArray
= dyn_cast<ConstantArrayType>(desugaredTy.getTypePtr())) {
@ -233,8 +243,7 @@ namespace cling {
// 2.1) arrays:
// call copyArray(T* src, void* placement, int size)
Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedCopyArray,
E->getLocStart(), CallArgs,
E->getLocEnd());
locStart, CallArgs, locEnd);
}
else {
@ -296,8 +305,7 @@ namespace cling {
CallArgs.push_back(E);
}
Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc,
E->getLocStart(), CallArgs,
E->getLocEnd());
locStart, CallArgs, locEnd);
}
else
assert(0 && "Unhandled code path?");

View File

@ -23,9 +23,13 @@ V // CHECK-NEXT: (cling::Value) boxes [(void) @0x{{.*}}]
// Returns must put the result in the Value.
bool cond = true;
gCling->evaluate("if (cond) return \"true\"; else return 0;", V);
V // CHECK: (cling::Value) boxes [(const char [5]) "true"]
V // CHECK-NEXT: (cling::Value) boxes [(const char [5]) "true"]
gCling->evaluate("if (cond) return; else return 12;", V);
V // CHECK-NEXT: (cling::Value) boxes [(void) @0x{{.*}}]
gCling->evaluate("if (cond) return; int aa = 12;", V);
V // CHECK-NEXT: (cling::Value) boxes [(void) @0x{{.*}}]
gCling->evaluate("cond = false; if (cond) return \"true\"; else return 0;", V);
V // CHECK: (cling::Value) boxes [(int) 0]
V // CHECK-NEXT: (cling::Value) boxes [(int) 0]
gCling->evaluate("auto a = 12.3; a;", V);
V // CHECK: (cling::Value) boxes [(double) 1.230000e+01]