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:
parent
e13eff3119
commit
fd2212c84e
@ -25,9 +25,9 @@ namespace cling {
|
|||||||
public:
|
public:
|
||||||
AutoFixer(Sema* S) : m_Sema(S), m_FoundDRE(0) {}
|
AutoFixer(Sema* S) : m_Sema(S), m_FoundDRE(0) {}
|
||||||
|
|
||||||
void Fix(CompoundStmt* CS) {
|
CompoundStmt* Fix(CompoundStmt* CS) {
|
||||||
if (!CS->size())
|
if (!CS->size())
|
||||||
return;
|
return nullptr;
|
||||||
typedef llvm::SmallVector<Stmt*, 32> Statements;
|
typedef llvm::SmallVector<Stmt*, 32> Statements;
|
||||||
Statements Stmts;
|
Statements Stmts;
|
||||||
Stmts.append(CS->body_begin(), CS->body_end());
|
Stmts.append(CS->body_begin(), CS->body_end());
|
||||||
@ -44,20 +44,32 @@ namespace cling {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CS->size() != Stmts.size())
|
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) {
|
CXXTryStmt* Fix(CXXTryStmt* TS) {
|
||||||
Fix(TS->getTryBlock());
|
CompoundStmt *TryBlock = TS->getTryBlock();
|
||||||
for(unsigned int h = 0; h < TS->getNumHandlers(); ++h) {
|
if (CompoundStmt *NewTryBlock = Fix(TryBlock))
|
||||||
Stmt *s = TS->getHandler(h)->getHandlerBlock();
|
TryBlock = NewTryBlock;
|
||||||
if (CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(s))
|
|
||||||
Fix(CS);
|
llvm::SmallVector<Stmt*, 4> Handlers(TS->getNumHandlers());
|
||||||
else if (CXXTryStmt *HandlerTS = dyn_cast_or_null<CXXTryStmt>(s))
|
for (unsigned int h = 0; h < TS->getNumHandlers(); ++h) {
|
||||||
Fix(HandlerTS);
|
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) {
|
bool VisitDeclRefExpr(DeclRefExpr* DRE) {
|
||||||
const Decl* D = DRE->getDecl();
|
const Decl* D = DRE->getDecl();
|
||||||
if (const AnnotateAttr* A = D->getAttr<AnnotateAttr>())
|
if (const AnnotateAttr* A = D->getAttr<AnnotateAttr>())
|
||||||
@ -92,9 +104,12 @@ namespace cling {
|
|||||||
// those.
|
// those.
|
||||||
Stmt *Body = FD->getBody();
|
Stmt *Body = FD->getBody();
|
||||||
if (CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(Body))
|
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))
|
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);
|
return Result(D, true);
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
if (hasNoErrors && !TouchedDecls.empty()) {
|
||||||
// Put the wrapper after its declarations. (Nice when AST dumping)
|
// Put the wrapper after its declarations. (Nice when AST dumping)
|
||||||
|
@ -289,15 +289,15 @@ namespace cling {
|
|||||||
"Cannot have more than one stmt at that point");
|
"Cannot have more than one stmt at that point");
|
||||||
|
|
||||||
if (NewNode.isForReplacement()) {
|
if (NewNode.isForReplacement()) {
|
||||||
if (Expr* E = NewNode.getAs<Expr>())
|
if (Expr* E = NewNode.getAs<Expr>()) {
|
||||||
// Assume void if still not escaped
|
// Assume void if still not escaped
|
||||||
*I = SubstituteUnknownSymbol(m_Context->VoidTy, E);
|
*I = SubstituteUnknownSymbol(m_Context->VoidTy, E);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
*I = NewNode.getAsSingleNode();
|
*I = NewNode.getAsSingleNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ASTNodeInfo(Node, 0);
|
return ASTNodeInfo(Node, 0);
|
||||||
}
|
}
|
||||||
@ -328,14 +328,21 @@ namespace cling {
|
|||||||
// where we know what to do. For Stmt, though, we need to substitute here,
|
// where we know what to do. For Stmt, though, we need to substitute here,
|
||||||
// knowing the "target" type.
|
// knowing the "target" type.
|
||||||
ASTNodeInfo thenInfo = Visit(Node->getThen());
|
ASTNodeInfo thenInfo = Visit(Node->getThen());
|
||||||
if (thenInfo.isForReplacement())
|
if (thenInfo.isForReplacement()) {
|
||||||
Node->setThen(SubstituteUnknownSymbol(m_Context->VoidTy,
|
Stmt* thenReplacement = thenInfo.getAsSingleNode();
|
||||||
thenInfo.getAs<Expr>()));
|
if (Expr* thenExpr = dyn_cast<Expr>(thenReplacement))
|
||||||
|
thenReplacement = SubstituteUnknownSymbol(m_Context->VoidTy, thenExpr);
|
||||||
|
Node->setThen(thenReplacement);
|
||||||
|
}
|
||||||
if (Stmt* ElseExpr = Node->getElse()) {
|
if (Stmt* ElseExpr = Node->getElse()) {
|
||||||
ASTNodeInfo elseInfo = Visit(ElseExpr);
|
ASTNodeInfo elseInfo = Visit(ElseExpr);
|
||||||
if (elseInfo.isForReplacement())
|
if (elseInfo.isForReplacement()) {
|
||||||
Node->setElse(SubstituteUnknownSymbol(m_Context->VoidTy,
|
Stmt* elseReplacement = elseInfo.getAsSingleNode();
|
||||||
elseInfo.getAs<Expr>()));
|
if (Expr* elseExpr = dyn_cast<Expr>(elseReplacement))
|
||||||
|
elseReplacement =
|
||||||
|
SubstituteUnknownSymbol(m_Context->VoidTy, elseExpr);
|
||||||
|
Node->setElse(elseReplacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ASTNodeInfo(Node, false);
|
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;
|
--m_NestedCompoundStmts;
|
||||||
return ASTNodeInfo(Node, 0);
|
return ASTNodeInfo(NewCS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
|
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
|
||||||
|
@ -105,7 +105,7 @@ namespace cling {
|
|||||||
*(CS->body_begin()+indexOfLastExpr) = Result;
|
*(CS->body_begin()+indexOfLastExpr) = Result;
|
||||||
}
|
}
|
||||||
// Clear the artificial NullStmt-s
|
// Clear the artificial NullStmt-s
|
||||||
if (!ClearNullStmts(CS)) {
|
if (!ClearNullStmts(FD)) {
|
||||||
// FIXME: Why it is here? Shouldn't it be in DeclExtractor?
|
// FIXME: Why it is here? Shouldn't it be in DeclExtractor?
|
||||||
// if no body remove the wrapper
|
// if no body remove the wrapper
|
||||||
DeclContext* DC = FD->getDeclContext();
|
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;
|
llvm::SmallVector<Stmt*, 8> FBody;
|
||||||
for (auto&& child: CS->children())
|
for (auto&& child: CS->children())
|
||||||
if (!isa<NullStmt>(child))
|
if (!isa<NullStmt>(child))
|
||||||
FBody.push_back(child);
|
FBody.push_back(child);
|
||||||
|
|
||||||
if (CS->size() != FBody.size())
|
// If body would be empty, return early - the function will be removed.
|
||||||
CS->replaceStmts(*m_Context, FBody);
|
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();
|
return FBody.size();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
class CompoundStmt;
|
|
||||||
class Decl;
|
class Decl;
|
||||||
class FunctionDecl;
|
class FunctionDecl;
|
||||||
class Expr;
|
class Expr;
|
||||||
@ -63,7 +62,7 @@ public:
|
|||||||
/// critical error.
|
/// critical error.
|
||||||
bool tryAttachVP(clang::FunctionDecl* FD);
|
bool tryAttachVP(clang::FunctionDecl* FD);
|
||||||
clang::Expr* SynthesizeVP(clang::Expr* E);
|
clang::Expr* SynthesizeVP(clang::Expr* E);
|
||||||
unsigned ClearNullStmts(clang::CompoundStmt* CS);
|
unsigned ClearNullStmts(clang::FunctionDecl* FD);
|
||||||
|
|
||||||
// Find and cache cling::runtime on first request.
|
// Find and cache cling::runtime on first request.
|
||||||
void FindAndCacheRuntimeLookupResult(clang::SourceLocation SourceLoc);
|
void FindAndCacheRuntimeLookupResult(clang::SourceLocation SourceLoc);
|
||||||
|
@ -169,8 +169,11 @@ namespace utils {
|
|||||||
indexOfLastExpr++;
|
indexOfLastExpr++;
|
||||||
newBody.insert(newBody.begin() + indexOfLastExpr, DRE);
|
newBody.insert(newBody.begin() + indexOfLastExpr, DRE);
|
||||||
|
|
||||||
// Attach the new body (note: it does dealloc/alloc of all nodes)
|
// Attach a new body.
|
||||||
CS->replaceStmts(S->getASTContext(), newBody);
|
auto newCS = CompoundStmt::Create(S->getASTContext(), newBody,
|
||||||
|
CS->getLBracLoc(),
|
||||||
|
CS->getRBracLoc());
|
||||||
|
FD->setBody(newCS);
|
||||||
if (FoundAt)
|
if (FoundAt)
|
||||||
*FoundAt = indexOfLastExpr;
|
*FoundAt = indexOfLastExpr;
|
||||||
return DRE;
|
return DRE;
|
||||||
|
Loading…
Reference in New Issue
Block a user