diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/ASTMatchers/Dynamic | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'clang/lib/ASTMatchers/Dynamic')
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp | 4 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.cpp | 172 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 264 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Registry.cpp | 33 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 11 |
5 files changed, 410 insertions, 74 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp index 8656bca870ec..88c2279afb2e 100644 --- a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -1,4 +1,4 @@ -//===--- Diagnostics.cpp - Helper class for error diagnostics -----*- C++ -*-===// +//===--- Diagnostics.cpp - Helper class for error diagnostics ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -98,6 +98,8 @@ static StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) { return "Ambiguous matcher overload."; case Diagnostics::ET_RegistryValueNotFound: return "Value not found: $0"; + case Diagnostics::ET_RegistryUnknownEnumWithReplace: + return "Unknown value '$1' for arg $0; did you mean '$2'"; case Diagnostics::ET_ParserStringError: return "Error parsing string token: <$0>"; diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp new file mode 100644 index 000000000000..989ee0fa75cd --- /dev/null +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp @@ -0,0 +1,172 @@ +//===--- Marshallers.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Marshallers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" +#include <string> + +static llvm::Optional<std::string> +getBestGuess(llvm::StringRef Search, llvm::ArrayRef<llvm::StringRef> Allowed, + llvm::StringRef DropPrefix = "", unsigned MaxEditDistance = 3) { + if (MaxEditDistance != ~0U) + ++MaxEditDistance; + llvm::StringRef Res; + for (const llvm::StringRef &Item : Allowed) { + if (Item.equals_lower(Search)) { + assert(!Item.equals(Search) && "This should be handled earlier on."); + MaxEditDistance = 1; + Res = Item; + continue; + } + unsigned Distance = Item.edit_distance(Search); + if (Distance < MaxEditDistance) { + MaxEditDistance = Distance; + Res = Item; + } + } + if (!Res.empty()) + return Res.str(); + if (!DropPrefix.empty()) { + --MaxEditDistance; // Treat dropping the prefix as 1 edit + for (const llvm::StringRef &Item : Allowed) { + auto NoPrefix = Item; + if (!NoPrefix.consume_front(DropPrefix)) + continue; + if (NoPrefix.equals_lower(Search)) { + if (NoPrefix.equals(Search)) + return Item.str(); + MaxEditDistance = 1; + Res = Item; + continue; + } + unsigned Distance = NoPrefix.edit_distance(Search); + if (Distance < MaxEditDistance) { + MaxEditDistance = Distance; + Res = Item; + } + } + if (!Res.empty()) + return Res.str(); + } + return llvm::None; +} + +llvm::Optional<std::string> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + clang::attr::Kind>::getBestGuess(const VariantValue &Value) { + static constexpr llvm::StringRef Allowed[] = { +#define ATTR(X) "attr::" #X, +#include "clang/Basic/AttrList.inc" + }; + if (Value.isString()) + return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), + "attr::"); + return llvm::None; +} + +llvm::Optional<std::string> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + clang::CastKind>::getBestGuess(const VariantValue &Value) { + static constexpr llvm::StringRef Allowed[] = { +#define CAST_OPERATION(Name) "CK_" #Name, +#include "clang/AST/OperationKinds.def" + }; + if (Value.isString()) + return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), + "CK_"); + return llvm::None; +} + +llvm::Optional<std::string> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + clang::OpenMPClauseKind>::getBestGuess(const VariantValue &Value) { + static constexpr llvm::StringRef Allowed[] = { +#define OMP_CLAUSE_CLASS(Enum, Str, Class) #Enum, +#include "llvm/Frontend/OpenMP/OMPKinds.def" + }; + if (Value.isString()) + return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), + "OMPC_"); + return llvm::None; +} + +llvm::Optional<std::string> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) { + static constexpr llvm::StringRef Allowed[] = { +#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, +#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, +#include "clang/Basic/TokenKinds.def" + }; + if (Value.isString()) + return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), + "UETT_"); + return llvm::None; +} + +static constexpr std::pair<llvm::StringRef, llvm::Regex::RegexFlags> + RegexMap[] = { + {"NoFlags", llvm::Regex::RegexFlags::NoFlags}, + {"IgnoreCase", llvm::Regex::RegexFlags::IgnoreCase}, + {"Newline", llvm::Regex::RegexFlags::Newline}, + {"BasicRegex", llvm::Regex::RegexFlags::BasicRegex}, +}; + +llvm::Optional<llvm::Regex::RegexFlags> getRegexFlag(llvm::StringRef Flag) { + for (const auto &StringFlag : RegexMap) { + if (Flag == StringFlag.first) + return StringFlag.second; + } + return llvm::None; +} + +llvm::Optional<llvm::StringRef> getCloseRegexMatch(llvm::StringRef Flag) { + for (const auto &StringFlag : RegexMap) { + if (Flag.edit_distance(StringFlag.first) < 3) + return StringFlag.first; + } + return llvm::None; +} + +llvm::Optional<llvm::Regex::RegexFlags> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + llvm::Regex::RegexFlags>::getFlags(llvm::StringRef Flags) { + llvm::Optional<llvm::Regex::RegexFlags> Flag; + SmallVector<StringRef, 4> Split; + Flags.split(Split, '|', -1, false); + for (StringRef OrFlag : Split) { + if (llvm::Optional<llvm::Regex::RegexFlags> NextFlag = + getRegexFlag(OrFlag.trim())) + Flag = Flag.getValueOr(llvm::Regex::NoFlags) | *NextFlag; + else + return None; + } + return Flag; +} + +llvm::Optional<std::string> +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + llvm::Regex::RegexFlags>::getBestGuess(const VariantValue &Value) { + if (!Value.isString()) + return llvm::None; + SmallVector<StringRef, 4> Split; + llvm::StringRef(Value.getString()).split(Split, '|', -1, false); + for (llvm::StringRef &Flag : Split) { + if (llvm::Optional<llvm::StringRef> BestGuess = + getCloseRegexMatch(Flag.trim())) + Flag = *BestGuess; + else + return None; + } + if (Split.empty()) + return None; + return llvm::join(Split, " | "); +} diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index 9f46108d1848..33f6d1e4155c 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -27,12 +27,15 @@ #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/TypeTraits.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Regex.h" #include <cassert> #include <cstddef> #include <iterator> @@ -64,6 +67,10 @@ template <> struct ArgTypeTraits<std::string> { static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &) { + return llvm::None; + } }; template <> @@ -80,7 +87,11 @@ template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T>> { } static ArgKind getKind() { - return ArgKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + return ArgKind(ASTNodeKind::getFromNodeKind<T>()); + } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &) { + return llvm::None; } }; @@ -94,6 +105,10 @@ template <> struct ArgTypeTraits<bool> { static ArgKind getKind() { return ArgKind(ArgKind::AK_Boolean); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &) { + return llvm::None; + } }; template <> struct ArgTypeTraits<double> { @@ -106,6 +121,10 @@ template <> struct ArgTypeTraits<double> { static ArgKind getKind() { return ArgKind(ArgKind::AK_Double); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &) { + return llvm::None; + } }; template <> struct ArgTypeTraits<unsigned> { @@ -118,6 +137,10 @@ template <> struct ArgTypeTraits<unsigned> { static ArgKind getKind() { return ArgKind(ArgKind::AK_Unsigned); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &) { + return llvm::None; + } }; template <> struct ArgTypeTraits<attr::Kind> { @@ -141,13 +164,15 @@ public: static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &Value); }; template <> struct ArgTypeTraits<CastKind> { private: static Optional<CastKind> getCastKind(llvm::StringRef AttrKind) { return llvm::StringSwitch<Optional<CastKind>>(AttrKind) -#define CAST_OPERATION(Name) .Case( #Name, CK_##Name) +#define CAST_OPERATION(Name) .Case("CK_" #Name, CK_##Name) #include "clang/AST/OperationKinds.def" .Default(llvm::None); } @@ -164,15 +189,34 @@ public: static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &Value); +}; + +template <> struct ArgTypeTraits<llvm::Regex::RegexFlags> { +private: + static Optional<llvm::Regex::RegexFlags> getFlags(llvm::StringRef Flags); + +public: + static bool is(const VariantValue &Value) { + return Value.isString() && getFlags(Value.getString()); + } + + static llvm::Regex::RegexFlags get(const VariantValue &Value) { + return *getFlags(Value.getString()); + } + + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &Value); }; template <> struct ArgTypeTraits<OpenMPClauseKind> { private: static Optional<OpenMPClauseKind> getClauseKind(llvm::StringRef ClauseKind) { return llvm::StringSwitch<Optional<OpenMPClauseKind>>(ClauseKind) -#define OPENMP_CLAUSE(TextualSpelling, Class) \ - .Case("OMPC_" #TextualSpelling, OMPC_##TextualSpelling) -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) .Case(#Enum, llvm::omp::Clause::Enum) +#include "llvm/Frontend/OpenMP/OMPKinds.def" .Default(llvm::None); } @@ -186,6 +230,35 @@ public: } static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &Value); +}; + +template <> struct ArgTypeTraits<UnaryExprOrTypeTrait> { +private: + static Optional<UnaryExprOrTypeTrait> + getUnaryOrTypeTraitKind(llvm::StringRef ClauseKind) { + return llvm::StringSwitch<Optional<UnaryExprOrTypeTrait>>(ClauseKind) +#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) \ + .Case("UETT_" #Name, UETT_##Name) +#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) \ + .Case("UETT_" #Name, UETT_##Name) +#include "clang/Basic/TokenKinds.def" + .Default(llvm::None); + } + +public: + static bool is(const VariantValue &Value) { + return Value.isString() && getUnaryOrTypeTraitKind(Value.getString()); + } + + static UnaryExprOrTypeTrait get(const VariantValue &Value) { + return *getUnaryOrTypeTraitKind(Value.getString()); + } + + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional<std::string> getBestGuess(const VariantValue &Value); }; /// Matcher descriptor interface. @@ -211,7 +284,7 @@ public: /// set of argument types accepted for argument \p ArgNo to \p ArgKinds. // FIXME: We should provide the ability to constrain the output of this // function based on the types of other matcher arguments. - virtual void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + virtual void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &ArgKinds) const = 0; /// Returns whether this matcher is convertible to the given type. If it is @@ -221,20 +294,19 @@ public: /// same matcher overload. Zero specificity indicates that this conversion /// would produce a trivial matcher that will either always or never match. /// Such matchers are excluded from code completion results. - virtual bool isConvertibleTo( - ast_type_traits::ASTNodeKind Kind, unsigned *Specificity = nullptr, - ast_type_traits::ASTNodeKind *LeastDerivedKind = nullptr) const = 0; + virtual bool + isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity = nullptr, + ASTNodeKind *LeastDerivedKind = nullptr) const = 0; /// Returns whether the matcher will, given a matcher of any type T, yield a /// matcher of type T. virtual bool isPolymorphic() const { return false; } }; -inline bool isRetKindConvertibleTo( - ArrayRef<ast_type_traits::ASTNodeKind> RetKinds, - ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) { - for (const ast_type_traits::ASTNodeKind &NodeKind : RetKinds) { +inline bool isRetKindConvertibleTo(ArrayRef<ASTNodeKind> RetKinds, + ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) { + for (const ASTNodeKind &NodeKind : RetKinds) { if (ArgKind(NodeKind).isConvertibleTo(Kind, Specificity)) { if (LeastDerivedKind) *LeastDerivedKind = NodeKind; @@ -264,10 +336,10 @@ public: /// \param RetKinds The list of matcher types to which the matcher is /// convertible. /// \param ArgKinds The types of the arguments this matcher takes. - FixedArgCountMatcherDescriptor( - MarshallerType Marshaller, void (*Func)(), StringRef MatcherName, - ArrayRef<ast_type_traits::ASTNodeKind> RetKinds, - ArrayRef<ArgKind> ArgKinds) + FixedArgCountMatcherDescriptor(MarshallerType Marshaller, void (*Func)(), + StringRef MatcherName, + ArrayRef<ASTNodeKind> RetKinds, + ArrayRef<ArgKind> ArgKinds) : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName), RetKinds(RetKinds.begin(), RetKinds.end()), ArgKinds(ArgKinds.begin(), ArgKinds.end()) {} @@ -281,14 +353,13 @@ public: bool isVariadic() const override { return false; } unsigned getNumArgs() const override { return ArgKinds.size(); } - void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ArgKinds[ArgNo]); } - bool isConvertibleTo( - ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { return isRetKindConvertibleTo(RetKinds, Kind, Specificity, LeastDerivedKind); } @@ -297,7 +368,7 @@ private: const MarshallerType Marshaller; void (* const Func)(); const std::string MatcherName; - const std::vector<ast_type_traits::ASTNodeKind> RetKinds; + const std::vector<ASTNodeKind> RetKinds; const std::vector<ArgKind> ArgKinds; }; @@ -321,7 +392,7 @@ static void mergePolyMatchers(const PolyMatcher &Poly, /// polymorphic matcher. For the former, we just construct the VariantMatcher. /// For the latter, we instantiate all the possible Matcher<T> of the poly /// matcher. -static VariantMatcher outvalueToVariantMatcher(const DynTypedMatcher &Matcher) { +inline VariantMatcher outvalueToVariantMatcher(const DynTypedMatcher &Matcher) { return VariantMatcher::SingleMatcher(Matcher); } @@ -336,36 +407,35 @@ static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher, } template <typename T> -inline void buildReturnTypeVectorFromTypeList( - std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { - RetTypes.push_back( - ast_type_traits::ASTNodeKind::getFromNodeKind<typename T::head>()); +inline void +buildReturnTypeVectorFromTypeList(std::vector<ASTNodeKind> &RetTypes) { + RetTypes.push_back(ASTNodeKind::getFromNodeKind<typename T::head>()); buildReturnTypeVectorFromTypeList<typename T::tail>(RetTypes); } template <> inline void buildReturnTypeVectorFromTypeList<ast_matchers::internal::EmptyTypeList>( - std::vector<ast_type_traits::ASTNodeKind> &RetTypes) {} + std::vector<ASTNodeKind> &RetTypes) {} template <typename T> struct BuildReturnTypeVector { - static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { + static void build(std::vector<ASTNodeKind> &RetTypes) { buildReturnTypeVectorFromTypeList<typename T::ReturnTypes>(RetTypes); } }; template <typename T> struct BuildReturnTypeVector<ast_matchers::internal::Matcher<T>> { - static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { - RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + static void build(std::vector<ASTNodeKind> &RetTypes) { + RetTypes.push_back(ASTNodeKind::getFromNodeKind<T>()); } }; template <typename T> struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T>> { - static void build(std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { - RetTypes.push_back(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + static void build(std::vector<ASTNodeKind> &RetTypes) { + RetTypes.push_back(ASTNodeKind::getFromNodeKind<T>()); } }; @@ -439,14 +509,13 @@ public: bool isVariadic() const override { return true; } unsigned getNumArgs() const override { return 0; } - void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ArgsKind); } - bool isConvertibleTo( - ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { return isRetKindConvertibleTo(RetKinds, Kind, Specificity, LeastDerivedKind); } @@ -454,7 +523,7 @@ public: private: const RunFunc Func; const std::string MatcherName; - std::vector<ast_type_traits::ASTNodeKind> RetKinds; + std::vector<ASTNodeKind> RetKinds; const ArgKind ArgsKind; }; @@ -466,12 +535,10 @@ public: ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT> Func, StringRef MatcherName) : VariadicFuncMatcherDescriptor(Func, MatcherName), - DerivedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<DerivedT>()) { - } + DerivedKind(ASTNodeKind::getFromNodeKind<DerivedT>()) {} - bool - isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { // If Kind is not a base of DerivedKind, either DerivedKind is a base of // Kind (in which case the match will always succeed) or Kind and // DerivedKind are unrelated (in which case it will always fail), so set @@ -489,7 +556,7 @@ public: } private: - const ast_type_traits::ASTNodeKind DerivedKind; + const ASTNodeKind DerivedKind; }; /// Helper macros to check the arguments on all marshaller functions. @@ -502,9 +569,16 @@ private: #define CHECK_ARG_TYPE(index, type) \ if (!ArgTypeTraits<type>::is(Args[index].Value)) { \ - Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \ - << (index + 1) << ArgTypeTraits<type>::getKind().asString() \ - << Args[index].Value.getTypeAsString(); \ + if (llvm::Optional<std::string> BestGuess = \ + ArgTypeTraits<type>::getBestGuess(Args[index].Value)) { \ + Error->addError(Args[index].Range, \ + Error->ET_RegistryUnknownEnumWithReplace) \ + << index + 1 << Args[index].Value.getString() << *BestGuess; \ + } else { \ + Error->addError(Args[index].Range, Error->ET_RegistryWrongArgType) \ + << (index + 1) << ArgTypeTraits<type>::getKind().asString() \ + << Args[index].Value.getTypeAsString(); \ + } \ return VariantMatcher(); \ } @@ -635,7 +709,7 @@ public: return Overload0NumArgs; } - void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { for (const auto &O : Overloads) { if (O->isConvertibleTo(ThisKind)) @@ -643,9 +717,8 @@ public: } } - bool isConvertibleTo( - ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { for (const auto &O : Overloads) { if (O->isConvertibleTo(Kind, Specificity, LeastDerivedKind)) return true; @@ -657,6 +730,71 @@ private: std::vector<std::unique_ptr<MatcherDescriptor>> Overloads; }; +template <typename ReturnType> +class RegexMatcherDescriptor : public MatcherDescriptor { +public: + RegexMatcherDescriptor(ReturnType (*WithFlags)(StringRef, + llvm::Regex::RegexFlags), + ReturnType (*NoFlags)(StringRef), + ArrayRef<ASTNodeKind> RetKinds) + : WithFlags(WithFlags), NoFlags(NoFlags), + RetKinds(RetKinds.begin(), RetKinds.end()) {} + bool isVariadic() const override { return true; } + unsigned getNumArgs() const override { return 0; } + + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, + std::vector<ArgKind> &Kinds) const override { + assert(ArgNo < 2); + Kinds.push_back(ArgKind::AK_String); + } + + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { + return isRetKindConvertibleTo(RetKinds, Kind, Specificity, + LeastDerivedKind); + } + + VariantMatcher create(SourceRange NameRange, ArrayRef<ParserValue> Args, + Diagnostics *Error) const override { + if (Args.size() < 1 || Args.size() > 2) { + Error->addError(NameRange, Diagnostics::ET_RegistryWrongArgCount) + << "1 or 2" << Args.size(); + return VariantMatcher(); + } + if (!ArgTypeTraits<StringRef>::is(Args[0].Value)) { + Error->addError(Args[0].Range, Error->ET_RegistryWrongArgType) + << 1 << ArgTypeTraits<StringRef>::getKind().asString() + << Args[0].Value.getTypeAsString(); + return VariantMatcher(); + } + if (Args.size() == 1) { + return outvalueToVariantMatcher( + NoFlags(ArgTypeTraits<StringRef>::get(Args[0].Value))); + } + if (!ArgTypeTraits<llvm::Regex::RegexFlags>::is(Args[1].Value)) { + if (llvm::Optional<std::string> BestGuess = + ArgTypeTraits<llvm::Regex::RegexFlags>::getBestGuess( + Args[1].Value)) { + Error->addError(Args[1].Range, Error->ET_RegistryUnknownEnumWithReplace) + << 2 << Args[1].Value.getString() << *BestGuess; + } else { + Error->addError(Args[1].Range, Error->ET_RegistryWrongArgType) + << 2 << ArgTypeTraits<llvm::Regex::RegexFlags>::getKind().asString() + << Args[1].Value.getTypeAsString(); + } + return VariantMatcher(); + } + return outvalueToVariantMatcher( + WithFlags(ArgTypeTraits<StringRef>::get(Args[0].Value), + ArgTypeTraits<llvm::Regex::RegexFlags>::get(Args[1].Value))); + } + +private: + ReturnType (*const WithFlags)(StringRef, llvm::Regex::RegexFlags); + ReturnType (*const NoFlags)(StringRef); + const std::vector<ASTNodeKind> RetKinds; +}; + /// Variadic operator marshaller function. class VariadicOperatorMatcherDescriptor : public MatcherDescriptor { public: @@ -697,13 +835,13 @@ public: bool isVariadic() const override { return true; } unsigned getNumArgs() const override { return 0; } - void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector<ArgKind> &Kinds) const override { Kinds.push_back(ThisKind); } - bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, - ast_type_traits::ASTNodeKind *LeastDerivedKind) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity, + ASTNodeKind *LeastDerivedKind) const override { if (Specificity) *Specificity = 1; if (LeastDerivedKind) @@ -727,7 +865,7 @@ private: template <typename ReturnType> std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) { - std::vector<ast_type_traits::ASTNodeKind> RetTypes; + std::vector<ASTNodeKind> RetTypes; BuildReturnTypeVector<ReturnType>::build(RetTypes); return std::make_unique<FixedArgCountMatcherDescriptor>( matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func), @@ -738,7 +876,7 @@ makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) { template <typename ReturnType, typename ArgType1> std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) { - std::vector<ast_type_traits::ASTNodeKind> RetTypes; + std::vector<ASTNodeKind> RetTypes; BuildReturnTypeVector<ReturnType>::build(RetTypes); ArgKind AK = ArgTypeTraits<ArgType1>::getKind(); return std::make_unique<FixedArgCountMatcherDescriptor>( @@ -751,7 +889,7 @@ template <typename ReturnType, typename ArgType1, typename ArgType2> std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2), StringRef MatcherName) { - std::vector<ast_type_traits::ASTNodeKind> RetTypes; + std::vector<ASTNodeKind> RetTypes; BuildReturnTypeVector<ReturnType>::build(RetTypes); ArgKind AKs[] = { ArgTypeTraits<ArgType1>::getKind(), ArgTypeTraits<ArgType2>::getKind() }; @@ -760,6 +898,16 @@ makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2), reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs); } +template <typename ReturnType> +std::unique_ptr<MatcherDescriptor> makeMatcherRegexMarshall( + ReturnType (*FuncFlags)(llvm::StringRef, llvm::Regex::RegexFlags), + ReturnType (*Func)(llvm::StringRef)) { + std::vector<ASTNodeKind> RetTypes; + BuildReturnTypeVector<ReturnType>::build(RetTypes); + return std::make_unique<RegexMatcherDescriptor<ReturnType>>(FuncFlags, Func, + RetTypes); +} + /// Variadic overload. template <typename ResultT, typename ArgT, ResultT (*Func)(ArrayRef<const ArgT *>)> diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 1c0930c5983a..ec2215804c09 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -90,14 +90,14 @@ void RegistryMaps::registerMatcher( REGISTER_MATCHER_OVERLOAD(name); \ } while (false) +#define REGISTER_REGEX_MATCHER(name) \ + registerMatcher(#name, internal::makeMatcherRegexMarshall(name, name)) + /// Generate a registry map with all the known matchers. /// Please keep sorted alphabetically! RegistryMaps::RegistryMaps() { // TODO: Here is the list of the missing matchers, grouped by reason. // - // Need Variant/Parser fixes: - // ofKind - // // Polymorphic + argument overload: // findAll // @@ -124,6 +124,10 @@ RegistryMaps::RegistryMaps() { }; REGISTER_MATCHER_OVERLOAD(equals); + REGISTER_REGEX_MATCHER(isExpansionInFileMatching); + REGISTER_REGEX_MATCHER(matchesName); + REGISTER_REGEX_MATCHER(matchesSelector); + REGISTER_MATCHER(accessSpecDecl); REGISTER_MATCHER(addrLabelExpr); REGISTER_MATCHER(alignOfExpr); @@ -154,6 +158,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(characterLiteral); REGISTER_MATCHER(chooseExpr); REGISTER_MATCHER(classTemplateDecl); + REGISTER_MATCHER(classTemplatePartialSpecializationDecl); REGISTER_MATCHER(classTemplateSpecializationDecl); REGISTER_MATCHER(complexType); REGISTER_MATCHER(compoundLiteralExpr); @@ -183,6 +188,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(cxxMemberCallExpr); REGISTER_MATCHER(cxxMethodDecl); REGISTER_MATCHER(cxxNewExpr); + REGISTER_MATCHER(cxxNoexceptExpr); REGISTER_MATCHER(cxxNullPtrLiteralExpr); REGISTER_MATCHER(cxxOperatorCallExpr); REGISTER_MATCHER(cxxRecordDecl); @@ -201,6 +207,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(declStmt); REGISTER_MATCHER(declaratorDecl); REGISTER_MATCHER(decltypeType); + REGISTER_MATCHER(deducedTemplateSpecializationType); REGISTER_MATCHER(defaultStmt); REGISTER_MATCHER(dependentSizedArrayType); REGISTER_MATCHER(designatedInitExpr); @@ -237,11 +244,15 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(has); REGISTER_MATCHER(hasAncestor); REGISTER_MATCHER(hasAnyArgument); + REGISTER_MATCHER(hasAnyBase); REGISTER_MATCHER(hasAnyClause); REGISTER_MATCHER(hasAnyConstructorInitializer); REGISTER_MATCHER(hasAnyDeclaration); REGISTER_MATCHER(hasAnyName); + REGISTER_MATCHER(hasAnyOperatorName); + REGISTER_MATCHER(hasAnyOverloadedOperatorName); REGISTER_MATCHER(hasAnyParameter); + REGISTER_MATCHER(hasAnyPlacementArg); REGISTER_MATCHER(hasAnySelector); REGISTER_MATCHER(hasAnySubstatement); REGISTER_MATCHER(hasAnyTemplateArgument); @@ -267,6 +278,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasDefinition); REGISTER_MATCHER(hasDescendant); REGISTER_MATCHER(hasDestinationType); + REGISTER_MATCHER(hasDirectBase); REGISTER_MATCHER(hasDynamicExceptionSpec); REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); @@ -292,6 +304,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasName); REGISTER_MATCHER(hasNullSelector); REGISTER_MATCHER(hasObjectExpression); + REGISTER_MATCHER(hasOperands); REGISTER_MATCHER(hasOperatorName); REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); @@ -303,6 +316,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasReceiverType); REGISTER_MATCHER(hasReplacementType); REGISTER_MATCHER(hasReturnValue); + REGISTER_MATCHER(hasPlacementArg); REGISTER_MATCHER(hasSelector); REGISTER_MATCHER(hasSingleDecl); REGISTER_MATCHER(hasSize); @@ -347,12 +361,14 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isArray); REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isAssignmentOperator); + REGISTER_MATCHER(isAtPosition); REGISTER_MATCHER(isBaseInitializer); REGISTER_MATCHER(isBitField); REGISTER_MATCHER(isCatchAll); REGISTER_MATCHER(isClass); REGISTER_MATCHER(isClassMessage); REGISTER_MATCHER(isClassMethod); + REGISTER_MATCHER(isComparisonOperator); REGISTER_MATCHER(isConst); REGISTER_MATCHER(isConstQualified); REGISTER_MATCHER(isConstexpr); @@ -363,8 +379,9 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isDefinition); REGISTER_MATCHER(isDelegatingConstructor); REGISTER_MATCHER(isDeleted); + REGISTER_MATCHER(isEnum); REGISTER_MATCHER(isExceptionVariable); - REGISTER_MATCHER(isExpansionInFileMatching); + REGISTER_MATCHER(isExpandedFromMacro); REGISTER_MATCHER(isExpansionInMainFile); REGISTER_MATCHER(isExpansionInSystemHeader); REGISTER_MATCHER(isExplicit); @@ -372,6 +389,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isExpr); REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isFinal); + REGISTER_MATCHER(isFirstPrivateKind); REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isInStdNamespace); REGISTER_MATCHER(isInTemplateInstantiation); @@ -391,7 +409,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isNoReturn); REGISTER_MATCHER(isNoThrow); REGISTER_MATCHER(isNoneKind); - REGISTER_MATCHER(isOMPStructuredBlock); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); @@ -420,8 +437,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(labelStmt); REGISTER_MATCHER(lambdaExpr); REGISTER_MATCHER(linkageSpecDecl); - REGISTER_MATCHER(matchesName); - REGISTER_MATCHER(matchesSelector); REGISTER_MATCHER(materializeTemporaryExpr); REGISTER_MATCHER(member); REGISTER_MATCHER(memberExpr); @@ -452,6 +467,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(objcThrowStmt); REGISTER_MATCHER(objcTryStmt); REGISTER_MATCHER(ofClass); + REGISTER_MATCHER(ofKind); REGISTER_MATCHER(ompDefaultClause); REGISTER_MATCHER(ompExecutableDirective); REGISTER_MATCHER(on); @@ -492,6 +508,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(substTemplateTypeParmType); REGISTER_MATCHER(switchCase); REGISTER_MATCHER(switchStmt); + REGISTER_MATCHER(tagDecl); REGISTER_MATCHER(tagType); REGISTER_MATCHER(templateArgument); REGISTER_MATCHER(templateArgumentCountIs); @@ -652,7 +669,7 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) { OS << "..."; OS << ")"; - std::string TypedText = Name; + std::string TypedText = std::string(Name); TypedText += "("; if (ArgsKinds.empty()) TypedText += ")"; diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp index 118ca2a41cb1..866e2d0e3491 100644 --- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -1,4 +1,4 @@ -//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/ +//===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -101,8 +101,7 @@ public: return llvm::None; } - bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, - unsigned *Specificity) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { return ArgKind(Matcher.getSupportedKind()) .isConvertibleTo(Kind, Specificity); } @@ -159,8 +158,7 @@ public: return llvm::None; } - bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, - unsigned *Specificity) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { unsigned MaxSpecificity = 0; for (const DynTypedMatcher &Matcher : Matchers) { unsigned ThisSpecificity; @@ -202,8 +200,7 @@ public: return Ops.constructVariadicOperator(Op, Args); } - bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, - unsigned *Specificity) const override { + bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override { for (const VariantMatcher &Matcher : Args) { if (!Matcher.isConvertibleTo(Kind, Specificity)) return false; |