NoQ created this revision. NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, rnkovacs. Herald added subscribers: cfe-commits, Szelethus, mikhail.ramalho, baloghadamsoftware.
`CallDescription` constructor now accepts an `ArrayRef<const char *>`, instead of two different constructors for `StringRef` and `std::vector<StringRef>`. This allows us to write an init-list of a vector of `CallDescription` objects as: vector<CallDescription> V = { { { "foo" }, 1 }, { { "q1", "q2", "bar" }, 2 }, ... }; achieving uniformity between unqualified and qualified descriptions, while still allowing the old syntax of `{ "foo", 1 }` (without braces around "foo"). Previously `{ { "foo" }, 1 }` wouldn't have compiled, because the compiler was unable to figure out which constructor to call (because `{}` are allowed to be omitted or added indefinitely as a redundancy). As a cost of that, i had to switch from `StringRef`s to raw pointers, because you can't automatically convert an initializer-list of C strings to an `ArrayRef` of `StringRef`s. But that doesn't seem bad, because `StringRef`s aren't that much different from raw pointers, and in practice only static strings will be used. Also squash a mutable copy of that array. Repository: rC Clang https://reviews.llvm.org/D51390 Files: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h lib/StaticAnalyzer/Core/CallEvent.cpp Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -371,23 +371,26 @@ // accuracy. if (CD.QualifiedName.size() > 1 && D) { const DeclContext *Ctx = D->getDeclContext(); - std::vector<StringRef> QualifiedName = CD.QualifiedName; - QualifiedName.pop_back(); + // See if we'll be able to match them all. + size_t NumUnmatched = CD.QualifiedName.size() - 1; for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) { + if (NumUnmatched == 0) + break; + if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) { - if (!QualifiedName.empty() && ND->getName() == QualifiedName.back()) - QualifiedName.pop_back(); + if (ND->getName() == CD.QualifiedName[NumUnmatched - 1]) + --NumUnmatched; continue; } if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) { - if (!QualifiedName.empty() && RD->getName() == QualifiedName.back()) - QualifiedName.pop_back(); + if (RD->getName() == CD.QualifiedName[NumUnmatched - 1]) + --NumUnmatched; continue; } } - if (!QualifiedName.empty()) + if (NumUnmatched > 0) return false; } Index: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -82,37 +82,26 @@ mutable bool IsLookupDone = false; // The list of the qualified names used to identify the specified CallEvent, // e.g. "{a, b}" represent the qualified names, like "a::b". - std::vector<StringRef> QualifiedName; + std::vector<const char *> QualifiedName; unsigned RequiredArgs; public: const static unsigned NoArgRequirement = std::numeric_limits<unsigned>::max(); /// Constructs a CallDescription object. /// - /// @param QualifiedName The list of the qualified names of the function that - /// will be matched. It does not require the user to provide the full list of - /// the qualified name. The more details provided, the more accurate the - /// matching. + /// @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(std::vector<StringRef> QualifiedName, + CallDescription(ArrayRef<const char *> QualifiedName, unsigned RequiredArgs = NoArgRequirement) : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {} - /// Constructs a CallDescription object. - /// - /// @param FuncName The name of the function that will be matched. - /// - /// @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(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : CallDescription(std::vector<StringRef>({FuncName}), NoArgRequirement) { - } - /// Get the name of the function that this object matches. StringRef getFunctionName() const { return QualifiedName.back(); } };
Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -371,23 +371,26 @@ // accuracy. if (CD.QualifiedName.size() > 1 && D) { const DeclContext *Ctx = D->getDeclContext(); - std::vector<StringRef> QualifiedName = CD.QualifiedName; - QualifiedName.pop_back(); + // See if we'll be able to match them all. + size_t NumUnmatched = CD.QualifiedName.size() - 1; for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) { + if (NumUnmatched == 0) + break; + if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) { - if (!QualifiedName.empty() && ND->getName() == QualifiedName.back()) - QualifiedName.pop_back(); + if (ND->getName() == CD.QualifiedName[NumUnmatched - 1]) + --NumUnmatched; continue; } if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) { - if (!QualifiedName.empty() && RD->getName() == QualifiedName.back()) - QualifiedName.pop_back(); + if (RD->getName() == CD.QualifiedName[NumUnmatched - 1]) + --NumUnmatched; continue; } } - if (!QualifiedName.empty()) + if (NumUnmatched > 0) return false; } Index: include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -82,37 +82,26 @@ mutable bool IsLookupDone = false; // The list of the qualified names used to identify the specified CallEvent, // e.g. "{a, b}" represent the qualified names, like "a::b". - std::vector<StringRef> QualifiedName; + std::vector<const char *> QualifiedName; unsigned RequiredArgs; public: const static unsigned NoArgRequirement = std::numeric_limits<unsigned>::max(); /// Constructs a CallDescription object. /// - /// @param QualifiedName The list of the qualified names of the function that - /// will be matched. It does not require the user to provide the full list of - /// the qualified name. The more details provided, the more accurate the - /// matching. + /// @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(std::vector<StringRef> QualifiedName, + CallDescription(ArrayRef<const char *> QualifiedName, unsigned RequiredArgs = NoArgRequirement) : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {} - /// Constructs a CallDescription object. - /// - /// @param FuncName The name of the function that will be matched. - /// - /// @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(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : CallDescription(std::vector<StringRef>({FuncName}), NoArgRequirement) { - } - /// Get the name of the function that this object matches. StringRef getFunctionName() const { return QualifiedName.back(); } };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits