Skip to content
Snippets Groups Projects
Commit 580ac1fe authored by Vassil Vassilev's avatar Vassil Vassilev
Browse files

Fix the issue with the temporary variable lifetime reported in PR#93006

The issue is as follows:
If one omits the ; of a given statement at the prompt we attach in the AST a 
templated function which prints out the value. The function looks like for 
int p = 12
PrintValue((llvm::raw_ostream *)22345600UL, (clang::Expr *)23270416UL, (clang::ASTContext *)22594960UL, p);

We manually get the expression and put it as a last argument of the PrintValue
That is safe when we have storage of p. I.e p is an lvalue.

However we might have: gCling->createUniqueName(), which returns std::string
That is an rvalue, which doesn't have storage and its lifetime lasts until the
end of the current statement. However if we attach it to the PrintValue we have
to extend the lifetime of the argument to last until the new end of statement.
Otherwise the argument will be destroyed before we manage to print it out.
What we do in that case is move the expression annotating the termination of the
temporary up as root expression of PrintValue call.

Attach a regression test for the reported problem


git-svn-id: http://root.cern.ch/svn/root/trunk@43526 27541ba8-7e3a-0410-8455-c3a389f83636
parent bed520a5
No related branches found
No related tags found
Loading
......@@ -13,6 +13,7 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
......@@ -129,6 +130,18 @@ namespace cling {
ASTContextRDTy,
(uint64_t)m_Context);
// E might contain temporaries. This means that the topmost expr is
// ExprWithCleanups. This contains the information about the temporaries and
// signals when they should be destroyed.
// Here we replace E with call to value printer and we must extend the life
// time of those temporaries to the end of the new CallExpr.
bool NeedsCleanup = false;
if (ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(E)) {
E = EWC->getSubExpr();
NeedsCleanup = true;
}
ASTOwningVector<Expr*> CallArgs(*m_Sema);
CallArgs.push_back(RawOStreamTy);
CallArgs.push_back(ExprTy);
......@@ -138,6 +151,15 @@ namespace cling {
Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
Expr* Result = m_Sema->ActOnCallExpr(S, UnresolvedLookup, NoSLoc,
move_arg(CallArgs), NoSLoc).take();
Result = m_Sema->ActOnFinishFullExpr(Result).take();
if (NeedsCleanup && !isa<ExprWithCleanups>(Result)) {
llvm::ArrayRef<ExprWithCleanups::CleanupObject> Cleanups;
ExprWithCleanups* EWC
= ExprWithCleanups::Create(*m_Context, Result, Cleanups);
Result = EWC;
}
assert(Result && "Cannot create value printer!");
return Result;
......
// RUN: cat %s | %cling | FileCheck %s
// This file should be used as regression test for the value printing subsystem
// Reproducers of fixed bugs should be put here
// PR #93006
.rawInput 1
extern "C" int printf(const char* fmt, ...);
class A {
public:
int Var;
A(int arg) { Var = arg; }
~A() { printf("A d'tor\n"); }
};
const A& foo(const A& arg) { return arg; }
.rawInput 0
foo(A(12)).Var
// CHECK: (const int) 12
// CHECK: A d'tor
// End PR #93006
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment