Index: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -45,6 +45,7 @@ #include #include #include +#include namespace clang { @@ -79,6 +80,8 @@ mutable IdentifierInfo *II = nullptr; mutable bool IsLookupDone = false; + // Represent the function name or method name, like "c_str" or + // "std::string::c_str". StringRef FuncName; unsigned RequiredArgs; @@ -96,7 +99,25 @@ : FuncName(FuncName), RequiredArgs(RequiredArgs) {} /// Get the name of the function that this object matches. - StringRef getFunctionName() const { return FuncName; } + StringRef getFunctionName() const { + auto QualifierNamePair = FuncName.rsplit("::"); + return QualifierNamePair.second.empty() ? QualifierNamePair.first + : QualifierNamePair.second; + } + + bool matchQualifiedName(llvm::StringRef QualifiedName) const { + llvm::SmallVector Names; + // Split the function name with the separator "::". + FuncName.split(Names, "::"); + + // FIXME: Since there is no perfect way to get the qualified name without + // template argument, we can only use a fuzzy matching approach. + for (auto item : Names) + if (QualifiedName.find(item) == StringRef::npos) + return false; + + return true; + } }; template Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -60,6 +60,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include #define DEBUG_TYPE "static-analyzer-call-event" @@ -256,11 +257,18 @@ return false; if (!CD.IsLookupDone) { CD.IsLookupDone = true; - CD.II = &getState()->getStateManager().getContext().Idents.get(CD.FuncName); + CD.II = &getState()->getStateManager().getContext().Idents.get( + CD.getFunctionName()); } const IdentifierInfo *II = getCalleeIdentifier(); if (!II || II != CD.II) return false; + + const auto *ND = dyn_cast_or_null(getDecl()); + if (!ND) + return false; + if (!CD.matchQualifiedName(ND->getQualifiedNameAsString())) + return false; return (CD.RequiredArgs == CallDescription::NoArgRequirement || CD.RequiredArgs == getNumArgs()); }