diff options
Diffstat (limited to 'clang/lib/ASTMatchers/Dynamic/Marshallers.h')
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 264 |
1 files changed, 206 insertions, 58 deletions
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 *>)> |