diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 8544f98b948..10594e331cb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/Builtins.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" using namespace clang; @@ -23,30 +24,32 @@ namespace { class BuiltinFunctionChecker : public Checker<eval::Call> { public: - bool evalCall(const CallExpr *CE, CheckerContext &C) const; + bool evalCall(const CallEvent &Call, CheckerContext &C) const; }; } -bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, +bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, CheckerContext &C) const { ProgramStateRef state = C.getState(); - const FunctionDecl *FD = C.getCalleeDecl(CE); - const LocationContext *LCtx = C.getLocationContext(); + const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); if (!FD) return false; + const LocationContext *LCtx = C.getLocationContext(); + const Expr *CE = Call.getOriginExpr(); + switch (FD->getBuiltinID()) { default: return false; case Builtin::BI__builtin_assume: { - assert (CE->arg_begin() != CE->arg_end()); - SVal ArgSVal = C.getSVal(CE->getArg(0)); - if (ArgSVal.isUndef()) + assert (Call.getNumArgs() > 0); + SVal Arg = Call.getArgSVal(0); + if (Arg.isUndef()) return true; // Return true to model purity. - state = state->assume(ArgSVal.castAs<DefinedOrUnknownSVal>(), true); + 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) { @@ -66,9 +69,9 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, // __builtin_assume_aligned, just return the value of the subexpression. // __builtin_addressof is going from a reference to a pointer, but those // are represented the same way in the analyzer. - assert (CE->arg_begin() != CE->arg_end()); - SVal X = C.getSVal(*(CE->arg_begin())); - C.addTransition(state->BindExpr(CE, LCtx, X)); + assert (Call.getNumArgs() > 0); + SVal Arg = Call.getArgSVal(0); + C.addTransition(state->BindExpr(CE, LCtx, Arg)); return true; } @@ -82,12 +85,14 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, // Set the extent of the region in bytes. This enables us to use the // SVal of the argument directly. If we save the extent in bits, we // cannot represent values like symbol*8. - auto Size = C.getSVal(*(CE->arg_begin())).castAs<DefinedOrUnknownSVal>(); + auto Size = Call.getArgSVal(0); + if (Size.isUndef()) + return true; // Return true to model purity. SValBuilder& svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); DefinedOrUnknownSVal extentMatchesSizeArg = - svalBuilder.evalEQ(state, Extent, Size); + svalBuilder.evalEQ(state, Extent, Size.castAs<DefinedOrUnknownSVal>()); state = state->assume(extentMatchesSizeArg, true); assert(state && "The region should not have any previous constraints"); |