diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 61521c259ca9..b198b1c2ff4d 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -6,7 +6,11 @@ // //===----------------------------------------------------------------------===// // -// This checker evaluates clang builtin functions. +// This checker evaluates "standalone" clang builtin functions that are not +// just special-cased variants of well-known non-builtin functions. +// Builtin functions like __builtin_memcpy and __builtin_alloca should be +// evaluated by the same checker that handles their non-builtin variant to +// ensure that the two variants are handled consistently. // //===----------------------------------------------------------------------===// @@ -14,6 +18,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,8 +31,40 @@ namespace { class BuiltinFunctionChecker : public Checker<eval::Call> { public: bool evalCall(const CallEvent &Call, CheckerContext &C) const; + +private: + // From: clang/include/clang/Basic/Builtins.def + // C++ standard library builtins in namespace 'std'. + const CallDescriptionSet BuiltinLikeStdFunctions{ + {CDM::SimpleFunc, {"std", "addressof"}}, // + {CDM::SimpleFunc, {"std", "__addressof"}}, // + {CDM::SimpleFunc, {"std", "as_const"}}, // + {CDM::SimpleFunc, {"std", "forward"}}, // + {CDM::SimpleFunc, {"std", "forward_like"}}, // + {CDM::SimpleFunc, {"std", "move"}}, // + {CDM::SimpleFunc, {"std", "move_if_noexcept"}}, // + }; + + bool isBuiltinLikeFunction(const CallEvent &Call) const; }; +} // namespace + +bool BuiltinFunctionChecker::isBuiltinLikeFunction( + const CallEvent &Call) const { + const auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(Call.getDecl()); + if (!FD || FD->getNumParams() != 1) + return false; + + if (QualType RetTy = FD->getReturnType(); + !RetTy->isPointerType() && !RetTy->isReferenceType()) + return false; + + if (QualType ParmTy = FD->getParamDecl(0)->getType(); + !ParmTy->isPointerType() && !ParmTy->isReferenceType()) + return false; + + return BuiltinLikeStdFunctions.contains(Call); } bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, @@ -40,11 +77,17 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, const LocationContext *LCtx = C.getLocationContext(); const Expr *CE = Call.getOriginExpr(); + if (isBuiltinLikeFunction(Call)) { + C.addTransition(state->BindExpr(CE, LCtx, Call.getArgSVal(0))); + return true; + } + switch (FD->getBuiltinID()) { default: return false; - case Builtin::BI__builtin_assume: { + case Builtin::BI__builtin_assume: + case Builtin::BI__assume: { assert (Call.getNumArgs() > 0); SVal Arg = Call.getArgSVal(0); if (Arg.isUndef()) @@ -79,25 +122,6 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, return true; } - case Builtin::BI__builtin_alloca_with_align: - case Builtin::BI__builtin_alloca: { - SValBuilder &SVB = C.getSValBuilder(); - const loc::MemRegionVal R = - SVB.getAllocaRegionVal(CE, C.getLocationContext(), C.blockCount()); - - // Set the extent of the region in bytes. This enables us to use the SVal - // of the argument directly. If we saved the extent in bits, it'd be more - // difficult to reason about values like symbol*8. - auto Size = Call.getArgSVal(0); - if (auto DefSize = Size.getAs<DefinedOrUnknownSVal>()) { - // This `getAs()` is mostly paranoia, because core.CallAndMessage reports - // undefined function arguments (unless it's disabled somehow). - state = setDynamicExtent(state, R.getRegion(), *DefSize, SVB); - } - C.addTransition(state->BindExpr(CE, LCtx, R)); - return true; - } - case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: case Builtin::BI__builtin_constant_p: { |