diff options
Diffstat (limited to 'include/clang/ASTMatchers/Dynamic')
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Diagnostics.h | 185 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Parser.h | 257 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Registry.h | 133 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/VariantValue.h | 326 |
4 files changed, 0 insertions, 901 deletions
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h deleted file mode 100644 index 2c76dda..0000000 --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ /dev/null @@ -1,185 +0,0 @@ -//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Diagnostics class to manage error messages. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H -#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H - -#include "clang/ASTMatchers/Dynamic/VariantValue.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" -#include <string> -#include <vector> - -namespace clang { -namespace ast_matchers { -namespace dynamic { - -struct SourceLocation { - SourceLocation() : Line(), Column() {} - unsigned Line; - unsigned Column; -}; - -struct SourceRange { - SourceLocation Start; - SourceLocation End; -}; - -/// \brief A VariantValue instance annotated with its parser context. -struct ParserValue { - ParserValue() : Text(), Range(), Value() {} - StringRef Text; - SourceRange Range; - VariantValue Value; -}; - -/// \brief Helper class to manage error messages. -class Diagnostics { -public: - /// \brief Parser context types. - enum ContextType { - CT_MatcherArg = 0, - CT_MatcherConstruct = 1 - }; - - /// \brief All errors from the system. - enum ErrorType { - ET_None = 0, - - ET_RegistryMatcherNotFound = 1, - ET_RegistryWrongArgCount = 2, - ET_RegistryWrongArgType = 3, - ET_RegistryNotBindable = 4, - ET_RegistryAmbiguousOverload = 5, - ET_RegistryValueNotFound = 6, - - ET_ParserStringError = 100, - ET_ParserNoOpenParen = 101, - ET_ParserNoCloseParen = 102, - ET_ParserNoComma = 103, - ET_ParserNoCode = 104, - ET_ParserNotAMatcher = 105, - ET_ParserInvalidToken = 106, - ET_ParserMalformedBindExpr = 107, - ET_ParserTrailingCode = 108, - ET_ParserUnsignedError = 109, - ET_ParserOverloadedType = 110 - }; - - /// \brief Helper stream class. - class ArgStream { - public: - ArgStream(std::vector<std::string> *Out) : Out(Out) {} - template <class T> ArgStream &operator<<(const T &Arg) { - return operator<<(Twine(Arg)); - } - ArgStream &operator<<(const Twine &Arg); - - private: - std::vector<std::string> *Out; - }; - - /// \brief Class defining a parser context. - /// - /// Used by the parser to specify (possibly recursive) contexts where the - /// parsing/construction can fail. Any error triggered within a context will - /// keep information about the context chain. - /// This class should be used as a RAII instance in the stack. - struct Context { - public: - /// \brief About to call the constructor for a matcher. - enum ConstructMatcherEnum { ConstructMatcher }; - Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName, - SourceRange MatcherRange); - /// \brief About to recurse into parsing one argument for a matcher. - enum MatcherArgEnum { MatcherArg }; - Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName, - SourceRange MatcherRange, unsigned ArgNumber); - ~Context(); - - private: - Diagnostics *const Error; - }; - - /// \brief Context for overloaded matcher construction. - /// - /// This context will take care of merging all errors that happen within it - /// as "candidate" overloads for the same matcher. - struct OverloadContext { - public: - OverloadContext(Diagnostics* Error); - ~OverloadContext(); - - /// \brief Revert all errors that happened within this context. - void revertErrors(); - - private: - Diagnostics *const Error; - unsigned BeginIndex; - }; - - /// \brief Add an error to the diagnostics. - /// - /// All the context information will be kept on the error message. - /// \return a helper class to allow the caller to pass the arguments for the - /// error message, using the << operator. - ArgStream addError(SourceRange Range, ErrorType Error); - - /// \brief Information stored for one frame of the context. - struct ContextFrame { - ContextType Type; - SourceRange Range; - std::vector<std::string> Args; - }; - - /// \brief Information stored for each error found. - struct ErrorContent { - std::vector<ContextFrame> ContextStack; - struct Message { - SourceRange Range; - ErrorType Type; - std::vector<std::string> Args; - }; - std::vector<Message> Messages; - }; - ArrayRef<ErrorContent> errors() const { return Errors; } - - /// \brief Returns a simple string representation of each error. - /// - /// Each error only shows the error message without any context. - void printToStream(llvm::raw_ostream &OS) const; - std::string toString() const; - - /// \brief Returns the full string representation of each error. - /// - /// Each error message contains the full context. - void printToStreamFull(llvm::raw_ostream &OS) const; - std::string toStringFull() const; - -private: - /// \brief Helper function used by the constructors of ContextFrame. - ArgStream pushContextFrame(ContextType Type, SourceRange Range); - - std::vector<ContextFrame> ContextStack; - std::vector<ErrorContent> Errors; -}; - -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang - -#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h deleted file mode 100644 index 76926f0..0000000 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ /dev/null @@ -1,257 +0,0 @@ -//===--- Parser.h - Matcher expression parser -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Simple matcher expression parser. -/// -/// The parser understands matcher expressions of the form: -/// MatcherName(Arg0, Arg1, ..., ArgN) -/// as well as simple types like strings. -/// The parser does not know how to process the matchers. It delegates this task -/// to a Sema object received as an argument. -/// -/// \code -/// Grammar for the expressions supported: -/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression> -/// <Literal> := <StringLiteral> | <Unsigned> -/// <StringLiteral> := "quoted string" -/// <Unsigned> := [0-9]+ -/// <NamedValue> := <Identifier> -/// <MatcherExpression> := <Identifier>(<ArgumentList>) | -/// <Identifier>(<ArgumentList>).bind(<StringLiteral>) -/// <Identifier> := [a-zA-Z]+ -/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList> -/// \endcode -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H -#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H - -#include "clang/ASTMatchers/Dynamic/Diagnostics.h" -#include "clang/ASTMatchers/Dynamic/Registry.h" -#include "clang/ASTMatchers/Dynamic/VariantValue.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" - -namespace clang { -namespace ast_matchers { -namespace dynamic { - -/// \brief Matcher expression parser. -class Parser { -public: - /// \brief Interface to connect the parser with the registry and more. - /// - /// The parser uses the Sema instance passed into - /// parseMatcherExpression() to handle all matcher tokens. The simplest - /// processor implementation would simply call into the registry to create - /// the matchers. - /// However, a more complex processor might decide to intercept the matcher - /// creation and do some extra work. For example, it could apply some - /// transformation to the matcher by adding some id() nodes, or could detect - /// specific matcher nodes for more efficient lookup. - class Sema { - public: - virtual ~Sema(); - - /// \brief Process a matcher expression. - /// - /// All the arguments passed here have already been processed. - /// - /// \param Ctor A matcher constructor looked up by lookupMatcherCtor. - /// - /// \param NameRange The location of the name in the matcher source. - /// Useful for error reporting. - /// - /// \param BindID The ID to use to bind the matcher, or a null \c StringRef - /// if no ID is specified. - /// - /// \param Args The argument list for the matcher. - /// - /// \return The matcher objects constructed by the processor, or a null - /// matcher if an error occurred. In that case, \c Error will contain a - /// description of the error. - virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, - SourceRange NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error) = 0; - - /// \brief Look up a matcher by name. - /// - /// \param MatcherName The matcher name found by the parser. - /// - /// \return The matcher constructor, or Optional<MatcherCtor>() if not - /// found. - virtual llvm::Optional<MatcherCtor> - lookupMatcherCtor(StringRef MatcherName) = 0; - - /// \brief Compute the list of completion types for \p Context. - /// - /// Each element of \p Context represents a matcher invocation, going from - /// outermost to innermost. Elements are pairs consisting of a reference to - /// the matcher constructor and the index of the next element in the - /// argument list of that matcher (or for the last element, the index of - /// the completion point in the argument list). An empty list requests - /// completion for the root matcher. - virtual std::vector<ArgKind> getAcceptedCompletionTypes( - llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); - - /// \brief Compute the list of completions that match any of - /// \p AcceptedTypes. - /// - /// \param AcceptedTypes All types accepted for this completion. - /// - /// \return All completions for the specified types. - /// Completions should be valid when used in \c lookupMatcherCtor(). - /// The matcher constructed from the return of \c lookupMatcherCtor() - /// should be convertible to some type in \p AcceptedTypes. - virtual std::vector<MatcherCompletion> - getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes); - }; - - /// \brief Sema implementation that uses the matcher registry to process the - /// tokens. - class RegistrySema : public Parser::Sema { - public: - ~RegistrySema() override; - - llvm::Optional<MatcherCtor> - lookupMatcherCtor(StringRef MatcherName) override; - - VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, - SourceRange NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error) override; - - std::vector<ArgKind> getAcceptedCompletionTypes( - llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override; - - std::vector<MatcherCompletion> - getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override; - }; - - typedef llvm::StringMap<VariantValue> NamedValueMap; - - /// \brief Parse a matcher expression. - /// - /// \param MatcherCode The matcher expression to parse. - /// - /// \param S The Sema instance that will help the parser - /// construct the matchers. If null, it uses the default registry. - /// - /// \param NamedValues A map of precomputed named values. This provides - /// the dictionary for the <NamedValue> rule of the grammar. - /// If null, it is ignored. - /// - /// \return The matcher object constructed by the processor, or an empty - /// Optional if an error occurred. In that case, \c Error will contain a - /// description of the error. - /// The caller takes ownership of the DynTypedMatcher object returned. - static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Sema *S, - const NamedValueMap *NamedValues, - Diagnostics *Error); - static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Sema *S, - Diagnostics *Error) { - return parseMatcherExpression(MatcherCode, S, nullptr, Error); - } - static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) { - return parseMatcherExpression(MatcherCode, nullptr, Error); - } - - /// \brief Parse an expression. - /// - /// Parses any expression supported by this parser. In general, the - /// \c parseMatcherExpression function is a better approach to get a matcher - /// object. - /// - /// \param S The Sema instance that will help the parser - /// construct the matchers. If null, it uses the default registry. - /// - /// \param NamedValues A map of precomputed named values. This provides - /// the dictionary for the <NamedValue> rule of the grammar. - /// If null, it is ignored. - static bool parseExpression(StringRef Code, Sema *S, - const NamedValueMap *NamedValues, - VariantValue *Value, Diagnostics *Error); - static bool parseExpression(StringRef Code, Sema *S, - VariantValue *Value, Diagnostics *Error) { - return parseExpression(Code, S, nullptr, Value, Error); - } - static bool parseExpression(StringRef Code, VariantValue *Value, - Diagnostics *Error) { - return parseExpression(Code, nullptr, Value, Error); - } - - /// \brief Complete an expression at the given offset. - /// - /// \param S The Sema instance that will help the parser - /// construct the matchers. If null, it uses the default registry. - /// - /// \param NamedValues A map of precomputed named values. This provides - /// the dictionary for the <NamedValue> rule of the grammar. - /// If null, it is ignored. - /// - /// \return The list of completions, which may be empty if there are no - /// available completions or if an error occurred. - static std::vector<MatcherCompletion> - completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, - const NamedValueMap *NamedValues); - static std::vector<MatcherCompletion> - completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) { - return completeExpression(Code, CompletionOffset, S, nullptr); - } - static std::vector<MatcherCompletion> - completeExpression(StringRef Code, unsigned CompletionOffset) { - return completeExpression(Code, CompletionOffset, nullptr); - } - -private: - class CodeTokenizer; - struct ScopedContextEntry; - struct TokenInfo; - - Parser(CodeTokenizer *Tokenizer, Sema *S, - const NamedValueMap *NamedValues, - Diagnostics *Error); - - bool parseExpressionImpl(VariantValue *Value); - bool parseMatcherExpressionImpl(const TokenInfo &NameToken, - VariantValue *Value); - bool parseIdentifierPrefixImpl(VariantValue *Value); - - void addCompletion(const TokenInfo &CompToken, - const MatcherCompletion &Completion); - void addExpressionCompletions(); - - std::vector<MatcherCompletion> - getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes); - - CodeTokenizer *const Tokenizer; - Sema *const S; - const NamedValueMap *const NamedValues; - Diagnostics *const Error; - - typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy; - ContextStackTy ContextStack; - std::vector<MatcherCompletion> Completions; -}; - -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang - -#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h deleted file mode 100644 index 3808adb..0000000 --- a/include/clang/ASTMatchers/Dynamic/Registry.h +++ /dev/null @@ -1,133 +0,0 @@ -//===--- Registry.h - Matcher registry -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Registry of all known matchers. -/// -/// The registry provides a generic interface to construct any matcher by name. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H -#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H - -#include "clang/ASTMatchers/Dynamic/Diagnostics.h" -#include "clang/ASTMatchers/Dynamic/VariantValue.h" -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" - -namespace clang { -namespace ast_matchers { -namespace dynamic { - -namespace internal { -class MatcherDescriptor; -} - -typedef const internal::MatcherDescriptor *MatcherCtor; - -struct MatcherCompletion { - MatcherCompletion() {} - MatcherCompletion(StringRef TypedText, StringRef MatcherDecl, - unsigned Specificity) - : TypedText(TypedText), MatcherDecl(MatcherDecl), - Specificity(Specificity) {} - - /// \brief The text to type to select this matcher. - std::string TypedText; - - /// \brief The "declaration" of the matcher, with type information. - std::string MatcherDecl; - - /// \brief Value corresponding to the "specificity" of the converted matcher. - /// - /// 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. - unsigned Specificity; - - bool operator==(const MatcherCompletion &Other) const { - return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl; - } -}; - -class Registry { -public: - /// \brief Look up a matcher in the registry by name, - /// - /// \return An opaque value which may be used to refer to the matcher - /// constructor, or Optional<MatcherCtor>() if not found. - static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName); - - /// \brief Compute the list of completion types for \p Context. - /// - /// Each element of \p Context represents a matcher invocation, going from - /// outermost to innermost. Elements are pairs consisting of a reference to - /// the matcher constructor and the index of the next element in the - /// argument list of that matcher (or for the last element, the index of - /// the completion point in the argument list). An empty list requests - /// completion for the root matcher. - static std::vector<ArgKind> getAcceptedCompletionTypes( - llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); - - /// \brief Compute the list of completions that match any of - /// \p AcceptedTypes. - /// - /// \param AcceptedTypes All types accepted for this completion. - /// - /// \return All completions for the specified types. - /// Completions should be valid when used in \c lookupMatcherCtor(). - /// The matcher constructed from the return of \c lookupMatcherCtor() - /// should be convertible to some type in \p AcceptedTypes. - static std::vector<MatcherCompletion> - getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes); - - /// \brief Construct a matcher from the registry. - /// - /// \param Ctor The matcher constructor to instantiate. - /// - /// \param NameRange The location of the name in the matcher source. - /// Useful for error reporting. - /// - /// \param Args The argument list for the matcher. The number and types of the - /// values must be valid for the matcher requested. Otherwise, the function - /// will return an error. - /// - /// \return The matcher object constructed if no error was found. - /// A null matcher if the number of arguments or argument types do not match - /// the signature. In that case \c Error will contain the description of - /// the error. - static VariantMatcher constructMatcher(MatcherCtor Ctor, - SourceRange NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error); - - /// \brief Construct a matcher from the registry and bind it. - /// - /// Similar the \c constructMatcher() above, but it then tries to bind the - /// matcher to the specified \c BindID. - /// If the matcher is not bindable, it sets an error in \c Error and returns - /// a null matcher. - static VariantMatcher constructBoundMatcher(MatcherCtor Ctor, - SourceRange NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error); - -private: - Registry() = delete; -}; - -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang - -#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h deleted file mode 100644 index c391b24..0000000 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ /dev/null @@ -1,326 +0,0 @@ -//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/ -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Polymorphic value type. -/// -/// Supports all the types required for dynamic Matcher construction. -/// Used by the registry to construct matchers in a generic way. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H -#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H - -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/Twine.h" -#include <memory> -#include <vector> - -namespace clang { -namespace ast_matchers { -namespace dynamic { - -/// \brief Kind identifier. -/// -/// It supports all types that VariantValue can contain. -class ArgKind { - public: - enum Kind { - AK_Matcher, - AK_Unsigned, - AK_String - }; - /// \brief Constructor for non-matcher types. - ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } - - /// \brief Constructor for matcher types. - ArgKind(ast_type_traits::ASTNodeKind MatcherKind) - : K(AK_Matcher), MatcherKind(MatcherKind) {} - - Kind getArgKind() const { return K; } - ast_type_traits::ASTNodeKind getMatcherKind() const { - assert(K == AK_Matcher); - return MatcherKind; - } - - /// \brief Determines if this type can be converted to \p To. - /// - /// \param To the requested destination type. - /// - /// \param Specificity value corresponding to the "specificity" of the - /// convertion. - bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; - - bool operator<(const ArgKind &Other) const { - if (K == AK_Matcher && Other.K == AK_Matcher) - return MatcherKind < Other.MatcherKind; - return K < Other.K; - } - - /// \brief String representation of the type. - std::string asString() const; - -private: - Kind K; - ast_type_traits::ASTNodeKind MatcherKind; -}; - -using ast_matchers::internal::DynTypedMatcher; - -/// \brief A variant matcher object. -/// -/// The purpose of this object is to abstract simple and polymorphic matchers -/// into a single object type. -/// Polymorphic matchers might be implemented as a list of all the possible -/// overloads of the matcher. \c VariantMatcher knows how to select the -/// appropriate overload when needed. -/// To get a real matcher object out of a \c VariantMatcher you can do: -/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous -/// to decide which matcher to return. Eg. it contains only a single -/// matcher, or a polymorphic one with only one overload. -/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if -/// the underlying matcher(s) can unambiguously return a Matcher<T>. -class VariantMatcher { - /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. - class MatcherOps { - public: - MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} - - bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const; - - /// \brief Convert \p Matcher the destination type and return it as a new - /// DynTypedMatcher. - virtual DynTypedMatcher - convertMatcher(const DynTypedMatcher &Matcher) const = 0; - - /// \brief Constructs a variadic typed matcher from \p InnerMatchers. - /// Will try to convert each inner matcher to the destination type and - /// return llvm::None if it fails to do so. - llvm::Optional<DynTypedMatcher> - constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, - ArrayRef<VariantMatcher> InnerMatchers) const; - - protected: - ~MatcherOps() = default; - - private: - ast_type_traits::ASTNodeKind NodeKind; - }; - - /// \brief Payload interface to be specialized by each matcher type. - /// - /// It follows a similar interface as VariantMatcher itself. - class Payload : public RefCountedBaseVPTR { - public: - ~Payload() override; - virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; - virtual std::string getTypeAsString() const = 0; - virtual llvm::Optional<DynTypedMatcher> - getTypedMatcher(const MatcherOps &Ops) const = 0; - virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, - unsigned *Specificity) const = 0; - }; - -public: - /// \brief A null matcher. - VariantMatcher(); - - /// \brief Clones the provided matcher. - static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); - - /// \brief Clones the provided matchers. - /// - /// They should be the result of a polymorphic matcher. - static VariantMatcher - PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); - - /// \brief Creates a 'variadic' operator matcher. - /// - /// It will bind to the appropriate type on getTypedMatcher<T>(). - static VariantMatcher - VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, - std::vector<VariantMatcher> Args); - - /// \brief Makes the matcher the "null" matcher. - void reset(); - - /// \brief Whether the matcher is null. - bool isNull() const { return !Value; } - - /// \brief Return a single matcher, if there is no ambiguity. - /// - /// \returns the matcher, if there is only one matcher. An empty Optional, if - /// the underlying matcher is a polymorphic matcher with more than one - /// representation. - llvm::Optional<DynTypedMatcher> getSingleMatcher() const; - - /// \brief Determines if the contained matcher can be converted to - /// \c Matcher<T>. - /// - /// For the Single case, it returns true if it can be converted to - /// \c Matcher<T>. - /// For the Polymorphic case, it returns true if one, and only one, of the - /// overloads can be converted to \c Matcher<T>. If there are more than one - /// that can, the result would be ambiguous and false is returned. - template <class T> - bool hasTypedMatcher() const { - if (!Value) return false; - return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); - } - - /// \brief Determines if the contained matcher can be converted to \p Kind. - /// - /// \param Kind the requested destination type. - /// - /// \param Specificity value corresponding to the "specificity" of the - /// convertion. - bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, - unsigned *Specificity) const { - if (Value) - return Value->isConvertibleTo(Kind, Specificity); - return false; - } - - /// \brief Return this matcher as a \c Matcher<T>. - /// - /// Handles the different types (Single, Polymorphic) accordingly. - /// Asserts that \c hasTypedMatcher<T>() is true. - template <class T> - ast_matchers::internal::Matcher<T> getTypedMatcher() const { - assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); - return Value->getTypedMatcher(TypedMatcherOps<T>()) - ->template convertTo<T>(); - } - - /// \brief String representation of the type of the value. - /// - /// If the underlying matcher is a polymorphic one, the string will show all - /// the types. - std::string getTypeAsString() const; - -private: - explicit VariantMatcher(Payload *Value) : Value(Value) {} - - template <typename T> struct TypedMatcherOps; - - class SinglePayload; - class PolymorphicPayload; - class VariadicOpPayload; - - IntrusiveRefCntPtr<const Payload> Value; -}; - -template <typename T> -struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { - TypedMatcherOps() - : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} - typedef ast_matchers::internal::Matcher<T> MatcherT; - - DynTypedMatcher - convertMatcher(const DynTypedMatcher &Matcher) const override { - return DynTypedMatcher(Matcher.convertTo<T>()); - } -}; - -/// \brief Variant value class. -/// -/// Basically, a tagged union with value type semantics. -/// It is used by the registry as the return value and argument type for the -/// matcher factory methods. -/// It can be constructed from any of the supported types. It supports -/// copy/assignment. -/// -/// Supported types: -/// - \c unsigned -/// - \c llvm::StringRef -/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>) -class VariantValue { -public: - VariantValue() : Type(VT_Nothing) {} - - VariantValue(const VariantValue &Other); - ~VariantValue(); - VariantValue &operator=(const VariantValue &Other); - - /// \brief Specific constructors for each supported type. - VariantValue(unsigned Unsigned); - VariantValue(StringRef String); - VariantValue(const VariantMatcher &Matchers); - - /// \brief Returns true iff this is not an empty value. - explicit operator bool() const { return hasValue(); } - bool hasValue() const { return Type != VT_Nothing; } - - /// \brief Unsigned value functions. - bool isUnsigned() const; - unsigned getUnsigned() const; - void setUnsigned(unsigned Unsigned); - - /// \brief String value functions. - bool isString() const; - const std::string &getString() const; - void setString(StringRef String); - - /// \brief Matcher value functions. - bool isMatcher() const; - const VariantMatcher &getMatcher() const; - void setMatcher(const VariantMatcher &Matcher); - - /// \brief Determines if the contained value can be converted to \p Kind. - /// - /// \param Kind the requested destination type. - /// - /// \param Specificity value corresponding to the "specificity" of the - /// convertion. - bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; - - /// \brief Determines if the contained value can be converted to any kind - /// in \p Kinds. - /// - /// \param Kinds the requested destination types. - /// - /// \param Specificity value corresponding to the "specificity" of the - /// convertion. It is the maximum specificity of all the possible - /// conversions. - bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; - - /// \brief String representation of the type of the value. - std::string getTypeAsString() const; - -private: - void reset(); - - /// \brief All supported value types. - enum ValueType { - VT_Nothing, - VT_Unsigned, - VT_String, - VT_Matcher - }; - - /// \brief All supported value types. - union AllValues { - unsigned Unsigned; - std::string *String; - VariantMatcher *Matcher; - }; - - ValueType Type; - AllValues Value; -}; - -} // end namespace dynamic -} // end namespace ast_matchers -} // end namespace clang - -#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H |