diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index 965838a4408c2..3432d2648633c 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -27,20 +27,48 @@ class IdentifierInfo; namespace clang { namespace ento { - -enum CallDescriptionFlags : unsigned { - CDF_None = 0, - - /// Describes a C standard function that is sometimes implemented as a macro - /// that expands to a compiler builtin with some __builtin prefix. - /// The builtin may as well have a few extra arguments on top of the requested - /// number of arguments. - CDF_MaybeBuiltin = 1 << 0, -}; - -/// This class represents a description of a function call using the number of -/// arguments and the name of the function. +/// A `CallDescription` is a pattern that can be used to _match_ calls +/// based on the qualified name and the argument/parameter counts. class CallDescription { +public: + enum class Mode { + /// Match calls to functions from the C standard library. On some platforms + /// some functions may be implemented as macros that expand to calls to + /// built-in variants of the given functions, so in this mode we use some + /// heuristics to recognize these implementation-defined variants: + /// - We also accept calls where the name is derived from the specified + /// name by adding "__builtin" or similar prefixes/suffixes. + /// - We also accept calls where the number of arguments or parameters is + /// greater than the specified value. + /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). + /// Note that functions whose declaration context is not a TU (e.g. + /// methods, functions in namespaces) are not accepted as C library + /// functions. + /// FIXME: If I understand it correctly, this discards calls where C++ code + /// refers a C library function through the namespace `std::` via headers + /// like . + CLibrary, + + /// Matches "simple" functions that are not methods. (Static methods are + /// methods.) + SimpleFunc, + + /// Matches a C++ method (may be static, may be virtual, may be an + /// overloaded operator, a constructor or a destructor). + CXXMethod, + + /// Match any CallEvent that is not an ObjCMethodCall. + /// FIXME: Previously this was the default behavior of CallDescription, but + /// its use should be replaced by a more specific mode almost everywhere. + Unspecified, + + /// FIXME: Add support for ObjCMethodCall events (I'm not adding it because + /// I'm not familiar with Objective-C). Note that currently an early return + /// in `bool matches(const CallEvent &Call) const;` discards all + /// Objective-C method calls. + }; + +private: friend class CallEvent; using MaybeCount = std::optional; @@ -50,20 +78,26 @@ class CallDescription { std::vector QualifiedName; MaybeCount RequiredArgs; MaybeCount RequiredParams; - int Flags; + Mode MatchAs; public: /// Constructs a CallDescription object. /// + /// @param MatchAs Specifies the kind of the call that should be matched. + /// /// @param QualifiedName The list of the name qualifiers of the function that /// will be matched. The user is allowed to skip any of the qualifiers. /// For example, {"std", "basic_string", "c_str"} would match both /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). /// - /// @param RequiredArgs The number of arguments that is expected to match a - /// call. Omit this parameter to match every occurrence of call with a given - /// name regardless the number of arguments. - CallDescription(CallDescriptionFlags Flags, ArrayRef QualifiedName, + /// @param RequiredArgs The expected number of arguments that are passed to + /// the function. Omit this parameter (or pass std::nullopt) to match every + /// occurrence without checking the argument count in the call. + /// + /// @param RequiredParams The expected number of parameters in the function + /// definition that is called. Omit this parameter to match every occurrence + /// without checking the parameter count in the definition. + CallDescription(Mode MatchAs, ArrayRef QualifiedName, MaybeCount RequiredArgs = std::nullopt, MaybeCount RequiredParams = std::nullopt); @@ -222,6 +256,10 @@ template class CallDescriptionMap { } }; +/// Enumerators of this enum class are used to construct CallDescription +/// objects; in that context the fully qualified name is needlessly verbose. +using CDM = CallDescription::Mode; + /// An immutable set of CallDescriptions. /// Checkers can efficiently decide if a given CallEvent matches any /// CallDescription in the set. diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index b7b64c3da4f6c..59be236ca1c76 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -124,48 +124,47 @@ class CStringChecker : public Checker< eval::Call, const CallEvent &)>; CallDescriptionMap Callbacks = { - {{CDF_MaybeBuiltin, {"memcpy"}, 3}, + {{CDM::CLibrary, {"memcpy"}, 3}, std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Regular)}, - {{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, + {{CDM::CLibrary, {"wmemcpy"}, 3}, std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Wide)}, - {{CDF_MaybeBuiltin, {"mempcpy"}, 3}, + {{CDM::CLibrary, {"mempcpy"}, 3}, std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Regular)}, - {{CDF_None, {"wmempcpy"}, 3}, + {{CDM::Unspecified, {"wmempcpy"}, 3}, std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Wide)}, - {{CDF_MaybeBuiltin, {"memcmp"}, 3}, + {{CDM::CLibrary, {"memcmp"}, 3}, std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)}, - {{CDF_MaybeBuiltin, {"wmemcmp"}, 3}, + {{CDM::CLibrary, {"wmemcmp"}, 3}, std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Wide)}, - {{CDF_MaybeBuiltin, {"memmove"}, 3}, + {{CDM::CLibrary, {"memmove"}, 3}, std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Regular)}, - {{CDF_MaybeBuiltin, {"wmemmove"}, 3}, + {{CDM::CLibrary, {"wmemmove"}, 3}, std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Wide)}, - {{CDF_MaybeBuiltin, {"memset"}, 3}, &CStringChecker::evalMemset}, - {{CDF_MaybeBuiltin, {"explicit_memset"}, 3}, &CStringChecker::evalMemset}, - {{CDF_MaybeBuiltin, {"strcpy"}, 2}, &CStringChecker::evalStrcpy}, - {{CDF_MaybeBuiltin, {"strncpy"}, 3}, &CStringChecker::evalStrncpy}, - {{CDF_MaybeBuiltin, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy}, - {{CDF_MaybeBuiltin, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy}, - {{CDF_MaybeBuiltin, {"strcat"}, 2}, &CStringChecker::evalStrcat}, - {{CDF_MaybeBuiltin, {"strncat"}, 3}, &CStringChecker::evalStrncat}, - {{CDF_MaybeBuiltin, {"strlcat"}, 3}, &CStringChecker::evalStrlcat}, - {{CDF_MaybeBuiltin, {"strlen"}, 1}, &CStringChecker::evalstrLength}, - {{CDF_MaybeBuiltin, {"wcslen"}, 1}, &CStringChecker::evalstrLength}, - {{CDF_MaybeBuiltin, {"strnlen"}, 2}, &CStringChecker::evalstrnLength}, - {{CDF_MaybeBuiltin, {"wcsnlen"}, 2}, &CStringChecker::evalstrnLength}, - {{CDF_MaybeBuiltin, {"strcmp"}, 2}, &CStringChecker::evalStrcmp}, - {{CDF_MaybeBuiltin, {"strncmp"}, 3}, &CStringChecker::evalStrncmp}, - {{CDF_MaybeBuiltin, {"strcasecmp"}, 2}, &CStringChecker::evalStrcasecmp}, - {{CDF_MaybeBuiltin, {"strncasecmp"}, 3}, - &CStringChecker::evalStrncasecmp}, - {{CDF_MaybeBuiltin, {"strsep"}, 2}, &CStringChecker::evalStrsep}, - {{CDF_MaybeBuiltin, {"bcopy"}, 3}, &CStringChecker::evalBcopy}, - {{CDF_MaybeBuiltin, {"bcmp"}, 3}, + {{CDM::CLibrary, {"memset"}, 3}, &CStringChecker::evalMemset}, + {{CDM::CLibrary, {"explicit_memset"}, 3}, &CStringChecker::evalMemset}, + {{CDM::CLibrary, {"strcpy"}, 2}, &CStringChecker::evalStrcpy}, + {{CDM::CLibrary, {"strncpy"}, 3}, &CStringChecker::evalStrncpy}, + {{CDM::CLibrary, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy}, + {{CDM::CLibrary, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy}, + {{CDM::CLibrary, {"strcat"}, 2}, &CStringChecker::evalStrcat}, + {{CDM::CLibrary, {"strncat"}, 3}, &CStringChecker::evalStrncat}, + {{CDM::CLibrary, {"strlcat"}, 3}, &CStringChecker::evalStrlcat}, + {{CDM::CLibrary, {"strlen"}, 1}, &CStringChecker::evalstrLength}, + {{CDM::CLibrary, {"wcslen"}, 1}, &CStringChecker::evalstrLength}, + {{CDM::CLibrary, {"strnlen"}, 2}, &CStringChecker::evalstrnLength}, + {{CDM::CLibrary, {"wcsnlen"}, 2}, &CStringChecker::evalstrnLength}, + {{CDM::CLibrary, {"strcmp"}, 2}, &CStringChecker::evalStrcmp}, + {{CDM::CLibrary, {"strncmp"}, 3}, &CStringChecker::evalStrncmp}, + {{CDM::CLibrary, {"strcasecmp"}, 2}, &CStringChecker::evalStrcasecmp}, + {{CDM::CLibrary, {"strncasecmp"}, 3}, &CStringChecker::evalStrncasecmp}, + {{CDM::CLibrary, {"strsep"}, 2}, &CStringChecker::evalStrsep}, + {{CDM::CLibrary, {"bcopy"}, 3}, &CStringChecker::evalBcopy}, + {{CDM::CLibrary, {"bcmp"}, 3}, std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)}, - {{CDF_MaybeBuiltin, {"bzero"}, 2}, &CStringChecker::evalBzero}, - {{CDF_MaybeBuiltin, {"explicit_bzero"}, 2}, &CStringChecker::evalBzero}, - {{CDF_MaybeBuiltin, {"sprintf"}, 2}, &CStringChecker::evalSprintf}, - {{CDF_MaybeBuiltin, {"snprintf"}, 2}, &CStringChecker::evalSnprintf}, + {{CDM::CLibrary, {"bzero"}, 2}, &CStringChecker::evalBzero}, + {{CDM::CLibrary, {"explicit_bzero"}, 2}, &CStringChecker::evalBzero}, + {{CDM::CLibrary, {"sprintf"}, 2}, &CStringChecker::evalSprintf}, + {{CDM::CLibrary, {"snprintf"}, 2}, &CStringChecker::evalSnprintf}, }; // These require a bit of special handling. diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index 4ceaf933d0bfc..4c48fdf498f7f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -718,28 +718,24 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const { {{{"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, {{{"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrncat)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BIstrncat)}}, TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrlcpy)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BIstrlcpy)}}, TR::Prop({{1, 2}}, {{0}})}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrlcat)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BIstrlcat)}}, TR::Prop({{1, 2}}, {{0}})}, - {{CDF_MaybeBuiltin, {{"snprintf"}}}, + {{CDM::CLibrary, {{"snprintf"}}}, TR::Prop({{1}, 3}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"sprintf"}}}, + {{CDM::CLibrary, {{"sprintf"}}}, TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"strcpy"}}}, + {{CDM::CLibrary, {{"strcpy"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {{"stpcpy"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {{"strcat"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, + {{CDM::CLibrary, {{"wcsncat"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"stpcpy"}}}, - TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"strcat"}}}, - TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"wcsncat"}}}, - TR::Prop({{1}}, {{0, ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"strdupa"}}}, - TR::Prop({{0}}, {{ReturnValueIndex}})}, - {{CDF_MaybeBuiltin, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {{"strdupa"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, + {{CDM::CLibrary, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})}, // Sinks {{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, @@ -753,31 +749,29 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const { {{{"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)}, {{{"execvpe"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)}, {{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)}, - {{CDF_MaybeBuiltin, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {{"alloca"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {{"memccpy"}}}, - TR::Sink({{3}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {{"realloc"}}}, - TR::Sink({{1}}, MsgTaintedBufferSize)}, + {{CDM::CLibrary, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, + {{CDM::CLibrary, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, + {{CDM::CLibrary, {{"alloca"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)}, + {{CDM::CLibrary, {{"memccpy"}}}, TR::Sink({{3}}, MsgTaintedBufferSize)}, + {{CDM::CLibrary, {{"realloc"}}}, TR::Sink({{1}}, MsgTaintedBufferSize)}, {{{{"setproctitle"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, {{{{"setproctitle_fast"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)}, // SinkProps - {{CDF_MaybeBuiltin, BI.getName(Builtin::BImemcpy)}, + {{CDM::CLibrary, BI.getName(Builtin::BImemcpy)}, TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BImemmove)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BImemmove)}}, TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrncpy)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BIstrncpy)}}, TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrndup)}}, + {{CDM::CLibrary, {BI.getName(Builtin::BIstrndup)}}, TR::SinkProp({{1}}, {{0, 1}}, {{ReturnValueIndex}}, MsgTaintedBufferSize)}, - {{CDF_MaybeBuiltin, {{"bcopy"}}}, + {{CDM::CLibrary, {{"bcopy"}}}, TR::SinkProp({{2}}, {{0, 2}}, {{1}}, MsgTaintedBufferSize)}}; // `getenv` returns taint only in untrusted environments. diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 79ab05f2c7866..b27ca6a449597 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -410,13 +410,13 @@ class MallocChecker {{{"malloc"}, 3}, &MallocChecker::checkKernelMalloc}, {{{"calloc"}, 2}, &MallocChecker::checkCalloc}, {{{"valloc"}, 1}, &MallocChecker::checkBasicAlloc}, - {{CDF_MaybeBuiltin, {"strndup"}, 2}, &MallocChecker::checkStrdup}, - {{CDF_MaybeBuiltin, {"strdup"}, 1}, &MallocChecker::checkStrdup}, + {{CDM::CLibrary, {"strndup"}, 2}, &MallocChecker::checkStrdup}, + {{CDM::CLibrary, {"strdup"}, 1}, &MallocChecker::checkStrdup}, {{{"_strdup"}, 1}, &MallocChecker::checkStrdup}, {{{"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc}, {{{"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex}, - {{CDF_MaybeBuiltin, {"wcsdup"}, 1}, &MallocChecker::checkStrdup}, - {{CDF_MaybeBuiltin, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup}, + {{CDM::CLibrary, {"wcsdup"}, 1}, &MallocChecker::checkStrdup}, + {{CDM::CLibrary, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup}, {{{"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc}, {{{"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0}, {{{"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc}, diff --git a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp index 94b2fde0a6f39..459e854cd44d9 100644 --- a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp @@ -35,13 +35,13 @@ static MaybeCount readRequiredParams(MaybeCount RequiredArgs, return std::nullopt; } -ento::CallDescription::CallDescription(CallDescriptionFlags Flags, +ento::CallDescription::CallDescription(Mode MatchAs, ArrayRef QualifiedName, MaybeCount RequiredArgs /*= None*/, MaybeCount RequiredParams /*= None*/) : RequiredArgs(RequiredArgs), RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)), - Flags(Flags) { + MatchAs(MatchAs) { assert(!QualifiedName.empty()); this->QualifiedName.reserve(QualifiedName.size()); llvm::transform(QualifiedName, std::back_inserter(this->QualifiedName), @@ -52,7 +52,8 @@ ento::CallDescription::CallDescription(CallDescriptionFlags Flags, ento::CallDescription::CallDescription(ArrayRef QualifiedName, MaybeCount RequiredArgs /*= None*/, MaybeCount RequiredParams /*= None*/) - : CallDescription(CDF_None, QualifiedName, RequiredArgs, RequiredParams) {} + : CallDescription(Mode::Unspecified, QualifiedName, RequiredArgs, + RequiredParams) {} bool ento::CallDescription::matches(const CallEvent &Call) const { // FIXME: Add ObjC Message support. @@ -74,14 +75,20 @@ bool ento::CallDescription::matchesAsWritten(const CallExpr &CE) const { return matchesImpl(FD, CE.getNumArgs(), FD->param_size()); } -bool ento::CallDescription::matchesImpl(const FunctionDecl *Callee, - size_t ArgCount, +bool ento::CallDescription::matchesImpl(const FunctionDecl *FD, size_t ArgCount, size_t ParamCount) const { - const auto *FD = Callee; if (!FD) return false; - if (Flags & CDF_MaybeBuiltin) { + const bool isMethod = isa(FD); + + if (MatchAs == Mode::SimpleFunc && isMethod) + return false; + + if (MatchAs == Mode::CXXMethod && !isMethod) + return false; + + if (MatchAs == Mode::CLibrary) { return CheckerContext::isCLibraryFunction(FD, getFunctionName()) && (!RequiredArgs || *RequiredArgs <= ArgCount) && (!RequiredParams || *RequiredParams <= ParamCount); diff --git a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp index e8b237b891ca8..3aac1f81f523d 100644 --- a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp +++ b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp @@ -488,11 +488,10 @@ TEST(CallDescription, NegativeMatchQualifiedNames) { } TEST(CallDescription, MatchBuiltins) { - // Test CDF_MaybeBuiltin - a flag that allows matching weird builtins. + // Test CDM::CLibrary - a flag that allows matching weird builtins. EXPECT_TRUE(tooling::runToolOnCode( std::unique_ptr(new CallDescriptionAction<>( - {{{{"memset"}, 3}, false}, - {{CDF_MaybeBuiltin, {"memset"}, 3}, true}})), + {{{{"memset"}, 3}, false}, {{CDM::CLibrary, {"memset"}, 3}, true}})), "void foo() {" " int x;" " __builtin___memset_chk(&x, 0, sizeof(x)," @@ -503,8 +502,8 @@ TEST(CallDescription, MatchBuiltins) { SCOPED_TRACE("multiple similar builtins"); EXPECT_TRUE(tooling::runToolOnCode( std::unique_ptr(new CallDescriptionAction<>( - {{{CDF_MaybeBuiltin, {"memcpy"}, 3}, false}, - {{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true}})), + {{{CDM::CLibrary, {"memcpy"}, 3}, false}, + {{CDM::CLibrary, {"wmemcpy"}, 3}, true}})), R"(void foo(wchar_t *x, wchar_t *y) { __builtin_wmemcpy(x, y, sizeof(wchar_t)); })")); @@ -513,8 +512,8 @@ TEST(CallDescription, MatchBuiltins) { SCOPED_TRACE("multiple similar builtins reversed order"); EXPECT_TRUE(tooling::runToolOnCode( std::unique_ptr(new CallDescriptionAction<>( - {{{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true}, - {{CDF_MaybeBuiltin, {"memcpy"}, 3}, false}})), + {{{CDM::CLibrary, {"wmemcpy"}, 3}, true}, + {{CDM::CLibrary, {"memcpy"}, 3}, false}})), R"(void foo(wchar_t *x, wchar_t *y) { __builtin_wmemcpy(x, y, sizeof(wchar_t)); })")); @@ -522,8 +521,8 @@ TEST(CallDescription, MatchBuiltins) { { SCOPED_TRACE("lookbehind and lookahead mismatches"); EXPECT_TRUE(tooling::runToolOnCode( - std::unique_ptr(new CallDescriptionAction<>( - {{{CDF_MaybeBuiltin, {"func"}}, false}})), + std::unique_ptr( + new CallDescriptionAction<>({{{CDM::CLibrary, {"func"}}, false}})), R"( void funcXXX(); void XXXfunc(); @@ -537,8 +536,8 @@ TEST(CallDescription, MatchBuiltins) { { SCOPED_TRACE("lookbehind and lookahead matches"); EXPECT_TRUE(tooling::runToolOnCode( - std::unique_ptr(new CallDescriptionAction<>( - {{{CDF_MaybeBuiltin, {"func"}}, true}})), + std::unique_ptr( + new CallDescriptionAction<>({{{CDM::CLibrary, {"func"}}, true}})), R"( void func(); void func_XXX();