summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
diff options
context:
space:
mode:
authorJordy Rose <jediknil@belkadan.com>2012-05-16 16:01:07 +0000
committerJordy Rose <jediknil@belkadan.com>2012-05-16 16:01:07 +0000
commit31ae259a41a196e89c9b0d60a1154257744bdccc (patch)
tree12cdf209c6ae84270b785c807906e32cac32345d /clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
parent4d16c4c669632e9b3170716e4548301d9a7bf558 (diff)
downloadbcm5719-llvm-31ae259a41a196e89c9b0d60a1154257744bdccc.tar.gz
bcm5719-llvm-31ae259a41a196e89c9b0d60a1154257744bdccc.zip
[analyzer] Introduce clang_analyzer_eval for regression test constraint checks.
The new debug.ExprInspection checker looks for calls to clang_analyzer_eval, and emits a warning of TRUE, FALSE, or UNKNOWN (or UNDEFINED) based on the constrained value of its (boolean) argument. It does not modify the analysis state though the conditions tested can result in branches (e.g. through the use of short-circuit operators). llvm-svn: 156919
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
new file mode 100644
index 00000000000..f638dda2d8e
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -0,0 +1,85 @@
+//==- ExprInspectionChecker.cpp - Used for regression tests ------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ExprInspectionChecker : public Checker< eval::Call > {
+ mutable OwningPtr<BugType> BT;
+public:
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+};
+}
+
+bool ExprInspectionChecker::evalCall(const CallExpr *CE,
+ CheckerContext &C) const {
+ // These checks should have no effect on the surrounding environment
+ // (globals should not be evaluated, etc), hence the use of evalCall.
+ ExplodedNode *N = C.getPredecessor();
+ const LocationContext *LC = N->getLocationContext();
+
+ if (!C.getCalleeName(CE).equals("clang_analyzer_eval"))
+ return false;
+
+ // A specific instantiation of an inlined function may have more constrained
+ // values than can generally be assumed. Skip the check.
+ if (LC->getParent() != 0)
+ return true;
+
+ const char *Msg = 0;
+
+ if (CE->getNumArgs() == 0)
+ Msg = "Missing assertion argument";
+ else {
+ ProgramStateRef State = N->getState();
+ const Expr *Assertion = CE->getArg(0);
+ SVal AssertionVal = State->getSVal(Assertion, LC);
+
+ if (AssertionVal.isUndef())
+ Msg = "UNDEFINED";
+ else {
+ ProgramStateRef StTrue, StFalse;
+ llvm::tie(StTrue, StFalse) =
+ State->assume(cast<DefinedOrUnknownSVal>(AssertionVal));
+
+ if (StTrue) {
+ if (StFalse)
+ Msg = "UNKNOWN";
+ else
+ Msg = "TRUE";
+ } else {
+ if (StFalse)
+ Msg = "FALSE";
+ else
+ llvm_unreachable("Invalid constraint; neither true or false.");
+ }
+ }
+ }
+
+ assert(Msg);
+
+ if (!BT)
+ BT.reset(new BugType("Checking analyzer assumptions", "debug"));
+
+ BugReport *R = new BugReport(*BT, Msg, N);
+ C.EmitReport(R);
+
+ return true;
+}
+
+void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<ExprInspectionChecker>();
+}
+
OpenPOWER on IntegriCloud