CompoundStmt::setStmts was reimplemented to save a pointer.
Unfortunately this break external tools such as cling which alters CompoundStmts to implement its interactive extensions. We have implemented a patch in clang which brings the old facilities only when the new interface CompoundStmt::replaceStmts is called. See llvm-mirror/clang@d0ee47a
This commit is contained in:
parent
ab1ea2bb02
commit
60bed9429d
@ -43,7 +43,7 @@ namespace cling {
|
||||
m_HandledDecls.insert(m_FoundDRE->getDecl());
|
||||
}
|
||||
}
|
||||
CS->setStmts(m_Sema->getASTContext(), Stmts);
|
||||
CS->replaceStmts(m_Sema->getASTContext(), Stmts);
|
||||
}
|
||||
|
||||
void Fix(CXXTryStmt* TS) {
|
||||
|
@ -210,7 +210,7 @@ namespace cling {
|
||||
}
|
||||
}
|
||||
|
||||
CS->setStmts(*m_Context, Stmts);
|
||||
CS->replaceStmts(*m_Context, Stmts);
|
||||
|
||||
if (hasNoErrors && !TouchedDecls.empty()) {
|
||||
// Put the wrapper after its declarations. (Nice when AST dumping)
|
||||
@ -261,8 +261,7 @@ namespace cling {
|
||||
|
||||
// Wrap Stmts into a function body.
|
||||
llvm::ArrayRef<Stmt*> StmtsRef(Stmts.data(), Stmts.size());
|
||||
CompoundStmt* CS = new (*m_Context)CompoundStmt(*m_Context, StmtsRef,
|
||||
Loc, Loc);
|
||||
CompoundStmt* CS = CompoundStmt::Create(*m_Context, StmtsRef, Loc, Loc);
|
||||
FD->setBody(CS);
|
||||
Emit(FD);
|
||||
|
||||
|
@ -359,7 +359,7 @@ namespace cling {
|
||||
for(unsigned i = 0; i < NewStmts.size(); ++i)
|
||||
NewChildren.push_back(NewStmts[i]);
|
||||
|
||||
Node->setStmts(*m_Context, NewChildren);
|
||||
Node->replaceStmts(*m_Context, NewChildren);
|
||||
// Resolve all 1:n replacements
|
||||
Visit(Node);
|
||||
}
|
||||
@ -388,7 +388,7 @@ namespace cling {
|
||||
}
|
||||
}
|
||||
|
||||
Node->setStmts(*m_Context, NewChildren);
|
||||
Node->replaceStmts(*m_Context, NewChildren);
|
||||
|
||||
--m_NestedCompoundStmts;
|
||||
return ASTNodeInfo(Node, 0);
|
||||
|
@ -626,8 +626,8 @@ static const char* BuildAndEmitVPWrapperBody(cling::Interpreter &Interp,
|
||||
if (RetStmt.isInvalid())
|
||||
return "ERROR in cling's callPrintValue(): cannot build return expression";
|
||||
|
||||
auto *Body = new (Ctx) clang::CompoundStmt(noSrcLoc);
|
||||
Body->setStmts(Ctx, {RetStmt.get()});
|
||||
auto *Body
|
||||
= clang::CompoundStmt::Create(Ctx, {RetStmt.get()}, noSrcLoc, noSrcLoc);
|
||||
WrapperFD->setBody(Body);
|
||||
auto &Consumer = Interp.getCI()->getASTConsumer();
|
||||
Consumer.HandleTopLevelDecl(clang::DeclGroupRef(WrapperFD));
|
||||
|
@ -172,7 +172,7 @@ namespace cling {
|
||||
if (!isa<NullStmt>(child))
|
||||
FBody.push_back(child);
|
||||
|
||||
CS->setStmts(*m_Context, FBody);
|
||||
CS->replaceStmts(*m_Context, FBody);
|
||||
return FBody.size();
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ namespace utils {
|
||||
newBody.insert(newBody.begin() + indexOfLastExpr, DRE);
|
||||
|
||||
// Attach the new body (note: it does dealloc/alloc of all nodes)
|
||||
CS->setStmts(S->getASTContext(), newBody);
|
||||
CS->replaceStmts(S->getASTContext(), newBody);
|
||||
if (FoundAt)
|
||||
*FoundAt = indexOfLastExpr;
|
||||
return DRE;
|
||||
|
101
patches/clang-compoundstmt-replaceStmts.diff
Normal file
101
patches/clang-compoundstmt-replaceStmts.diff
Normal file
@ -0,0 +1,101 @@
|
||||
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
|
||||
index 403b88ac3a..f852ee4b86 100644
|
||||
--- a/include/clang/AST/Stmt.h
|
||||
+++ b/include/clang/AST/Stmt.h
|
||||
@@ -131,7 +131,8 @@ protected:
|
||||
|
||||
unsigned : NumStmtBits;
|
||||
|
||||
- unsigned NumStmts : 32 - NumStmtBits;
|
||||
+ unsigned WasReplaced : 1;
|
||||
+ unsigned NumStmts : 32 - (NumStmtBits + 1);
|
||||
|
||||
/// The location of the opening "{".
|
||||
SourceLocation LBraceLoc;
|
||||
@@ -1328,6 +1329,7 @@ public:
|
||||
explicit CompoundStmt(SourceLocation Loc)
|
||||
: Stmt(CompoundStmtClass), RBraceLoc(Loc) {
|
||||
CompoundStmtBits.NumStmts = 0;
|
||||
+ CompoundStmtBits.WasReplaced = 0;
|
||||
CompoundStmtBits.LBraceLoc = Loc;
|
||||
}
|
||||
|
||||
@@ -1341,7 +1343,10 @@ public:
|
||||
using body_range = llvm::iterator_range<body_iterator>;
|
||||
|
||||
body_range body() { return body_range(body_begin(), body_end()); }
|
||||
- body_iterator body_begin() { return getTrailingObjects<Stmt *>(); }
|
||||
+ body_iterator body_begin() {
|
||||
+ Stmt** begin = getTrailingObjects<Stmt *>();
|
||||
+ return !CompoundStmtBits.WasReplaced ? begin : (body_iterator)begin[0];
|
||||
+ }
|
||||
body_iterator body_end() { return body_begin() + size(); }
|
||||
Stmt *body_front() { return !body_empty() ? body_begin()[0] : nullptr; }
|
||||
|
||||
@@ -1357,7 +1362,7 @@ public:
|
||||
}
|
||||
|
||||
const_body_iterator body_begin() const {
|
||||
- return getTrailingObjects<Stmt *>();
|
||||
+ return const_cast<CompoundStmt*>(this)->body_begin();
|
||||
}
|
||||
|
||||
const_body_iterator body_end() const { return body_begin() + size(); }
|
||||
@@ -1391,6 +1396,8 @@ public:
|
||||
return const_reverse_body_iterator(body_begin());
|
||||
}
|
||||
|
||||
+ void replaceStmts(const ASTContext &C, llvm::ArrayRef<Stmt*> Stmts);
|
||||
+
|
||||
// Get the Stmt that StmtExpr would consider to be the result of this
|
||||
// compound statement. This is used by StmtExpr to properly emulate the GCC
|
||||
// compound expression extension, which ignores trailing NullStmts when
|
||||
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
|
||||
index 0a4d403106..86d47cf82d 100644
|
||||
--- a/lib/AST/Stmt.cpp
|
||||
+++ b/lib/AST/Stmt.cpp
|
||||
@@ -293,6 +293,7 @@ CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
|
||||
SourceLocation RB)
|
||||
: Stmt(CompoundStmtClass), RBraceLoc(RB) {
|
||||
CompoundStmtBits.NumStmts = Stmts.size();
|
||||
+ CompoundStmtBits.WasReplaced = 0;
|
||||
setStmts(Stmts);
|
||||
CompoundStmtBits.LBraceLoc = LB;
|
||||
}
|
||||
@@ -300,7 +301,7 @@ CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
|
||||
void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
|
||||
assert(CompoundStmtBits.NumStmts == Stmts.size() &&
|
||||
"NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
|
||||
-
|
||||
+ assert(!CompoundStmtBits.WasReplaced && "Call replaceStmts!");
|
||||
std::copy(Stmts.begin(), Stmts.end(), body_begin());
|
||||
}
|
||||
|
||||
@@ -320,6 +321,27 @@ CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C,
|
||||
return New;
|
||||
}
|
||||
|
||||
+void CompoundStmt::replaceStmts(const ASTContext &C,
|
||||
+ llvm::ArrayRef<Stmt*> Stmts) {
|
||||
+ Stmt** Body = body_begin();
|
||||
+
|
||||
+ if (CompoundStmtBits.WasReplaced)
|
||||
+ C.Deallocate(Body);
|
||||
+ else
|
||||
+ memset(body_begin(), 0, size());
|
||||
+
|
||||
+ CompoundStmtBits.NumStmts = Stmts.size();
|
||||
+ assert(CompoundStmtBits.NumStmts == Stmts.size() &&
|
||||
+ "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
|
||||
+
|
||||
+ Body = new (C) Stmt*[Stmts.size()];
|
||||
+ std::copy(Stmts.begin(), Stmts.end(), Body);
|
||||
+
|
||||
+ getTrailingObjects<Stmt *>()[0] = reinterpret_cast<Stmt*>(Body);
|
||||
+
|
||||
+ CompoundStmtBits.WasReplaced = 1;
|
||||
+}
|
||||
+
|
||||
const Expr *ValueStmt::getExprStmt() const {
|
||||
const Stmt *S = this;
|
||||
do {
|
Loading…
x
Reference in New Issue
Block a user