diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -248,9 +248,12 @@ return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES); } +static bool isStdFunctionCall(const CallEvent &Call) { + return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace(); +} + bool isStdOstreamOperatorCall(const CallEvent &Call) { - if (Call.getNumArgs() != 2 || - !Call.getDecl()->getDeclContext()->isStdNamespace()) + if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call)) return false; const auto *FC = dyn_cast(&Call); if (!FC) @@ -265,6 +268,13 @@ isStdBasicOstream(Call.getArgExpr(0)); } +static bool isPotentiallyComparisionOpCall(const CallEvent &Call) { + if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call)) + return false; + return smartptr::isStdSmartPtr(Call.getArgExpr(0)) || + smartptr::isStdSmartPtr(Call.getArgExpr(1)); +} + bool SmartPtrModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { @@ -272,14 +282,11 @@ // If any one of the arg is a unique_ptr, then // we can try this function - if (Call.getNumArgs() == 2 && - Call.getDecl()->getDeclContext()->isStdNamespace()) - if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) || - smartptr::isStdSmartPtr(Call.getArgExpr(1))) - if (handleComparisionOp(Call, C)) - return true; - - if (isStdOstreamOperatorCall(Call)) + if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call)) + if (handleComparisionOp(Call, C)) + return true; + + if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call)) return handleOstreamOperator(Call, C); if (Call.isCalled(StdSwapCall)) { diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp --- a/clang/test/Analysis/smart-ptr.cpp +++ b/clang/test/Analysis/smart-ptr.cpp @@ -536,3 +536,10 @@ } #endif + +// The following test isn't really a "smart-ptr" test +// It came up during a bug fix (D106296) +void testCheckForFunctionsWithNoDecl(void (*bar)(bool, bool)) { + // This should NOT crash. + bar(true, false); +}