Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -1064,8 +1064,19 @@ // e.g. "{a, b}" represent the qualified names, like "a::b". std::vector QualifiedName; Optional RequiredArgs; + Optional RequiredParams; int Flags; + // A constructor helper. + static Optional readRequiredParams(Optional RequiredArgs, + Optional RequiredParams) { + if (RequiredParams) + return RequiredParams; + if (RequiredArgs) + return static_cast(*RequiredArgs); + return None; + } + public: /// Constructs a CallDescription object. /// @@ -1078,14 +1089,17 @@ /// call. Omit this parameter to match every occurrence of call with a given /// name regardless the number of arguments. CallDescription(int Flags, ArrayRef QualifiedName, - Optional RequiredArgs = None) + Optional RequiredArgs = None, + Optional RequiredParams = None) : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs), + RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)), Flags(Flags) {} /// Construct a CallDescription with default flags. CallDescription(ArrayRef QualifiedName, - Optional RequiredArgs = None) - : CallDescription(0, QualifiedName, RequiredArgs) {} + Optional RequiredArgs = None, + Optional RequiredParams = None) + : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {} /// Get the name of the function that this object matches. StringRef getFunctionName() const { return QualifiedName.back(); } Index: cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -116,7 +116,9 @@ // vswprintf is the wide version of vsnprintf, // vsprintf has no wide version {{"vswscanf", 3}, 2}}; -const CallDescription ValistChecker::VaStart("__builtin_va_start", 2), + +const CallDescription + ValistChecker::VaStart("__builtin_va_start", /*Args=*/2, /*Params=*/1), ValistChecker::VaCopy("__builtin_va_copy", 2), ValistChecker::VaEnd("__builtin_va_end", 1); } // end anonymous namespace Index: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -368,7 +368,8 @@ if (CD.Flags & CDF_MaybeBuiltin) { return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) && - (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs()); + (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs()) && + (!CD.RequiredParams || CD.RequiredParams <= parameters().size()); } if (!CD.IsLookupDone) { @@ -407,7 +408,8 @@ return false; } - return (!CD.RequiredArgs || CD.RequiredArgs == getNumArgs()); + return (!CD.RequiredArgs || CD.RequiredArgs == getNumArgs()) && + (!CD.RequiredParams || CD.RequiredParams == parameters().size()); } SVal CallEvent::getArgSVal(unsigned Index) const { Index: cfe/trunk/test/Analysis/cast-value-weird.cpp =================================================================== --- cfe/trunk/test/Analysis/cast-value-weird.cpp +++ cfe/trunk/test/Analysis/cast-value-weird.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling -verify %s + +// expected-no-diagnostics + +namespace llvm { +template +void cast(...); +void a() { cast(int()); } // no-crash +} // namespace llvm