From: Samuel Benzaquen Date: Tue, 4 Jun 2013 15:46:22 +0000 (+0000) Subject: Parser/Registry argument enhancements. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a337af9e8bc752a2d3b227e4058ed2baf7a19d1;p=clang Parser/Registry argument enhancements. Summary: Parser/Registry argument enhancements. - 2 argument support. - unsigned values support. Reviewers: klimek CC: cfe-commits, revane Differential Revision: http://llvm-reviews.chandlerc.com/D915 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183231 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h index 38e87ce37a..21e08ff2da 100644 --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -69,7 +69,8 @@ class Diagnostics { ET_ParserNotAMatcher = 107, ET_ParserInvalidToken = 108, ET_ParserMalformedBindExpr = 109, - ET_ParserTrailingCode = 110 + ET_ParserTrailingCode = 110, + ET_ParserUnsignedError = 111 }; /// \brief Helper stream class. diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h index b6cd4afebe..51dbc8a5a4 100644 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/include/clang/ASTMatchers/Dynamic/Parser.h @@ -18,8 +18,10 @@ /// /// \code /// Grammar for the expressions supported: -/// := | +/// := | +/// := | /// := "quoted string" +/// := [0-9]+ /// := () | /// ().bind() /// := [a-zA-Z]+ diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h index 9a41b448cf..fa6f08e67a 100644 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -37,6 +37,7 @@ using ast_matchers::internal::DynTypedMatcher; /// copy/assignment. /// /// Supported types: +/// - \c unsigned /// - \c std::string /// - \c DynTypedMatcher, and any \c Matcher class VariantValue { @@ -48,9 +49,15 @@ public: VariantValue &operator=(const VariantValue &Other); /// \brief Specific constructors for each supported type. + VariantValue(unsigned Unsigned); VariantValue(const std::string &String); VariantValue(const DynTypedMatcher &Matcher); + /// \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; @@ -104,12 +111,14 @@ private: /// \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; DynTypedMatcher *Matcher; }; diff --git a/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/lib/ASTMatchers/Dynamic/Diagnostics.cpp index 4b01b997a1..79c9389cf5 100644 --- a/lib/ASTMatchers/Dynamic/Diagnostics.cpp +++ b/lib/ASTMatchers/Dynamic/Diagnostics.cpp @@ -62,6 +62,8 @@ StringRef ErrorTypeToString(Diagnostics::ErrorType Type) { return "Malformed bind() expression."; case Diagnostics::ET_ParserTrailingCode: return "Expected end of code."; + case Diagnostics::ET_ParserUnsignedError: + return "Error parsing unsigned token: <$0>"; case Diagnostics::ET_None: return ""; diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h index a41ed24998..2cc5f7cdaa 100644 --- a/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/lib/ASTMatchers/Dynamic/Marshallers.h @@ -55,7 +55,13 @@ template struct ArgTypeTraits > { static ast_matchers::internal::Matcher get(const VariantValue &Value) { return Value.getTypedMatcher(); } +}; +template <> struct ArgTypeTraits { + static bool is(const VariantValue &Value) { return Value.isUnsigned(); } + static unsigned get(const VariantValue &Value) { + return Value.getUnsigned(); + } }; /// \brief Generic MatcherCreate interface. @@ -116,15 +122,6 @@ createMarshallerCallback(MarshallerType Marshaller, FuncType Func, return NULL; \ } -/// \brief Metafunction to normalize argument types. -/// -/// We need to remove the const& out of the function parameters to be able to -/// find values on VariantValue. -template -struct remove_const_ref : - public llvm::remove_const::type> { -}; - /// \brief 0-arg marshaller function. template DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName, @@ -136,18 +133,31 @@ DynTypedMatcher *matcherMarshall0(ReturnType (*Func)(), StringRef MatcherName, } /// \brief 1-arg marshaller function. -template -DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(InArgType1), +template +DynTypedMatcher *matcherMarshall1(ReturnType (*Func)(ArgType1), StringRef MatcherName, const SourceRange &NameRange, ArrayRef Args, Diagnostics *Error) { - typedef typename remove_const_ref::type ArgType1; CHECK_ARG_COUNT(1); CHECK_ARG_TYPE(0, ArgType1); return Func(ArgTypeTraits::get(Args[0].Value)).clone(); } +/// \brief 2-arg marshaller function. +template +DynTypedMatcher *matcherMarshall2(ReturnType (*Func)(ArgType1, ArgType2), + StringRef MatcherName, + const SourceRange &NameRange, + ArrayRef Args, + Diagnostics *Error) { + CHECK_ARG_COUNT(2); + CHECK_ARG_TYPE(0, ArgType1); + CHECK_ARG_TYPE(1, ArgType2); + return Func(ArgTypeTraits::get(Args[0].Value), + ArgTypeTraits::get(Args[1].Value)).clone(); +} + /// \brief Variadic marshaller function. template class VariadicMatcherCreateCallback : public MatcherCreateCallback { @@ -197,6 +207,15 @@ MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), MatcherName); } +/// \brief 2-arg overload +template +MatcherCreateCallback *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, + ArgType2), + StringRef MatcherName) { + return createMarshallerCallback( + matcherMarshall2, Func, MatcherName); +} + /// \brief Variadic overload. template MatcherCreateCallback *makeMatcherAutoMarshall( diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp index 1ed40f3050..eff50f4061 100644 --- a/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/lib/ASTMatchers/Dynamic/Parser.cpp @@ -112,6 +112,12 @@ private: consumeStringLiteral(&Result); break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + // Parse an unsigned literal. + consumeUnsignedLiteral(&Result); + break; + default: if (isAlphanumeric(Code[0])) { // Parse an identifier @@ -133,6 +139,35 @@ private: return Result; } + /// \brief Consume an unsigned literal. + void consumeUnsignedLiteral(TokenInfo *Result) { + unsigned Length = 1; + if (Code.size() > 1) { + // Consume the 'x' or 'b' radix modifier, if present. + switch (toLowercase(Code[1])) { + case 'x': case 'b': Length = 2; + } + } + while (Length < Code.size() && isHexDigit(Code[Length])) + ++Length; + + Result->Text = Code.substr(0, Length); + Code = Code.drop_front(Length); + + unsigned Value; + if (!Result->Text.getAsInteger(0, Value)) { + Result->Kind = TokenInfo::TK_Literal; + Result->Value = Value; + } else { + SourceRange Range; + Range.Start = Result->Range.Start; + Range.End = currentLocation(); + Error->pushErrorFrame(Range, Error->ET_ParserUnsignedError) + << Result->Text; + Result->Kind = TokenInfo::TK_Error; + } + } + /// \brief Consume a string literal. /// /// \c Code must be positioned at the start of the literal (the opening diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 6e543fc850..5f6b35df69 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -44,6 +44,7 @@ private: void RegistryMaps::registerMatcher(StringRef MatcherName, MatcherCreateCallback *Callback) { + assert(Constructors.find(MatcherName) == Constructors.end()); Constructors[MatcherName] = Callback; } @@ -53,70 +54,236 @@ void RegistryMaps::registerMatcher(StringRef MatcherName, /// \brief Generate a registry map with all the known matchers. RegistryMaps::RegistryMaps() { - // TODO: This list is not complete. It only has non-overloaded matchers, - // which are the simplest to add to the system. Overloaded matchers require - // more supporting code that was omitted from the first revision for - // simplicitly of code review. + // TODO: Here is the list of the missing matchers, grouped by reason. + // + // Need DynTypedNode fixes: + // hasAnyTemplateArgument + // hasTemplateArgument + // + // Need Variant/Parser fixes: + // ofKind + // + // CXXCtorInitializer support: + // hasAnyConstructorInitializer + // forField + // withInitializer + // isWritten + // isImplicit + // + // Type traversal: + // hasElementType + // hasValueType + // hasDeducedType + // innerType + // pointee + // + // Function overloaded by args: + // hasType + // callee + // hasPrefix + // isDerivedFrom + // isSameOrDerivedFrom + // pointsTo + // references + // thisPointerType + // + // Polymorphic matchers: + // anything + // hasAnyArgument + // isTemplateInstantiation + // isExplicitTemplateSpecialization + // isDefinition + // hasOperatorName + // hasOverloadedOperatorName + // hasCondition + // hasBody + // argumentCountIs + // hasArgument + // + // Polymorphic + argument overload: + // unless + // eachOf + // anyOf + // allOf + // findAll + // + // Adaptative matcher (similar to polymorphic matcher): + // has + // forEach + // forEachDescendant + // hasDescendant + // hasParent + // hasAncestor + // + // Other: + // loc + // equals + // equalsNode + // hasDeclaration + REGISTER_MATCHER(accessSpecDecl); + REGISTER_MATCHER(alignOfExpr); + REGISTER_MATCHER(arraySubscriptExpr); + REGISTER_MATCHER(arrayType); + REGISTER_MATCHER(asString); + REGISTER_MATCHER(asmStmt); + REGISTER_MATCHER(atomicType); + REGISTER_MATCHER(autoType); REGISTER_MATCHER(binaryOperator); REGISTER_MATCHER(bindTemporaryExpr); + REGISTER_MATCHER(blockPointerType); REGISTER_MATCHER(boolLiteral); + REGISTER_MATCHER(breakStmt); + REGISTER_MATCHER(builtinType); + REGISTER_MATCHER(cStyleCastExpr); REGISTER_MATCHER(callExpr); + REGISTER_MATCHER(castExpr); + REGISTER_MATCHER(catchStmt); REGISTER_MATCHER(characterLiteral); + REGISTER_MATCHER(classTemplateDecl); + REGISTER_MATCHER(classTemplateSpecializationDecl); + REGISTER_MATCHER(complexType); + REGISTER_MATCHER(compoundLiteralExpr); REGISTER_MATCHER(compoundStmt); REGISTER_MATCHER(conditionalOperator); REGISTER_MATCHER(constCastExpr); + REGISTER_MATCHER(constantArrayType); REGISTER_MATCHER(constructExpr); REGISTER_MATCHER(constructorDecl); + REGISTER_MATCHER(containsDeclaration); + REGISTER_MATCHER(continueStmt); + REGISTER_MATCHER(decl); + REGISTER_MATCHER(declCountIs); REGISTER_MATCHER(declRefExpr); REGISTER_MATCHER(declStmt); REGISTER_MATCHER(defaultArgExpr); + REGISTER_MATCHER(deleteExpr); + REGISTER_MATCHER(dependentSizedArrayType); + REGISTER_MATCHER(destructorDecl); REGISTER_MATCHER(doStmt); REGISTER_MATCHER(dynamicCastExpr); + REGISTER_MATCHER(elaboratedType); + REGISTER_MATCHER(enumConstantDecl); + REGISTER_MATCHER(enumDecl); REGISTER_MATCHER(explicitCastExpr); REGISTER_MATCHER(expr); REGISTER_MATCHER(fieldDecl); + REGISTER_MATCHER(forRangeStmt); REGISTER_MATCHER(forStmt); REGISTER_MATCHER(functionDecl); + REGISTER_MATCHER(functionTemplateDecl); + REGISTER_MATCHER(functionType); + REGISTER_MATCHER(functionalCastExpr); + REGISTER_MATCHER(gotoStmt); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnySubstatement); + REGISTER_MATCHER(hasAnyUsingShadowDecl); + REGISTER_MATCHER(hasArgumentOfType); + REGISTER_MATCHER(hasBase); + REGISTER_MATCHER(hasCanonicalType); REGISTER_MATCHER(hasConditionVariableStatement); + REGISTER_MATCHER(hasDeclContext); REGISTER_MATCHER(hasDestinationType); REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasFalseExpression); REGISTER_MATCHER(hasImplicitDestinationType); + REGISTER_MATCHER(hasIncrement); + REGISTER_MATCHER(hasIndex); REGISTER_MATCHER(hasInitializer); REGISTER_MATCHER(hasLHS); + REGISTER_MATCHER(hasLocalQualifiers); + REGISTER_MATCHER(hasLoopInit); + REGISTER_MATCHER(hasMethod); REGISTER_MATCHER(hasName); REGISTER_MATCHER(hasObjectExpression); + REGISTER_MATCHER(hasParameter); + REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRHS); + REGISTER_MATCHER(hasSingleDecl); + REGISTER_MATCHER(hasSize); + REGISTER_MATCHER(hasSizeExpr); REGISTER_MATCHER(hasSourceExpression); + REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTrueExpression); REGISTER_MATCHER(hasUnaryOperand); REGISTER_MATCHER(ifStmt); + REGISTER_MATCHER(ignoringImpCasts); + REGISTER_MATCHER(ignoringParenCasts); + REGISTER_MATCHER(ignoringParenImpCasts); REGISTER_MATCHER(implicitCastExpr); + REGISTER_MATCHER(incompleteArrayType); + REGISTER_MATCHER(initListExpr); REGISTER_MATCHER(integerLiteral); REGISTER_MATCHER(isArrow); REGISTER_MATCHER(isConstQualified); + REGISTER_MATCHER(isExternC); REGISTER_MATCHER(isImplicit); + REGISTER_MATCHER(isInteger); + REGISTER_MATCHER(isOverride); + REGISTER_MATCHER(isPrivate); + REGISTER_MATCHER(isProtected); + REGISTER_MATCHER(isPublic); + REGISTER_MATCHER(isVirtual); + REGISTER_MATCHER(lValueReferenceType); + REGISTER_MATCHER(labelStmt); + REGISTER_MATCHER(lambdaExpr); + REGISTER_MATCHER(matchesName); + REGISTER_MATCHER(materializeTemporaryExpr); REGISTER_MATCHER(member); + REGISTER_MATCHER(memberCallExpr); REGISTER_MATCHER(memberExpr); + REGISTER_MATCHER(memberPointerType); REGISTER_MATCHER(methodDecl); REGISTER_MATCHER(namedDecl); + REGISTER_MATCHER(namesType); + REGISTER_MATCHER(namespaceDecl); + REGISTER_MATCHER(nestedNameSpecifier); + REGISTER_MATCHER(nestedNameSpecifierLoc); REGISTER_MATCHER(newExpr); + REGISTER_MATCHER(nullPtrLiteralExpr); + REGISTER_MATCHER(nullStmt); REGISTER_MATCHER(ofClass); REGISTER_MATCHER(on); REGISTER_MATCHER(onImplicitObjectArgument); REGISTER_MATCHER(operatorCallExpr); + REGISTER_MATCHER(parameterCountIs); + REGISTER_MATCHER(parenType); + REGISTER_MATCHER(pointerType); + REGISTER_MATCHER(qualType); + REGISTER_MATCHER(rValueReferenceType); REGISTER_MATCHER(recordDecl); + REGISTER_MATCHER(recordType); + REGISTER_MATCHER(referenceType); + REGISTER_MATCHER(refersToDeclaration); + REGISTER_MATCHER(refersToType); REGISTER_MATCHER(reinterpretCastExpr); + REGISTER_MATCHER(returnStmt); + REGISTER_MATCHER(returns); + REGISTER_MATCHER(sizeOfExpr); + REGISTER_MATCHER(specifiesNamespace); + REGISTER_MATCHER(specifiesType); + REGISTER_MATCHER(specifiesTypeLoc); + REGISTER_MATCHER(statementCountIs); REGISTER_MATCHER(staticCastExpr); REGISTER_MATCHER(stmt); REGISTER_MATCHER(stringLiteral); REGISTER_MATCHER(switchCase); + REGISTER_MATCHER(switchStmt); + REGISTER_MATCHER(templateSpecializationType); + REGISTER_MATCHER(thisExpr); + REGISTER_MATCHER(throughUsingDecl); + REGISTER_MATCHER(throwExpr); REGISTER_MATCHER(to); + REGISTER_MATCHER(tryStmt); + REGISTER_MATCHER(type); + REGISTER_MATCHER(typeLoc); + REGISTER_MATCHER(typedefType); + REGISTER_MATCHER(unaryExprOrTypeTraitExpr); REGISTER_MATCHER(unaryOperator); + REGISTER_MATCHER(userDefinedLiteral); + REGISTER_MATCHER(usingDecl); REGISTER_MATCHER(varDecl); + REGISTER_MATCHER(variableArrayType); REGISTER_MATCHER(whileStmt); } diff --git a/lib/ASTMatchers/Dynamic/VariantValue.cpp b/lib/ASTMatchers/Dynamic/VariantValue.cpp index e310fbfc58..6fcbe7fc49 100644 --- a/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -22,20 +22,27 @@ VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { *this = Other; } -VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) { - setMatcher(Matcher); +VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) { + setUnsigned(Unsigned); } VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) { setString(String); } +VariantValue::VariantValue(const DynTypedMatcher &Matcher) : Type(VT_Nothing) { + setMatcher(Matcher); +} + VariantValue::~VariantValue() { reset(); } VariantValue &VariantValue::operator=(const VariantValue &Other) { if (this == &Other) return *this; reset(); switch (Other.Type) { + case VT_Unsigned: + setUnsigned(Other.getUnsigned()); + break; case VT_String: setString(Other.getString()); break; @@ -58,12 +65,28 @@ void VariantValue::reset() { delete Value.Matcher; break; // Cases that do nothing. + case VT_Unsigned: case VT_Nothing: break; } Type = VT_Nothing; } +bool VariantValue::isUnsigned() const { + return Type == VT_Unsigned; +} + +unsigned VariantValue::getUnsigned() const { + assert(isUnsigned()); + return Value.Unsigned; +} + +void VariantValue::setUnsigned(unsigned NewValue) { + reset(); + Type = VT_Unsigned; + Value.Unsigned = NewValue; +} + bool VariantValue::isString() const { return Type == VT_String; } diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp index 310108a38c..b20c1ac6e9 100644 --- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp +++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp @@ -96,6 +96,21 @@ public: llvm::StringMap ExpectedMatchers; }; +TEST(ParserTest, ParseUnsigned) { + MockSema Sema; + Sema.parse("0"); + Sema.parse("123"); + Sema.parse("0x1f"); + Sema.parse("12345678901"); + Sema.parse("1a1"); + EXPECT_EQ(5U, Sema.Values.size()); + EXPECT_EQ(0U, Sema.Values[0].getUnsigned()); + EXPECT_EQ(123U, Sema.Values[1].getUnsigned()); + EXPECT_EQ(31U, Sema.Values[2].getUnsigned()); + EXPECT_EQ("1:1: Error parsing unsigned token: <12345678901>", Sema.Errors[3]); + EXPECT_EQ("1:1: Error parsing unsigned token: <1a1>", Sema.Errors[4]); +} + TEST(ParserTest, ParseString) { MockSema Sema; Sema.parse("\"Foo\""); @@ -122,7 +137,7 @@ TEST(ParserTest, ParseMatcher) { const uint64_t ExpectedFoo = Sema.expectMatcher("Foo"); const uint64_t ExpectedBar = Sema.expectMatcher("Bar"); const uint64_t ExpectedBaz = Sema.expectMatcher("Baz"); - Sema.parse(" Foo ( Bar (), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") "); + Sema.parse(" Foo ( Bar ( 17), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") "); for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) { EXPECT_EQ("", Sema.Errors[i]); } @@ -135,12 +150,13 @@ TEST(ParserTest, ParseMatcher) { EXPECT_EQ(3ULL, Sema.Matchers.size()); const MockSema::MatcherInfo Bar = Sema.Matchers[0]; EXPECT_EQ("Bar", Bar.MatcherName); - EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 14)); - EXPECT_EQ(0ULL, Bar.Args.size()); + EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 17)); + EXPECT_EQ(1ULL, Bar.Args.size()); + EXPECT_EQ(17U, Bar.Args[0].Value.getUnsigned()); const MockSema::MatcherInfo Baz = Sema.Matchers[1]; EXPECT_EQ("Baz", Baz.MatcherName); - EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 16, 10)); + EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 19, 10)); EXPECT_EQ(1ULL, Baz.Args.size()); EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString()); @@ -161,6 +177,11 @@ TEST(ParserTest, FullParserTest) { EXPECT_TRUE(matchesDynamic("int x = 1 + false;", *Matcher)); EXPECT_FALSE(matchesDynamic("int x = true + 1;", *Matcher)); + Matcher.reset( + Parser::parseMatcherExpression("hasParameter(1, hasName(\"x\"))", NULL)); + EXPECT_TRUE(matchesDynamic("void f(int a, int x);", *Matcher)); + EXPECT_FALSE(matchesDynamic("void f(int x, int a);", *Matcher)); + Diagnostics Error; EXPECT_TRUE(Parser::parseMatcherExpression( "hasInitializer(\n binaryOperator(hasLHS(\"A\")))", &Error) == NULL); diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index 64af120193..1055233846 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -63,6 +63,10 @@ TEST(RegistryTest, ConstructWithSimpleArgs) { constructMatcher("hasName", std::string("X"), NULL)); EXPECT_TRUE(matchesDynamic("class X {};", *Value)); EXPECT_FALSE(matchesDynamic("int x;", *Value)); + + Value.reset(constructMatcher("parameterCountIs", 2, NULL)); + EXPECT_TRUE(matchesDynamic("void foo(int,int);", *Value)); + EXPECT_FALSE(matchesDynamic("void foo(int);", *Value)); } TEST(RegistryTest, ConstructWithMatcherArgs) { @@ -82,6 +86,11 @@ TEST(RegistryTest, ConstructWithMatcherArgs) { code = "int y(); int i = y();"; EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple)); EXPECT_TRUE(matchesDynamic(code, *HasInitializerComplex)); + + OwningPtr HasParameter( + constructMatcher("hasParameter", 1, hasName("x"), NULL)); + EXPECT_TRUE(matchesDynamic("void f(int a, int x);", *HasParameter)); + EXPECT_FALSE(matchesDynamic("void f(int x, int a);", *HasParameter)); } TEST(RegistryTest, Errors) { diff --git a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp index 6c202e52fa..2aa0e425ca 100644 --- a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp +++ b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp @@ -19,6 +19,19 @@ namespace { using ast_matchers::internal::DynTypedMatcher; using ast_matchers::internal::Matcher; +TEST(VariantValueTest, Unsigned) { + const unsigned kUnsigned = 17; + VariantValue Value = kUnsigned; + + EXPECT_TRUE(Value.isUnsigned()); + EXPECT_EQ(kUnsigned, Value.getUnsigned()); + + EXPECT_FALSE(Value.isString()); + EXPECT_FALSE(Value.isMatcher()); + EXPECT_FALSE(Value.isTypedMatcher()); + EXPECT_FALSE(Value.isTypedMatcher()); +} + TEST(VariantValueTest, String) { const ::std::string kString = "string"; VariantValue Value = kString; @@ -26,6 +39,7 @@ TEST(VariantValueTest, String) { EXPECT_TRUE(Value.isString()); EXPECT_EQ(kString, Value.getString()); + EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isMatcher()); EXPECT_FALSE(Value.isTypedMatcher()); EXPECT_FALSE(Value.isTypedMatcher()); @@ -34,6 +48,7 @@ TEST(VariantValueTest, String) { TEST(VariantValueTest, DynTypedMatcher) { VariantValue Value = stmt(); + EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isString()); EXPECT_TRUE(Value.isMatcher()); @@ -59,15 +74,24 @@ TEST(VariantValueTest, Assignment) { VariantValue Value = std::string("A"); EXPECT_TRUE(Value.isString()); EXPECT_EQ("A", Value.getString()); + EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isMatcher()); Value = recordDecl(); + EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isString()); EXPECT_TRUE(Value.isMatcher()); EXPECT_TRUE(Value.isTypedMatcher()); EXPECT_TRUE(Value.isTypedMatcher()); + Value = 17; + EXPECT_TRUE(Value.isUnsigned()); + EXPECT_EQ(17U, Value.getUnsigned()); + EXPECT_FALSE(Value.isMatcher()); + EXPECT_FALSE(Value.isString()); + Value = VariantValue(); + EXPECT_FALSE(Value.isUnsigned()); EXPECT_FALSE(Value.isString()); EXPECT_FALSE(Value.isMatcher()); }