diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/ASTMatchers')
7 files changed, 927 insertions, 293 deletions
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp index f6dcb97..23708e2 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -58,11 +58,8 @@ struct MatchKey { BoundNodesTreeBuilder BoundNodes; bool operator<(const MatchKey &Other) const { - if (MatcherID != Other.MatcherID) - return MatcherID < Other.MatcherID; - if (Node != Other.Node) - return Node < Other.Node; - return BoundNodes < Other.BoundNodes; + return std::tie(MatcherID, Node, BoundNodes) < + std::tie(Other.MatcherID, Other.Node, Other.BoundNodes); } }; @@ -140,7 +137,7 @@ public: // of the public API of this class. bool TraverseDecl(Decl *DeclNode) { ScopedIncrement ScopedDepth(&CurrentDepth); - return (DeclNode == NULL) || traverse(*DeclNode); + return (DeclNode == nullptr) || traverse(*DeclNode); } bool TraverseStmt(Stmt *StmtNode) { ScopedIncrement ScopedDepth(&CurrentDepth); @@ -148,11 +145,11 @@ public: if (Traversal == ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses) { const Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode); - if (ExprNode != NULL) { + if (ExprNode) { StmtToTraverse = ExprNode->IgnoreParenImpCasts(); } } - return (StmtToTraverse == NULL) || traverse(*StmtToTraverse); + return (StmtToTraverse == nullptr) || traverse(*StmtToTraverse); } // We assume that the QualType and the contained type are on the same // hierarchy level. Thus, we try to match either of them. @@ -183,7 +180,7 @@ public: } bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { ScopedIncrement ScopedDepth(&CurrentDepth); - return (NNS == NULL) || traverse(*NNS); + return (NNS == nullptr) || traverse(*NNS); } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { if (!NNS) @@ -272,8 +269,8 @@ private: // traversal should continue after this function returns. template <typename T> bool traverse(const T &Node) { - TOOLING_COMPILE_ASSERT(IsBaseType<T>::value, - traverse_can_only_be_instantiated_with_base_type); + static_assert(IsBaseType<T>::value, + "traverse can only be instantiated with base type"); if (!match(Node)) return false; return baseTraverse(Node); @@ -298,7 +295,7 @@ public: MatchASTVisitor( std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > * MatcherCallbackPairs) - : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) {} + : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {} void onStartOfTranslationUnit() { for (std::vector<std::pair<internal::DynTypedMatcher, @@ -410,36 +407,36 @@ public: return Visitor.findMatch(Node); } - virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, - const Matcher<NamedDecl> &Base, - BoundNodesTreeBuilder *Builder); + bool classIsDerivedFrom(const CXXRecordDecl *Declaration, + const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder) override; // Implements ASTMatchFinder::matchesChildOf. - virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traversal, - BindKind Bind) { + bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traversal, + BindKind Bind) override { if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal, Bind); } // Implements ASTMatchFinder::matchesDescendantOf. - virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) { + bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) override { if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX, TK_AsIs, Bind); } // Implements ASTMatchFinder::matchesAncestorOf. - virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, - AncestorMatchMode MatchMode) { + bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) override { // Reset the cache outside of the recursive call to make sure we // don't invalidate any iterators. if (ResultCache.size() > MaxMemoizationEntries) @@ -469,7 +466,7 @@ public: } // Implements ASTMatchFinder::getASTContext. - virtual ASTContext &getASTContext() const { return *ActiveASTContext; } + ASTContext &getASTContext() const override { return *ActiveASTContext; } bool shouldVisitTemplateInstantiations() const { return true; } bool shouldVisitImplicitCode() const { return true; } @@ -576,7 +573,7 @@ private: : Context(Context), Callback(Callback) {} - virtual void visitMatch(const BoundNodes& BoundNodesView) { + void visitMatch(const BoundNodes& BoundNodesView) override { Callback->run(MatchFinder::MatchResult(BoundNodesView, Context)); } @@ -619,21 +616,21 @@ private: static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) { // Type::getAs<...>() drills through typedefs. - if (TypeNode->getAs<DependentNameType>() != NULL || - TypeNode->getAs<DependentTemplateSpecializationType>() != NULL || - TypeNode->getAs<TemplateTypeParmType>() != NULL) + if (TypeNode->getAs<DependentNameType>() != nullptr || + TypeNode->getAs<DependentTemplateSpecializationType>() != nullptr || + TypeNode->getAs<TemplateTypeParmType>() != nullptr) // Dependent names and template TypeNode parameters will be matched when // the template is instantiated. - return NULL; + return nullptr; TemplateSpecializationType const *TemplateType = TypeNode->getAs<TemplateSpecializationType>(); - if (TemplateType == NULL) { + if (!TemplateType) { return TypeNode->getAsCXXRecordDecl(); } if (TemplateType->getTemplateName().isDependent()) // Dependent template specializations will be matched when the // template is instantiated. - return NULL; + return nullptr; // For template specialization types which are specializing a template // declaration which is an explicit or partial specialization of another @@ -645,7 +642,7 @@ static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) { // another template declaration, getAsCXXRecordDecl() returns NULL and // we get the CXXRecordDecl of the templated declaration. CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl(); - if (SpecializationDecl != NULL) { + if (SpecializationDecl) { return SpecializationDecl; } NamedDecl *Templated = @@ -667,17 +664,14 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, BoundNodesTreeBuilder *Builder) { if (!Declaration->hasDefinition()) return false; - typedef CXXRecordDecl::base_class_const_iterator BaseIterator; - for (BaseIterator It = Declaration->bases_begin(), - End = Declaration->bases_end(); - It != End; ++It) { - const Type *TypeNode = It->getType().getTypePtr(); + for (const auto &It : Declaration->bases()) { + const Type *TypeNode = It.getType().getTypePtr(); if (typeHasMatchingAlias(TypeNode, Base, Builder)) return true; CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode); - if (ClassDecl == NULL) + if (!ClassDecl) continue; if (ClassDecl == Declaration) { // This can happen for recursive template definitions; if the @@ -696,7 +690,7 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, } bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { - if (DeclNode == NULL) { + if (!DeclNode) { return true; } match(*DeclNode); @@ -704,7 +698,7 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { } bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode) { - if (StmtNode == NULL) { + if (!StmtNode) { return true; } match(*StmtNode); @@ -749,8 +743,8 @@ public: : Finder(Finder), ParsingDone(ParsingDone) {} private: - virtual void HandleTranslationUnit(ASTContext &Context) { - if (ParsingDone != NULL) { + void HandleTranslationUnit(ASTContext &Context) override { + if (ParsingDone != nullptr) { ParsingDone->run(); } Finder->matchAST(Context); @@ -771,7 +765,7 @@ MatchFinder::MatchResult::MatchResult(const BoundNodes &Nodes, MatchFinder::MatchCallback::~MatchCallback() {} MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {} -MatchFinder::MatchFinder() : ParsingDone(NULL) {} +MatchFinder::MatchFinder() : ParsingDone(nullptr) {} MatchFinder::~MatchFinder() {} diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index d15eb54..47b8b6d 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -34,6 +34,26 @@ void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { } } +bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, + ArrayRef<DynTypedMatcher> InnerMatchers) { + if (InnerMatchers.size() != 1) + return false; + + // The 'unless' matcher will always discard the result: + // If the inner matcher doesn't match, unless returns true, + // but the inner matcher cannot have bound anything. + // If the inner matcher matches, the result is false, and + // any possible binding will be discarded. + // We still need to hand in all the bound nodes up to this + // point so the inner matcher can depend on bound nodes, + // and we need to actively discard the bound nodes, otherwise + // the inner matcher will reset the bound nodes if it doesn't + // match, but this would be inversed by 'unless'. + BoundNodesTreeBuilder Discard(*Builder); + return !InnerMatchers[0].matches(DynNode, Finder, &Discard); +} + bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp index da2ed9a..b0abdc7 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -87,7 +87,7 @@ StringRef contextTypeToFormatString(Diagnostics::ContextType Type) { StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) { switch (Type) { - case Diagnostics::ET_RegistryNotFound: + case Diagnostics::ET_RegistryMatcherNotFound: return "Matcher not found: $0"; case Diagnostics::ET_RegistryWrongArgCount: return "Incorrect argument count. (Expected = $0) != (Actual = $1)"; @@ -98,6 +98,8 @@ StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) { case Diagnostics::ET_RegistryAmbiguousOverload: // TODO: Add type info about the overload error. return "Ambiguous matcher overload."; + case Diagnostics::ET_RegistryValueNotFound: + return "Value not found: $0"; case Diagnostics::ET_ParserStringError: return "Error parsing string token: <$0>"; diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h index ae0c300..6e144cd 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -20,14 +20,12 @@ #ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H #define LLVM_CLANG_AST_MATCHERS_DYNAMIC_MARSHALLERS_H -#include <string> - #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/type_traits.h" +#include <string> namespace clang { namespace ast_matchers { @@ -35,6 +33,46 @@ namespace dynamic { namespace internal { +struct ArgKind { + enum Kind { + AK_Matcher, + AK_Unsigned, + AK_String + }; + ArgKind(Kind K) + : K(K) {} + ArgKind(ast_type_traits::ASTNodeKind MatcherKind) + : K(AK_Matcher), MatcherKind(MatcherKind) {} + + std::string asString() const { + switch (getArgKind()) { + case AK_Matcher: + return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str(); + case AK_Unsigned: + return "unsigned"; + case AK_String: + return "string"; + } + llvm_unreachable("unhandled ArgKind"); + } + + Kind getArgKind() const { return K; } + ast_type_traits::ASTNodeKind getMatcherKind() const { + assert(K == AK_Matcher); + return MatcherKind; + } + + bool operator<(const ArgKind &Other) const { + if (K == AK_Matcher && Other.K == AK_Matcher) + return MatcherKind < Other.MatcherKind; + return K < Other.K; + } + +private: + Kind K; + ast_type_traits::ASTNodeKind MatcherKind; +}; + /// \brief Helper template class to just from argument type to the right is/get /// functions in VariantValue. /// Used to verify and extract the matcher arguments below. @@ -43,11 +81,13 @@ template <class T> struct ArgTypeTraits<const T &> : public ArgTypeTraits<T> { }; template <> struct ArgTypeTraits<std::string> { - static StringRef asString() { return "String"; } static bool is(const VariantValue &Value) { return Value.isString(); } static const std::string &get(const VariantValue &Value) { return Value.getString(); } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_String); + } }; template <> @@ -55,46 +95,95 @@ struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { }; template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { - static std::string asString() { - return (Twine("Matcher<") + - ast_type_traits::ASTNodeKind::getFromNodeKind<T>().asStringRef() + - ">").str(); - } static bool is(const VariantValue &Value) { return Value.isMatcher() && Value.getMatcher().hasTypedMatcher<T>(); } static ast_matchers::internal::Matcher<T> get(const VariantValue &Value) { return Value.getMatcher().getTypedMatcher<T>(); } + static ArgKind getKind() { + return ArgKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + } }; template <> struct ArgTypeTraits<unsigned> { - static std::string asString() { return "Unsigned"; } static bool is(const VariantValue &Value) { return Value.isUnsigned(); } static unsigned get(const VariantValue &Value) { return Value.getUnsigned(); } + static ArgKind getKind() { + return ArgKind(ArgKind::AK_Unsigned); + } }; -/// \brief Generic MatcherCreate interface. +/// \brief Matcher descriptor interface. /// -/// Provides a \c run() method that constructs the matcher from the provided -/// arguments. -class MatcherCreateCallback { +/// Provides a \c create() method that constructs the matcher from the provided +/// arguments, and various other methods for type introspection. +class MatcherDescriptor { public: - virtual ~MatcherCreateCallback() {} - virtual VariantMatcher run(const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) const = 0; + virtual ~MatcherDescriptor() {} + virtual VariantMatcher create(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) const = 0; + + /// Returns whether the matcher is variadic. Variadic matchers can take any + /// number of arguments, but they must be of the same type. + virtual bool isVariadic() const = 0; + + /// Returns the number of arguments accepted by the matcher if not variadic. + virtual unsigned getNumArgs() const = 0; + + /// Given that the matcher is being converted to type \p ThisKind, append the + /// 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, + std::vector<ArgKind> &ArgKinds) const = 0; + + /// Returns whether this matcher is convertible to the given type. If it is + /// so convertible, store in *Specificity a value corresponding to the + /// "specificity" of the converted matcher to the given context, and in + /// *LeastDerivedKind the least derived matcher kind which would result in the + /// 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; + + /// 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 (ArrayRef<ast_type_traits::ASTNodeKind>::const_iterator + i = RetKinds.begin(), + e = RetKinds.end(); + i != e; ++i) { + unsigned Distance; + if (i->isBaseOf(Kind, &Distance)) { + if (Specificity) + *Specificity = 100 - Distance; + if (LeastDerivedKind) + *LeastDerivedKind = *i; + return true; + } + } + return false; +} + /// \brief Simple callback implementation. Marshaller and function are provided. /// /// This class wraps a function of arbitrary signature and a marshaller -/// function into a MatcherCreateCallback. +/// function into a MatcherDescriptor. /// The marshaller is in charge of taking the VariantValue arguments, checking /// their types, unpacking them and calling the underlying function. -class FixedArgCountMatcherCreateCallback : public MatcherCreateCallback { +class FixedArgCountMatcherDescriptor : public MatcherDescriptor { public: typedef VariantMatcher (*MarshallerType)(void (*Func)(), StringRef MatcherName, @@ -105,46 +194,225 @@ public: /// \param Marshaller Function to unpack the arguments and call \c Func /// \param Func Matcher construct function. This is the function that /// compile-time matcher expressions would use to create the matcher. - FixedArgCountMatcherCreateCallback(MarshallerType Marshaller, void (*Func)(), - StringRef MatcherName) - : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName) {} - - VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, - Diagnostics *Error) const { + /// \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) + : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName), + RetKinds(RetKinds.begin(), RetKinds.end()), + ArgKinds(ArgKinds.begin(), ArgKinds.end()) {} + + VariantMatcher create(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, Diagnostics *Error) const { return Marshaller(Func, MatcherName, NameRange, Args, Error); } + bool isVariadic() const { return false; } + unsigned getNumArgs() const { return ArgKinds.size(); } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + std::vector<ArgKind> &Kinds) const { + Kinds.push_back(ArgKinds[ArgNo]); + } + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, + ast_type_traits::ASTNodeKind *LeastDerivedKind) const { + return isRetKindConvertibleTo(RetKinds, Kind, Specificity, + LeastDerivedKind); + } + private: const MarshallerType Marshaller; void (* const Func)(); const std::string MatcherName; + const std::vector<ast_type_traits::ASTNodeKind> RetKinds; + const std::vector<ArgKind> ArgKinds; }; -/// \brief Simple callback implementation. Free function is wrapped. +/// \brief Helper methods to extract and merge all possible typed matchers +/// out of the polymorphic object. +template <class PolyMatcher> +static void mergePolyMatchers(const PolyMatcher &Poly, + std::vector<DynTypedMatcher> &Out, + ast_matchers::internal::EmptyTypeList) {} + +template <class PolyMatcher, class TypeList> +static void mergePolyMatchers(const PolyMatcher &Poly, + std::vector<DynTypedMatcher> &Out, TypeList) { + Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); + mergePolyMatchers(Poly, Out, typename TypeList::tail()); +} + +/// \brief Convert the return values of the functions into a VariantMatcher. /// -/// This class simply wraps a free function with the right signature to export -/// it as a MatcherCreateCallback. +/// There are 2 cases right now: The return value is a Matcher<T> or is a +/// 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) { + return VariantMatcher::SingleMatcher(Matcher); +} + +template <typename T> +static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher, + typename T::ReturnTypes * = + NULL) { + std::vector<DynTypedMatcher> Matchers; + mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes()); + VariantMatcher Out = VariantMatcher::PolymorphicMatcher(std::move(Matchers)); + return Out; +} + +template <typename T> +inline void buildReturnTypeVectorFromTypeList( + std::vector<ast_type_traits::ASTNodeKind> &RetTypes) { + RetTypes.push_back( + ast_type_traits::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) {} + +template <typename T> +struct BuildReturnTypeVector { + static void build(std::vector<ast_type_traits::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>()); + } +}; + +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>()); + } +}; + +/// \brief Variadic marshaller function. +template <typename ResultT, typename ArgT, + ResultT (*Func)(ArrayRef<const ArgT *>)> +VariantMatcher +variadicMatcherDescriptor(StringRef MatcherName, const SourceRange &NameRange, + ArrayRef<ParserValue> Args, Diagnostics *Error) { + ArgT **InnerArgs = new ArgT *[Args.size()](); + + bool HasError = false; + for (size_t i = 0, e = Args.size(); i != e; ++i) { + typedef ArgTypeTraits<ArgT> ArgTraits; + const ParserValue &Arg = Args[i]; + const VariantValue &Value = Arg.Value; + if (!ArgTraits::is(Value)) { + Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) + << (i + 1) << ArgTraits::getKind().asString() << Value.getTypeAsString(); + HasError = true; + break; + } + InnerArgs[i] = new ArgT(ArgTraits::get(Value)); + } + + VariantMatcher Out; + if (!HasError) { + Out = outvalueToVariantMatcher( + Func(ArrayRef<const ArgT *>(InnerArgs, Args.size()))); + } + + for (size_t i = 0, e = Args.size(); i != e; ++i) { + delete InnerArgs[i]; + } + delete[] InnerArgs; + return Out; +} + +/// \brief Matcher descriptor for variadic functions. +/// +/// This class simply wraps a VariadicFunction with the right signature to export +/// it as a MatcherDescriptor. /// This allows us to have one implementation of the interface for as many free /// functions as we want, reducing the number of symbols and size of the /// object file. -class FreeFuncMatcherCreateCallback : public MatcherCreateCallback { +class VariadicFuncMatcherDescriptor : public MatcherDescriptor { public: typedef VariantMatcher (*RunFunc)(StringRef MatcherName, const SourceRange &NameRange, ArrayRef<ParserValue> Args, Diagnostics *Error); - FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName) - : Func(Func), MatcherName(MatcherName.str()) {} + template <typename ResultT, typename ArgT, + ResultT (*F)(ArrayRef<const ArgT *>)> + VariadicFuncMatcherDescriptor(llvm::VariadicFunction<ResultT, ArgT, F> Func, + StringRef MatcherName) + : Func(&variadicMatcherDescriptor<ResultT, ArgT, F>), + MatcherName(MatcherName.str()), + ArgsKind(ArgTypeTraits<ArgT>::getKind()) { + BuildReturnTypeVector<ResultT>::build(RetKinds); + } - VariantMatcher run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, - Diagnostics *Error) const { + VariantMatcher create(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, Diagnostics *Error) const { return Func(MatcherName, NameRange, Args, Error); } + bool isVariadic() const { return true; } + unsigned getNumArgs() const { return 0; } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + std::vector<ArgKind> &Kinds) const { + Kinds.push_back(ArgsKind); + } + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, + ast_type_traits::ASTNodeKind *LeastDerivedKind) const { + return isRetKindConvertibleTo(RetKinds, Kind, Specificity, + LeastDerivedKind); + } + private: const RunFunc Func; const std::string MatcherName; + std::vector<ast_type_traits::ASTNodeKind> RetKinds; + const ArgKind ArgsKind; +}; + +/// \brief Return CK_Trivial when appropriate for VariadicDynCastAllOfMatchers. +class DynCastAllOfMatcherDescriptor : public VariadicFuncMatcherDescriptor { +public: + template <typename BaseT, typename DerivedT> + DynCastAllOfMatcherDescriptor( + ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT> Func, + StringRef MatcherName) + : VariadicFuncMatcherDescriptor(Func, MatcherName), + DerivedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<DerivedT>()) { + } + + bool + isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, + ast_type_traits::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 + // Specificity to 0. + if (VariadicFuncMatcherDescriptor::isConvertibleTo(Kind, Specificity, + LeastDerivedKind)) { + if (Kind.isSame(DerivedKind) || !Kind.isBaseOf(DerivedKind)) { + if (Specificity) + *Specificity = 0; + } + return true; + } else { + return false; + } + } + +private: + const ast_type_traits::ASTNodeKind DerivedKind; }; /// \brief Helper macros to check the arguments on all marshaller functions. @@ -158,44 +426,11 @@ 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>::asString() \ + << (index + 1) << ArgTypeTraits<type>::getKind().asString() \ << Args[index].Value.getTypeAsString(); \ return VariantMatcher(); \ } -/// \brief Helper methods to extract and merge all possible typed matchers -/// out of the polymorphic object. -template <class PolyMatcher> -static void mergePolyMatchers(const PolyMatcher &Poly, - std::vector<DynTypedMatcher> &Out, - ast_matchers::internal::EmptyTypeList) {} - -template <class PolyMatcher, class TypeList> -static void mergePolyMatchers(const PolyMatcher &Poly, - std::vector<DynTypedMatcher> &Out, TypeList) { - Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); - mergePolyMatchers(Poly, Out, typename TypeList::tail()); -} - -/// \brief Convert the return values of the functions into a VariantMatcher. -/// -/// There are 2 cases right now: The return value is a Matcher<T> or is a -/// 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) { - return VariantMatcher::SingleMatcher(Matcher); -} - -template <typename T> -static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher, - typename T::ReturnTypes * = - NULL) { - std::vector<DynTypedMatcher> Matchers; - mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes()); - VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers); - return Out; -} /// \brief 0-arg marshaller function. template <typename ReturnType> @@ -239,42 +474,6 @@ static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName, #undef CHECK_ARG_COUNT #undef CHECK_ARG_TYPE -/// \brief Variadic marshaller function. -template <typename ResultT, typename ArgT, - ResultT (*Func)(ArrayRef<const ArgT *>)> -VariantMatcher -variadicMatcherCreateCallback(StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, Diagnostics *Error) { - ArgT **InnerArgs = new ArgT *[Args.size()](); - - bool HasError = false; - for (size_t i = 0, e = Args.size(); i != e; ++i) { - typedef ArgTypeTraits<ArgT> ArgTraits; - const ParserValue &Arg = Args[i]; - const VariantValue &Value = Arg.Value; - if (!ArgTraits::is(Value)) { - Error->addError(Arg.Range, Error->ET_RegistryWrongArgType) - << (i + 1) << ArgTraits::asString() << Value.getTypeAsString(); - HasError = true; - break; - } - InnerArgs[i] = new ArgT(ArgTraits::get(Value)); - } - - VariantMatcher Out; - if (!HasError) { - Out = outvalueToVariantMatcher( - Func(ArrayRef<const ArgT *>(InnerArgs, Args.size()))); - } - - for (size_t i = 0, e = Args.size(); i != e; ++i) { - delete InnerArgs[i]; - } - delete[] InnerArgs; - return Out; -} - /// \brief Helper class used to collect all the possible overloads of an /// argument adaptative matcher function. template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, @@ -282,7 +481,7 @@ template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, class AdaptativeOverloadCollector { public: AdaptativeOverloadCollector(StringRef Name, - std::vector<MatcherCreateCallback *> &Out) + std::vector<MatcherDescriptor *> &Out) : Name(Name), Out(Out) { collect(FromTypes()); } @@ -296,33 +495,32 @@ private: /// \brief Recursive case. Get the overload for the head of the list, and /// recurse to the tail. - template <typename FromTypeList> inline void collect(FromTypeList); + template <typename FromTypeList> + inline void collect(FromTypeList); const StringRef Name; - std::vector<MatcherCreateCallback *> &Out; + std::vector<MatcherDescriptor *> &Out; }; -/// \brief MatcherCreateCallback that wraps multiple "overloads" of the same +/// \brief MatcherDescriptor that wraps multiple "overloads" of the same /// matcher. /// /// It will try every overload and generate appropriate errors for when none or /// more than one overloads match the arguments. -class OverloadedMatcherCreateCallback : public MatcherCreateCallback { +class OverloadedMatcherDescriptor : public MatcherDescriptor { public: - OverloadedMatcherCreateCallback(ArrayRef<MatcherCreateCallback *> Callbacks) - : Overloads(Callbacks) {} + OverloadedMatcherDescriptor(ArrayRef<MatcherDescriptor *> Callbacks) + : Overloads(Callbacks.begin(), Callbacks.end()) {} - virtual ~OverloadedMatcherCreateCallback() { - llvm::DeleteContainerPointers(Overloads); - } + virtual ~OverloadedMatcherDescriptor() {} - virtual VariantMatcher run(const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) const { + virtual VariantMatcher create(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) const { std::vector<VariantMatcher> Constructed; Diagnostics::OverloadContext Ctx(Error); - for (size_t i = 0, e = Overloads.size(); i != e; ++i) { - VariantMatcher SubMatcher = Overloads[i]->run(NameRange, Args, Error); + for (const auto &O : Overloads) { + VariantMatcher SubMatcher = O->create(NameRange, Args, Error); if (!SubMatcher.isNull()) { Constructed.push_back(SubMatcher); } @@ -339,20 +537,67 @@ public: return Constructed[0]; } + bool isVariadic() const { + bool Overload0Variadic = Overloads[0]->isVariadic(); +#ifndef NDEBUG + for (const auto &O : Overloads) { + assert(Overload0Variadic == O->isVariadic()); + } +#endif + return Overload0Variadic; + } + + unsigned getNumArgs() const { + unsigned Overload0NumArgs = Overloads[0]->getNumArgs(); +#ifndef NDEBUG + for (const auto &O : Overloads) { + assert(Overload0NumArgs == O->getNumArgs()); + } +#endif + return Overload0NumArgs; + } + + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + std::vector<ArgKind> &Kinds) const { + for (const auto &O : Overloads) { + if (O->isConvertibleTo(ThisKind)) + O->getArgKinds(ThisKind, ArgNo, Kinds); + } + } + + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, + ast_type_traits::ASTNodeKind *LeastDerivedKind) const { + for (const auto &O : Overloads) { + if (O->isConvertibleTo(Kind, Specificity, LeastDerivedKind)) + return true; + } + return false; + } + private: - std::vector<MatcherCreateCallback *> Overloads; + std::vector<std::unique_ptr<MatcherDescriptor>> Overloads; }; /// \brief Variadic operator marshaller function. -class VariadicOperatorMatcherCreateCallback : public MatcherCreateCallback { +class VariadicOperatorMatcherDescriptor : public MatcherDescriptor { public: typedef ast_matchers::internal::VariadicOperatorFunction VarFunc; - VariadicOperatorMatcherCreateCallback(VarFunc Func, StringRef MatcherName) - : Func(Func), MatcherName(MatcherName) {} + VariadicOperatorMatcherDescriptor(unsigned MinCount, unsigned MaxCount, + VarFunc Func, StringRef MatcherName) + : MinCount(MinCount), MaxCount(MaxCount), Func(Func), + MatcherName(MatcherName) {} + + virtual VariantMatcher create(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) const { + if (Args.size() < MinCount || MaxCount < Args.size()) { + const std::string MaxStr = + (MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str(); + Error->addError(NameRange, Error->ET_RegistryWrongArgCount) + << ("(" + Twine(MinCount) + ", " + MaxStr + ")") << Args.size(); + return VariantMatcher(); + } - virtual VariantMatcher run(const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) const { std::vector<VariantMatcher> InnerArgs; for (size_t i = 0, e = Args.size(); i != e; ++i) { const ParserValue &Arg = Args[i]; @@ -364,85 +609,123 @@ public: } InnerArgs.push_back(Value.getMatcher()); } - return VariantMatcher::VariadicOperatorMatcher(Func, InnerArgs); + return VariantMatcher::VariadicOperatorMatcher(Func, std::move(InnerArgs)); } + bool isVariadic() const { return true; } + unsigned getNumArgs() const { return 0; } + void getArgKinds(ast_type_traits::ASTNodeKind ThisKind, unsigned ArgNo, + std::vector<ArgKind> &Kinds) const { + Kinds.push_back(ThisKind); + } + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity, + ast_type_traits::ASTNodeKind *LeastDerivedKind) const { + if (Specificity) + *Specificity = 1; + if (LeastDerivedKind) + *LeastDerivedKind = Kind; + return true; + } + bool isPolymorphic() const override { return true; } + private: + const unsigned MinCount; + const unsigned MaxCount; const VarFunc Func; const StringRef MatcherName; }; - /// Helper functions to select the appropriate marshaller functions. /// They detect the number of arguments, arguments types and return type. /// \brief 0-arg overload template <typename ReturnType> -MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(), - StringRef MatcherName) { - return new FixedArgCountMatcherCreateCallback( +MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(), + StringRef MatcherName) { + std::vector<ast_type_traits::ASTNodeKind> RetTypes; + BuildReturnTypeVector<ReturnType>::build(RetTypes); + return new FixedArgCountMatcherDescriptor( matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func), - MatcherName); + MatcherName, RetTypes, None); } /// \brief 1-arg overload template <typename ReturnType, typename ArgType1> -MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), - StringRef MatcherName) { - return new FixedArgCountMatcherCreateCallback( +MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), + StringRef MatcherName) { + std::vector<ast_type_traits::ASTNodeKind> RetTypes; + BuildReturnTypeVector<ReturnType>::build(RetTypes); + ArgKind AK = ArgTypeTraits<ArgType1>::getKind(); + return new FixedArgCountMatcherDescriptor( matcherMarshall1<ReturnType, ArgType1>, - reinterpret_cast<void (*)()>(Func), MatcherName); + reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK); } /// \brief 2-arg overload template <typename ReturnType, typename ArgType1, typename ArgType2> -MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, - ArgType2), - StringRef MatcherName) { - return new FixedArgCountMatcherCreateCallback( +MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2), + StringRef MatcherName) { + std::vector<ast_type_traits::ASTNodeKind> RetTypes; + BuildReturnTypeVector<ReturnType>::build(RetTypes); + ArgKind AKs[] = { ArgTypeTraits<ArgType1>::getKind(), + ArgTypeTraits<ArgType2>::getKind() }; + return new FixedArgCountMatcherDescriptor( matcherMarshall2<ReturnType, ArgType1, ArgType2>, - reinterpret_cast<void (*)()>(Func), MatcherName); + reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs); } /// \brief Variadic overload. template <typename ResultT, typename ArgT, ResultT (*Func)(ArrayRef<const ArgT *>)> -MatcherCreateCallback * +MatcherDescriptor * makeMatcherAutoMarshall(llvm::VariadicFunction<ResultT, ArgT, Func> VarFunc, StringRef MatcherName) { - return new FreeFuncMatcherCreateCallback( - &variadicMatcherCreateCallback<ResultT, ArgT, Func>, MatcherName); + return new VariadicFuncMatcherDescriptor(VarFunc, MatcherName); +} + +/// \brief Overload for VariadicDynCastAllOfMatchers. +/// +/// Not strictly necessary, but DynCastAllOfMatcherDescriptor gives us better +/// completion results for that type of matcher. +template <typename BaseT, typename DerivedT> +MatcherDescriptor * +makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher< + BaseT, DerivedT> VarFunc, + StringRef MatcherName) { + return new DynCastAllOfMatcherDescriptor(VarFunc, MatcherName); } /// \brief Argument adaptative overload. template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, typename FromTypes, typename ToTypes> -MatcherCreateCallback * +MatcherDescriptor * makeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc< ArgumentAdapterT, FromTypes, ToTypes>, StringRef MatcherName) { - std::vector<MatcherCreateCallback *> Overloads; + std::vector<MatcherDescriptor *> Overloads; AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName, Overloads); - return new OverloadedMatcherCreateCallback(Overloads); + return new OverloadedMatcherDescriptor(Overloads); } template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, typename FromTypes, typename ToTypes> template <typename FromTypeList> -inline void -AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>::collect( - FromTypeList) { +inline void AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, + ToTypes>::collect(FromTypeList) { Out.push_back(makeMatcherAutoMarshall( &AdaptativeFunc::template create<typename FromTypeList::head>, Name)); collect(typename FromTypeList::tail()); } /// \brief Variadic operator overload. -MatcherCreateCallback *makeMatcherAutoMarshall( - ast_matchers::internal::VariadicOperatorMatcherFunc Func, - StringRef MatcherName) { - return new VariadicOperatorMatcherCreateCallback(Func.Func, MatcherName); +template <unsigned MinCount, unsigned MaxCount> +MatcherDescriptor * +makeMatcherAutoMarshall(ast_matchers::internal::VariadicOperatorMatcherFunc< + MinCount, MaxCount> Func, + StringRef MatcherName) { + return new VariadicOperatorMatcherDescriptor(MinCount, MaxCount, Func.Func, + MatcherName); } } // namespace internal diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp index df9596e..25629d9 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp @@ -12,13 +12,13 @@ /// //===----------------------------------------------------------------------===// -#include <string> -#include <vector> - #include "clang/ASTMatchers/Dynamic/Parser.h" #include "clang/ASTMatchers/Dynamic/Registry.h" #include "clang/Basic/CharInfo.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/Twine.h" +#include <string> +#include <vector> namespace clang { namespace ast_matchers { @@ -28,15 +28,16 @@ namespace dynamic { struct Parser::TokenInfo { /// \brief Different possible tokens. enum TokenKind { - TK_Eof = 0, - TK_OpenParen = 1, - TK_CloseParen = 2, - TK_Comma = 3, - TK_Period = 4, - TK_Literal = 5, - TK_Ident = 6, - TK_InvalidChar = 7, - TK_Error = 8 + TK_Eof, + TK_OpenParen, + TK_CloseParen, + TK_Comma, + TK_Period, + TK_Literal, + TK_Ident, + TK_InvalidChar, + TK_Error, + TK_CodeCompletion }; /// \brief Some known identifiers. @@ -56,7 +57,15 @@ const char* const Parser::TokenInfo::ID_Bind = "bind"; class Parser::CodeTokenizer { public: explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error) - : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error) { + : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), + CodeCompletionLocation(nullptr) { + NextToken = getNextToken(); + } + + CodeTokenizer(StringRef MatcherCode, Diagnostics *Error, + unsigned CodeCompletionOffset) + : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), + CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) { NextToken = getNextToken(); } @@ -78,6 +87,13 @@ private: TokenInfo Result; Result.Range.Start = currentLocation(); + if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) { + Result.Kind = TokenInfo::TK_CodeCompletion; + Result.Text = StringRef(CodeCompletionLocation, 0); + CodeCompletionLocation = nullptr; + return Result; + } + if (Code.empty()) { Result.Kind = TokenInfo::TK_Eof; Result.Text = ""; @@ -122,8 +138,21 @@ private: if (isAlphanumeric(Code[0])) { // Parse an identifier size_t TokenLength = 1; - while (TokenLength < Code.size() && isAlphanumeric(Code[TokenLength])) + while (1) { + // A code completion location in/immediately after an identifier will + // cause the portion of the identifier before the code completion + // location to become a code completion token. + if (CodeCompletionLocation == Code.data() + TokenLength) { + CodeCompletionLocation = nullptr; + Result.Kind = TokenInfo::TK_CodeCompletion; + Result.Text = Code.substr(0, TokenLength); + Code = Code.drop_front(TokenLength); + return Result; + } + if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength])) + break; ++TokenLength; + } Result.Kind = TokenInfo::TK_Ident; Result.Text = Code.substr(0, TokenLength); Code = Code.drop_front(TokenLength); @@ -224,16 +253,68 @@ private: unsigned Line; Diagnostics *Error; TokenInfo NextToken; + const char *CodeCompletionLocation; }; Parser::Sema::~Sema() {} +VariantValue Parser::Sema::getNamedValue(StringRef Name) { + return VariantValue(); +} + +struct Parser::ScopedContextEntry { + Parser *P; + + ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) { + P->ContextStack.push_back(std::make_pair(C, 0u)); + } + + ~ScopedContextEntry() { + P->ContextStack.pop_back(); + } + + void nextArg() { + ++P->ContextStack.back().second; + } +}; + +/// \brief Parse expressions that start with an identifier. +/// +/// This function can parse named values and matchers. +/// In case of failure it will try to determine the user's intent to give +/// an appropriate error message. +bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) { + const TokenInfo NameToken = Tokenizer->consumeNextToken(); + + if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) { + // Parse as a named value. + if (const VariantValue NamedValue = S->getNamedValue(NameToken.Text)) { + *Value = NamedValue; + return true; + } + // If the syntax is correct and the name is not a matcher either, report + // unknown named value. + if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma || + Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen || + Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) && + !S->lookupMatcherCtor(NameToken.Text)) { + Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound) + << NameToken.Text; + return false; + } + // Otherwise, fallback to the matcher parser. + } + + // Parse as a matcher expression. + return parseMatcherExpressionImpl(NameToken, Value); +} + /// \brief Parse and validate a matcher expression. /// \return \c true on success, in which case \c Value has the matcher parsed. /// If the input is malformed, or some argument has an error, it /// returns \c false. -bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { - const TokenInfo NameToken = Tokenizer->consumeNextToken(); +bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken, + VariantValue *Value) { assert(NameToken.Kind == TokenInfo::TK_Ident); const TokenInfo OpenToken = Tokenizer->consumeNextToken(); if (OpenToken.Kind != TokenInfo::TK_OpenParen) { @@ -242,32 +323,49 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { return false; } + llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text); + + if (!Ctor) { + Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound) + << NameToken.Text; + // Do not return here. We need to continue to give completion suggestions. + } + std::vector<ParserValue> Args; TokenInfo EndToken; - while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) { - if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) { - // End of args. - EndToken = Tokenizer->consumeNextToken(); - break; - } - if (Args.size() > 0) { - // We must find a , token to continue. - const TokenInfo CommaToken = Tokenizer->consumeNextToken(); - if (CommaToken.Kind != TokenInfo::TK_Comma) { - Error->addError(CommaToken.Range, Error->ET_ParserNoComma) - << CommaToken.Text; - return false; + + { + ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr); + + while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) { + if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) { + // End of args. + EndToken = Tokenizer->consumeNextToken(); + break; + } + if (Args.size() > 0) { + // We must find a , token to continue. + const TokenInfo CommaToken = Tokenizer->consumeNextToken(); + if (CommaToken.Kind != TokenInfo::TK_Comma) { + Error->addError(CommaToken.Range, Error->ET_ParserNoComma) + << CommaToken.Text; + return false; + } } - } - Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error, - NameToken.Text, NameToken.Range, Args.size() + 1); - ParserValue ArgValue; - ArgValue.Text = Tokenizer->peekNextToken().Text; - ArgValue.Range = Tokenizer->peekNextToken().Range; - if (!parseExpressionImpl(&ArgValue.Value)) return false; + Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error, + NameToken.Text, NameToken.Range, + Args.size() + 1); + ParserValue ArgValue; + ArgValue.Text = Tokenizer->peekNextToken().Text; + ArgValue.Range = Tokenizer->peekNextToken().Range; + if (!parseExpressionImpl(&ArgValue.Value)) { + return false; + } - Args.push_back(ArgValue); + Args.push_back(ArgValue); + SCE.nextArg(); + } } if (EndToken.Kind == TokenInfo::TK_Eof) { @@ -280,6 +378,11 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { // Parse .bind("foo") Tokenizer->consumeNextToken(); // consume the period. const TokenInfo BindToken = Tokenizer->consumeNextToken(); + if (BindToken.Kind == TokenInfo::TK_CodeCompletion) { + addCompletion(BindToken, "bind(\"", "bind"); + return false; + } + const TokenInfo OpenToken = Tokenizer->consumeNextToken(); const TokenInfo IDToken = Tokenizer->consumeNextToken(); const TokenInfo CloseToken = Tokenizer->consumeNextToken(); @@ -306,19 +409,55 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { BindID = IDToken.Value.getString(); } + if (!Ctor) + return false; + // Merge the start and end infos. Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, NameToken.Text, NameToken.Range); SourceRange MatcherRange = NameToken.Range; MatcherRange.End = EndToken.Range.End; VariantMatcher Result = S->actOnMatcherExpression( - NameToken.Text, MatcherRange, BindID, Args, Error); + *Ctor, MatcherRange, BindID, Args, Error); if (Result.isNull()) return false; *Value = Result; return true; } +// If the prefix of this completion matches the completion token, add it to +// Completions minus the prefix. +void Parser::addCompletion(const TokenInfo &CompToken, StringRef TypedText, + StringRef Decl) { + if (TypedText.size() >= CompToken.Text.size() && + TypedText.substr(0, CompToken.Text.size()) == CompToken.Text) { + Completions.push_back( + MatcherCompletion(TypedText.substr(CompToken.Text.size()), Decl)); + } +} + +void Parser::addExpressionCompletions() { + const TokenInfo CompToken = Tokenizer->consumeNextToken(); + assert(CompToken.Kind == TokenInfo::TK_CodeCompletion); + + // We cannot complete code if there is an invalid element on the context + // stack. + for (ContextStackTy::iterator I = ContextStack.begin(), + E = ContextStack.end(); + I != E; ++I) { + if (!I->first) + return; + } + + std::vector<MatcherCompletion> RegCompletions = + Registry::getCompletions(ContextStack); + for (std::vector<MatcherCompletion>::iterator I = RegCompletions.begin(), + E = RegCompletions.end(); + I != E; ++I) { + addCompletion(CompToken, I->TypedText, I->MatcherDecl); + } +} + /// \brief Parse an <Expresssion> bool Parser::parseExpressionImpl(VariantValue *Value) { switch (Tokenizer->nextTokenKind()) { @@ -327,7 +466,11 @@ bool Parser::parseExpressionImpl(VariantValue *Value) { return true; case TokenInfo::TK_Ident: - return parseMatcherExpressionImpl(Value); + return parseIdentifierPrefixImpl(Value); + + case TokenInfo::TK_CodeCompletion: + addExpressionCompletions(); + return false; case TokenInfo::TK_Eof: Error->addError(Tokenizer->consumeNextToken().Range, @@ -355,22 +498,23 @@ Parser::Parser(CodeTokenizer *Tokenizer, Sema *S, Diagnostics *Error) : Tokenizer(Tokenizer), S(S), Error(Error) {} -class RegistrySema : public Parser::Sema { -public: - virtual ~RegistrySema() {} - VariantMatcher actOnMatcherExpression(StringRef MatcherName, - const SourceRange &NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { - if (BindID.empty()) { - return Registry::constructMatcher(MatcherName, NameRange, Args, Error); - } else { - return Registry::constructBoundMatcher(MatcherName, NameRange, BindID, - Args, Error); - } +Parser::RegistrySema::~RegistrySema() {} + +llvm::Optional<MatcherCtor> +Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) { + return Registry::lookupMatcherCtor(MatcherName); +} + +VariantMatcher Parser::RegistrySema::actOnMatcherExpression( + MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID, + ArrayRef<ParserValue> Args, Diagnostics *Error) { + if (BindID.empty()) { + return Registry::constructMatcher(Ctor, NameRange, Args, Error); + } else { + return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args, + Error); } -}; +} bool Parser::parseExpression(StringRef Code, VariantValue *Value, Diagnostics *Error) { @@ -390,6 +534,18 @@ bool Parser::parseExpression(StringRef Code, Sema *S, return true; } +std::vector<MatcherCompletion> +Parser::completeExpression(StringRef Code, unsigned CompletionOffset) { + Diagnostics Error; + CodeTokenizer Tokenizer(Code, &Error, CompletionOffset); + RegistrySema S; + Parser P(&Tokenizer, &S, &Error); + VariantValue Dummy; + P.parseExpressionImpl(&Dummy); + + return P.Completions; +} + llvm::Optional<DynTypedMatcher> Parser::parseMatcherExpression(StringRef Code, Diagnostics *Error) { RegistrySema S; diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 70e956e..4bc50a0 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -13,23 +13,24 @@ //===------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/Registry.h" - -#include <utility> - #include "Marshallers.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ManagedStatic.h" +#include <set> +#include <utility> + +using namespace clang::ast_type_traits; namespace clang { namespace ast_matchers { namespace dynamic { namespace { -using internal::MatcherCreateCallback; +using internal::MatcherDescriptor; -typedef llvm::StringMap<const MatcherCreateCallback *> ConstructorMap; +typedef llvm::StringMap<const MatcherDescriptor *> ConstructorMap; class RegistryMaps { public: RegistryMaps(); @@ -38,12 +39,12 @@ public: const ConstructorMap &constructors() const { return Constructors; } private: - void registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback); + void registerMatcher(StringRef MatcherName, MatcherDescriptor *Callback); ConstructorMap Constructors; }; void RegistryMaps::registerMatcher(StringRef MatcherName, - MatcherCreateCallback *Callback) { + MatcherDescriptor *Callback) { assert(Constructors.find(MatcherName) == Constructors.end()); Constructors[MatcherName] = Callback; } @@ -58,14 +59,14 @@ void RegistryMaps::registerMatcher(StringRef MatcherName, #define REGISTER_OVERLOADED_2(name) \ do { \ - MatcherCreateCallback *Callbacks[] = { \ + MatcherDescriptor *Callbacks[] = { \ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \ #name), \ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \ #name) \ }; \ registerMatcher(#name, \ - new internal::OverloadedMatcherCreateCallback(Callbacks)); \ + new internal::OverloadedMatcherDescriptor(Callbacks)); \ } while (0) /// \brief Generate a registry map with all the known matchers. @@ -76,11 +77,9 @@ RegistryMaps::RegistryMaps() { // ofKind // // Polymorphic + argument overload: - // unless // findAll // // Other: - // loc // equals // equalsNode @@ -89,6 +88,7 @@ RegistryMaps::RegistryMaps() { REGISTER_OVERLOADED_2(hasType); REGISTER_OVERLOADED_2(isDerivedFrom); REGISTER_OVERLOADED_2(isSameOrDerivedFrom); + REGISTER_OVERLOADED_2(loc); REGISTER_OVERLOADED_2(pointsTo); REGISTER_OVERLOADED_2(references); REGISTER_OVERLOADED_2(thisPointerType); @@ -113,6 +113,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(builtinType); REGISTER_MATCHER(cStyleCastExpr); REGISTER_MATCHER(callExpr); + REGISTER_MATCHER(caseStmt); REGISTER_MATCHER(castExpr); REGISTER_MATCHER(catchStmt); REGISTER_MATCHER(characterLiteral); @@ -133,7 +134,9 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(declCountIs); REGISTER_MATCHER(declRefExpr); REGISTER_MATCHER(declStmt); + REGISTER_MATCHER(declaratorDecl); REGISTER_MATCHER(defaultArgExpr); + REGISTER_MATCHER(defaultStmt); REGISTER_MATCHER(deleteExpr); REGISTER_MATCHER(dependentSizedArrayType); REGISTER_MATCHER(destructorDecl); @@ -143,15 +146,20 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(elaboratedType); REGISTER_MATCHER(enumConstantDecl); REGISTER_MATCHER(enumDecl); + REGISTER_MATCHER(equalsBoundNode); REGISTER_MATCHER(explicitCastExpr); REGISTER_MATCHER(expr); + REGISTER_MATCHER(exprWithCleanups); REGISTER_MATCHER(fieldDecl); REGISTER_MATCHER(floatLiteral); REGISTER_MATCHER(forEach); + REGISTER_MATCHER(forEachConstructorInitializer); REGISTER_MATCHER(forEachDescendant); + REGISTER_MATCHER(forEachSwitchCase); REGISTER_MATCHER(forField); REGISTER_MATCHER(forRangeStmt); REGISTER_MATCHER(forStmt); + REGISTER_MATCHER(friendDecl); REGISTER_MATCHER(functionDecl); REGISTER_MATCHER(functionTemplateDecl); REGISTER_MATCHER(functionType); @@ -170,6 +178,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasBase); REGISTER_MATCHER(hasBody); REGISTER_MATCHER(hasCanonicalType); + REGISTER_MATCHER(hasCaseConstant); REGISTER_MATCHER(hasCondition); REGISTER_MATCHER(hasConditionVariableStatement); REGISTER_MATCHER(hasDeclContext); @@ -180,12 +189,14 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); REGISTER_MATCHER(hasFalseExpression); + REGISTER_MATCHER(hasGlobalStorage); REGISTER_MATCHER(hasImplicitDestinationType); REGISTER_MATCHER(hasIncrement); REGISTER_MATCHER(hasIndex); REGISTER_MATCHER(hasInitializer); REGISTER_MATCHER(hasLHS); REGISTER_MATCHER(hasLocalQualifiers); + REGISTER_MATCHER(hasLocalStorage); REGISTER_MATCHER(hasLoopInit); REGISTER_MATCHER(hasMethod); REGISTER_MATCHER(hasName); @@ -203,6 +214,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); REGISTER_MATCHER(hasTrueExpression); + REGISTER_MATCHER(hasTypeLoc); REGISTER_MATCHER(hasUnaryOperand); REGISTER_MATCHER(hasValueType); REGISTER_MATCHER(ifStmt); @@ -215,12 +227,15 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(innerType); REGISTER_MATCHER(integerLiteral); REGISTER_MATCHER(isArrow); + REGISTER_MATCHER(isConst); REGISTER_MATCHER(isConstQualified); REGISTER_MATCHER(isDefinition); REGISTER_MATCHER(isExplicitTemplateSpecialization); + REGISTER_MATCHER(isExpr); REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isInteger); + REGISTER_MATCHER(isListInitialization); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); @@ -252,6 +267,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(operatorCallExpr); REGISTER_MATCHER(parameterCountIs); REGISTER_MATCHER(parenType); + REGISTER_MATCHER(parmVarDecl); REGISTER_MATCHER(pointee); REGISTER_MATCHER(pointerType); REGISTER_MATCHER(qualType); @@ -275,6 +291,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(switchCase); REGISTER_MATCHER(switchStmt); REGISTER_MATCHER(templateSpecializationType); + REGISTER_MATCHER(temporaryObjectExpr); REGISTER_MATCHER(thisExpr); REGISTER_MATCHER(throughUsingDecl); REGISTER_MATCHER(throwExpr); @@ -285,6 +302,10 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(typedefType); REGISTER_MATCHER(unaryExprOrTypeTraitExpr); REGISTER_MATCHER(unaryOperator); + REGISTER_MATCHER(unaryTransformType); + REGISTER_MATCHER(unless); + REGISTER_MATCHER(unresolvedConstructExpr); + REGISTER_MATCHER(unresolvedUsingValueDecl); REGISTER_MATCHER(userDefinedLiteral); REGISTER_MATCHER(usingDecl); REGISTER_MATCHER(varDecl); @@ -306,27 +327,175 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData; } // anonymous namespace // static -VariantMatcher Registry::constructMatcher(StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) { ConstructorMap::const_iterator it = RegistryData->constructors().find(MatcherName); - if (it == RegistryData->constructors().end()) { - Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName; - return VariantMatcher(); + return it == RegistryData->constructors().end() + ? llvm::Optional<MatcherCtor>() + : it->second; +} + +namespace { + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const std::set<ASTNodeKind> &KS) { + unsigned Count = 0; + for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end(); + I != E; ++I) { + if (I != KS.begin()) + OS << "|"; + if (Count++ == 3) { + OS << "..."; + break; + } + OS << *I; + } + return OS; +} + +struct ReverseSpecificityThenName { + bool operator()(const std::pair<unsigned, std::string> &A, + const std::pair<unsigned, std::string> &B) const { + return A.first > B.first || (A.first == B.first && A.second < B.second); } +}; + +} + +std::vector<MatcherCompletion> Registry::getCompletions( + ArrayRef<std::pair<MatcherCtor, unsigned> > Context) { + ASTNodeKind InitialTypes[] = { + ASTNodeKind::getFromNodeKind<Decl>(), + ASTNodeKind::getFromNodeKind<QualType>(), + ASTNodeKind::getFromNodeKind<Type>(), + ASTNodeKind::getFromNodeKind<Stmt>(), + ASTNodeKind::getFromNodeKind<NestedNameSpecifier>(), + ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>(), + ASTNodeKind::getFromNodeKind<TypeLoc>() + }; + ArrayRef<ASTNodeKind> InitialTypesRef(InitialTypes); - return it->second->run(NameRange, Args, Error); + // Starting with the above seed of acceptable top-level matcher types, compute + // the acceptable type set for the argument indicated by each context element. + std::set<ASTNodeKind> TypeSet(InitialTypesRef.begin(), InitialTypesRef.end()); + for (ArrayRef<std::pair<MatcherCtor, unsigned> >::iterator + CtxI = Context.begin(), + CtxE = Context.end(); + CtxI != CtxE; ++CtxI) { + std::vector<internal::ArgKind> NextTypeSet; + for (std::set<ASTNodeKind>::iterator I = TypeSet.begin(), E = TypeSet.end(); + I != E; ++I) { + if (CtxI->first->isConvertibleTo(*I) && + (CtxI->first->isVariadic() || + CtxI->second < CtxI->first->getNumArgs())) + CtxI->first->getArgKinds(*I, CtxI->second, NextTypeSet); + } + TypeSet.clear(); + for (std::vector<internal::ArgKind>::iterator I = NextTypeSet.begin(), + E = NextTypeSet.end(); + I != E; ++I) { + if (I->getArgKind() == internal::ArgKind::AK_Matcher) + TypeSet.insert(I->getMatcherKind()); + } + } + + typedef std::map<std::pair<unsigned, std::string>, MatcherCompletion, + ReverseSpecificityThenName> CompletionsTy; + CompletionsTy Completions; + + // TypeSet now contains the list of acceptable types for the argument we are + // completing. Search the registry for acceptable matchers. + for (ConstructorMap::const_iterator I = RegistryData->constructors().begin(), + E = RegistryData->constructors().end(); + I != E; ++I) { + std::set<ASTNodeKind> RetKinds; + unsigned NumArgs = I->second->isVariadic() ? 1 : I->second->getNumArgs(); + bool IsPolymorphic = I->second->isPolymorphic(); + std::vector<std::vector<internal::ArgKind> > ArgsKinds(NumArgs); + unsigned MaxSpecificity = 0; + for (std::set<ASTNodeKind>::iterator TI = TypeSet.begin(), + TE = TypeSet.end(); + TI != TE; ++TI) { + unsigned Specificity; + ASTNodeKind LeastDerivedKind; + if (I->second->isConvertibleTo(*TI, &Specificity, &LeastDerivedKind)) { + if (MaxSpecificity < Specificity) + MaxSpecificity = Specificity; + RetKinds.insert(LeastDerivedKind); + for (unsigned Arg = 0; Arg != NumArgs; ++Arg) + I->second->getArgKinds(*TI, Arg, ArgsKinds[Arg]); + if (IsPolymorphic) + break; + } + } + + if (!RetKinds.empty() && MaxSpecificity > 0) { + std::string Decl; + llvm::raw_string_ostream OS(Decl); + + if (IsPolymorphic) { + OS << "Matcher<T> " << I->first() << "(Matcher<T>"; + } else { + OS << "Matcher<" << RetKinds << "> " << I->first() << "("; + for (std::vector<std::vector<internal::ArgKind> >::iterator + KI = ArgsKinds.begin(), + KE = ArgsKinds.end(); + KI != KE; ++KI) { + if (KI != ArgsKinds.begin()) + OS << ", "; + // This currently assumes that a matcher may not overload a + // non-matcher, and all non-matcher overloads have identical + // arguments. + if ((*KI)[0].getArgKind() == internal::ArgKind::AK_Matcher) { + std::set<ASTNodeKind> MatcherKinds; + std::transform( + KI->begin(), KI->end(), + std::inserter(MatcherKinds, MatcherKinds.end()), + std::mem_fun_ref(&internal::ArgKind::getMatcherKind)); + OS << "Matcher<" << MatcherKinds << ">"; + } else { + OS << (*KI)[0].asString(); + } + } + } + if (I->second->isVariadic()) + OS << "..."; + OS << ")"; + + std::string TypedText = I->first(); + TypedText += "("; + if (ArgsKinds.empty()) + TypedText += ")"; + else if (ArgsKinds[0][0].getArgKind() == internal::ArgKind::AK_String) + TypedText += "\""; + + Completions[std::make_pair(MaxSpecificity, I->first())] = + MatcherCompletion(TypedText, OS.str()); + } + } + + std::vector<MatcherCompletion> RetVal; + for (CompletionsTy::iterator I = Completions.begin(), E = Completions.end(); + I != E; ++I) + RetVal.push_back(I->second); + return RetVal; +} + +// static +VariantMatcher Registry::constructMatcher(MatcherCtor Ctor, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { + return Ctor->create(NameRange, Args, Error); } // static -VariantMatcher Registry::constructBoundMatcher(StringRef MatcherName, +VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID, ArrayRef<ParserValue> Args, Diagnostics *Error) { - VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error); + VariantMatcher Out = constructMatcher(Ctor, NameRange, Args, Error); if (Out.isNull()) return Out; llvm::Optional<DynTypedMatcher> Result = Out.getSingleMatcher(); diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp index 3e49e1b..18c9894 100644 --- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "clang/ASTMatchers/Dynamic/VariantValue.h" - #include "clang/Basic/LLVM.h" #include "llvm/ADT/STLExtras.h" @@ -38,7 +37,8 @@ public: } virtual void makeTypedMatcher(MatcherOps &Ops) const { - if (Ops.canConstructFrom(Matcher)) + bool Ignore; + if (Ops.canConstructFrom(Matcher, Ignore)) Ops.constructFrom(Matcher); } @@ -48,8 +48,8 @@ private: class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { public: - PolymorphicPayload(ArrayRef<DynTypedMatcher> MatchersIn) - : Matchers(MatchersIn) {} + PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn) + : Matchers(std::move(MatchersIn)) {} virtual ~PolymorphicPayload() {} @@ -70,15 +70,25 @@ public: } virtual void makeTypedMatcher(MatcherOps &Ops) const { - const DynTypedMatcher *Found = NULL; + bool FoundIsExact = false; + const DynTypedMatcher *Found = nullptr; + int NumFound = 0; for (size_t i = 0, e = Matchers.size(); i != e; ++i) { - if (Ops.canConstructFrom(Matchers[i])) { - if (Found) - return; + bool IsExactMatch; + if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { + if (Found) { + if (FoundIsExact) { + assert(!IsExactMatch && "We should not have two exact matches."); + continue; + } + } Found = &Matchers[i]; + FoundIsExact = IsExactMatch; + ++NumFound; } } - if (Found) + // We only succeed if we found exactly one, or if we found an exact match. + if (Found && (FoundIsExact || NumFound == 1)) Ops.constructFrom(*Found); } @@ -88,8 +98,8 @@ public: class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload { public: VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> Args) - : Func(Func), Args(Args) {} + std::vector<VariantMatcher> Args) + : Func(Func), Args(std::move(Args)) {} virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const { return llvm::Optional<DynTypedMatcher>(); @@ -121,14 +131,14 @@ VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { } VariantMatcher -VariantMatcher::PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers) { - return VariantMatcher(new PolymorphicPayload(Matchers)); +VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { + return VariantMatcher(new PolymorphicPayload(std::move(Matchers))); } VariantMatcher VariantMatcher::VariadicOperatorMatcher( ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> Args) { - return VariantMatcher(new VariadicOpPayload(Func, Args)); + std::vector<VariantMatcher> Args) { + return VariantMatcher(new VariadicOpPayload(Func, std::move(Args))); } llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const { |