vrnithinkumar updated this revision to Diff 273117.
vrnithinkumar added a comment.
Fixing test failures
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D82256/new/
https://reviews.llvm.org/D82256
Files:
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
clang/test/Analysis/analyzer-config.c
clang/test/Analysis/cxxctr-evalcall-analysis-order.cpp
clang/test/Analysis/new-ctor-conservative.cpp
Index: clang/test/Analysis/new-ctor-conservative.cpp
===================================================================
--- clang/test/Analysis/new-ctor-conservative.cpp
+++ clang/test/Analysis/new-ctor-conservative.cpp
@@ -27,6 +27,7 @@
S *s = new S[10];
// FIXME: Should be true once we inline array constructors.
clang_analyzer_eval(s[0].x == 1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(s[1].x == 1); // expected-warning{{UNKNOWN}}
}
struct NullS {
Index: clang/test/Analysis/cxxctr-evalcall-analysis-order.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/cxxctr-evalcall-analysis-order.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN: -analyzer-checker=debug.AnalysisOrder \
+// RUN: -analyzer-config debug.AnalysisOrder:EvalCall=true \
+// RUN: -analyzer-config debug.AnalysisOrder:PreCall=true \
+// RUN: -analyzer-config debug.AnalysisOrder:PostCall=true \
+// RUN: 2>&1 | FileCheck %s
+
+// This test ensures that eval::Call event will be triggered for constructors.
+
+class C {
+public:
+ C(){};
+ C(int x){};
+ C(int x, int y){};
+};
+
+void foo() {
+ C C0;
+ C C1(42);
+ C *C2 = new C{2, 3};
+}
+
+// CHECK: PreCall (C::C) [CXXConstructorCall]
+// CHECK-NEXT: EvalCall (C::C) {argno: 0} [CXXConstructorCall]
+// CHECK-NEXT: PostCall (C::C) [CXXConstructorCall]
+// CHECK-NEXT: PreCall (C::C) [CXXConstructorCall]
+// CHECK-NEXT: EvalCall (C::C) {argno: 1} [CXXConstructorCall]
+// CHECK-NEXT: PostCall (C::C) [CXXConstructorCall]
+// CHECK-NEXT: PreCall (operator new) [CXXAllocatorCall]
+// CHECK-NEXT: PostCall (operator new) [CXXAllocatorCall]
+// CHECK-NEXT: PreCall (C::C) [CXXConstructorCall]
+// CHECK-NEXT: EvalCall (C::C) {argno: 2} [CXXConstructorCall]
+// CHECK-NEXT: PostCall (C::C) [CXXConstructorCall]
Index: clang/test/Analysis/analyzer-config.c
===================================================================
--- clang/test/Analysis/analyzer-config.c
+++ clang/test/Analysis/analyzer-config.c
@@ -50,6 +50,7 @@
// CHECK-NEXT: debug.AnalysisOrder:Bind = false
// CHECK-NEXT: debug.AnalysisOrder:EndAnalysis = false
// CHECK-NEXT: debug.AnalysisOrder:EndFunction = false
+// CHECK-NEXT: debug.AnalysisOrder:EvalCall = false
// CHECK-NEXT: debug.AnalysisOrder:LiveSymbols = false
// CHECK-NEXT: debug.AnalysisOrder:NewAllocator = false
// CHECK-NEXT: debug.AnalysisOrder:PointerEscape = false
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -584,7 +584,7 @@
// defaultEvalCall if all of them fail.
ExplodedNodeSet dstCallEvaluated;
getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit,
- Call, *this);
+ Call, *this, EvalCallOptions());
// If there were other constructors called for object-type arguments
// of this call, clean them up.
@@ -717,7 +717,7 @@
ExprEngine::CallInlinePolicy
ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
AnalyzerOptions &Opts,
- const ExprEngine::EvalCallOptions &CallOpts) {
+ const EvalCallOptions &CallOpts) {
const LocationContext *CurLC = Pred->getLocationContext();
const StackFrameContext *CallerSFC = CurLC->getStackFrame();
switch (Call.getKind()) {
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -615,7 +615,8 @@
} else {
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
- defaultEvalCall(Bldr, *I, *Call, CallOpts);
+ getCheckerManager().runCheckersForEvalCall(DstEvaluated, *I, *Call, *this,
+ CallOpts);
}
// If the CFG was constructed without elements for temporary destructors
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -653,7 +653,8 @@
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const CallEvent &Call,
- ExprEngine &Eng) {
+ ExprEngine &Eng,
+ const EvalCallOptions &CallOpts) {
for (auto *const Pred : Src) {
bool anyEvaluated = false;
@@ -665,7 +666,7 @@
// TODO: Support the situation when the call doesn't correspond
// to any Expr.
ProgramPoint L = ProgramPoint::getProgramPoint(
- cast<CallExpr>(Call.getOriginExpr()),
+ Call.getOriginExpr(),
ProgramPoint::PostStmtKind,
Pred->getLocationContext(),
EvalCallChecker.Checker);
@@ -690,7 +691,7 @@
// If none of the checkers evaluated the call, ask ExprEngine to handle it.
if (!anyEvaluated) {
NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
- Eng.defaultEvalCall(B, Pred, Call);
+ Eng.defaultEvalCall(B, Pred, Call, CallOpts);
}
}
}
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -523,7 +523,7 @@
if (!CC)
return None;
- ExprEngine::EvalCallOptions CallOpts;
+ EvalCallOptions CallOpts;
ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
SVal RetVal =
Engine.computeObjectUnderConstruction(getOriginExpr(), getState(),
Index: clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -38,7 +38,7 @@
check::PostStmt<OffsetOfExpr>, check::PreCall, check::PostCall,
check::EndFunction, check::EndAnalysis, check::NewAllocator,
check::Bind, check::PointerEscape, check::RegionChanges,
- check::LiveSymbols> {
+ check::LiveSymbols, eval::Call> {
bool isCallbackEnabled(const AnalyzerOptions &Opts,
StringRef CallbackName) const {
@@ -122,6 +122,19 @@
llvm::errs() << "PostStmt<OffsetOfExpr>\n";
}
+ bool evalCall(const CallEvent &Call, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "EvalCall")) {
+ llvm::errs() << "EvalCall";
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
+ llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+ llvm::errs() << " {argno: " << Call.getNumArgs() << '}';
+ llvm::errs() << " [" << Call.getKindAsString() << ']';
+ llvm::errs() << '\n';
+ return true;
+ }
+ return false;
+ }
+
void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
if (isCallbackEnabled(C, "PreCall")) {
llvm::errs() << "PreCall";
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -96,8 +96,37 @@
class SymbolManager;
class SwitchNodeBuilder;
+/// Hints for figuring out of a call should be inlined during evalCall().
+struct EvalCallOptions {
+ /// This call is a constructor or a destructor for which we do not currently
+ /// compute the this-region correctly.
+ bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false;
+
+ /// This call is a constructor or a destructor for a single element within
+ /// an array, a part of array construction or destruction.
+ bool IsArrayCtorOrDtor = false;
+
+ /// This call is a constructor or a destructor of a temporary value.
+ bool IsTemporaryCtorOrDtor = false;
+
+ /// This call is a constructor for a temporary that is lifetime-extended
+ /// by binding it to a reference-type field within an aggregate,
+ /// for example 'A { const C &c; }; A a = { C() };'
+ bool IsTemporaryLifetimeExtendedViaAggregate = false;
+
+ /// This call is a pre-C++17 elidable constructor that we failed to elide
+ /// because we failed to compute the target region into which
+ /// this constructor would have been ultimately elided. Analysis that
+ /// we perform in this case is still correct but it behaves differently,
+ /// as if copy elision is disabled.
+ bool IsElidableCtorThatHasNotBeenElided = false;
+
+ EvalCallOptions() {}
+};
+
class ExprEngine {
void anchor();
+
public:
/// The modes of inlining, which override the default analysis-wide settings.
enum InliningModes {
@@ -108,34 +137,6 @@
Inline_Minimal = 0x1
};
- /// Hints for figuring out of a call should be inlined during evalCall().
- struct EvalCallOptions {
- /// This call is a constructor or a destructor for which we do not currently
- /// compute the this-region correctly.
- bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false;
-
- /// This call is a constructor or a destructor for a single element within
- /// an array, a part of array construction or destruction.
- bool IsArrayCtorOrDtor = false;
-
- /// This call is a constructor or a destructor of a temporary value.
- bool IsTemporaryCtorOrDtor = false;
-
- /// This call is a constructor for a temporary that is lifetime-extended
- /// by binding it to a reference-type field within an aggregate,
- /// for example 'A { const C &c; }; A a = { C() };'
- bool IsTemporaryLifetimeExtendedViaAggregate = false;
-
- /// This call is a pre-C++17 elidable constructor that we failed to elide
- /// because we failed to compute the target region into which
- /// this constructor would have been ultimately elided. Analysis that
- /// we perform in this case is still correct but it behaves differently,
- /// as if copy elision is disabled.
- bool IsElidableCtorThatHasNotBeenElided = false;
-
- EvalCallOptions() {}
- };
-
private:
cross_tu::CrossTranslationUnitContext &CTU;
Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -47,6 +47,7 @@
class ExplodedNode;
class ExplodedNodeSet;
class ExprEngine;
+struct EvalCallOptions;
class MemRegion;
struct NodeBuilderContext;
class ObjCMethodCall;
@@ -433,9 +434,9 @@
/// Run checkers for evaluating a call.
///
/// Warning: Currently, the CallEvent MUST come from a CallExpr!
- void runCheckersForEvalCall(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const CallEvent &CE, ExprEngine &Eng);
+ void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const CallEvent &CE, ExprEngine &Eng,
+ const EvalCallOptions &CallOpts);
/// Run checkers for the entire Translation Unit.
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
Index: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1372,6 +1372,12 @@
"false",
Released,
Hide>,
+ CmdLineOption<Boolean,
+ "EvalCall",
+ "",
+ "false",
+ Released,
+ Hide>,
CmdLineOption<Boolean,
"PreCall",
"",
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits