diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -251,6 +251,7 @@ struct Signature { const ArgTypes ArgTys; const QualType RetTy; + Signature(){}; Signature(ArgTypes ArgTys, QualType RetTy) : ArgTys(ArgTys), RetTy(RetTy) { assertRetTypeSuitableForSignature(RetTy); for (size_t I = 0, E = ArgTys.size(); I != E; ++I) { @@ -259,6 +260,10 @@ } } bool matches(const FunctionDecl *FD) const; + bool isIrrelevant() const { + return StdLibraryFunctionsChecker::isIrrelevant(RetTy) && + ArgTys.size() == 0; + } private: static void assertArgTypeSuitableForSignature(QualType T) { @@ -316,6 +321,9 @@ Summary(ArgTypes ArgTys, QualType RetTy, InvalidationKind InvalidationKd) : Sign(ArgTys, RetTy), InvalidationKd(InvalidationKd) {} + // Create with irrelevant signature. + Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {} + Summary &Case(ConstraintSet&& CS) { CaseConstraints.push_back(std::move(CS)); return *this; @@ -338,6 +346,7 @@ bool matchesSignature(const FunctionDecl *FD) const { return Sign.matches(FD) && validate(FD); } + bool hasIrrelevantSignature() const { return Sign.isIrrelevant(); } private: // Once we know the exact type of the function then do sanity check on all @@ -596,19 +605,23 @@ bool StdLibraryFunctionsChecker::Signature::matches( const FunctionDecl *FD) const { + // Irrelevant signature matches everything. + if (isIrrelevant()) + return true; + // Check number of arguments: if (FD->param_size() != ArgTys.size()) return false; // Check return type. - if (!isIrrelevant(RetTy)) + if (!StdLibraryFunctionsChecker::isIrrelevant(RetTy)) if (RetTy != FD->getReturnType().getCanonicalType()) return false; // Check argument types. for (size_t I = 0, E = ArgTys.size(); I != E; ++I) { QualType ArgTy = ArgTys[I]; - if (isIrrelevant(ArgTy)) + if (StdLibraryFunctionsChecker::isIrrelevant(ArgTy)) continue; if (ArgTy != FD->getParamDecl(I)->getType().getCanonicalType()) return false; @@ -721,15 +734,21 @@ auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); if (LookupRes.size() == 0) return; - for (Decl *D : LookupRes) { - if (auto *FD = dyn_cast(D)) { - if (S.matchesSignature(FD)) { - S.setFunctionDecl(FD); - auto Res = Map.insert({FD->getCanonicalDecl(), S}); - assert(Res.second && "Function already has a summary set!"); - (void)Res; - return; - } + // Get all FunctionDecls. + SmallVector FDs; + for (Decl *D : LookupRes) + if (auto *FD = dyn_cast(D)) + FDs.push_back(FD); + // Irrelevant signatures should be used only without name overloading. + if (FDs.size() > 1 && S.hasIrrelevantSignature()) + return; + for (FunctionDecl *FD : FDs) { + if (S.matchesSignature(FD)) { + S.setFunctionDecl(FD); + auto Res = Map.insert({FD->getCanonicalDecl(), S}); + assert(Res.second && "Function already has a summary set!"); + (void)Res; + return; } } }