[clang] [analyzer] Teach analzer about ms __analyzer_assume(bool) and friends (PR #80456)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 2 08:12:34 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Balazs Benics (steakhal)
<details>
<summary>Changes</summary>
See the MS docs:
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/using-the--analysis-assume-function-to-suppress-false-defects https://learn.microsoft.com/en-us/cpp/code-quality/how-to-specify-additional-code-information-by-using-analysis-assume
TBH, I don't really know what is the difference between the two APIs.
---
Full diff: https://github.com/llvm/llvm-project/pull/80456.diff
2 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp (+40-17)
- (modified) clang/test/Analysis/builtin-functions.cpp (+22)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 61521c259ca90..ea874c1529b3b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -14,6 +14,7 @@
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
@@ -26,10 +27,41 @@ namespace {
class BuiltinFunctionChecker : public Checker<eval::Call> {
public:
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
+
+private:
+ const CallDescriptionSet MicrosoftAnalysisAssume{
+ {{"__analysis_assume"}, 1},
+ {{"_Analysis_assume_"}, 1},
+ };
+
+ void evalCallAssume(const CallEvent &Call, CheckerContext &C) const;
};
}
+void BuiltinFunctionChecker::evalCallAssume(const CallEvent &Call,
+ CheckerContext &C) const {
+ assert(Call.getNumArgs() > 0);
+ assert(Call.getResultType()->isVoidType());
+ SVal Arg = Call.getArgSVal(0);
+
+ if (Arg.isUndef())
+ return; // Return true to model purity.
+
+ ProgramStateRef State = C.getState();
+ State = State->assume(Arg.castAs<DefinedOrUnknownSVal>(), true);
+
+ // FIXME: do we want to warn here? Not right now. The most reports might
+ // come from infeasible paths, thus being false positives.
+ if (!State) {
+ C.generateSink(C.getState(), C.getPredecessor());
+ return;
+ }
+
+ C.addTransition(State);
+ return;
+}
+
bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
@@ -39,29 +71,20 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
const LocationContext *LCtx = C.getLocationContext();
const Expr *CE = Call.getOriginExpr();
+ bool ReturnsVoid = Call.getResultType()->isVoidType();
+
+ if (MicrosoftAnalysisAssume.contains(Call) && ReturnsVoid) {
+ evalCallAssume(Call, C);
+ return true;
+ }
switch (FD->getBuiltinID()) {
default:
return false;
- case Builtin::BI__builtin_assume: {
- assert (Call.getNumArgs() > 0);
- SVal Arg = Call.getArgSVal(0);
- if (Arg.isUndef())
- return true; // Return true to model purity.
-
- state = state->assume(Arg.castAs<DefinedOrUnknownSVal>(), true);
- // FIXME: do we want to warn here? Not right now. The most reports might
- // come from infeasible paths, thus being false positives.
- if (!state) {
- C.generateSink(C.getState(), C.getPredecessor());
- return true;
- }
-
- C.addTransition(state);
+ case Builtin::BI__builtin_assume:
+ evalCallAssume(Call, C);
return true;
- }
-
case Builtin::BI__builtin_unpredictable:
case Builtin::BI__builtin_expect:
case Builtin::BI__builtin_expect_with_probability:
diff --git a/clang/test/Analysis/builtin-functions.cpp b/clang/test/Analysis/builtin-functions.cpp
index 37e522049b174..4a26f82ffcb16 100644
--- a/clang/test/Analysis/builtin-functions.cpp
+++ b/clang/test/Analysis/builtin-functions.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection %s -std=c++11 -verify
+void __analysis_assume(bool);
+void _Analysis_assume_(bool);
void clang_analyzer_eval(bool);
void clang_analyzer_warnIfReached();
@@ -82,3 +84,23 @@ void test_constant_p(void *ptr) {
clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}
clang_analyzer_eval(__builtin_constant_p(ptr == 0)); // expected-warning {{FALSE}}
}
+
+void test_ms_analysis_assume(int *p) {
+ __analysis_assume(p);
+ if (!p) {
+ clang_analyzer_warnIfReached(); // no-warning: dead code.
+ }
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+ __analysis_assume(false);
+ clang_analyzer_warnIfReached(); // no-warning: dead code.
+}
+
+void test_ms_Analysis_assume_(int *p) {
+ _Analysis_assume_(p);
+ if (!p) {
+ clang_analyzer_warnIfReached(); // no-warning: dead code.
+ }
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+ _Analysis_assume_(false);
+ clang_analyzer_warnIfReached(); // no-warning: dead code.
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/80456
More information about the cfe-commits
mailing list