[clang] Revert "[Clang][analyzer] replace Stmt* with ConstCFGElementRef in SymbolConjured" (PR #137304)
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 25 02:56:02 PDT 2025
https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/137304
Reverts llvm/llvm-project#128251
ASAN bots reported some errors: https://lab.llvm.org/buildbot/#/builders/55/builds/10398
Reverting for investigation.
```
Failed Tests (6):
Clang :: Analysis/loop-widening-ignore-static-methods.cpp
Clang :: Analysis/loop-widening-notes.cpp
Clang :: Analysis/loop-widening-preserve-reference-type.cpp
Clang :: Analysis/loop-widening.c
Clang :: Analysis/loop-widening.cpp
Clang :: Analysis/this-pointer.cpp
Testing Time: 411.55s
Total Discovered Tests: 118563
Skipped : 33 (0.03%)
Unsupported : 2015 (1.70%)
Passed : 116291 (98.08%)
Expectedly Failed: 218 (0.18%)
Failed : 6 (0.01%)
FAILED: CMakeFiles/check-all /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/CMakeFiles/check-all
cd /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan && /usr/bin/python3 /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/./bin/llvm-lit -sv --param USE_Z3_SOLVER=0 /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/utils/mlgo-utils /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/lld/test /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/mlir/test /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/test /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/utils/lit /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test
ninja: build stopped: subcommand failed.
```
```
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/lib/clang/21/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/test/Analysis/loop-widening.c # RUN: at line 1
+ /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/lib/clang/21/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/test/Analysis/loop-widening.c
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/lib/clang/21/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/test/Analysis/loop-widening.c
1. <eof> parser at end of file
2. While analyzing stack:
#0 Calling nested_loop_inner_widen
#0 0x0000c894cca289cc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:13
#1 0x0000c894cca23324 llvm::sys::RunSignalHandlers() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/lib/Support/Signals.cpp:106:18
#2 0x0000c894cca29bbc SignalHandler(int, siginfo_t*, void*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/lib/Support/Unix/Signals.inc:0:3
#3 0x0000f6898da4a8f8 (linux-vdso.so.1+0x8f8)
#4 0x0000f6898d377608 (/lib/aarch64-linux-gnu/libc.so.6+0x87608)
#5 0x0000f6898d32cb3c raise (/lib/aarch64-linux-gnu/libc.so.6+0x3cb3c)
#6 0x0000f6898d317e00 abort (/lib/aarch64-linux-gnu/libc.so.6+0x27e00)
#7 0x0000c894c5e77fec __sanitizer::Atexit(void (*)()) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp:168:10
#8 0x0000c894c5e76680 __sanitizer::Die() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_termination.cpp:52:5
#9 0x0000c894c5e69650 Unlock /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_mutex.h:250:16
#10 0x0000c894c5e69650 ~GenericScopedLock /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_mutex.h:386:51
#11 0x0000c894c5e69650 __hwasan::ScopedReport::~ScopedReport() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_report.cpp:54:5
#12 0x0000c894c5e68de0 __hwasan::(anonymous namespace)::BaseReport::~BaseReport() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_report.cpp:476:7
#13 0x0000c894c5e66b74 __hwasan::ReportTagMismatch(__sanitizer::StackTrace*, unsigned long, unsigned long, bool, bool, unsigned long*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_report.cpp:1091:1
#14 0x0000c894c5e52cf8 Destroy /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_common.h:532:31
#15 0x0000c894c5e52cf8 ~InternalMmapVector /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_common.h:642:56
#16 0x0000c894c5e52cf8 __hwasan::HandleTagMismatch(__hwasan::AccessInfo, unsigned long, unsigned long, void*, unsigned long*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan.cpp:245:1
#17 0x0000c894c5e551c8 __hwasan_tag_mismatch4 /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan.cpp:764:1
#18 0x0000c894c5e6a2f8 __interception::InterceptFunction(char const*, unsigned long*, unsigned long, unsigned long) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/interception/interception_linux.cpp:60:0
#19 0x0000c894d166f664 getBlock /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h:217:45
#20 0x0000c894d166f664 getCFGElementRef /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h:230:59
#21 0x0000c894d166f664 clang::ento::ExprEngine::processCFGBlockEntrance(clang::BlockEdge const&, clang::ento::NodeBuilderWithSinks&, clang::ento::ExplodedNode*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp:2570:45
#22 0x0000c894d15f3a1c hasGeneratedNodes /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h:333:37
#23 0x0000c894d15f3a1c clang::ento::CoreEngine::HandleBlockEdge(clang::BlockEdge const&, clang::ento::ExplodedNode*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:319:20
#24 0x0000c894d15f2c34 clang::ento::CoreEngine::dispatchWorkItem(clang::ento::ExplodedNode*, clang::ProgramPoint, clang::ento::WorkListUnit const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:220:7
#25 0x0000c894d15f2398 operator-> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/unique_ptr.h:267:101
#26 0x0000c894d15f2398 clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>)::$_0::operator()(unsigned int) const /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:140:12
#27 0x0000c894d15f14b4 clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp:165:7
#28 0x0000c894d0ebb9dc release /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h:232:9
#29 0x0000c894d0ebb9dc ~IntrusiveRefCntPtr /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h:196:27
#30 0x0000c894d0ebb9dc ExecuteWorkList /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h:192:5
#31 0x0000c894d0ebb9dc RunPathSensitiveChecks /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:772:7
#32 0x0000c894d0ebb9dc (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*, void>>*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:741:5
#33 0x0000c894d0eb6ee4 begin /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/ADT/DenseMap.h:0:0
#34 0x0000c894d0eb6ee4 begin /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/ADT/DenseSet.h:187:45
#35 0x0000c894d0eb6ee4 HandleDeclsCallGraph /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:516:29
#36 0x0000c894d0eb6ee4 runAnalysisOnTranslationUnit /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:584:5
#37 0x0000c894d0eb6ee4 (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:647:3
#38 0x0000c894d18a7a38 clang::ParseAST(clang::Sema&, bool, bool) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Parse/ParseAST.cpp:0:13
#39 0x0000c894ce81ed70 clang::FrontendAction::Execute() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1231:10
#40 0x0000c894ce6f2144 getPtr /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/Support/Error.h:278:42
#41 0x0000c894ce6f2144 operator bool /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/Support/Error.h:241:16
#42 0x0000c894ce6f2144 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1058:23
#43 0x0000c894cea718cc operator-> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/shared_ptr.h:635:12
#44 0x0000c894cea718cc getFrontendOpts /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/include/clang/Frontend/CompilerInstance.h:307:12
#45 0x0000c894cea718cc clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:301:14
#46 0x0000c894c5e9cf28 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/tools/driver/cc1_main.cpp:294:15
#47 0x0000c894c5e92a9c ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/tools/driver/driver.cpp:223:12
#48 0x0000c894c5e902ac clang_main(int, char**, llvm::ToolContext const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/tools/driver/driver.cpp:0:12
#49 0x0000c894c5eb2e34 main /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/tools/driver/clang-driver.cpp:17:3
#50 0x0000f6898d3184c4 (/lib/aarch64-linux-gnu/libc.so.6+0x284c4)
#51 0x0000f6898d318598 __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28598)
#52 0x0000c894c5e52a30 _start (/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/clang+0x6512a30)
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/test/Analysis/Output/loop-widening.c.script: line 2: 2870204 Aborted /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/clang -cc1 -internal-isystem /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/lib/clang/21/include -nostdsysteminc -analyze -analyzer-constraints=range -setup-static-analyzer -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify -analyzer-config eagerly-assume=false /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/test/Analysis/loop-widening.c
```
>From 2eb1d806d5a01c32f981ef88ef483f74bd6b3108 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Fri, 25 Apr 2025 11:54:07 +0200
Subject: [PATCH] =?UTF-8?q?Revert=20"[Clang][analyzer]=20Replace=20Stmt*?=
=?UTF-8?q?=20with=20ConstCFGElementRef=20in=20SymbolConj=E2=80=A6"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit ec936b3186e3512a9297c5a12b58d627ef1a1b32.
---
clang/include/clang/Analysis/CFG.h | 10 +-
.../StaticAnalyzer/Checkers/SValExplainer.h | 11 +-
.../Core/PathSensitive/CheckerContext.h | 2 -
.../Core/PathSensitive/ExprEngine.h | 2 +-
.../Core/PathSensitive/LoopWidening.h | 3 +-
.../Core/PathSensitive/ProgramState.h | 15 ++-
.../Core/PathSensitive/SValBuilder.h | 37 ++++--
.../StaticAnalyzer/Core/PathSensitive/Store.h | 8 +-
.../Core/PathSensitive/SymbolManager.h | 71 ++++--------
clang/lib/Analysis/CFG.cpp | 46 ++++----
.../Checkers/CStringChecker.cpp | 107 +++++++++---------
.../Checkers/ContainerModeling.cpp | 55 +++++----
.../StaticAnalyzer/Checkers/ErrnoModeling.cpp | 6 +-
.../StaticAnalyzer/Checkers/ErrnoModeling.h | 5 +-
.../Checkers/ErrnoTesterChecker.cpp | 3 +-
.../lib/StaticAnalyzer/Checkers/Iterator.cpp | 5 +-
clang/lib/StaticAnalyzer/Checkers/Iterator.h | 3 +-
.../Checkers/IteratorModeling.cpp | 93 +++++++--------
.../StaticAnalyzer/Checkers/MallocChecker.cpp | 8 +-
.../RetainCountChecker/RetainCountChecker.cpp | 3 +-
.../Checkers/STLAlgorithmModeling.cpp | 26 ++---
.../Checkers/SmartPtrModeling.cpp | 28 +++--
.../Checkers/StdLibraryFunctionsChecker.cpp | 7 +-
.../StaticAnalyzer/Checkers/StreamChecker.cpp | 43 ++++---
.../Checkers/cert/InvalidPtrChecker.cpp | 2 +-
clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 2 +-
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 47 ++++----
clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 53 ++++-----
.../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 13 +--
.../Core/ExprEngineCallAndReturn.cpp | 7 +-
.../StaticAnalyzer/Core/ExprEngineObjC.cpp | 14 +--
.../lib/StaticAnalyzer/Core/LoopWidening.cpp | 29 ++++-
.../lib/StaticAnalyzer/Core/ProgramState.cpp | 8 +-
clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 53 +++++----
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 25 ++--
.../lib/StaticAnalyzer/Core/SymbolManager.cpp | 2 +-
clang/test/Analysis/PR57270.cpp | 30 -----
clang/test/Analysis/container-modeling.cpp | 4 +-
clang/test/Analysis/dump_egraph.cpp | 1 +
clang/test/Analysis/explain-svals.cpp | 12 +-
clang/test/Analysis/explain-svals.m | 4 +-
41 files changed, 407 insertions(+), 496 deletions(-)
delete mode 100644 clang/test/Analysis/PR57270.cpp
diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index e70c70335e597..a7ff38c786a8f 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -122,8 +122,7 @@ class CFGElement {
return (Kind) x;
}
- void dumpToStream(llvm::raw_ostream &OS,
- bool TerminateWithNewLine = true) const;
+ void dumpToStream(llvm::raw_ostream &OS) const;
void dump() const {
dumpToStream(llvm::errs());
@@ -696,11 +695,6 @@ class CFGBlock {
void dump() const {
dumpToStream(llvm::errs());
}
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(Parent);
- ID.AddInteger(Index);
- }
};
template <bool IsReverse, bool IsConst> class ElementRefIterator {
@@ -1196,8 +1190,6 @@ class CFGBlock {
}
};
-using ConstCFGElementRef = CFGBlock::ConstCFGElementRef;
-
/// CFGCallback defines methods that should be called when a logical
/// operator error is found when building the CFG.
class CFGCallback {
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 6c1025ecc7f4d..519d2d5b3676b 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -19,7 +19,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -30,13 +29,6 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
ASTContext &ACtx;
ProgramStateRef State;
- std::string printCFGElementRef(ConstCFGElementRef Elem) {
- std::string Str;
- llvm::raw_string_ostream OS(Str);
- Elem->dumpToStream(OS, /*TerminateWithNewLine=*/false);
- return Str;
- }
-
std::string printStmt(const Stmt *S) {
std::string Str;
llvm::raw_string_ostream OS(Str);
@@ -122,8 +114,7 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
std::string VisitSymbolConjured(const SymbolConjured *S) {
return "symbol of type '" + S->getType().getAsString() +
- "' conjured at CFG element '" +
- printCFGElementRef(S->getCFGElementRef()) + "'";
+ "' conjured at statement '" + printStmt(S->getStmt()) + "'";
}
std::string VisitSymbolDerived(const SymbolDerived *S) {
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 63ca3efc6d228..bb33a6912bec7 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -151,8 +151,6 @@ class CheckerContext {
return Pred->getSVal(S);
}
- ConstCFGElementRef getCFGElementRef() const { return Eng.getCFGElementRef(); }
-
/// Returns true if the value of \p E is greater than or equal to \p
/// Val under unsigned comparison.
bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 285194148d3d3..5f855251b3cde 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -226,7 +226,7 @@ class ExprEngine {
return (*G.roots_begin())->getLocation().getLocationContext();
}
- ConstCFGElementRef getCFGElementRef() const {
+ CFGBlock::ConstCFGElementRef getCFGElementRef() const {
const CFGBlock *blockPtr = currBldrCtx ? currBldrCtx->getBlock() : nullptr;
return {blockPtr, currStmtIdx};
}
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
index 50f2197b8a174..e75228f92a8e5 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -27,8 +27,7 @@ namespace ento {
/// by the loop body in any iteration.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
const LocationContext *LCtx,
- unsigned BlockCount,
- ConstCFGElementRef Elem);
+ unsigned BlockCount, const Stmt *LoopStmt);
} // end namespace ento
} // end namespace clang
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 52714535e7907..4d66e086a2c2c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -313,7 +313,7 @@ class ProgramState : public llvm::FoldingSetNode {
/// be triggered by this event.
///
/// \param Regions the set of regions to be invalidated.
- /// \param Elem The CFG Element that caused the invalidation.
+ /// \param E the expression that caused the invalidation.
/// \param BlockCount The number of times the current basic block has been
/// visited.
/// \param CausesPointerEscape the flag is set to true when the invalidation
@@ -325,17 +325,16 @@ class ProgramState : public llvm::FoldingSetNode {
/// \param ITraits information about special handling for particular regions
/// or symbols.
[[nodiscard]] ProgramStateRef
- invalidateRegions(ArrayRef<const MemRegion *> Regions,
- ConstCFGElementRef Elem, unsigned BlockCount,
- const LocationContext *LCtx, bool CausesPointerEscape,
- InvalidatedSymbols *IS = nullptr,
+ invalidateRegions(ArrayRef<const MemRegion *> Regions, const Stmt *S,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
[[nodiscard]] ProgramStateRef
- invalidateRegions(ArrayRef<SVal> Values, ConstCFGElementRef Elem,
- unsigned BlockCount, const LocationContext *LCtx,
- bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
+ invalidateRegions(ArrayRef<SVal> Values, const Stmt *S, unsigned BlockCount,
+ const LocationContext *LCtx, bool CausesPointerEscape,
+ InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index bd5d245645788..54430d426a82a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -19,7 +19,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Type.h"
-#include "clang/Analysis/CFG.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
@@ -172,11 +171,19 @@ class SValBuilder {
// Forwarding methods to SymbolManager.
- const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
+ const SymbolConjured* conjureSymbol(const Stmt *stmt,
const LocationContext *LCtx,
- QualType type, unsigned visitCount,
+ QualType type,
+ unsigned visitCount,
const void *symbolTag = nullptr) {
- return SymMgr.conjureSymbol(Elem, LCtx, type, visitCount, symbolTag);
+ return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
+ }
+
+ const SymbolConjured* conjureSymbol(const Expr *expr,
+ const LocationContext *LCtx,
+ unsigned visitCount,
+ const void *symbolTag = nullptr) {
+ return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
}
/// Construct an SVal representing '0' for the specified type.
@@ -192,19 +199,29 @@ class SValBuilder {
/// preserve the relation between related(or even equivalent) expressions, so
/// conjured symbols should be used sparingly.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
- ConstCFGElementRef elem,
+ const Expr *expr,
const LocationContext *LCtx,
unsigned count);
- DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
- ConstCFGElementRef elem,
+ DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
const LocationContext *LCtx,
QualType type, unsigned count);
- DefinedOrUnknownSVal conjureSymbolVal(ConstCFGElementRef elem,
+ DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
const LocationContext *LCtx,
- QualType type, unsigned visitCount);
+ QualType type,
+ unsigned visitCount);
/// Conjure a symbol representing heap allocated memory region.
- DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem,
+ ///
+ /// Note, the expression should represent a location.
+ DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned Count);
+
+ /// Conjure a symbol representing heap allocated memory region.
+ ///
+ /// Note, now, the expression *doesn't* need to represent a location.
+ /// But the type need to!
+ DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
const LocationContext *LCtx,
QualType type, unsigned Count);
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 29a53fcc9e28d..cf7623c7be409 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -14,13 +14,13 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
#include "clang/AST/Type.h"
-#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -223,7 +223,7 @@ class StoreManager {
///
/// \param[in] store The initial store.
/// \param[in] Values The values to invalidate.
- /// \param[in] Elem The current CFG Element being evaluated. Used to conjure
+ /// \param[in] S The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
/// symbols to mark the values of invalidated regions.
@@ -241,8 +241,8 @@ class StoreManager {
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(
- Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem,
- unsigned Count, const LocationContext *LCtx, const CallEvent *Call,
+ Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
+ const LocationContext *LCtx, const CallEvent *Call,
InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 9e7c98fdded17..cbbea1b56bb40 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -80,62 +80,29 @@ class SymbolRegionValue : public SymbolData {
/// A symbol representing the result of an expression in the case when we do
/// not know anything about what the expression is.
class SymbolConjured : public SymbolData {
- ConstCFGElementRef Elem;
+ const Stmt *S;
QualType T;
unsigned Count;
const LocationContext *LCtx;
const void *SymbolTag;
friend class SymExprAllocator;
- SymbolConjured(SymbolID sym, ConstCFGElementRef elem,
- const LocationContext *lctx, QualType t, unsigned count,
- const void *symbolTag)
- : SymbolData(SymbolConjuredKind, sym), Elem(elem), T(t), Count(count),
+ SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
+ QualType t, unsigned count, const void *symbolTag)
+ : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
LCtx(lctx), SymbolTag(symbolTag) {
+ // FIXME: 's' might be a nullptr if we're conducting invalidation
+ // that was caused by a destructor call on a temporary object,
+ // which has no statement associated with it.
+ // Due to this, we might be creating the same invalidation symbol for
+ // two different invalidation passes (for two different temporaries).
assert(lctx);
assert(isValidTypeForSymbol(t));
}
public:
- ConstCFGElementRef getCFGElementRef() const { return Elem; }
-
- // It might return null.
- const Stmt *getStmt() const {
- switch (Elem->getKind()) {
- case CFGElement::Initializer:
- return Elem->castAs<CFGInitializer>().getInitializer()->getInit();
- case CFGElement::ScopeBegin:
- return Elem->castAs<CFGScopeBegin>().getTriggerStmt();
- case CFGElement::ScopeEnd:
- return Elem->castAs<CFGScopeEnd>().getTriggerStmt();
- case CFGElement::NewAllocator:
- return Elem->castAs<CFGNewAllocator>().getAllocatorExpr();
- case CFGElement::LifetimeEnds:
- return Elem->castAs<CFGLifetimeEnds>().getTriggerStmt();
- case CFGElement::LoopExit:
- return Elem->castAs<CFGLoopExit>().getLoopStmt();
- case CFGElement::Statement:
- return Elem->castAs<CFGStmt>().getStmt();
- case CFGElement::Constructor:
- return Elem->castAs<CFGConstructor>().getStmt();
- case CFGElement::CXXRecordTypedCall:
- return Elem->castAs<CFGCXXRecordTypedCall>().getStmt();
- case CFGElement::AutomaticObjectDtor:
- return Elem->castAs<CFGAutomaticObjDtor>().getTriggerStmt();
- case CFGElement::DeleteDtor:
- return Elem->castAs<CFGDeleteDtor>().getDeleteExpr();
- case CFGElement::BaseDtor:
- return nullptr;
- case CFGElement::MemberDtor:
- return nullptr;
- case CFGElement::TemporaryDtor:
- return Elem->castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
- case CFGElement::CleanupFunction:
- return nullptr;
- }
- return nullptr;
- }
-
+ /// It might return null.
+ const Stmt *getStmt() const { return S; }
unsigned getCount() const { return Count; }
/// It might return null.
const void *getTag() const { return SymbolTag; }
@@ -146,11 +113,11 @@ class SymbolConjured : public SymbolData {
void dumpToStream(raw_ostream &os) const override;
- static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
+ static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
const LocationContext *LCtx, QualType T, unsigned Count,
const void *SymbolTag) {
profile.AddInteger((unsigned)SymbolConjuredKind);
- profile.Add(Elem);
+ profile.AddPointer(S);
profile.AddPointer(LCtx);
profile.Add(T);
profile.AddInteger(Count);
@@ -158,7 +125,7 @@ class SymbolConjured : public SymbolData {
}
void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, Elem, LCtx, T, Count, SymbolTag);
+ Profile(profile, S, LCtx, T, Count, SymbolTag);
}
// Implement isa<T> support.
@@ -566,12 +533,18 @@ class SymbolManager {
template <typename SymExprT, typename... Args>
const SymExprT *acquire(Args &&...args);
- const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
+ const SymbolConjured *conjureSymbol(const Stmt *E,
const LocationContext *LCtx, QualType T,
unsigned VisitCount,
const void *SymbolTag = nullptr) {
+ return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
+ }
- return acquire<SymbolConjured>(Elem, LCtx, T, VisitCount, SymbolTag);
+ const SymbolConjured* conjureSymbol(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned VisitCount,
+ const void *SymbolTag = nullptr) {
+ return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
}
QualType getType(const SymExpr *SE) const {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 4b50b9248d21a..d03a0a544b016 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -5803,17 +5803,16 @@ static void print_construction_context(raw_ostream &OS,
}
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
- const CFGElement &E, bool TerminateWithNewLine = true);
+ const CFGElement &E);
-void CFGElement::dumpToStream(llvm::raw_ostream &OS,
- bool TerminateWithNewLine) const {
+void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
LangOptions LangOpts;
StmtPrinterHelper Helper(nullptr, LangOpts);
- print_elem(OS, Helper, *this, TerminateWithNewLine);
+ print_elem(OS, Helper, *this);
}
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
- const CFGElement &E, bool TerminateWithNewLine) {
+ const CFGElement &E) {
switch (E.getKind()) {
case CFGElement::Kind::Statement:
case CFGElement::Kind::CXXRecordTypedCall:
@@ -5830,9 +5829,7 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (Children.begin() != Children.end()) {
OS << "({ ... ; ";
Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
- OS << " })";
- if (TerminateWithNewLine)
- OS << '\n';
+ OS << " })\n";
return;
}
}
@@ -5841,8 +5838,7 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (B->getOpcode() == BO_Comma) {
OS << "... , ";
Helper.handledStmt(B->getRHS(),OS);
- if (TerminateWithNewLine)
- OS << '\n';
+ OS << '\n';
return;
}
}
@@ -5870,14 +5866,15 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
}
// Expressions need a newline.
- if (isa<Expr>(S) && TerminateWithNewLine)
+ if (isa<Expr>(S))
OS << '\n';
- return;
+ break;
}
case CFGElement::Kind::Initializer:
print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
+ OS << '\n';
break;
case CFGElement::Kind::AutomaticObjectDtor: {
@@ -5891,44 +5888,43 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
OS << ".~";
T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
- OS << "() (Implicit destructor)";
+ OS << "() (Implicit destructor)\n";
break;
}
case CFGElement::Kind::CleanupFunction:
OS << "CleanupFunction ("
- << E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")";
+ << E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")\n";
break;
case CFGElement::Kind::LifetimeEnds:
Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
- OS << " (Lifetime ends)";
+ OS << " (Lifetime ends)\n";
break;
case CFGElement::Kind::LoopExit:
- OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName()
- << " (LoopExit)";
+ OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
break;
case CFGElement::Kind::ScopeBegin:
OS << "CFGScopeBegin(";
if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
OS << VD->getQualifiedNameAsString();
- OS << ")";
+ OS << ")\n";
break;
case CFGElement::Kind::ScopeEnd:
OS << "CFGScopeEnd(";
if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
OS << VD->getQualifiedNameAsString();
- OS << ")";
+ OS << ")\n";
break;
case CFGElement::Kind::NewAllocator:
OS << "CFGNewAllocator(";
if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
- OS << ")";
+ OS << ")\n";
break;
case CFGElement::Kind::DeleteDtor: {
@@ -5940,14 +5936,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)";
+ OS << " (Implicit destructor)\n";
break;
}
case CFGElement::Kind::BaseDtor: {
const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
- OS << " (Base object destructor)";
+ OS << " (Base object destructor)\n";
break;
}
@@ -5956,7 +5952,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)";
+ OS << " (Member object destructor)\n";
break;
}
@@ -5965,12 +5961,10 @@ 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)";
+ OS << "() (Temporary object destructor)\n";
break;
}
}
- if (TerminateWithNewLine)
- OS << '\n';
}
static void print_block(raw_ostream &OS, const CFG* cfg,
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 49ca39fd4ac3b..39dcaf02dbe25 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -273,29 +273,28 @@ class CStringChecker : public Checker< eval::Call,
/// Invalidate the destination buffer determined by characters copied.
static ProgramStateRef
invalidateDestinationBufferBySize(CheckerContext &C, ProgramStateRef S,
- const Expr *BufE, ConstCFGElementRef Elem,
- SVal BufV, SVal SizeV, QualType SizeTy);
+ const Expr *BufE, SVal BufV, SVal SizeV,
+ QualType SizeTy);
/// Operation never overflows, do not invalidate the super region.
static ProgramStateRef invalidateDestinationBufferNeverOverflows(
- CheckerContext &C, ProgramStateRef S, ConstCFGElementRef Elem, SVal BufV);
+ CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV);
/// We do not know whether the operation can overflow (e.g. size is unknown),
/// invalidate the super region and escape related pointers.
static ProgramStateRef invalidateDestinationBufferAlwaysEscapeSuperRegion(
- CheckerContext &C, ProgramStateRef S, ConstCFGElementRef Elem, SVal BufV);
+ CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV);
/// Invalidate the source buffer for escaping pointers.
static ProgramStateRef invalidateSourceBuffer(CheckerContext &C,
ProgramStateRef S,
- ConstCFGElementRef Elem,
- SVal BufV);
+ const Expr *BufE, SVal BufV);
/// @param InvalidationTraitOperations Determine how to invlidate the
/// MemRegion by setting the invalidation traits. Return true to cause pointer
/// escape, or false otherwise.
static ProgramStateRef invalidateBufferAux(
- CheckerContext &C, ProgramStateRef State, ConstCFGElementRef Elem, SVal V,
+ CheckerContext &C, ProgramStateRef State, const Expr *Ex, SVal V,
llvm::function_ref<bool(RegionAndSymbolInvalidationTraits &,
const MemRegion *)>
InvalidationTraitOperations);
@@ -303,8 +302,8 @@ class CStringChecker : public Checker< eval::Call,
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR);
- static bool memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
- SVal CharE, const Expr *Size, CheckerContext &C,
+ static bool memsetAux(const Expr *DstBuffer, SVal CharE,
+ const Expr *Size, CheckerContext &C,
ProgramStateRef &State);
// Re-usable checks
@@ -1212,8 +1211,8 @@ bool CStringChecker::isFirstBufInBound(CheckerContext &C, ProgramStateRef State,
}
ProgramStateRef CStringChecker::invalidateDestinationBufferBySize(
- CheckerContext &C, ProgramStateRef S, const Expr *BufE,
- ConstCFGElementRef Elem, SVal BufV, SVal SizeV, QualType SizeTy) {
+ CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV,
+ SVal SizeV, QualType SizeTy) {
auto InvalidationTraitOperations =
[&C, S, BufTy = BufE->getType(), BufV, SizeV,
SizeTy](RegionAndSymbolInvalidationTraits &ITraits, const MemRegion *R) {
@@ -1228,22 +1227,22 @@ ProgramStateRef CStringChecker::invalidateDestinationBufferBySize(
return false;
};
- return invalidateBufferAux(C, S, Elem, BufV, InvalidationTraitOperations);
+ return invalidateBufferAux(C, S, BufE, BufV, InvalidationTraitOperations);
}
ProgramStateRef
CStringChecker::invalidateDestinationBufferAlwaysEscapeSuperRegion(
- CheckerContext &C, ProgramStateRef S, ConstCFGElementRef Elem, SVal BufV) {
+ CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV) {
auto InvalidationTraitOperations = [](RegionAndSymbolInvalidationTraits &,
const MemRegion *R) {
return isa<FieldRegion>(R);
};
- return invalidateBufferAux(C, S, Elem, BufV, InvalidationTraitOperations);
+ return invalidateBufferAux(C, S, BufE, BufV, InvalidationTraitOperations);
}
ProgramStateRef CStringChecker::invalidateDestinationBufferNeverOverflows(
- CheckerContext &C, ProgramStateRef S, ConstCFGElementRef Elem, SVal BufV) {
+ CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV) {
auto InvalidationTraitOperations =
[](RegionAndSymbolInvalidationTraits &ITraits, const MemRegion *R) {
if (MemRegion::FieldRegionKind == R->getKind())
@@ -1253,12 +1252,12 @@ ProgramStateRef CStringChecker::invalidateDestinationBufferNeverOverflows(
return false;
};
- return invalidateBufferAux(C, S, Elem, BufV, InvalidationTraitOperations);
+ return invalidateBufferAux(C, S, BufE, BufV, InvalidationTraitOperations);
}
ProgramStateRef CStringChecker::invalidateSourceBuffer(CheckerContext &C,
ProgramStateRef S,
- ConstCFGElementRef Elem,
+ const Expr *BufE,
SVal BufV) {
auto InvalidationTraitOperations =
[](RegionAndSymbolInvalidationTraits &ITraits, const MemRegion *R) {
@@ -1270,11 +1269,11 @@ ProgramStateRef CStringChecker::invalidateSourceBuffer(CheckerContext &C,
return true;
};
- return invalidateBufferAux(C, S, Elem, BufV, InvalidationTraitOperations);
+ return invalidateBufferAux(C, S, BufE, BufV, InvalidationTraitOperations);
}
ProgramStateRef CStringChecker::invalidateBufferAux(
- CheckerContext &C, ProgramStateRef State, ConstCFGElementRef Elem, SVal V,
+ CheckerContext &C, ProgramStateRef State, const Expr *E, SVal V,
llvm::function_ref<bool(RegionAndSymbolInvalidationTraits &,
const MemRegion *)>
InvalidationTraitOperations) {
@@ -1300,7 +1299,7 @@ ProgramStateRef CStringChecker::invalidateBufferAux(
RegionAndSymbolInvalidationTraits ITraits;
bool CausesPointerEscape = InvalidationTraitOperations(ITraits, R);
- return State->invalidateRegions(R, Elem, C.blockCount(), LCtx,
+ return State->invalidateRegions(R, E, C.blockCount(), LCtx,
CausesPointerEscape, nullptr, nullptr,
&ITraits);
}
@@ -1350,9 +1349,9 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
}
}
-bool CStringChecker::memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
- SVal CharVal, const Expr *Size,
- CheckerContext &C, ProgramStateRef &State) {
+bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal,
+ const Expr *Size, CheckerContext &C,
+ ProgramStateRef &State) {
SVal MemVal = C.getSVal(DstBuffer);
SVal SizeVal = C.getSVal(Size);
const MemRegion *MR = MemVal.getAsRegion();
@@ -1405,8 +1404,8 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
} else {
// If the destination buffer's extent is not equal to the value of
// third argument, just invalidate buffer.
- State = invalidateDestinationBufferBySize(
- C, State, DstBuffer, Elem, MemVal, SizeVal, Size->getType());
+ State = invalidateDestinationBufferBySize(C, State, DstBuffer, MemVal,
+ SizeVal, Size->getType());
}
if (StateNullChar && !StateNonNullChar) {
@@ -1431,7 +1430,7 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
} else {
// If the offset is not zero and char value is not concrete, we can do
// nothing but invalidate the buffer.
- State = invalidateDestinationBufferBySize(C, State, DstBuffer, Elem, MemVal,
+ State = invalidateDestinationBufferBySize(C, State, DstBuffer, MemVal,
SizeVal, Size->getType());
}
return true;
@@ -1516,8 +1515,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
// conjure a return value for later.
if (lastElement.isUnknown())
lastElement = C.getSValBuilder().conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx,
- C.blockCount());
+ nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
// The byte after the last byte copied is the return value.
state = state->BindExpr(Call.getOriginExpr(), LCtx, lastElement);
@@ -1534,12 +1532,12 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
// This would probably remove any existing bindings past the end of the
// copied region, but that's still an improvement over blank invalidation.
state = invalidateDestinationBufferBySize(
- C, state, Dest.Expression, Call.getCFGElementRef(),
- C.getSVal(Dest.Expression), sizeVal, Size.Expression->getType());
+ C, state, Dest.Expression, C.getSVal(Dest.Expression), sizeVal,
+ Size.Expression->getType());
// Invalidate the source (const-invalidation without const-pointer-escaping
// the address of the top-level region).
- state = invalidateSourceBuffer(C, state, Call.getCFGElementRef(),
+ state = invalidateSourceBuffer(C, state, Source.Expression,
C.getSVal(Source.Expression));
C.addTransition(state);
@@ -1667,8 +1665,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
State = CheckBufferAccess(C, State, Left, Size, AccessKind::read, CK);
if (State) {
// The return value is the comparison result, which we don't know.
- SVal CmpV = Builder.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ SVal CmpV = Builder.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
+ C.blockCount());
State = State->BindExpr(Call.getOriginExpr(), LCtx, CmpV);
C.addTransition(State);
}
@@ -1772,7 +1770,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// All we know is the return value is the min of the string length
// and the limit. This is better than nothing.
result = C.getSValBuilder().conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
NonLoc resultNL = result.castAs<NonLoc>();
if (strLengthNL) {
@@ -1796,7 +1794,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// value, so it can be used in constraints, at least.
if (result.isUnknown()) {
result = C.getSValBuilder().conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
}
}
@@ -2237,13 +2235,13 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
// can use LazyCompoundVals to copy the source values into the destination.
// This would probably remove any existing bindings past the end of the
// string, but that's still an improvement over blank invalidation.
- state = invalidateDestinationBufferBySize(
- C, state, Dst.Expression, Call.getCFGElementRef(), *dstRegVal,
- amountCopied, C.getASTContext().getSizeType());
+ state = invalidateDestinationBufferBySize(C, state, Dst.Expression,
+ *dstRegVal, amountCopied,
+ C.getASTContext().getSizeType());
// Invalidate the source (const-invalidation without const-pointer-escaping
// the address of the top-level region).
- state = invalidateSourceBuffer(C, state, Call.getCFGElementRef(), srcVal);
+ state = invalidateSourceBuffer(C, state, srcExpr.Expression, srcVal);
// Set the C string length of the destination, if we know it.
if (IsBounded && (appendK == ConcatFnKind::none)) {
@@ -2263,8 +2261,8 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
// If this is a stpcpy-style copy, but we were unable to check for a buffer
// overflow, we still need a result. Conjure a return value.
if (ReturnEnd && Result.isUnknown()) {
- Result = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ Result = svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
+ C.blockCount());
}
}
// Set the return value.
@@ -2363,8 +2361,8 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
const StringLiteral *RightStrLiteral =
getCStringLiteral(C, state, Right.Expression, RightVal);
bool canComputeResult = false;
- SVal resultVal = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, Call.getOriginExpr(),
+ LCtx, C.blockCount());
if (LeftStrLiteral && RightStrLiteral) {
StringRef LeftStrRef = LeftStrLiteral->getString();
@@ -2465,20 +2463,20 @@ void CStringChecker::evalStrsep(CheckerContext &C,
// character to NUL.
// As the replacement never overflows, do not invalidate its super region.
State = invalidateDestinationBufferNeverOverflows(
- C, State, Call.getCFGElementRef(), Result);
+ C, State, SearchStrPtr.Expression, Result);
// Overwrite the search string pointer. The new value is either an address
// further along in the same string, or NULL if there are no more tokens.
State =
State->bindLoc(*SearchStrLoc,
- SVB.conjureSymbolVal(getTag(), Call.getCFGElementRef(),
+ SVB.conjureSymbolVal(getTag(), Call.getOriginExpr(),
LCtx, CharPtrTy, C.blockCount()),
LCtx);
} else {
assert(SearchStrVal.isUnknown());
// Conjure a symbolic value. It's the best we can do.
- Result = SVB.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ Result = SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx,
+ C.blockCount());
}
// Set the return value, and finish.
@@ -2516,13 +2514,13 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
SVal DstVal = State->getSVal(Dst, LCtx);
// FIXME: As we do not know how many items are copied, we also invalidate the
// super region containing the target location.
- State = invalidateDestinationBufferAlwaysEscapeSuperRegion(
- C, State, Call.getCFGElementRef(), DstVal);
+ State =
+ invalidateDestinationBufferAlwaysEscapeSuperRegion(C, State, Dst, DstVal);
SValBuilder &SVB = C.getSValBuilder();
- SVal ResultVal = SVB.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), LCtx, C.blockCount());
+ SVal ResultVal =
+ SVB.conjureSymbolVal(nullptr, Call.getOriginExpr(), LCtx, C.blockCount());
State = State->BindExpr(Call.getOriginExpr(), LCtx, ResultVal);
C.addTransition(State);
@@ -2571,8 +2569,8 @@ void CStringChecker::evalMemset(CheckerContext &C,
// According to the values of the arguments, bind the value of the second
// argument to the destination buffer and set string length, or just
// invalidate the destination buffer.
- if (!memsetAux(Buffer.Expression, Call.getCFGElementRef(),
- C.getSVal(CharE.Expression), Size.Expression, C, State))
+ if (!memsetAux(Buffer.Expression, C.getSVal(CharE.Expression),
+ Size.Expression, C, State))
return;
State = State->BindExpr(Call.getOriginExpr(), LCtx, BufferPtrVal);
@@ -2616,8 +2614,7 @@ void CStringChecker::evalBzero(CheckerContext &C, const CallEvent &Call) const {
if (!State)
return;
- if (!memsetAux(Buffer.Expression, Call.getCFGElementRef(), Zero,
- Size.Expression, C, State))
+ if (!memsetAux(Buffer.Expression, Zero, Size.Expression, C, State))
return;
C.addTransition(State);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 3cc49e408387b..d850344db6591 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -33,11 +33,11 @@ namespace {
class ContainerModeling
: public Checker<check::PostCall, check::LiveSymbols, check::DeadSymbols> {
- void handleBegin(CheckerContext &C, ConstCFGElementRef Elem, SVal RetVal,
+ void handleBegin(CheckerContext &C, const Expr *CE, SVal RetVal,
SVal Cont) const;
- void handleEnd(CheckerContext &C, ConstCFGElementRef Elem, SVal RetVal,
+ void handleEnd(CheckerContext &C, const Expr *CE, SVal RetVal,
SVal Cont) const;
- void handleAssignment(CheckerContext &C, SVal Cont, ConstCFGElementRef Elem,
+ void handleAssignment(CheckerContext &C, SVal Cont, const Expr *CE = nullptr,
SVal OldCont = UndefinedVal()) const;
void handleAssign(CheckerContext &C, SVal Cont, const Expr *ContE) const;
void handleClear(CheckerContext &C, SVal Cont, const Expr *ContE) const;
@@ -108,12 +108,11 @@ bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
ProgramStateRef createContainerBegin(ProgramStateRef State,
- const MemRegion *Cont,
- ConstCFGElementRef Elem, QualType T,
- const LocationContext *LCtx,
+ const MemRegion *Cont, const Expr *E,
+ QualType T, const LocationContext *LCtx,
unsigned BlockCount);
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
- ConstCFGElementRef Elem, QualType T,
+ const Expr *E, QualType T,
const LocationContext *LCtx,
unsigned BlockCount);
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
@@ -164,12 +163,12 @@ void ContainerModeling::checkPostCall(const CallEvent &Call,
return;
if (cast<CXXMethodDecl>(Func)->isMoveAssignmentOperator()) {
- handleAssignment(C, InstCall->getCXXThisVal(), Call.getCFGElementRef(),
- Call.getArgSVal(0));
+ handleAssignment(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
+ Call.getArgSVal(0));
return;
}
- handleAssignment(C, InstCall->getCXXThisVal(), C.getCFGElementRef());
+ handleAssignment(C, InstCall->getCXXThisVal());
return;
}
} else {
@@ -199,13 +198,13 @@ void ContainerModeling::checkPostCall(const CallEvent &Call,
return;
if (isBeginCall(Func)) {
- handleBegin(C, Call.getCFGElementRef(), Call.getReturnValue(),
+ handleBegin(C, OrigExpr, Call.getReturnValue(),
InstCall->getCXXThisVal());
return;
}
if (isEndCall(Func)) {
- handleEnd(C, Call.getCFGElementRef(), Call.getReturnValue(),
+ handleEnd(C, OrigExpr, Call.getReturnValue(),
InstCall->getCXXThisVal());
return;
}
@@ -251,8 +250,8 @@ void ContainerModeling::checkDeadSymbols(SymbolReaper &SR,
C.addTransition(State);
}
-void ContainerModeling::handleBegin(CheckerContext &C, ConstCFGElementRef Elem,
- SVal RetVal, SVal Cont) const {
+void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
+ SVal RetVal, SVal Cont) const {
const auto *ContReg = Cont.getAsRegion();
if (!ContReg)
return;
@@ -264,7 +263,7 @@ void ContainerModeling::handleBegin(CheckerContext &C, ConstCFGElementRef Elem,
auto State = C.getState();
auto BeginSym = getContainerBegin(State, ContReg);
if (!BeginSym) {
- State = createContainerBegin(State, ContReg, Elem, C.getASTContext().LongTy,
+ State = createContainerBegin(State, ContReg, CE, C.getASTContext().LongTy,
C.getLocationContext(), C.blockCount());
BeginSym = getContainerBegin(State, ContReg);
}
@@ -273,8 +272,8 @@ void ContainerModeling::handleBegin(CheckerContext &C, ConstCFGElementRef Elem,
C.addTransition(State);
}
-void ContainerModeling::handleEnd(CheckerContext &C, ConstCFGElementRef Elem,
- SVal RetVal, SVal Cont) const {
+void ContainerModeling::handleEnd(CheckerContext &C, const Expr *CE,
+ SVal RetVal, SVal Cont) const {
const auto *ContReg = Cont.getAsRegion();
if (!ContReg)
return;
@@ -286,7 +285,7 @@ void ContainerModeling::handleEnd(CheckerContext &C, ConstCFGElementRef Elem,
auto State = C.getState();
auto EndSym = getContainerEnd(State, ContReg);
if (!EndSym) {
- State = createContainerEnd(State, ContReg, Elem, C.getASTContext().LongTy,
+ State = createContainerEnd(State, ContReg, CE, C.getASTContext().LongTy,
C.getLocationContext(), C.blockCount());
EndSym = getContainerEnd(State, ContReg);
}
@@ -296,8 +295,7 @@ void ContainerModeling::handleEnd(CheckerContext &C, ConstCFGElementRef Elem,
}
void ContainerModeling::handleAssignment(CheckerContext &C, SVal Cont,
- ConstCFGElementRef Elem,
- SVal OldCont) const {
+ const Expr *CE, SVal OldCont) const {
const auto *ContReg = Cont.getAsRegion();
if (!ContReg)
return;
@@ -331,7 +329,7 @@ void ContainerModeling::handleAssignment(CheckerContext &C, SVal Cont,
auto &SVB = C.getSValBuilder();
// Then generate and assign a new "end" symbol for the new container.
auto NewEndSym =
- SymMgr.conjureSymbol(Elem, C.getLocationContext(),
+ SymMgr.conjureSymbol(CE, C.getLocationContext(),
C.getASTContext().LongTy, C.blockCount());
State = assumeNoOverflow(State, NewEndSym, 4);
if (CData) {
@@ -850,9 +848,8 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
}
ProgramStateRef createContainerBegin(ProgramStateRef State,
- const MemRegion *Cont,
- ConstCFGElementRef Elem, QualType T,
- const LocationContext *LCtx,
+ const MemRegion *Cont, const Expr *E,
+ QualType T, const LocationContext *LCtx,
unsigned BlockCount) {
// Only create if it does not exist
const auto *CDataPtr = getContainerData(State, Cont);
@@ -860,8 +857,8 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
return State;
auto &SymMgr = State->getSymbolManager();
- const SymbolConjured *Sym =
- SymMgr.conjureSymbol(Elem, LCtx, T, BlockCount, "begin");
+ const SymbolConjured *Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount,
+ "begin");
State = assumeNoOverflow(State, Sym, 4);
if (CDataPtr) {
@@ -874,7 +871,7 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
}
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
- ConstCFGElementRef Elem, QualType T,
+ const Expr *E, QualType T,
const LocationContext *LCtx,
unsigned BlockCount) {
// Only create if it does not exist
@@ -883,8 +880,8 @@ ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
return State;
auto &SymMgr = State->getSymbolManager();
- const SymbolConjured *Sym =
- SymMgr.conjureSymbol(Elem, LCtx, T, BlockCount, "end");
+ const SymbolConjured *Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount,
+ "end");
State = assumeNoOverflow(State, Sym, 4);
if (CDataPtr) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
index abfc5d20d3094..6ffc05f06742b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -124,7 +124,7 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
// of the data member `ErrnoDecl` of the singleton `ErrnoModeling` checker
// object.
const SymbolConjured *Sym = SVB.conjureSymbol(
- C.getCFGElementRef(), C.getLocationContext(),
+ nullptr, C.getLocationContext(),
ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl);
// The symbolic region is untyped, create a typed sub-region in it.
@@ -256,11 +256,11 @@ ProgramStateRef setErrnoForStdFailure(ProgramStateRef State, CheckerContext &C,
ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
CheckerContext &C,
- ConstCFGElementRef Elem) {
+ const Expr *InvalE) {
const MemRegion *ErrnoR = State->get<ErrnoRegion>();
if (!ErrnoR)
return State;
- State = State->invalidateRegions(ErrnoR, Elem, C.blockCount(),
+ State = State->invalidateRegions(ErrnoR, InvalE, C.blockCount(),
C.getLocationContext(), false);
if (!State)
return nullptr;
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
index e414353322054..95da8a28d3253 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
@@ -96,10 +96,9 @@ ProgramStateRef setErrnoForStdFailure(ProgramStateRef State, CheckerContext &C,
/// Set errno state for the common case when a standard function indicates
/// failure only by \c errno. Sets \c ErrnoCheckState to \c MustBeChecked, and
/// invalidates the errno region (clear of previous value).
-/// \arg \c Elem CFG Element that causes invalidation of \c errno.
+/// \arg \c InvalE Expression that causes invalidation of \c errno.
ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
- CheckerContext &C,
- ConstCFGElementRef Elem);
+ CheckerContext &C, const Expr *InvalE);
} // namespace errno_modeling
} // namespace ento
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
index be70819175299..6076a6bc78973 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoTesterChecker.cpp
@@ -131,8 +131,7 @@ void ErrnoTesterChecker::evalSetErrnoIfErrorRange(CheckerContext &C,
ProgramStateRef StateFailure = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
DefinedOrUnknownSVal ErrnoVal = SVB.conjureSymbolVal(
- /*symbolTag=*/nullptr, Call.getCFGElementRef(), C.getLocationContext(),
- C.blockCount());
+ nullptr, Call.getOriginExpr(), C.getLocationContext(), C.blockCount());
StateFailure = StateFailure->assume(ErrnoVal, true);
assert(StateFailure && "Failed to assume on an initial value.");
StateFailure =
diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index e9825b7077c7d..ba561ddebdb69 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -207,15 +207,14 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
}
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
- const MemRegion *Cont,
- ConstCFGElementRef Elem,
+ const MemRegion *Cont, const Stmt *S,
const LocationContext *LCtx,
unsigned blockCount) {
auto &StateMgr = State->getStateManager();
auto &SymMgr = StateMgr.getSymbolManager();
auto &ACtx = StateMgr.getContext();
- auto *Sym = SymMgr.conjureSymbol(Elem, LCtx, ACtx.LongTy, blockCount);
+ auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
State = assumeNoOverflow(State, Sym, 4);
return setIteratorPosition(State, Val,
IteratorPosition::getPosition(Cont, Sym));
diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.h b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
index 0a26db0f2b0a1..46de8ea01d77b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Iterator.h
+++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.h
@@ -165,8 +165,7 @@ const IteratorPosition *getIteratorPosition(ProgramStateRef State, SVal Val);
ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
const IteratorPosition &Pos);
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
- const MemRegion *Cont,
- ConstCFGElementRef Elem,
+ const MemRegion *Cont, const Stmt *S,
const LocationContext *LCtx,
unsigned blockCount);
ProgramStateRef advancePosition(ProgramStateRef State, SVal Iter,
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 6139585f1c409..d4ce73b03acb8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -90,9 +90,8 @@ class IteratorModeling
check::PostStmt<MaterializeTemporaryExpr>,
check::Bind, check::LiveSymbols, check::DeadSymbols> {
- using AdvanceFn = void (IteratorModeling::*)(CheckerContext &,
- ConstCFGElementRef, SVal, SVal,
- SVal) const;
+ using AdvanceFn = void (IteratorModeling::*)(CheckerContext &, const Expr *,
+ SVal, SVal, SVal) const;
void handleOverloadedOperator(CheckerContext &C, const CallEvent &Call,
OverloadedOperatorKind Op) const;
@@ -100,9 +99,8 @@ class IteratorModeling
const Expr *OrigExpr,
const AdvanceFn *Handler) const;
- void handleComparison(CheckerContext &C, const Expr *CE,
- ConstCFGElementRef Elem, SVal RetVal, SVal LVal,
- SVal RVal, OverloadedOperatorKind Op) const;
+ void handleComparison(CheckerContext &C, const Expr *CE, SVal RetVal,
+ SVal LVal, SVal RVal, OverloadedOperatorKind Op) const;
void processComparison(CheckerContext &C, ProgramStateRef State,
SymbolRef Sym1, SymbolRef Sym2, SVal RetVal,
OverloadedOperatorKind Op) const;
@@ -110,20 +108,19 @@ class IteratorModeling
bool Postfix) const;
void handleDecrement(CheckerContext &C, SVal RetVal, SVal Iter,
bool Postfix) const;
- void handleRandomIncrOrDecr(CheckerContext &C, ConstCFGElementRef Elem,
+ void handleRandomIncrOrDecr(CheckerContext &C, const Expr *CE,
OverloadedOperatorKind Op, SVal RetVal,
SVal Iterator, SVal Amount) const;
void handlePtrIncrOrDecr(CheckerContext &C, const Expr *Iterator,
- ConstCFGElementRef Elem, OverloadedOperatorKind OK,
- SVal Offset) const;
- void handleAdvance(CheckerContext &C, ConstCFGElementRef Elem, SVal RetVal,
- SVal Iter, SVal Amount) const;
- void handlePrev(CheckerContext &C, ConstCFGElementRef Elem, SVal RetVal,
- SVal Iter, SVal Amount) const;
- void handleNext(CheckerContext &C, ConstCFGElementRef Elem, SVal RetVal,
- SVal Iter, SVal Amount) const;
- void assignToContainer(CheckerContext &C, ConstCFGElementRef Elem,
- SVal RetVal, const MemRegion *Cont) const;
+ OverloadedOperatorKind OK, SVal Offset) const;
+ void handleAdvance(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
+ SVal Amount) const;
+ void handlePrev(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
+ SVal Amount) const;
+ void handleNext(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
+ SVal Amount) const;
+ void assignToContainer(CheckerContext &C, const Expr *CE, SVal RetVal,
+ const MemRegion *Cont) const;
bool noChangeInAdvance(CheckerContext &C, SVal Iter, const Expr *CE) const;
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
const char *Sep) const override;
@@ -227,7 +224,7 @@ void IteratorModeling::checkPostCall(const CallEvent &Call,
C.getASTContext()).getTypePtr() ==
Call.getResultType().getDesugaredType(C.getASTContext()).getTypePtr()) {
if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(i))) {
- assignToContainer(C, Call.getCFGElementRef(), Call.getReturnValue(),
+ assignToContainer(C, OrigExpr, Call.getReturnValue(),
Pos->getContainer());
return;
}
@@ -258,7 +255,7 @@ void IteratorModeling::checkPostStmt(const UnaryOperator *UO,
return;
auto &SVB = C.getSValBuilder();
- handlePtrIncrOrDecr(C, UO->getSubExpr(), C.getCFGElementRef(),
+ handlePtrIncrOrDecr(C, UO->getSubExpr(),
isIncrementOperator(OK) ? OO_Plus : OO_Minus,
SVB.makeArrayIndex(1));
}
@@ -274,7 +271,7 @@ void IteratorModeling::checkPostStmt(const BinaryOperator *BO,
if (isSimpleComparisonOperator(BO->getOpcode())) {
SVal Result = State->getSVal(BO, C.getLocationContext());
- handleComparison(C, BO, C.getCFGElementRef(), Result, LVal, RVal,
+ handleComparison(C, BO, Result, LVal, RVal,
BinaryOperator::getOverloadedOperator(OK));
} else if (isRandomIncrOrDecrOperator(OK)) {
// In case of operator+ the iterator can be either on the LHS (eg.: it + 1),
@@ -287,8 +284,8 @@ void IteratorModeling::checkPostStmt(const BinaryOperator *BO,
if (!AmountExpr->getType()->isIntegralOrEnumerationType())
return;
SVal AmountVal = IsIterOnLHS ? RVal : LVal;
- handlePtrIncrOrDecr(C, IterExpr, C.getCFGElementRef(),
- BinaryOperator::getOverloadedOperator(OK), AmountVal);
+ handlePtrIncrOrDecr(C, IterExpr, BinaryOperator::getOverloadedOperator(OK),
+ AmountVal);
}
}
@@ -354,29 +351,27 @@ IteratorModeling::handleOverloadedOperator(CheckerContext &C,
OverloadedOperatorKind Op) const {
if (isSimpleComparisonOperator(Op)) {
const auto *OrigExpr = Call.getOriginExpr();
- const auto Elem = Call.getCFGElementRef();
if (!OrigExpr)
return;
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
- handleComparison(C, OrigExpr, Elem, Call.getReturnValue(),
+ handleComparison(C, OrigExpr, Call.getReturnValue(),
InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
return;
}
- handleComparison(C, OrigExpr, Elem, Call.getReturnValue(),
- Call.getArgSVal(0), Call.getArgSVal(1), Op);
+ handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
+ Call.getArgSVal(1), Op);
return;
} else if (isRandomIncrOrDecrOperator(Op)) {
const auto *OrigExpr = Call.getOriginExpr();
- const auto Elem = Call.getCFGElementRef();
if (!OrigExpr)
return;
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
if (Call.getNumArgs() >= 1 &&
Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
- handleRandomIncrOrDecr(C, Elem, Op, Call.getReturnValue(),
+ handleRandomIncrOrDecr(C, OrigExpr, Op, Call.getReturnValue(),
InstCall->getCXXThisVal(), Call.getArgSVal(0));
return;
}
@@ -396,8 +391,8 @@ IteratorModeling::handleOverloadedOperator(CheckerContext &C,
SVal Iterator = IsIterFirst ? FirstArg : SecondArg;
SVal Amount = IsIterFirst ? SecondArg : FirstArg;
- handleRandomIncrOrDecr(C, Elem, Op, Call.getReturnValue(), Iterator,
- Amount);
+ handleRandomIncrOrDecr(C, OrigExpr, Op, Call.getReturnValue(),
+ Iterator, Amount);
return;
}
}
@@ -430,7 +425,7 @@ IteratorModeling::handleAdvanceLikeFunction(CheckerContext &C,
const Expr *OrigExpr,
const AdvanceFn *Handler) const {
if (!C.wasInlined) {
- (this->**Handler)(C, Call.getCFGElementRef(), Call.getReturnValue(),
+ (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
Call.getArgSVal(0), Call.getArgSVal(1));
return;
}
@@ -441,7 +436,7 @@ IteratorModeling::handleAdvanceLikeFunction(CheckerContext &C,
if (IdInfo) {
if (IdInfo->getName() == "advance") {
if (noChangeInAdvance(C, Call.getArgSVal(0), OrigExpr)) {
- (this->**Handler)(C, Call.getCFGElementRef(), Call.getReturnValue(),
+ (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
Call.getArgSVal(0), Call.getArgSVal(1));
}
}
@@ -449,8 +444,7 @@ IteratorModeling::handleAdvanceLikeFunction(CheckerContext &C,
}
void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
- ConstCFGElementRef Elem, SVal RetVal,
- SVal LVal, SVal RVal,
+ SVal RetVal, SVal LVal, SVal RVal,
OverloadedOperatorKind Op) const {
// Record the operands and the operator of the comparison for the next
// evalAssume, if the result is a symbolic expression. If it is a concrete
@@ -473,7 +467,7 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
SymbolRef Sym;
if (!LPos || !RPos) {
auto &SymMgr = C.getSymbolManager();
- Sym = SymMgr.conjureSymbol(Elem, C.getLocationContext(),
+ Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
C.getASTContext().LongTy, C.blockCount());
State = assumeNoOverflow(State, Sym, 4);
}
@@ -500,7 +494,7 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
auto &SymMgr = C.getSymbolManager();
auto *LCtx = C.getLocationContext();
RetVal = nonloc::SymbolVal(SymMgr.conjureSymbol(
- Elem, LCtx, C.getASTContext().BoolTy, C.blockCount()));
+ CE, LCtx, C.getASTContext().BoolTy, C.blockCount()));
State = State->BindExpr(CE, LCtx, RetVal);
}
@@ -589,8 +583,7 @@ void IteratorModeling::handleDecrement(CheckerContext &C, SVal RetVal,
C.addTransition(State);
}
-void IteratorModeling::handleRandomIncrOrDecr(CheckerContext &C,
- ConstCFGElementRef Elem,
+void IteratorModeling::handleRandomIncrOrDecr(CheckerContext &C, const Expr *CE,
OverloadedOperatorKind Op,
SVal RetVal, SVal Iterator,
SVal Amount) const {
@@ -624,13 +617,12 @@ void IteratorModeling::handleRandomIncrOrDecr(CheckerContext &C,
State = setIteratorPosition(State, TgtVal, *NewPos);
C.addTransition(State);
} else {
- assignToContainer(C, Elem, TgtVal, Pos->getContainer());
+ assignToContainer(C, CE, TgtVal, Pos->getContainer());
}
}
void IteratorModeling::handlePtrIncrOrDecr(CheckerContext &C,
const Expr *Iterator,
- ConstCFGElementRef Elem,
OverloadedOperatorKind OK,
SVal Offset) const {
if (!isa<DefinedSVal>(Offset))
@@ -669,35 +661,34 @@ void IteratorModeling::handlePtrIncrOrDecr(CheckerContext &C,
ProgramStateRef NewState = setIteratorPosition(State, NewVal, *NewPos);
C.addTransition(NewState);
} else {
- assignToContainer(C, Elem, NewVal, OldPos->getContainer());
+ assignToContainer(C, Iterator, NewVal, OldPos->getContainer());
}
}
-void IteratorModeling::handleAdvance(CheckerContext &C, ConstCFGElementRef Elem,
+void IteratorModeling::handleAdvance(CheckerContext &C, const Expr *CE,
SVal RetVal, SVal Iter,
SVal Amount) const {
- handleRandomIncrOrDecr(C, Elem, OO_PlusEqual, RetVal, Iter, Amount);
+ handleRandomIncrOrDecr(C, CE, OO_PlusEqual, RetVal, Iter, Amount);
}
-void IteratorModeling::handlePrev(CheckerContext &C, ConstCFGElementRef Elem,
+void IteratorModeling::handlePrev(CheckerContext &C, const Expr *CE,
SVal RetVal, SVal Iter, SVal Amount) const {
- handleRandomIncrOrDecr(C, Elem, OO_Minus, RetVal, Iter, Amount);
+ handleRandomIncrOrDecr(C, CE, OO_Minus, RetVal, Iter, Amount);
}
-void IteratorModeling::handleNext(CheckerContext &C, ConstCFGElementRef Elem,
+void IteratorModeling::handleNext(CheckerContext &C, const Expr *CE,
SVal RetVal, SVal Iter, SVal Amount) const {
- handleRandomIncrOrDecr(C, Elem, OO_Plus, RetVal, Iter, Amount);
+ handleRandomIncrOrDecr(C, CE, OO_Plus, RetVal, Iter, Amount);
}
-void IteratorModeling::assignToContainer(CheckerContext &C,
- ConstCFGElementRef Elem, SVal RetVal,
+void IteratorModeling::assignToContainer(CheckerContext &C, const Expr *CE,
+ SVal RetVal,
const MemRegion *Cont) const {
Cont = Cont->getMostDerivedObjectRegion();
auto State = C.getState();
const auto *LCtx = C.getLocationContext();
- State =
- createIteratorPosition(State, RetVal, Cont, Elem, LCtx, C.blockCount());
+ State = createIteratorPosition(State, RetVal, Cont, CE, LCtx, C.blockCount());
C.addTransition(State);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index e970a891d75d0..1c4293c30abdb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1833,10 +1833,8 @@ ProgramStateRef MallocChecker::MallocBindRetVal(CheckerContext &C,
unsigned Count = C.blockCount();
SValBuilder &SVB = C.getSValBuilder();
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
- DefinedSVal RetVal =
- isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
- : SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
- CE->getType(), Count);
+ DefinedSVal RetVal = isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
+ : SVB.getConjuredHeapSymbolVal(CE, LCtx, Count);
return State->BindExpr(CE, C.getLocationContext(), RetVal);
}
@@ -2306,7 +2304,7 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
// Assume that after memory is freed, it contains unknown values. This
// conforts languages standards, since reading from freed memory is considered
// UB and may result in arbitrary value.
- State = State->invalidateRegions({location}, Call.getCFGElementRef(),
+ State = State->invalidateRegions({location}, Call.getOriginExpr(),
C.blockCount(), C.getLocationContext(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index 03a6b60f93375..cc1ced7358710 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -932,8 +932,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
(hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
SValBuilder &SVB = C.getSValBuilder();
RetVal =
- SVB.conjureSymbolVal(/*symbolTag=*/nullptr, Call.getCFGElementRef(),
- LCtx, ResultTy, C.blockCount());
+ SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
}
// Bind the value.
diff --git a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
index 8e1996306d7a5..e037719b90298 100644
--- a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
@@ -25,12 +25,12 @@ using namespace iterator;
namespace {
class STLAlgorithmModeling : public Checker<eval::Call> {
- bool evalFind(CheckerContext &C, const CallEvent &Call) const;
+ bool evalFind(CheckerContext &C, const CallExpr *CE) const;
- void Find(CheckerContext &C, const CallEvent &Call, unsigned paramNum) const;
+ void Find(CheckerContext &C, const CallExpr *CE, unsigned paramNum) const;
using FnCheck = bool (STLAlgorithmModeling::*)(CheckerContext &,
- const CallEvent &Call) const;
+ const CallExpr *) const;
const CallDescriptionMap<FnCheck> Callbacks = {
{{CDM::SimpleFunc, {"std", "find"}, 3}, &STLAlgorithmModeling::evalFind},
@@ -97,12 +97,11 @@ bool STLAlgorithmModeling::evalCall(const CallEvent &Call,
if (!Handler)
return false;
- return (this->**Handler)(C, Call);
+ return (this->**Handler)(C, CE);
}
bool STLAlgorithmModeling::evalFind(CheckerContext &C,
- const CallEvent &Call) const {
- const auto *CE = dyn_cast<CallExpr>(Call.getOriginExpr());
+ const CallExpr *CE) const {
// std::find()-like functions either take their primary range in the first
// two parameters, or if the first parameter is "execution policy" then in
// the second and third. This means that the second parameter must always be
@@ -113,29 +112,27 @@ bool STLAlgorithmModeling::evalFind(CheckerContext &C,
// If no "execution policy" parameter is used then the first argument is the
// beginning of the range.
if (isIteratorType(CE->getArg(0)->getType())) {
- Find(C, Call, 0);
+ Find(C, CE, 0);
return true;
}
// If "execution policy" parameter is used then the second argument is the
// beginning of the range.
if (isIteratorType(CE->getArg(2)->getType())) {
- Find(C, Call, 1);
+ Find(C, CE, 1);
return true;
}
return false;
}
-void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
+void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
unsigned paramNum) const {
- const auto *CE = dyn_cast<CallExpr>(Call.getOriginExpr());
- const auto &Elem = Call.getCFGElementRef();
auto State = C.getState();
auto &SVB = C.getSValBuilder();
const auto *LCtx = C.getLocationContext();
- SVal RetVal = SVB.conjureSymbolVal(nullptr, Elem, LCtx, C.blockCount());
+ SVal RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
SVal Param = State->getSVal(CE->getArg(paramNum), LCtx);
auto StateFound = State->BindExpr(CE, LCtx, RetVal);
@@ -147,7 +144,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
const auto *Pos = getIteratorPosition(State, Param);
if (Pos) {
StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
- Elem, LCtx, C.blockCount());
+ CE, LCtx, C.blockCount());
const auto *NewPos = getIteratorPosition(StateFound, RetVal);
assert(NewPos && "Failed to create new iterator position.");
@@ -169,7 +166,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
Pos = getIteratorPosition(State, Param);
if (Pos) {
StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
- Elem, LCtx, C.blockCount());
+ CE, LCtx, C.blockCount());
const auto *NewPos = getIteratorPosition(StateFound, RetVal);
assert(NewPos && "Failed to create new iterator position.");
@@ -202,3 +199,4 @@ void ento::registerSTLAlgorithmModeling(CheckerManager &Mgr) {
bool ento::shouldRegisterSTLAlgorithmModeling(const CheckerManager &mgr) {
return true;
}
+
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index 9b0ce151954f3..321388ad857f4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -78,9 +78,10 @@ class SmartPtrModeling
bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
bool handleSwap(ProgramStateRef State, SVal First, SVal Second,
CheckerContext &C) const;
- std::pair<SVal, ProgramStateRef> retrieveOrConjureInnerPtrVal(
- ProgramStateRef State, const MemRegion *ThisRegion,
- ConstCFGElementRef Elem, QualType Type, CheckerContext &C) const;
+ std::pair<SVal, ProgramStateRef>
+ retrieveOrConjureInnerPtrVal(ProgramStateRef State,
+ const MemRegion *ThisRegion, const Expr *E,
+ QualType Type, CheckerContext &C) const;
using SmartPtrMethodHandlerFn =
void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -305,7 +306,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
return false;
const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
- Call.getCFGElementRef(), C.getLocationContext(),
+ Call.getOriginExpr(), C.getLocationContext(),
getPointerTypeFromTemplateArg(Call, C), C.blockCount());
const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
@@ -436,12 +437,12 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
}
std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
- ProgramStateRef State, const MemRegion *ThisRegion, ConstCFGElementRef Elem,
+ ProgramStateRef State, const MemRegion *ThisRegion, const Expr *E,
QualType Type, CheckerContext &C) const {
const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
if (Ptr)
return {*Ptr, State};
- auto Val = C.getSValBuilder().conjureSymbolVal(Elem, C.getLocationContext(),
+ auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(),
Type, C.blockCount());
State = State->set<TrackedRegionMap>(ThisRegion, Val);
return {Val, State};
@@ -468,7 +469,6 @@ bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
// https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp.
auto makeSValFor = [&C, this](ProgramStateRef State, const Expr *E,
- ConstCFGElementRef Elem,
SVal S) -> std::pair<SVal, ProgramStateRef> {
if (S.isZeroConstant()) {
return {S, State};
@@ -477,7 +477,7 @@ bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
assert(Reg &&
"this pointer of std::unique_ptr should be obtainable as MemRegion");
QualType Type = getInnerPointerType(C, E->getType()->getAsCXXRecordDecl());
- return retrieveOrConjureInnerPtrVal(State, Reg, Elem, Type, C);
+ return retrieveOrConjureInnerPtrVal(State, Reg, E, Type, C);
};
SVal First = Call.getArgSVal(0);
@@ -491,10 +491,8 @@ bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
ProgramStateRef State = C.getState();
SVal FirstPtrVal, SecondPtrVal;
- std::tie(FirstPtrVal, State) =
- makeSValFor(State, FirstExpr, Call.getCFGElementRef(), First);
- std::tie(SecondPtrVal, State) =
- makeSValFor(State, SecondExpr, Call.getCFGElementRef(), Second);
+ std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr, First);
+ std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second);
BinaryOperatorKind BOK =
operationKindFromOverloadedOperator(OOK, true).GetBinaryOpUnsafe();
auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
@@ -532,7 +530,7 @@ bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
if (!StreamThisRegion)
return false;
State =
- State->invalidateRegions({StreamThisRegion}, Call.getCFGElementRef(),
+ State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
C.blockCount(), C.getLocationContext(), false);
State =
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
@@ -724,7 +722,7 @@ void SmartPtrModeling::handleGet(const CallEvent &Call,
SVal InnerPointerVal;
std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
- State, ThisRegion, Call.getCFGElementRef(), Call.getResultType(), C);
+ State, ThisRegion, Call.getOriginExpr(), Call.getResultType(), C);
State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
InnerPointerVal);
// TODO: Add NoteTag, for how the raw pointer got using 'get' method.
@@ -855,7 +853,7 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
const LocationContext *LC = C.getLocationContext();
InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
- Call.getCFGElementRef(), LC, InnerPointerType, C.blockCount());
+ CallExpr, LC, InnerPointerType, C.blockCount());
State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3628a146fe537..9c0b79ab58618 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -585,7 +585,7 @@ class StdLibraryFunctionsChecker
CheckerContext &C) const override {
SValBuilder &SVB = C.getSValBuilder();
NonLoc ErrnoSVal =
- SVB.conjureSymbolVal(&Tag, Call.getCFGElementRef(),
+ SVB.conjureSymbolVal(&Tag, Call.getOriginExpr(),
C.getLocationContext(), C.getASTContext().IntTy,
C.blockCount())
.castAs<NonLoc>();
@@ -621,7 +621,7 @@ class StdLibraryFunctionsChecker
const Summary &Summary,
CheckerContext &C) const override {
return errno_modeling::setErrnoStdMustBeChecked(State, C,
- Call.getCFGElementRef());
+ Call.getOriginExpr());
}
const std::string describe(CheckerContext &C) const override {
@@ -1482,8 +1482,7 @@ bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
const LocationContext *LC = C.getLocationContext();
const auto *CE = cast<CallExpr>(Call.getOriginExpr());
SVal V = C.getSValBuilder().conjureSymbolVal(
- Call.getCFGElementRef(), LC, CE->getType().getCanonicalType(),
- C.blockCount());
+ CE, LC, CE->getType().getCanonicalType(), C.blockCount());
State = State->BindExpr(CE, LC, V);
C.addTransition(State);
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 6481b76e69171..80969ce664530 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -224,16 +224,18 @@ SVal getStreamArg(const FnDescription *Desc, const CallEvent &Call) {
}
/// Create a conjured symbol return value for a call expression.
-DefinedSVal makeRetVal(CheckerContext &C, ConstCFGElementRef Elem) {
+DefinedSVal makeRetVal(CheckerContext &C, const CallExpr *CE) {
+ assert(CE && "Expecting a call expression.");
+
+ const LocationContext *LCtx = C.getLocationContext();
return C.getSValBuilder()
- .conjureSymbolVal(/*symbolTag=*/nullptr, Elem, C.getLocationContext(),
- C.blockCount())
+ .conjureSymbolVal(nullptr, CE, LCtx, C.blockCount())
.castAs<DefinedSVal>();
}
ProgramStateRef bindAndAssumeTrue(ProgramStateRef State, CheckerContext &C,
- const CallExpr *CE, ConstCFGElementRef Elem) {
- DefinedSVal RetVal = makeRetVal(C, Elem);
+ const CallExpr *CE) {
+ DefinedSVal RetVal = makeRetVal(C, CE);
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
State = State->assume(RetVal, true);
assert(State && "Assumption on new value should not fail.");
@@ -643,7 +645,6 @@ struct StreamOperationEvaluator {
SymbolRef StreamSym = nullptr;
const StreamState *SS = nullptr;
const CallExpr *CE = nullptr;
- std::optional<ConstCFGElementRef> Elem;
StreamErrorState NewES;
StreamOperationEvaluator(CheckerContext &C)
@@ -663,7 +664,6 @@ struct StreamOperationEvaluator {
CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
if (!CE)
return false;
- Elem = Call.getCFGElementRef();
assertStreamStateOpened(SS);
@@ -683,7 +683,7 @@ struct StreamOperationEvaluator {
}
ProgramStateRef makeAndBindRetVal(ProgramStateRef State, CheckerContext &C) {
- NonLoc RetVal = makeRetVal(C, Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>();
return State->BindExpr(CE, C.getLocationContext(), RetVal);
}
@@ -716,7 +716,7 @@ struct StreamOperationEvaluator {
ConstraintManager::ProgramStatePair
makeRetValAndAssumeDual(ProgramStateRef State, CheckerContext &C) {
- DefinedSVal RetVal = makeRetVal(C, Elem.value());
+ DefinedSVal RetVal = makeRetVal(C, CE);
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
return C.getConstraintManager().assumeDual(State, RetVal);
}
@@ -858,7 +858,7 @@ escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
}
return State->invalidateRegions(
- EscapingVals, Call.getCFGElementRef(), BlockCount, LCtx,
+ EscapingVals, Call.getOriginExpr(), BlockCount, LCtx,
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
}
@@ -868,7 +868,7 @@ static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
ArrayRef<unsigned int> EscapingArgs) {
auto GetArgSVal = [&Call](int Idx) { return Call.getArgSVal(Idx); };
auto EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
- State = State->invalidateRegions(EscapingVals, Call.getCFGElementRef(),
+ State = State->invalidateRegions(EscapingVals, Call.getOriginExpr(),
C.blockCount(), C.getLocationContext(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
@@ -931,7 +931,7 @@ void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call,
if (!CE)
return;
- DefinedSVal RetVal = makeRetVal(C, Call.getCFGElementRef());
+ DefinedSVal RetVal = makeRetVal(C, CE);
SymbolRef RetSym = RetVal.getAsSymbol();
assert(RetSym && "RetVal must be a symbol here.");
@@ -1200,7 +1200,7 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
if (!IsFread && !PedanticMode)
return;
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
StateFailed = E.assumeBinOpNN(StateFailed, BO_LT, RetVal, *NMembVal);
@@ -1235,7 +1235,7 @@ void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
State = escapeArgs(State, C, Call, {0});
if (SingleChar) {
// Generate a transition for the success state of `fgetc`.
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
// The returned 'unsigned char' of `fgetc` is converted to 'int',
@@ -1300,7 +1300,7 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
C.addTransition(StateNotFailed);
} else {
// Generate a transition for the success state of `fputs`.
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
StateNotFailed =
@@ -1334,7 +1334,7 @@ void StreamChecker::evalFprintf(const FnDescription *Desc,
if (!E.Init(Desc, Call, C, State))
return;
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
State = State->BindExpr(E.CE, C.getLocationContext(), RetVal);
auto Cond =
E.SVB
@@ -1379,7 +1379,7 @@ void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
// case, and no error flags are set on the stream. This is probably not
// accurate, and the POSIX documentation does not tell more.
if (!E.isStreamEof()) {
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
StateNotFailed =
@@ -1460,7 +1460,7 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc,
State = escapeArgs(State, C, Call, {0, 1});
// Add transition for the successful state.
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed = E.bindReturnValue(State, C, RetVal);
StateNotFailed =
E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call));
@@ -1601,7 +1601,7 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call,
if (!E.Init(Desc, Call, C, State))
return;
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
StateNotFailed =
@@ -1735,8 +1735,7 @@ void StreamChecker::evalFeofFerror(const FnDescription *Desc,
// Execution path with error of ErrorKind.
// Function returns true.
// From now on it is the only one error state.
- ProgramStateRef TrueState =
- bindAndAssumeTrue(State, C, E.CE, E.Elem.value());
+ ProgramStateRef TrueState = bindAndAssumeTrue(State, C, E.CE);
C.addTransition(E.setStreamState(
TrueState, StreamState::getOpened(Desc, ErrorKind,
E.SS->FilePositionIndeterminate &&
@@ -1770,7 +1769,7 @@ void StreamChecker::evalFileno(const FnDescription *Desc, const CallEvent &Call,
if (!E.Init(Desc, Call, C, State))
return;
- NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
+ NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>();
State = State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State = E.assumeBinOpNN(State, BO_GE, RetVal, E.getZeroVal(Call));
if (!State)
diff --git a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
index 044f9ba61113b..fefe846b6911f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
@@ -207,7 +207,7 @@ void InvalidPtrChecker::postPreviousReturnInvalidatingCall(
// Function call will return a pointer to the new symbolic region.
DefinedOrUnknownSVal RetVal = C.getSValBuilder().conjureSymbolVal(
- Call.getCFGElementRef(), LCtx, CE->getType(), C.blockCount());
+ CE, LCtx, CE->getType(), C.blockCount());
State = State->BindExpr(CE, LCtx, RetVal);
const auto *SymRegOfRetVal =
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 583315f4f3a90..bb4a39f68280c 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -280,7 +280,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
// Invalidate designated regions using the batch invalidation API.
// NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
// global variables.
- return Result->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
+ return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
/*Symbols=*/nullptr, this, &ETraits);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 2af6a60273a9c..86e2e8f634bfd 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -422,7 +422,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
break;
case SubobjectAdjustment::MemberPointerAdjustment:
// FIXME: Unimplemented.
- State = State->invalidateRegions(Reg, getCFGElementRef(),
+ State = State->invalidateRegions(Reg, InitWithAdjustments,
currBldrCtx->blockCount(), LC, true,
nullptr, nullptr, nullptr);
return State;
@@ -439,8 +439,8 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
// values inside Reg would be correct.
SVal InitVal = State->getSVal(Init, LC);
if (InitVal.isUnknown()) {
- InitVal = getSValBuilder().conjureSymbolVal(
- getCFGElementRef(), LC, Init->getType(), currBldrCtx->blockCount());
+ InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(),
+ currBldrCtx->blockCount());
State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
// Then we'd need to take the value that certainly exists and bind it
@@ -449,7 +449,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
// Try to recover some path sensitivity in case we couldn't
// compute the value.
InitValWithAdjustments = getSValBuilder().conjureSymbolVal(
- getCFGElementRef(), LC, InitWithAdjustments->getType(),
+ Result, LC, InitWithAdjustments->getType(),
currBldrCtx->blockCount());
}
State =
@@ -1215,9 +1215,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
// If we fail to get the value for some reason, use a symbolic value.
if (InitVal.isUnknownOrUndef()) {
SValBuilder &SVB = getSValBuilder();
- InitVal =
- SVB.conjureSymbolVal(getCFGElementRef(), stackFrame,
- Field->getType(), currBldrCtx->blockCount());
+ InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
+ Field->getType(),
+ currBldrCtx->blockCount());
}
} else {
InitVal = State->getSVal(BMI->getInit(), stackFrame);
@@ -2051,9 +2051,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
for (const auto N : preVisit) {
const LocationContext *LCtx = N->getLocationContext();
- SVal result = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
- currBldrCtx->blockCount());
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
+ resultType,
+ currBldrCtx->blockCount());
ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
// Escape pointers passed into the list, unless it's an ObjC boxed
@@ -2556,18 +2556,10 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
return;
-
// Widen.
const LocationContext *LCtx = Pred->getLocationContext();
-
- // FIXME:
- // We cannot use the CFG element from the via `ExprEngine::getCFGElementRef`
- // since we are currently at the block entrance and the current reference
- // would be stale. Ideally, we should pass on the terminator of the CFG
- // block, but the terminator cannot be referred as a CFG element.
- // Here we just pass the current stale block.
- ProgramStateRef WidenedState = getWidenedLoopState(
- Pred->getState(), LCtx, BlockCount, getCFGElementRef());
+ ProgramStateRef WidenedState =
+ getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
nodeBuilder.generateNode(WidenedState, Pred);
return;
}
@@ -3549,10 +3541,11 @@ void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
ValuesToInvalidate.push_back(SubExprVal);
}
- State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
- currBldrCtx->blockCount(), LCtx,
- /*CausedByPointerEscape*/ true,
- /*Symbols=*/nullptr);
+ State = State->invalidateRegions(ValuesToInvalidate, AE,
+ currBldrCtx->blockCount(),
+ LCtx,
+ /*CausedByPointerEscape*/true,
+ /*Symbols=*/nullptr);
SVal ResultVal = UnknownVal();
State = State->BindExpr(AE, LCtx, ResultVal);
@@ -3899,8 +3892,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
if (std::optional<Loc> LV = X.getAs<Loc>())
- state = state->invalidateRegions(*LV, getCFGElementRef(),
- currBldrCtx->blockCount(),
+ state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
Pred->getLocationContext(),
/*CausedByPointerEscape=*/true);
}
@@ -3910,8 +3902,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
SVal X = state->getSVal(I, Pred->getLocationContext());
if (std::optional<Loc> LV = X.getAs<Loc>())
- state = state->invalidateRegions(*LV, getCFGElementRef(),
- currBldrCtx->blockCount(),
+ state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
Pred->getLocationContext(),
/*CausedByPointerEscape=*/true);
}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 6e52df5e90944..3d0a69a515ab8 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -21,19 +21,18 @@ using namespace ento;
using llvm::APSInt;
/// Optionally conjure and return a symbol for offset when processing
-/// \p Elem.
+/// an expression \p Expression.
/// If \p Other is a location, conjure a symbol for \p Symbol
/// (offset) if it is unknown so that memory arithmetic always
/// results in an ElementRegion.
/// \p Count The number of times the current basic block was visited.
-static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
- ConstCFGElementRef Elem, QualType Ty,
- SValBuilder &svalBuilder,
- unsigned Count,
- const LocationContext *LCtx) {
+static SVal conjureOffsetSymbolOnLocation(
+ SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder,
+ unsigned Count, const LocationContext *LCtx) {
+ QualType Ty = Expression->getType();
if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
Symbol.isUnknown()) {
- return svalBuilder.conjureSymbolVal(Elem, LCtx, Ty, Count);
+ return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count);
}
return Symbol;
}
@@ -66,7 +65,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = currBldrCtx->blockCount();
- RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+ RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
Count);
}
// Simulate the effects of a "store": bind the value of the RHS
@@ -85,11 +84,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// SymSymExpr.
unsigned Count = currBldrCtx->blockCount();
RightV = conjureOffsetSymbolOnLocation(
- RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
- Count, LCtx);
- LeftV = conjureOffsetSymbolOnLocation(LeftV, RightV, getCFGElementRef(),
- LHS->getType(), svalBuilder,
- Count, LCtx);
+ RightV, LeftV, RHS, svalBuilder, Count, LCtx);
+ LeftV = conjureOffsetSymbolOnLocation(
+ LeftV, RightV, LHS, svalBuilder, Count, LCtx);
}
// Although we don't yet model pointers-to-members, we do need to make
@@ -168,8 +165,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// The symbolic value is actually for the type of the left-hand side
// expression, not the computation type, as this is the value the
// LValue on the LHS will bind to.
- LHSVal = svalBuilder.conjureSymbolVal(/*symbolTag=*/nullptr,
- getCFGElementRef(), LCtx, LTy,
+ LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy,
currBldrCtx->blockCount());
// However, we need to convert the symbol to the computation type.
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
@@ -463,9 +459,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
} else {
// If we don't know if the cast succeeded, conjure a new symbol.
if (val.isUnknown()) {
- DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
- currBldrCtx->blockCount());
+ DefinedOrUnknownSVal NewSym =
+ svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
+ currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, NewSym);
} else
// Else, bind to the derived region value.
@@ -487,9 +483,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
// Failed to cast or the result is unknown, fall back to conservative.
if (val.isUnknown()) {
- val = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
- currBldrCtx->blockCount());
+ val =
+ svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
+ currBldrCtx->blockCount());
}
state = state->BindExpr(CastE, LCtx, val);
Bldr.generateNode(CastE, Pred, state);
@@ -533,7 +529,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
if (CastE->isGLValue())
resultType = getContext().getPointerType(resultType);
SVal result = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
+ /*symbolTag=*/nullptr, CastE, LCtx, resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, result);
Bldr.generateNode(CastE, Pred, state);
@@ -625,9 +621,8 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
Ty = getContext().getPointerType(Ty);
}
- InitVal = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LC, Ty,
- currBldrCtx->blockCount());
+ InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
+ currBldrCtx->blockCount());
}
@@ -844,7 +839,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
}
if (!hasValue)
- V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
+ V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
currBldrCtx->blockCount());
// Generate a new node with the binding from the appropriate path.
@@ -1126,9 +1121,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
- DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx,
- currBldrCtx->blockCount());
+ DefinedOrUnknownSVal SymVal =
+ svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
+ currBldrCtx->blockCount());
Result = SymVal;
// If the value is a location, ++/-- should always preserve
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 5804dc17115b2..92ce3fa2225c8 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -242,8 +242,8 @@ SVal ExprEngine::computeObjectUnderConstruction(
assert(RetE && "Void returns should not have a construction context");
QualType ReturnTy = RetE->getType();
QualType RegionTy = ACtx.getPointerType(ReturnTy);
- return SVB.conjureSymbolVal(&TopLevelSymRegionTag, getCFGElementRef(),
- SFC, RegionTy, currBldrCtx->blockCount());
+ return SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC, RegionTy,
+ currBldrCtx->blockCount());
}
llvm_unreachable("Unhandled return value construction context!");
}
@@ -975,11 +975,10 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
// a custom global allocator.
if (symVal.isUnknown()) {
if (IsStandardGlobalOpNewFunction)
- symVal = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,
- CNE->getType(), blockCount);
+ symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
else
- symVal = svalBuilder.conjureSymbolVal(
- /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, blockCount);
+ symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
+ blockCount);
}
CallEventManager &CEMgr = getStateManager().getCallEventManager();
@@ -1112,7 +1111,7 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
}
const LocationContext *LCtx = Pred->getLocationContext();
- SVal V = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, VD->getType(),
+ SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(),
currBldrCtx->blockCount());
ProgramStateRef state = Pred->getState();
state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 90625a96e9059..1a44ba4f49133 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -746,7 +746,6 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
const LocationContext *LCtx,
ProgramStateRef State) {
const Expr *E = Call.getOriginExpr();
- const ConstCFGElementRef &Elem = Call.getCFGElementRef();
if (!E)
return State;
@@ -789,7 +788,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
RegionAndSymbolInvalidationTraits ITraits;
ITraits.setTrait(TargetR,
RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
- State = State->invalidateRegions(TargetR, Elem, Count, LCtx,
+ State = State->invalidateRegions(TargetR, E, Count, LCtx,
/* CausesPointerEscape=*/false, nullptr,
&Call, &ITraits);
@@ -801,7 +800,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
// a regular unknown pointer.
const auto *CNE = dyn_cast<CXXNewExpr>(E);
if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
- R = svalBuilder.getConjuredHeapSymbolVal(Elem, LCtx, E->getType(), Count);
+ R = svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count);
const MemRegion *MR = R.getAsRegion()->StripCasts();
// Store the extent of the allocated object(s).
@@ -825,7 +824,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
State = setDynamicExtent(State, MR, Size.castAs<DefinedOrUnknownSVal>());
} else {
- R = svalBuilder.conjureSymbolVal(Elem, LCtx, ResultTy, Count);
+ R = svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
}
}
return State->BindExpr(E, LCtx, R);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index f2e5a163afb62..9426e0afd65a0 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -45,7 +45,7 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
/// for-loop iterator.
static void populateObjCForDestinationSet(
ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder,
- const ObjCForCollectionStmt *S, ConstCFGElementRef elem, SVal elementV,
+ const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV,
SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
StmtNodeBuilder &Bldr, bool hasElements) {
@@ -66,8 +66,8 @@ static void populateObjCForDestinationSet(
SVal V;
if (hasElements) {
- SymbolRef Sym =
- SymMgr.conjureSymbol(elem, LCtx, T, currBldrCtx->blockCount());
+ SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
+ currBldrCtx->blockCount());
V = svalBuilder.makeLoc(Sym);
} else {
V = svalBuilder.makeIntVal(0, T);
@@ -110,7 +110,6 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
const Stmt *elem = S->getElement();
const Stmt *collection = S->getCollection();
- const ConstCFGElementRef &elemRef = getCFGElementRef();
ProgramStateRef state = Pred->getState();
SVal collectionV = state->getSVal(collection, Pred->getLocationContext());
@@ -133,12 +132,11 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
StmtNodeBuilder Bldr(dstLocation, Tmp, *currBldrCtx);
if (!isContainerNull)
- populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S,
- elemRef, elementV, SymMgr, currBldrCtx,
- Bldr,
+ populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elem,
+ elementV, SymMgr, currBldrCtx, Bldr,
/*hasElements=*/true);
- populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elemRef,
+ populateObjCForDestinationSet(DstLocationSingleton, svalBuilder, S, elem,
elementV, SymMgr, currBldrCtx, Bldr,
/*hasElements=*/false);
diff --git a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
index 2cddf1faa1619..9e42801760622 100644
--- a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
+++ b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -13,10 +13,10 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
#include "clang/AST/AST.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
using namespace clang;
using namespace ento;
@@ -24,13 +24,31 @@ using namespace clang::ast_matchers;
const auto MatchRef = "matchref";
+/// Return the loops condition Stmt or NULL if LoopStmt is not a loop
+static const Expr *getLoopCondition(const Stmt *LoopStmt) {
+ switch (LoopStmt->getStmtClass()) {
+ default:
+ return nullptr;
+ case Stmt::ForStmtClass:
+ return cast<ForStmt>(LoopStmt)->getCond();
+ case Stmt::WhileStmtClass:
+ return cast<WhileStmt>(LoopStmt)->getCond();
+ case Stmt::DoStmtClass:
+ return cast<DoStmt>(LoopStmt)->getCond();
+ case Stmt::CXXForRangeStmtClass:
+ return cast<CXXForRangeStmt>(LoopStmt)->getCond();
+ }
+}
+
namespace clang {
namespace ento {
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
const LocationContext *LCtx,
- unsigned BlockCount,
- ConstCFGElementRef Elem) {
+ unsigned BlockCount, const Stmt *LoopStmt) {
+
+ assert((isa<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(LoopStmt)));
+
// Invalidate values in the current state.
// TODO Make this more conservative by only invalidating values that might
// be modified by the body of the loop.
@@ -75,8 +93,9 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
}
- return PrevState->invalidateRegions(Regions, Elem, BlockCount, LCtx, true,
- nullptr, nullptr, &ITraits);
+ return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt),
+ BlockCount, LCtx, true, nullptr, nullptr,
+ &ITraits);
}
} // end namespace ento
diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 19af8993f41ed..492209d4d2bf0 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -149,7 +149,7 @@ typedef ArrayRef<const MemRegion *> RegionList;
typedef ArrayRef<SVal> ValueList;
ProgramStateRef ProgramState::invalidateRegions(
- RegionList Regions, ConstCFGElementRef Elem, unsigned Count,
+ RegionList Regions, const Stmt *S, unsigned Count,
const LocationContext *LCtx, bool CausedByPointerEscape,
InvalidatedSymbols *IS, const CallEvent *Call,
RegionAndSymbolInvalidationTraits *ITraits) const {
@@ -157,12 +157,12 @@ ProgramStateRef ProgramState::invalidateRegions(
for (const MemRegion *Reg : Regions)
Values.push_back(loc::MemRegionVal(Reg));
- return invalidateRegions(Values, Elem, Count, LCtx, CausedByPointerEscape, IS,
+ return invalidateRegions(Values, S, Count, LCtx, CausedByPointerEscape, IS,
Call, ITraits);
}
ProgramStateRef ProgramState::invalidateRegions(
- ValueList Values, ConstCFGElementRef Elem, unsigned Count,
+ ValueList Values, const Stmt *S, unsigned Count,
const LocationContext *LCtx, bool CausedByPointerEscape,
InvalidatedSymbols *IS, const CallEvent *Call,
RegionAndSymbolInvalidationTraits *ITraits) const {
@@ -181,7 +181,7 @@ ProgramStateRef ProgramState::invalidateRegions(
StoreManager::InvalidatedRegions TopLevelInvalidated;
StoreManager::InvalidatedRegions Invalidated;
const StoreRef &NewStore = Mgr.StoreMgr->invalidateRegions(
- getStore(), Values, Elem, Count, LCtx, Call, *IS, *ITraits,
+ getStore(), Values, S, Count, LCtx, Call, *IS, *ITraits,
&TopLevelInvalidated, &Invalidated);
ProgramStateRef NewState = makeWithStore(NewStore);
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index b6928372e2716..1cc9cb84cbfa4 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -563,15 +563,15 @@ class RegionStoreManager : public StoreManager {
//===-------------------------------------------------------------------===//
// Binding values to regions.
//===-------------------------------------------------------------------===//
- RegionBindingsRef
- invalidateGlobalRegion(MemRegion::Kind K, ConstCFGElementRef Elem,
- unsigned Count, const LocationContext *LCtx,
- RegionBindingsRef B, InvalidatedRegions *Invalidated);
-
- StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values,
- ConstCFGElementRef Elem, unsigned Count,
- const LocationContext *LCtx, const CallEvent *Call,
- InvalidatedSymbols &IS,
+ RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K, const Stmt *S,
+ unsigned Count,
+ const LocationContext *LCtx,
+ RegionBindingsRef B,
+ InvalidatedRegions *Invalidated);
+
+ StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values, const Stmt *S,
+ unsigned Count, const LocationContext *LCtx,
+ const CallEvent *Call, InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *Invalidated,
InvalidatedRegions *InvalidatedTopLevel) override;
@@ -1147,7 +1147,7 @@ RegionStoreManager::removeSubRegionBindings(LimitedRegionBindingsConstRef B,
namespace {
class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
{
- ConstCFGElementRef Elem;
+ const Stmt *S;
unsigned Count;
const LocationContext *LCtx;
InvalidatedSymbols &IS;
@@ -1156,13 +1156,12 @@ class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
GlobalsFilterKind GlobalsFilter;
public:
InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
- RegionBindingsRef b, ConstCFGElementRef elem,
- unsigned count, const LocationContext *lctx,
- InvalidatedSymbols &is,
+ RegionBindingsRef b, const Stmt *S, unsigned count,
+ const LocationContext *lctx, InvalidatedSymbols &is,
RegionAndSymbolInvalidationTraits &ITraitsIn,
StoreManager::InvalidatedRegions *r,
GlobalsFilterKind GFK)
- : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), Elem(elem),
+ : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), S(S),
Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
GlobalsFilter(GFK) {}
@@ -1297,7 +1296,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelevant.
DefinedOrUnknownSVal V =
- svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, Ctx.IntTy, Count);
+ svalBuilder.conjureSymbolVal(baseR, S, LCtx, Ctx.IntTy, Count);
B = B.addBinding(baseR, BindingKey::Default, V);
return;
}
@@ -1319,7 +1318,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelevant.
DefinedOrUnknownSVal V =
- svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, Ctx.IntTy, Count);
+ svalBuilder.conjureSymbolVal(baseR, S, LCtx, Ctx.IntTy, Count);
B = B.addBinding(baseR, BindingKey::Default, V);
return;
}
@@ -1387,13 +1386,13 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
conjure_default:
// Set the default value of the array to conjured symbol.
DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(
- baseR, Elem, LCtx, AT->getElementType(), Count);
+ baseR, S, LCtx, AT->getElementType(), Count);
B = B.addBinding(baseR, BindingKey::Default, V);
return;
}
DefinedOrUnknownSVal V =
- svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, T, Count);
+ svalBuilder.conjureSymbolVal(baseR, S, LCtx, T, Count);
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
B = B.addBinding(baseR, BindingKey::Direct, V);
}
@@ -1422,15 +1421,15 @@ bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
}
RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
- MemRegion::Kind K, ConstCFGElementRef Elem, unsigned Count,
+ MemRegion::Kind K, const Stmt *S, unsigned Count,
const LocationContext *LCtx, RegionBindingsRef B,
InvalidatedRegions *Invalidated) {
// Bind the globals memory space to a new symbol that we will use to derive
// the bindings for all globals.
const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
- SVal V = svalBuilder.conjureSymbolVal(
- /* symbolTag = */ (const void *)GS, Elem, LCtx,
- /* type does not matter */ Ctx.IntTy, Count);
+ SVal V =
+ svalBuilder.conjureSymbolVal(/* symbolTag = */ (const void *)GS, S, LCtx,
+ /* type does not matter */ Ctx.IntTy, Count);
B = B.removeBinding(GS)
.addBinding(BindingKey::Make(GS, BindingKey::Default), V);
@@ -1465,7 +1464,7 @@ void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
}
StoreRef RegionStoreManager::invalidateRegions(
- Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem, unsigned Count,
+ Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
@@ -1480,7 +1479,7 @@ StoreRef RegionStoreManager::invalidateRegions(
}
RegionBindingsRef B = getRegionBindings(store);
- InvalidateRegionsWorker W(*this, StateMgr, B, Elem, Count, LCtx, IS, ITraits,
+ InvalidateRegionsWorker W(*this, StateMgr, B, S, Count, LCtx, IS, ITraits,
Invalidated, GlobalsFilter);
// Scan the bindings and generate the clusters.
@@ -1500,12 +1499,12 @@ StoreRef RegionStoreManager::invalidateRegions(
// TODO: This could possibly be more precise with modules.
switch (GlobalsFilter) {
case GFK_All:
- B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
+ B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, S,
Count, LCtx, B, Invalidated);
[[fallthrough]];
case GFK_SystemOnly:
- B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
- Count, LCtx, B, Invalidated);
+ B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, S, Count,
+ LCtx, B, Invalidated);
[[fallthrough]];
case GFK_None:
break;
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index f1f842e64ed39..eb5054708fece 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -152,11 +152,9 @@ SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
}
DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
- ConstCFGElementRef elem,
+ const Expr *Ex,
const LocationContext *LCtx,
unsigned Count) {
- const Expr *Ex = dyn_cast<Expr>(elem->getAs<CFGStmt>()->getStmt());
- assert(Ex && "elem must be a CFGStmt containing an Expr");
QualType T = Ex->getType();
if (T->isNullPtrType())
@@ -168,11 +166,11 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
if (Ex->isGLValue())
T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
- return conjureSymbolVal(SymbolTag, elem, LCtx, T, Count);
+ return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
}
DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
- ConstCFGElementRef elem,
+ const Stmt *St,
const LocationContext *LCtx,
QualType type,
unsigned count) {
@@ -182,7 +180,7 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
if (!SymbolManager::canSymbolicate(type))
return UnknownVal();
- SymbolRef sym = SymMgr.conjureSymbol(elem, LCtx, type, count, symbolTag);
+ SymbolRef sym = SymMgr.conjureSymbol(St, LCtx, type, count, symbolTag);
if (Loc::isLocType(type))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
@@ -190,7 +188,7 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
return nonloc::SymbolVal(sym);
}
-DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(ConstCFGElementRef elem,
+DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
const LocationContext *LCtx,
QualType type,
unsigned visitCount) {
@@ -200,7 +198,7 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(ConstCFGElementRef elem,
if (!SymbolManager::canSymbolicate(type))
return UnknownVal();
- SymbolRef sym = SymMgr.conjureSymbol(elem, LCtx, type, visitCount);
+ SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);
if (Loc::isLocType(type))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
@@ -208,7 +206,14 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(ConstCFGElementRef elem,
return nonloc::SymbolVal(sym);
}
-DefinedSVal SValBuilder::getConjuredHeapSymbolVal(ConstCFGElementRef elem,
+DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned VisitCount) {
+ QualType T = E->getType();
+ return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
+
+DefinedSVal SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
const LocationContext *LCtx,
QualType type,
unsigned VisitCount) {
@@ -220,7 +225,7 @@ DefinedSVal SValBuilder::getConjuredHeapSymbolVal(ConstCFGElementRef elem,
return makeZeroVal(type).castAs<DefinedSVal>();
}
- SymbolRef sym = SymMgr.conjureSymbol(elem, LCtx, type, VisitCount);
+ SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
}
diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index a6ade661d04a2..a4648f5922ef1 100644
--- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -82,7 +82,7 @@ void UnarySymExpr::dumpToStream(raw_ostream &os) const {
void SymbolConjured::dumpToStream(raw_ostream &os) const {
os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
- if (auto *S = getStmt())
+ if (S)
os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
else
os << ", no stmt";
diff --git a/clang/test/Analysis/PR57270.cpp b/clang/test/Analysis/PR57270.cpp
deleted file mode 100644
index 7d7a658ef441b..0000000000000
--- a/clang/test/Analysis/PR57270.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s
-
-using size_t = __typeof(sizeof(int));
-
-void clang_analyzer_explain(int);
-void clang_analyzer_dump(int);
-void *memset(void *, int, size_t);
-
-struct S
-{
- static int a;
- ~S(){};
-};
-
-int S::a = 0;
-
-void foo()
-{
- S::a = 0;
-
- int x = 3;
- memset(&x, 1, sizeof(x));
-
- S *arr = new S[x];
- delete[] arr;
-
- clang_analyzer_dump(S::a); // expected-warning-re{{{{derived_\$[0-9]+{conj_\$[0-9]+{int, LC[0-9]+, S[0-9]+, #[0-9]+},a}}}}}
-
- clang_analyzer_explain(S::a); // expected-warning-re{{{{value derived from \(symbol of type 'int' conjured at CFG element '->~S\(\) \(Implicit destructor\)'\) for global variable 'S::a'}}}}
-}
diff --git a/clang/test/Analysis/container-modeling.cpp b/clang/test/Analysis/container-modeling.cpp
index 5dcb6274b071a..bf4a12a0e0fe2 100644
--- a/clang/test/Analysis/container-modeling.cpp
+++ b/clang/test/Analysis/container-modeling.cpp
@@ -196,7 +196,7 @@ void pop_front(std::list<int> &L, int n) {
void push_back() {
std::vector<int> V;
V.end();
-
+
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
V.push_back(1); // expected-note{{Container 'V' extended to the back by 1 position}}
@@ -256,7 +256,7 @@ void print_state(std::vector<int> &V) {
V.cend();
clang_analyzer_printState();
-
+
// CHECK: "checker_messages": [
// CHECK-NEXT: { "checker": "alpha.cplusplus.ContainerModeling", "messages": [
// CHECK-NEXT: "Container Data :",
diff --git a/clang/test/Analysis/dump_egraph.cpp b/clang/test/Analysis/dump_egraph.cpp
index 2cea5f705f116..13459699a06f6 100644
--- a/clang/test/Analysis/dump_egraph.cpp
+++ b/clang/test/Analysis/dump_egraph.cpp
@@ -24,3 +24,4 @@ void foo() {
// CHECK: \"cluster\": \"t\", \"pointer\": \"{{0x[0-9a-f]+}}\", \"items\": [\l \{ \"kind\": \"Default\", \"offset\": 0, \"value\": \"conj_$3\{int, LC5, no stmt, #1\}\"
// CHECK: \"dynamic_types\": [\l \{ \"region\": \"HeapSymRegion\{conj_$1\{S *, LC1, S{{[0-9]+}}, #1\}\}\", \"dyn_type\": \"S\", \"sub_classable\": false \}\l
+
diff --git a/clang/test/Analysis/explain-svals.cpp b/clang/test/Analysis/explain-svals.cpp
index 267980c3b20c8..d1615e6cc6c9a 100644
--- a/clang/test/Analysis/explain-svals.cpp
+++ b/clang/test/Analysis/explain-svals.cpp
@@ -47,12 +47,12 @@ void test_1(int param, void *ptr) {
void test_2(char *ptr, int ext) {
clang_analyzer_explain((void *) "asdf"); // expected-warning-re{{{{^pointer to element of type 'char' with index 0 of string literal "asdf"$}}}}
clang_analyzer_explain(strlen(ptr)); // expected-warning-re{{{{^metadata of type 'unsigned long' tied to pointee of argument 'ptr'$}}}}
- clang_analyzer_explain(conjure()); // expected-warning-re{{{{^symbol of type 'int' conjured at CFG element 'conjure\(\)'$}}}}
- clang_analyzer_explain(glob); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at CFG element 'conjure\(\)'\) for global variable 'glob'$}}}}
- clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at CFG element 'conjure\(\)'\) for global variable 'glob_ptr'$}}}}
+ clang_analyzer_explain(conjure()); // expected-warning-re{{{{^symbol of type 'int' conjured at statement 'conjure\(\)'$}}}}
+ clang_analyzer_explain(glob); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob'$}}}}
+ clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob_ptr'$}}}}
clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re{{{{^extent of pointee of argument 'ptr'$}}}}
int *x = new int[ext];
- clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at CFG element 'CFGNewAllocator\(int \*\)'$}}}}
+ clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
// Sic! What gets computed is the extent of the element-region.
clang_analyzer_explain(clang_analyzer_getExtent(x)); // expected-warning-re{{{{^\(argument 'ext'\) \* 4$}}}}
delete[] x;
@@ -99,8 +99,8 @@ class C {
} // end of anonymous namespace
void test_6() {
- clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^symbol of type 'int' conjured at CFG element 'conjure_S\(\) \(CXXRecordTypedCall, \+0\)'$}}}}
- clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at CFG element 'conjure_S\(\) \(CXXRecordTypedCall, \)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+ clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^symbol of type 'int' conjured at statement 'conjure_S\(\)'$}}}}
+ clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
}
class C_top_level {
diff --git a/clang/test/Analysis/explain-svals.m b/clang/test/Analysis/explain-svals.m
index e79ceabcacebb..e93258b3626a5 100644
--- a/clang/test/Analysis/explain-svals.m
+++ b/clang/test/Analysis/explain-svals.m
@@ -17,8 +17,8 @@ void test_1(Object *p) {
clang_analyzer_explain(p); // expected-warning-re{{{{^argument 'p'$}}}}
clang_analyzer_explain(p->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at argument 'p'$}}}}
Object *q = [[Object alloc] init];
- clang_analyzer_explain(q); // expected-warning-re{{{{^symbol of type 'Object \*' conjured at CFG element '\[\[Object alloc\] init\]'$}}}}
- clang_analyzer_explain(q->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at symbol of type 'Object \*' conjured at CFG element '\[\[Object alloc\] init\]'$}}}}
+ clang_analyzer_explain(q); // expected-warning-re{{{{^symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
+ clang_analyzer_explain(q->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
}
void test_2(void) {
More information about the cfe-commits
mailing list