Skip to content

Commit

Permalink
[cling] Create new CompoundStmt instead of replacing children
Browse files Browse the repository at this point in the history
For the update of LLVM 9, Cling required another patch to Clang for
replacing the children of a CompoundStmt. Instead solve this by
creating a new CompoundStmt with the right Stmts attached.

Co-authored-by: Jonas Hahnfeld <[email protected]>
Co-authored-by: Jonas Hahnfeld <[email protected]>
  • Loading branch information
3 people committed Apr 23, 2021
1 parent f5b4562 commit 34590ae
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 34 deletions.
41 changes: 28 additions & 13 deletions interpreter/cling/lib/Interpreter/AutoSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ namespace cling {
public:
AutoFixer(Sema* S) : m_Sema(S), m_FoundDRE(0) {}

void Fix(CompoundStmt* CS) {
CompoundStmt* Fix(CompoundStmt* CS) {
if (!CS->size())
return;
return nullptr;
typedef llvm::SmallVector<Stmt*, 32> Statements;
Statements Stmts;
Stmts.append(CS->body_begin(), CS->body_end());
Expand All @@ -44,18 +44,30 @@ namespace cling {
}
}
if (CS->size() != Stmts.size())
CS->replaceStmts(m_Sema->getASTContext(), Stmts);
return CompoundStmt::Create(m_Sema->getASTContext(), Stmts,
CS->getLBracLoc(), CS->getRBracLoc());
return nullptr;
}

void Fix(CXXTryStmt* TS) {
Fix(TS->getTryBlock());
for(unsigned int h = 0; h < TS->getNumHandlers(); ++h) {
Stmt *s = TS->getHandler(h)->getHandlerBlock();
if (CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(s))
Fix(CS);
else if (CXXTryStmt *HandlerTS = dyn_cast_or_null<CXXTryStmt>(s))
Fix(HandlerTS);
CXXTryStmt* Fix(CXXTryStmt* TS) {
CompoundStmt *TryBlock = TS->getTryBlock();
if (CompoundStmt *NewTryBlock = Fix(TryBlock))
TryBlock = NewTryBlock;

llvm::SmallVector<Stmt*, 4> Handlers(TS->getNumHandlers());
for (unsigned int h = 0; h < TS->getNumHandlers(); ++h) {
Stmt *HandlerBlock = TS->getHandler(h)->getHandlerBlock();
if (CompoundStmt *HandlerCS = dyn_cast_or_null<CompoundStmt>(HandlerBlock)) {
if (CompoundStmt *NewHandlerCS = Fix(HandlerCS))
HandlerBlock = NewHandlerCS;
} else if (CXXTryStmt *HandlerTS = dyn_cast_or_null<CXXTryStmt>(HandlerBlock)) {
if (CXXTryStmt *NewHandlerTS = Fix(HandlerTS))
HandlerBlock = NewHandlerTS;
}
}

return CXXTryStmt::Create(m_Sema->getASTContext(), TS->getTryLoc(),
TryBlock, Handlers);
}

bool VisitDeclRefExpr(DeclRefExpr* DRE) {
Expand Down Expand Up @@ -92,9 +104,12 @@ namespace cling {
// those.
Stmt *Body = FD->getBody();
if (CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(Body))
m_AutoFixer->Fix(CS);
Body = m_AutoFixer->Fix(CS);
else if (CXXTryStmt *TS = dyn_cast_or_null<CXXTryStmt>(Body))
m_AutoFixer->Fix(TS);
Body = m_AutoFixer->Fix(TS);

if (Body != nullptr)
FD->setBody(Body);
}
return Result(D, true);
}
Expand Down
5 changes: 4 additions & 1 deletion interpreter/cling/lib/Interpreter/DeclExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ namespace cling {
}
}

CS->replaceStmts(*m_Context, Stmts);
// Create a new body.
auto newCS = CompoundStmt::Create(*m_Context, Stmts, CS->getLBracLoc(),
CS->getRBracLoc());
FD->setBody(newCS);

if (hasNoErrors && !TouchedDecls.empty()) {
// Put the wrapper after its declarations. (Nice when AST dumping)
Expand Down
33 changes: 21 additions & 12 deletions interpreter/cling/lib/Interpreter/DynamicLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,12 @@ namespace cling {
"Cannot have more than one stmt at that point");

if (NewNode.isForReplacement()) {
if (Expr* E = NewNode.getAs<Expr>())
if (Expr* E = NewNode.getAs<Expr>()) {
// Assume void if still not escaped
*I = SubstituteUnknownSymbol(m_Context->VoidTy, E);
}
else {
*I = NewNode.getAsSingleNode();
} else {
*I = NewNode.getAsSingleNode();
}
}
}
}
Expand Down Expand Up @@ -328,14 +328,21 @@ namespace cling {
// where we know what to do. For Stmt, though, we need to substitute here,
// knowing the "target" type.
ASTNodeInfo thenInfo = Visit(Node->getThen());
if (thenInfo.isForReplacement())
Node->setThen(SubstituteUnknownSymbol(m_Context->VoidTy,
thenInfo.getAs<Expr>()));
if (thenInfo.isForReplacement()) {
Stmt* thenReplacement = thenInfo.getAsSingleNode();
if (Expr* thenExpr = dyn_cast<Expr>(thenReplacement))
thenReplacement = SubstituteUnknownSymbol(m_Context->VoidTy, thenExpr);
Node->setThen(thenReplacement);
}
if (Stmt* ElseExpr = Node->getElse()) {
ASTNodeInfo elseInfo = Visit(ElseExpr);
if (elseInfo.isForReplacement())
Node->setElse(SubstituteUnknownSymbol(m_Context->VoidTy,
elseInfo.getAs<Expr>()));
if (elseInfo.isForReplacement()) {
Stmt* elseReplacement = elseInfo.getAsSingleNode();
if (Expr* elseExpr = dyn_cast<Expr>(elseReplacement))
elseReplacement =
SubstituteUnknownSymbol(m_Context->VoidTy, elseExpr);
Node->setElse(elseReplacement);
}
}

return ASTNodeInfo(Node, false);
Expand Down Expand Up @@ -382,10 +389,12 @@ namespace cling {
}
}

Node->replaceStmts(*m_Context, NewChildren);
auto* NewCS = CompoundStmt::Create(*m_Context, NewChildren,
Node->getLBracLoc(),
Node->getRBracLoc());

--m_NestedCompoundStmts;
return ASTNodeInfo(Node, 0);
return ASTNodeInfo(NewCS, true);
}

ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
Expand Down
18 changes: 14 additions & 4 deletions interpreter/cling/lib/Interpreter/ValuePrinterSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ namespace cling {
*(CS->body_begin()+indexOfLastExpr) = Result;
}
// Clear the artificial NullStmt-s
if (!ClearNullStmts(CS)) {
if (!ClearNullStmts(FD)) {
// FIXME: Why it is here? Shouldn't it be in DeclExtractor?
// if no body remove the wrapper
DeclContext* DC = FD->getDeclContext();
Expand Down Expand Up @@ -166,14 +166,24 @@ namespace cling {
}


unsigned ValuePrinterSynthesizer::ClearNullStmts(CompoundStmt* CS) {
unsigned ValuePrinterSynthesizer::ClearNullStmts(FunctionDecl* FD) {
CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
assert(CS && "Missing body?");

llvm::SmallVector<Stmt*, 8> FBody;
for (auto&& child: CS->children())
if (!isa<NullStmt>(child))
FBody.push_back(child);

if (CS->size() != FBody.size())
CS->replaceStmts(*m_Context, FBody);
// If body would be empty, return early - the function will be removed.
if (FBody.empty())
return 0;

if (CS->size() != FBody.size()) {
auto BodyCS = CompoundStmt::Create(*m_Context, FBody, CS->getLBracLoc(),
CS->getRBracLoc());
FD->setBody(BodyCS);
}

return FBody.size();
}
Expand Down
3 changes: 1 addition & 2 deletions interpreter/cling/lib/Interpreter/ValuePrinterSynthesizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

namespace clang {
class ASTContext;
class CompoundStmt;
class Decl;
class FunctionDecl;
class Expr;
Expand Down Expand Up @@ -63,7 +62,7 @@ namespace cling {
/// critical error.
bool tryAttachVP(clang::FunctionDecl* FD);
clang::Expr* SynthesizeVP(clang::Expr* E);
unsigned ClearNullStmts(clang::CompoundStmt* CS);
unsigned ClearNullStmts(clang::FunctionDecl* FD);

// Find and cache cling::runtime on first request.
void FindAndCacheRuntimeLookupResult(clang::SourceLocation SourceLoc);
Expand Down
7 changes: 5 additions & 2 deletions interpreter/cling/lib/Utils/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,11 @@ namespace utils {
indexOfLastExpr++;
newBody.insert(newBody.begin() + indexOfLastExpr, DRE);

// Attach the new body (note: it does dealloc/alloc of all nodes)
CS->replaceStmts(S->getASTContext(), newBody);
// Attach a new body.
auto newCS = CompoundStmt::Create(S->getASTContext(), newBody,
CS->getLBracLoc(),
CS->getRBracLoc());
FD->setBody(newCS);
if (FoundAt)
*FoundAt = indexOfLastExpr;
return DRE;
Expand Down

0 comments on commit 34590ae

Please sign in to comment.