[cfe-commits] r161708 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp test/Analysis/inline.c
Jordan Rose
jordan_rose at apple.com
Fri Aug 10 15:26:30 PDT 2012
Author: jrose
Date: Fri Aug 10 17:26:29 2012
New Revision: 161708
URL: http://llvm.org/viewvc/llvm-project?rev=161708&view=rev
Log:
[analyzer] Add clang_analyzer_checkInlined for debugging purposes.
This check is also accessible through the debug.ExprInspection checker.
Like clang_analyzer_eval, you can use it to test the analyzer engine's
current state; the argument should be true or false to indicate whether or
not you expect the function to be inlined.
When used in the positive case (clang_analyzer_checkInlined(true)), the
analyzer prints the message "TRUE" if the function is ever inlined. However,
clang_analyzer_checkInlined(false) should never print a message; this asserts
that there should be no paths on which the current function is inlined, but
then there are no paths on which to print a message! (If the assertion is
violated, the message "FALSE" will be printed.)
This asymmetry comes from the fact that the only other chance to print a
message is when the function is analyzed as a top-level function. However,
when we do that, we can't be sure it isn't also inlined elsewhere (such as
in a recursive function, or if we want to analyze in both general or
specialized cases). Rather than have all checkInlined calls have an appended,
meaningless "FALSE" or "TOP-LEVEL" case, there is just no message printed.
void clang_analyzer_checkInlined(int);
For debugging purposes only!
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
cfe/trunk/test/Analysis/inline.c
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=161708&r1=161707&r2=161708&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Fri Aug 10 17:26:29 2012
@@ -18,65 +18,102 @@
namespace {
class ExprInspectionChecker : public Checker< eval::Call > {
mutable OwningPtr<BugType> BT;
+
+ void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
+
+ typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
+ CheckerContext &C) const;
+
public:
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
};
}
bool ExprInspectionChecker::evalCall(const CallExpr *CE,
- CheckerContext &C) const {
+ CheckerContext &C) const {
// These checks should have no effect on the surrounding environment
- // (globals should not be evaluated, etc), hence the use of evalCall.
+ // (globals should not be invalidated, etc), hence the use of evalCall.
+ FnCheck Handler = llvm::StringSwitch<FnCheck>(C.getCalleeName(CE))
+ .Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
+ .Case("clang_analyzer_checkInlined",
+ &ExprInspectionChecker::analyzerCheckInlined)
+ .Default(0);
+
+ if (!Handler)
+ return false;
+
+ (this->*Handler)(CE, C);
+ return true;
+}
+
+static const char *getArgumentValueString(const CallExpr *CE,
+ CheckerContext &C) {
+ if (CE->getNumArgs() == 0)
+ return "Missing assertion argument";
+
ExplodedNode *N = C.getPredecessor();
const LocationContext *LC = N->getLocationContext();
+ ProgramStateRef State = N->getState();
- if (!C.getCalleeName(CE).equals("clang_analyzer_eval"))
- return false;
+ const Expr *Assertion = CE->getArg(0);
+ SVal AssertionVal = State->getSVal(Assertion, LC);
+
+ if (AssertionVal.isUndef())
+ return "UNDEFINED";
+
+ ProgramStateRef StTrue, StFalse;
+ llvm::tie(StTrue, StFalse) =
+ State->assume(cast<DefinedOrUnknownSVal>(AssertionVal));
+
+ if (StTrue) {
+ if (StFalse)
+ return "UNKNOWN";
+ else
+ return "TRUE";
+ } else {
+ if (StFalse)
+ return "FALSE";
+ else
+ llvm_unreachable("Invalid constraint; neither true or false.");
+ }
+}
+
+void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
+ CheckerContext &C) const {
+ ExplodedNode *N = C.getPredecessor();
+ const LocationContext *LC = N->getLocationContext();
// 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;
+ if (LC->getCurrentStackFrame()->getParent() != 0)
+ return;
- const char *Msg = 0;
+ if (!BT)
+ BT.reset(new BugType("Checking analyzer assumptions", "debug"));
- 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.");
- }
- }
- }
+ BugReport *R = new BugReport(*BT, getArgumentValueString(CE, C), N);
+ C.EmitReport(R);
+}
- assert(Msg);
+void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
+ CheckerContext &C) const {
+ ExplodedNode *N = C.getPredecessor();
+ const LocationContext *LC = N->getLocationContext();
+
+ // An inlined function could conceivably also be analyzed as a top-level
+ // function. We ignore this case and only emit a message (TRUE or FALSE)
+ // when we are analyzing it as an inlined function. This means that
+ // clang_analyzer_checkInlined(true) should always print TRUE, but
+ // clang_analyzer_checkInlined(false) should never actually print anything.
+ if (LC->getCurrentStackFrame()->getParent() == 0)
+ return;
if (!BT)
BT.reset(new BugType("Checking analyzer assumptions", "debug"));
- BugReport *R = new BugReport(*BT, Msg, N);
+ BugReport *R = new BugReport(*BT, getArgumentValueString(CE, C), N);
C.EmitReport(R);
-
- return true;
}
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
Modified: cfe/trunk/test/Analysis/inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.c?rev=161708&r1=161707&r2=161708&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.c (original)
+++ cfe/trunk/test/Analysis/inline.c Fri Aug 10 17:26:29 2012
@@ -1,10 +1,12 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -analyzer-store region -verify %s
void clang_analyzer_eval(int);
+void clang_analyzer_checkInlined(int);
int test1_f1() {
int y = 1;
y++;
+ clang_analyzer_checkInlined(1); // expected-warning{{TRUE}}
return y;
}
@@ -103,3 +105,8 @@
return x + 1;
}
+
+void never_called_by_anyone() {
+ clang_analyzer_checkInlined(0); // no-warning
+}
+
More information about the cfe-commits
mailing list