diff options
| author | Samuel Benzaquen <sbenza@google.com> | 2013-06-21 15:51:31 +0000 |
|---|---|---|
| committer | Samuel Benzaquen <sbenza@google.com> | 2013-06-21 15:51:31 +0000 |
| commit | c6f2c9b5665e1547af171dd9a25672a44e9280a4 (patch) | |
| tree | 8993afbf11fbbf9f4b16563b2b6178346dda5b26 /clang/lib | |
| parent | 38fa1ff71026374aec2895e61e142a9cdfd32018 (diff) | |
| download | bcm5719-llvm-c6f2c9b5665e1547af171dd9a25672a44e9280a4.tar.gz bcm5719-llvm-c6f2c9b5665e1547af171dd9a25672a44e9280a4.zip | |
Add support for polymorphic matchers. Use runtime type checking to determine the right polymorphic overload to use.
llvm-svn: 184558
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 123 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Parser.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Registry.cpp | 64 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 82 |
5 files changed, 190 insertions, 106 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp index 6b1d6609a21..1ca1f365398 100644 --- a/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -64,6 +64,8 @@ StringRef ErrorTypeToString(Diagnostics::ErrorType Type) { return "Expected end of code."; case Diagnostics::ET_ParserUnsignedError: return "Error parsing unsigned token: <$0>"; + case Diagnostics::ET_ParserOverloadedType: + return "Input value has unresolved overloaded type: $0"; case Diagnostics::ET_None: return "<N/A>"; diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index aceddc987fe..c3a5260eb43 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -49,6 +49,10 @@ template <> struct ArgTypeTraits<std::string> { } }; +template <> +struct ArgTypeTraits<StringRef> : public ArgTypeTraits<std::string> { +}; + template <class T> struct ArgTypeTraits<ast_matchers::internal::Matcher<T> > { static std::string asString() { return (Twine("Matcher<") + @@ -78,9 +82,9 @@ template <> struct ArgTypeTraits<unsigned> { class MatcherCreateCallback { public: virtual ~MatcherCreateCallback() {} - virtual DynTypedMatcher *run(const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) const = 0; + virtual MatcherList run(const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) const = 0; }; /// \brief Simple callback implementation. Marshaller and function are provided. @@ -95,10 +99,10 @@ public: /// FIXME: Use void(*)() as FuncType on this interface to remove the template /// argument of this class. The marshaller can cast the function pointer back /// to the original type. - typedef DynTypedMatcher *(*MarshallerType)(FuncType, StringRef, - const SourceRange &, - ArrayRef<ParserValue>, - Diagnostics *); + typedef MatcherList (*MarshallerType)(FuncType, StringRef, + const SourceRange &, + ArrayRef<ParserValue>, + Diagnostics *); /// \param Marshaller Function to unpack the arguments and call \c Func /// \param Func Matcher construct function. This is the function that @@ -107,8 +111,8 @@ public: StringRef MatcherName) : Marshaller(Marshaller), Func(Func), MatcherName(MatcherName.str()) {} - DynTypedMatcher *run(const SourceRange &NameRange, - ArrayRef<ParserValue> Args, Diagnostics *Error) const { + MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, + Diagnostics *Error) const { return Marshaller(Func, MatcherName, NameRange, Args, Error); } @@ -127,16 +131,16 @@ private: /// object file. class FreeFuncMatcherCreateCallback : public MatcherCreateCallback { public: - typedef DynTypedMatcher *(*RunFunc)(StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error); + typedef MatcherList (*RunFunc)(StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error); FreeFuncMatcherCreateCallback(RunFunc Func, StringRef MatcherName) : Func(Func), MatcherName(MatcherName.str()) {} - DynTypedMatcher *run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, - Diagnostics *Error) const { + MatcherList run(const SourceRange &NameRange, ArrayRef<ParserValue> Args, + Diagnostics *Error) const { return Func(MatcherName, NameRange, Args, Error); } @@ -150,7 +154,7 @@ private: if (Args.size() != count) { \ Error->pushErrorFrame(NameRange, Error->ET_RegistryWrongArgCount) \ << count << Args.size(); \ - return NULL; \ + return MatcherList(); \ } #define CHECK_ARG_TYPE(index, type) \ @@ -158,43 +162,78 @@ private: Error->pushErrorFrame(Args[index].Range, Error->ET_RegistryWrongArgType) \ << (index + 1) << ArgTypeTraits<type>::asString() \ << Args[index].Value.getTypeAsString(); \ - return NULL; \ + return MatcherList(); \ } +/// \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, MatcherList *Out, + ast_matchers::internal::EmptyTypeList) {} + +template <class PolyMatcher, class TypeList> +static void mergePolyMatchers(const PolyMatcher &Poly, MatcherList *Out, + TypeList) { + Out->add(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)); + mergePolyMatchers(Poly, Out, typename TypeList::tail()); +} + +/// \brief Convert the return values of the functions into a MatcherList. +/// +/// 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 MatcherList. For +/// the latter, we instantiate all the possible Matcher<T> of the poly matcher. +template <typename T> +static MatcherList +outvalueToMatcherList(const ast_matchers::internal::Matcher<T> &Matcher) { + return MatcherList(Matcher); +} + +template <typename T> +static MatcherList +outvalueToMatcherList(const T& PolyMatcher, typename T::ReturnTypes* = NULL) { + MatcherList Matchers; + mergePolyMatchers(PolyMatcher, &Matchers, typename T::ReturnTypes()); + return Matchers; +} + /// \brief 0-arg marshaller function. template <typename ReturnType> -DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +static MatcherList matcherMarshall0(ReturnType (*Func)(), + StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { CHECK_ARG_COUNT(0); - return Func().clone(); + return outvalueToMatcherList(Func()); } /// \brief 1-arg marshaller function. template <typename ReturnType, typename ArgType1> -DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1), - StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +static MatcherList matcherMarshall1(ReturnType (*Func)(ArgType1), + StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { CHECK_ARG_COUNT(1); CHECK_ARG_TYPE(0, ArgType1); - return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value)).clone(); + return outvalueToMatcherList( + Func(ArgTypeTraits<ArgType1>::get(Args[0].Value))); } /// \brief 2-arg marshaller function. template <typename ReturnType, typename ArgType1, typename ArgType2> -DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), - StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +static MatcherList matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), + StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { CHECK_ARG_COUNT(2); CHECK_ARG_TYPE(0, ArgType1); CHECK_ARG_TYPE(1, ArgType2); - return Func(ArgTypeTraits<ArgType1>::get(Args[0].Value), - ArgTypeTraits<ArgType2>::get(Args[1].Value)).clone(); + return outvalueToMatcherList( + Func(ArgTypeTraits<ArgType1>::get(Args[0].Value), + ArgTypeTraits<ArgType2>::get(Args[1].Value))); } #undef CHECK_ARG_COUNT @@ -202,10 +241,10 @@ DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), /// \brief Variadic marshaller function. template <typename BaseType, typename DerivedType> -DynTypedMatcher *VariadicMatcherCreateCallback(StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +MatcherList VariadicMatcherCreateCallback(StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { typedef ast_matchers::internal::Matcher<DerivedType> DerivedMatcherType; DerivedMatcherType **InnerArgs = new DerivedMatcherType *[Args.size()](); @@ -223,10 +262,10 @@ DynTypedMatcher *VariadicMatcherCreateCallback(StringRef MatcherName, InnerArgs[i] = new DerivedMatcherType(DerivedTraits::get(Value)); } - DynTypedMatcher *Out = NULL; + MatcherList Out; if (!HasError) { Out = ast_matchers::internal::makeDynCastAllOfComposite<BaseType>( - ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size())).clone(); + ArrayRef<const DerivedMatcherType *>(InnerArgs, Args.size())); } for (size_t i = 0, e = Args.size(); i != e; ++i) { @@ -264,7 +303,7 @@ MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ReturnType (*)(ArgType1, ArgType2)>(matcherMarshall2, Func, MatcherName); } -/// \brief Variadic overload. +/// \brief Variadic overloads. template <typename MatcherType> MatcherCreateCallback *makeMatcherAutoMarshall( ast_matchers::internal::VariadicAllOfMatcher<MatcherType> Func, diff --git a/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/clang/lib/ASTMatchers/Dynamic/Parser.cpp index eff50f4061c..fc09a30ddd9 100644 --- a/clang/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Parser.cpp @@ -315,15 +315,15 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { // Merge the start and end infos. SourceRange MatcherRange = NameToken.Range; MatcherRange.End = EndToken.Range.End; - DynTypedMatcher *Result = S->actOnMatcherExpression( + MatcherList Result = S->actOnMatcherExpression( NameToken.Text, MatcherRange, BindID, Args, Error); - if (Result == NULL) { + if (Result.empty()) { Error->pushErrorFrame(NameToken.Range, Error->ET_ParserMatcherFailure) << NameToken.Text; return false; } - Value->takeMatcher(Result); + *Value = Result; return true; } @@ -367,11 +367,11 @@ Parser::Parser(CodeTokenizer *Tokenizer, Sema *S, class RegistrySema : public Parser::Sema { public: virtual ~RegistrySema() {} - DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName, - const SourceRange &NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { + MatcherList actOnMatcherExpression(StringRef MatcherName, + const SourceRange &NameRange, + StringRef BindID, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { if (BindID.empty()) { return Registry::constructMatcher(MatcherName, NameRange, Args, Error); } else { @@ -411,11 +411,16 @@ DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code, VariantValue Value; if (!parseExpression(Code, S, &Value, Error)) return NULL; - if (!Value.isMatcher()) { + if (!Value.isMatchers()) { Error->pushErrorFrame(SourceRange(), Error->ET_ParserNotAMatcher); return NULL; } - return Value.getMatcher().clone(); + if (Value.getMatchers().matchers().size() != 1) { + Error->pushErrorFrame(SourceRange(), Error->ET_ParserOverloadedType) + << Value.getTypeAsString(); + return NULL; + } + return Value.getMatchers().matchers()[0]->clone(); } } // namespace dynamic diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 5f6b35df696..c887f3da603 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -68,7 +68,6 @@ RegistryMaps::RegistryMaps() { // forField // withInitializer // isWritten - // isImplicit // // Type traversal: // hasElementType @@ -87,19 +86,6 @@ RegistryMaps::RegistryMaps() { // references // thisPointerType // - // Polymorphic matchers: - // anything - // hasAnyArgument - // isTemplateInstantiation - // isExplicitTemplateSpecialization - // isDefinition - // hasOperatorName - // hasOverloadedOperatorName - // hasCondition - // hasBody - // argumentCountIs - // hasArgument - // // Polymorphic + argument overload: // unless // eachOf @@ -123,6 +109,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(accessSpecDecl); REGISTER_MATCHER(alignOfExpr); + REGISTER_MATCHER(anything); + REGISTER_MATCHER(argumentCountIs); REGISTER_MATCHER(arraySubscriptExpr); REGISTER_MATCHER(arrayType); REGISTER_MATCHER(asString); @@ -175,12 +163,16 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(functionType); REGISTER_MATCHER(functionalCastExpr); REGISTER_MATCHER(gotoStmt); + REGISTER_MATCHER(hasAnyArgument); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnySubstatement); REGISTER_MATCHER(hasAnyUsingShadowDecl); + REGISTER_MATCHER(hasArgument); REGISTER_MATCHER(hasArgumentOfType); REGISTER_MATCHER(hasBase); + REGISTER_MATCHER(hasBody); REGISTER_MATCHER(hasCanonicalType); + REGISTER_MATCHER(hasCondition); REGISTER_MATCHER(hasConditionVariableStatement); REGISTER_MATCHER(hasDeclContext); REGISTER_MATCHER(hasDestinationType); @@ -196,6 +188,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasMethod); REGISTER_MATCHER(hasName); REGISTER_MATCHER(hasObjectExpression); + REGISTER_MATCHER(hasOperatorName); + REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRHS); @@ -216,6 +210,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(integerLiteral); REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isConstQualified); + REGISTER_MATCHER(isDefinition); + REGISTER_MATCHER(isExplicitTemplateSpecialization); REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isInteger); @@ -223,6 +219,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); REGISTER_MATCHER(isPublic); + REGISTER_MATCHER(isTemplateInstantiation); REGISTER_MATCHER(isVirtual); REGISTER_MATCHER(lValueReferenceType); REGISTER_MATCHER(labelStmt); @@ -300,36 +297,39 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData; } // anonymous namespace // static -DynTypedMatcher *Registry::constructMatcher(StringRef MatcherName, - const SourceRange &NameRange, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { +MatcherList Registry::constructMatcher(StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { ConstructorMap::const_iterator it = RegistryData->constructors().find(MatcherName); if (it == RegistryData->constructors().end()) { Error->pushErrorFrame(NameRange, Error->ET_RegistryNotFound) << MatcherName; - return NULL; + return MatcherList(); } return it->second->run(NameRange, Args, Error); } // static -DynTypedMatcher *Registry::constructBoundMatcher(StringRef MatcherName, - const SourceRange &NameRange, - StringRef BindID, - ArrayRef<ParserValue> Args, - Diagnostics *Error) { - OwningPtr<DynTypedMatcher> Out( - constructMatcher(MatcherName, NameRange, Args, Error)); - if (!Out) return NULL; - DynTypedMatcher *Bound = Out->tryBind(BindID); - if (!Bound) { - Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable); - return NULL; +MatcherList Registry::constructBoundMatcher(StringRef MatcherName, + const SourceRange &NameRange, + StringRef BindID, + ArrayRef<ParserValue> Args, + Diagnostics *Error) { + MatcherList Out = constructMatcher(MatcherName, NameRange, Args, Error); + if (Out.empty()) return Out; + + ArrayRef<const DynTypedMatcher*> Matchers = Out.matchers(); + if (Matchers.size() == 1) { + OwningPtr<DynTypedMatcher> Bound(Matchers[0]->tryBind(BindID)); + if (Bound) { + return *Bound; + } } - return Bound; + Error->pushErrorFrame(NameRange, Error->ET_RegistryNotBindable); + return MatcherList(); } } // namespace dynamic diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp index 912858f5485..79c5c8e23a6 100644 --- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -20,6 +20,48 @@ namespace clang { namespace ast_matchers { namespace dynamic { +MatcherList::MatcherList() : List() {} + +MatcherList::MatcherList(const DynTypedMatcher &Matcher) + : List(1, Matcher.clone()) {} + +MatcherList::MatcherList(const MatcherList& Other) { + *this = Other; +} + +MatcherList::~MatcherList() { + reset(); +} + +MatcherList &MatcherList::operator=(const MatcherList &Other) { + if (this == &Other) return *this; + reset(); + for (size_t i = 0, e = Other.List.size(); i != e; ++i) { + List.push_back(Other.List[i]->clone()); + } + return *this; +} + +void MatcherList::add(const DynTypedMatcher &Matcher) { + List.push_back(Matcher.clone()); +} + +void MatcherList::reset() { + for (size_t i = 0, e = List.size(); i != e; ++i) { + delete List[i]; + } + List.resize(0); +} + +std::string MatcherList::getTypeAsString() const { + std::string Inner; + for (size_t I = 0, E = List.size(); I != E; ++I) { + if (I != 0) Inner += "|"; + Inner += List[I]->getSupportedKind().asStringRef(); + } + return (Twine("Matcher<") + Inner + ">").str(); +} + VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { *this = Other; } @@ -33,7 +75,11 @@ VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) { } VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) { - setMatcher(Matcher); + setMatchers(MatcherList(Matcher)); +} + +VariantValue::VariantValue(const MatcherList &Matchers) : Type(VT_Nothing) { + setMatchers(Matchers); } VariantValue::~VariantValue() { reset(); } @@ -48,8 +94,8 @@ VariantValue &VariantValue::operator=(const VariantValue &Other) { case VT_String: setString(Other.getString()); break; - case VT_Matcher: - setMatcher(Other.getMatcher()); + case VT_Matchers: + setMatchers(Other.getMatchers()); break; case VT_Nothing: Type = VT_Nothing; @@ -63,8 +109,8 @@ void VariantValue::reset() { case VT_String: delete Value.String; break; - case VT_Matcher: - delete Value.Matcher; + case VT_Matchers: + delete Value.Matchers; break; // Cases that do nothing. case VT_Unsigned: @@ -104,33 +150,25 @@ void VariantValue::setString(const std::string &NewValue) { Value.String = new std::string(NewValue); } -bool VariantValue::isMatcher() const { - return Type == VT_Matcher; +bool VariantValue::isMatchers() const { + return Type == VT_Matchers; } -const DynTypedMatcher &VariantValue::getMatcher() const { - assert(isMatcher()); - return *Value.Matcher; -} - -void VariantValue::setMatcher(const DynTypedMatcher &NewValue) { - reset(); - Type = VT_Matcher; - Value.Matcher = NewValue.clone(); +const MatcherList &VariantValue::getMatchers() const { + assert(isMatchers()); + return *Value.Matchers; } -void VariantValue::takeMatcher(DynTypedMatcher *NewValue) { +void VariantValue::setMatchers(const MatcherList &NewValue) { reset(); - Type = VT_Matcher; - Value.Matcher = NewValue; + Type = VT_Matchers; + Value.Matchers = new MatcherList(NewValue); } std::string VariantValue::getTypeAsString() const { switch (Type) { case VT_String: return "String"; - case VT_Matcher: - return (Twine("Matcher<") + getMatcher().getSupportedKind().asStringRef() + - ">").str(); + case VT_Matchers: return getMatchers().getTypeAsString(); case VT_Unsigned: return "Unsigned"; case VT_Nothing: return "Nothing"; } |

