DynScopes: recurse into Decls.

This commit is contained in:
Axel Naumann 2016-08-31 17:54:08 +02:00 committed by sftnight
parent a8608d0a67
commit 608a560140

View File

@ -109,7 +109,42 @@ namespace {
return false;
}
};
};
class DynScopeDeclVisitor:
public DeclVisitor<DynScopeDeclVisitor, bool> {
private:
cling::EvaluateTSynthesizer& m_EvalTSynth;
public:
DynScopeDeclVisitor(cling::EvaluateTSynthesizer& evalTSynth):
m_EvalTSynth(evalTSynth) {}
bool VisitFunctionDecl(FunctionDecl* FD) {
cling::ASTNodeInfo Replacement = m_EvalTSynth.Visit(FD->getBody());
if (Replacement.hasErrorOccurred()) {
FD->setBody(nullptr);
return true;
}
if (Replacement.isForReplacement()) {
// FIXME: support multiple Stmt Replacement!
FD->setBody(Replacement.getAsSingleNode());
return true;
}
return false;
}
bool VisitDecl(Decl* D) {
bool Replaced = false;
if (auto DC = dyn_cast<DeclContext>(D)) {
for (auto C: DC->decls())
Replaced |= Visit(C);
}
return Replaced;
}
};
} // end anonymous namespace
namespace cling {
@ -356,16 +391,15 @@ namespace cling {
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
// Visit all the children, which are the contents of the DeclGroupRef
for (Stmt::child_iterator
I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
if (*I) {
Expr* E = cast_or_null<Expr>(*I);
if (!E || !IsArtificiallyDependent(E))
if (VarDecl* CuredDecl = dyn_cast<VarDecl>(Node->getSingleDecl())) {
//FIXME: don't assume there is only one decl.
assert(Node->isSingleDecl() && "There is more that one decl in stmt");
for (Stmt::child_iterator
I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
Expr* InitExpr = cast_or_null<Expr>(*I);
if (!InitExpr || !IsArtificiallyDependent(InitExpr))
continue;
//FIXME: don't assume there is only one decl.
assert(Node->isSingleDecl() && "There is more that one decl in stmt");
VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl());
assert(CuredDecl && "Not a variable declaration!");
QualType CuredDeclTy = CuredDecl->getType();
if (isa<AutoType>(CuredDeclTy)) {
ASTNodeInfo result(Node, false);
@ -410,7 +444,7 @@ namespace cling {
// "MyClass"
// Interpreter* Interp)
// Build Arg0 DynamicExprInfo
Inits.push_back(BuildDynamicExprInfo(E));
Inits.push_back(BuildDynamicExprInfo(InitExpr));
// Build Arg1 DeclContext* DC
QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl);
Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy,
@ -512,10 +546,20 @@ namespace cling {
// Restore Sema's original DeclContext
m_Sema->CurContext = OldDC;
// FIXME: this only works if this is the only Decl in the DeclGroup...
return NewNode;
}
}
return ASTNodeInfo(Node, 0);
// Recurse over Decls; they might need transformations, too; e.g. in
// void wrapper() { struct X { void f() { ++dynScope; } }; }
bool HaveReplacement = false;
DynScopeDeclVisitor DSDV(*this);
// DynScopeDeclVisitor always changes the Decls in-place, no need to pick up
// new ones.
for (auto DGI: Node->getDeclGroup())
HaveReplacement |= DSDV.Visit(DGI);
return ASTNodeInfo(Node, HaveReplacement);
}
ASTNodeInfo EvaluateTSynthesizer::VisitCXXDeleteExpr(CXXDeleteExpr* Node) {