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:
Vassil Vassilev 2020-03-15 14:29:49 +02:00 committed by jenkins
parent ab1ea2bb02
commit 60bed9429d
7 changed files with 110 additions and 10 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 {