Create new CompoundStmt instead of replacing children

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 <Hahnfeld@itc.rwth-aachen.de>
Co-authored-by: Jonas Hahnfeld <hahnjo@hahnjo.de>
This commit is contained in:
Jonas Hahnfeld 2021-03-12 10:01:12 +01:00 committed by jenkins
parent e13eff3119
commit fd2212c84e
6 changed files with 73 additions and 34 deletions

View File

@ -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());
@ -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) {
@ -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);
}

View File

@ -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)

View File

@ -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();
}
}
}
}
@ -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);
@ -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) {

View File

@ -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();
@ -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();
}

View File

@ -16,7 +16,6 @@
namespace clang {
class ASTContext;
class CompoundStmt;
class Decl;
class FunctionDecl;
class Expr;
@ -63,7 +62,7 @@ public:
/// 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);

View File

@ -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;