aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
authorFangyi Zhou <me@fangyi.io>2025-05-12 13:19:44 +0100
committerGitHub <noreply@github.com>2025-05-12 14:19:44 +0200
commit6078f5eb214d4cbb74ca9b024b88ff88d963ffd2 (patch)
tree92f9aadd7725231e0159b44193f6eed928e39705 /clang/lib/Analysis
parentd5974524de6d7bccb95a1b3f074d1b6b76b60497 (diff)
downloadllvm-6078f5eb214d4cbb74ca9b024b88ff88d963ffd2.zip
llvm-6078f5eb214d4cbb74ca9b024b88ff88d963ffd2.tar.gz
llvm-6078f5eb214d4cbb74ca9b024b88ff88d963ffd2.tar.bz2
Reland [Clang][analyzer] replace Stmt* with ConstCFGElement in SymbolConjured (#137355)
Closes #57270. This PR changes the `Stmt *` field in `SymbolConjured` with `CFGBlock::ConstCFGElementRef`. The motivation is that, when conjuring a symbol, there might not always be a statement available, causing information to be lost for conjured symbols, whereas the CFGElementRef can always be provided at the callsite. Following the idea, this PR changes callsites of functions to create conjured symbols, and replaces them with appropriate `CFGElementRef`s. There is a caveat at loop widening, where the correct location is the CFG terminator (which is not an element and does not have a ref). In this case, the first element in the block is passed as a location. Previous PR #128251, Reverted at #137304.
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/CFG.cpp46
1 files changed, 26 insertions, 20 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index f58d31ba..23876d5 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -5841,16 +5841,17 @@ static void print_construction_context(raw_ostream &OS,
}
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
- const CFGElement &E);
+ const CFGElement &E, bool TerminateWithNewLine = true);
-void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
+void CFGElement::dumpToStream(llvm::raw_ostream &OS,
+ bool TerminateWithNewLine) const {
LangOptions LangOpts;
StmtPrinterHelper Helper(nullptr, LangOpts);
- print_elem(OS, Helper, *this);
+ print_elem(OS, Helper, *this, TerminateWithNewLine);
}
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
- const CFGElement &E) {
+ const CFGElement &E, bool TerminateWithNewLine) {
switch (E.getKind()) {
case CFGElement::Kind::Statement:
case CFGElement::Kind::CXXRecordTypedCall:
@@ -5867,7 +5868,9 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (Children.begin() != Children.end()) {
OS << "({ ... ; ";
Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
- OS << " })\n";
+ OS << " })";
+ if (TerminateWithNewLine)
+ OS << '\n';
return;
}
}
@@ -5876,7 +5879,8 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (B->getOpcode() == BO_Comma) {
OS << "... , ";
Helper.handledStmt(B->getRHS(),OS);
- OS << '\n';
+ if (TerminateWithNewLine)
+ OS << '\n';
return;
}
}
@@ -5904,15 +5908,14 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
}
// Expressions need a newline.
- if (isa<Expr>(S))
+ if (isa<Expr>(S) && TerminateWithNewLine)
OS << '\n';
- break;
+ return;
}
case CFGElement::Kind::Initializer:
print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
- OS << '\n';
break;
case CFGElement::Kind::AutomaticObjectDtor: {
@@ -5926,43 +5929,44 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
OS << ".~";
T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
- OS << "() (Implicit destructor)\n";
+ OS << "() (Implicit destructor)";
break;
}
case CFGElement::Kind::CleanupFunction:
OS << "CleanupFunction ("
- << E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")\n";
+ << E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")";
break;
case CFGElement::Kind::LifetimeEnds:
Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
- OS << " (Lifetime ends)\n";
+ OS << " (Lifetime ends)";
break;
case CFGElement::Kind::LoopExit:
- OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
+ OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName()
+ << " (LoopExit)";
break;
case CFGElement::Kind::ScopeBegin:
OS << "CFGScopeBegin(";
if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
OS << VD->getQualifiedNameAsString();
- OS << ")\n";
+ OS << ")";
break;
case CFGElement::Kind::ScopeEnd:
OS << "CFGScopeEnd(";
if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
OS << VD->getQualifiedNameAsString();
- OS << ")\n";
+ OS << ")";
break;
case CFGElement::Kind::NewAllocator:
OS << "CFGNewAllocator(";
if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
- OS << ")\n";
+ OS << ")";
break;
case CFGElement::Kind::DeleteDtor: {
@@ -5974,14 +5978,14 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());
Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
OS << "->~" << RD->getName().str() << "()";
- OS << " (Implicit destructor)\n";
+ OS << " (Implicit destructor)";
break;
}
case CFGElement::Kind::BaseDtor: {
const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
- OS << " (Base object destructor)\n";
+ OS << " (Base object destructor)";
break;
}
@@ -5990,7 +5994,7 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const Type *T = FD->getType()->getBaseElementTypeUnsafe();
OS << "this->" << FD->getName();
OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
- OS << " (Member object destructor)\n";
+ OS << " (Member object destructor)";
break;
}
@@ -5999,10 +6003,12 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
OS << "~";
BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
- OS << "() (Temporary object destructor)\n";
+ OS << "() (Temporary object destructor)";
break;
}
}
+ if (TerminateWithNewLine)
+ OS << '\n';
}
static void print_block(raw_ostream &OS, const CFG* cfg,