Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -1308,6 +1308,18 @@ +Matcher<Type>functionProtoTypeMatcher<FunctionProtoType>... +
Matches FunctionProtoType nodes.
+
+Given
+  int (*f)(int);
+  void g();
+functionProtoType()
+  matches "int (*f)(int)" and the type of "g" in C++ mode.
+  In C mode, "g" is not matched because it does not contain a prototype.
+
+ + Matcher<Type>functionTypeMatcher<FunctionType>...
Matches FunctionType nodes.
 
@@ -2335,13 +2347,40 @@
 
 
 Matcher<FunctionDecl>parameterCountIsunsigned N
-
Matches FunctionDecls that have a specific parameter count.
+
Matches FunctionDecls and FunctionProtoTypes that have a
+specific parameter count.
+
+Given
+  void f(int i) {}
+  void g(int i, int j) {}
+  void h(int i, int j);
+  void j(int i);
+  void k(int x, int y, int z, ...);
+functionDecl(parameterCountIs(2))
+  matches void g(int i, int j) {}
+functionProtoType(parameterCountIs(2))
+  matches void h(int i, int j)
+functionProtoType(parameterCountIs(3))
+  matches void k(int x, int y, int z, ...);
+
+ + +Matcher<FunctionProtoType>parameterCountIsunsigned N +
Matches FunctionDecls and FunctionProtoTypes that have a
+specific parameter count.
 
 Given
   void f(int i) {}
   void g(int i, int j) {}
+  void h(int i, int j);
+  void j(int i);
+  void k(int x, int y, int z, ...);
 functionDecl(parameterCountIs(2))
-  matches g(int i, int j) {}
+  matches void g(int i, int j) {}
+functionProtoType(parameterCountIs(2))
+  matches void h(int i, int j)
+functionProtoType(parameterCountIs(3))
+  matches void k(int x, int y, int z, ...);
 
@@ -3995,8 +4034,8 @@
-Matcher<Expr>hasTypeMatcher<Decl> InnerMatcher -
Overloaded to match the declaration of the expression's or value
+Matcher<Expr>hasTypeMatcher<Decl> InnerMatcher
+
Overloaded to match the declaration of the expression's or value
 declaration's type.
 
 In case of a value declaration (for example a variable declaration),
@@ -4020,8 +4059,10 @@
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and U (matcher = typedefDecl(hasType(asString("int")))
  class X {};
  void y(X &x) { x; X z; }
+ typedef int U;
 
@@ -4796,6 +4837,19 @@
+Matcher<TypedefDecl>hasTypeMatcher<QualType> InnerMatcher +
Matches if the expression's or declaration's type matches a type
+matcher.
+
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+            and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and U (matcher = typedefDecl(hasType(asString("int")))
+ class X {};
+ void y(X &x) { x; X z; }
+ typedef int U;
+
+ + Matcher<TypedefType>hasDeclarationMatcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
@@ -4881,8 +4935,8 @@
   matches using X::b but not using X::a 
-Matcher<ValueDecl>hasTypeMatcher<Decl> InnerMatcher -
Overloaded to match the declaration of the expression's or value
+Matcher<ValueDecl>hasTypeMatcher<Decl> InnerMatcher
+
Overloaded to match the declaration of the expression's or value
 declaration's type.
 
 In case of a value declaration (for example a variable declaration),
@@ -4900,14 +4954,16 @@
 
-Matcher<ValueDecl>hasTypeMatcher<QualType> InnerMatcher -
Matches if the expression's or declaration's type matches a type
+Matcher<ValueDecl>hasTypeMatcher<QualType> InnerMatcher
+
Matches if the expression's or declaration's type matches a type
 matcher.
 
 Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
             and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+            and U (matcher = typedefDecl(hasType(asString("int")))
  class X {};
  void y(X &x) { x; X z; }
+ typedef int U;
 
Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2298,14 +2298,17 @@ /// /// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) /// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) +/// and U (matcher = typedefDecl(hasType(asString("int"))) /// \code /// class X {}; /// void y(X &x) { x; X z; } +/// typedef int U; /// \endcode AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl), + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefDecl, ValueDecl), internal::Matcher, InnerMatcher, 0) { - return InnerMatcher.matches(Node.getType(), Finder, Builder); + return InnerMatcher.matches(internal::getUnderlyingType(Node), + Finder, Builder); } /// \brief Overloaded to match the declaration of the expression's or value @@ -2951,16 +2954,27 @@ Node.param_end(), Finder, Builder); } -/// \brief Matches \c FunctionDecls that have a specific parameter count. +/// \brief Matches \c FunctionDecls and \c FunctionProtoTypes that have a +/// specific parameter count. /// /// Given /// \code /// void f(int i) {} /// void g(int i, int j) {} +/// void h(int i, int j); +/// void j(int i); +/// void k(int x, int y, int z, ...); /// \endcode /// functionDecl(parameterCountIs(2)) -/// matches g(int i, int j) {} -AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { +/// matches void g(int i, int j) {} +/// functionProtoType(parameterCountIs(2)) +/// matches void h(int i, int j) +/// functionProtoType(parameterCountIs(3)) +/// matches void k(int x, int y, int z, ...); +AST_POLYMORPHIC_MATCHER_P(parameterCountIs, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + FunctionProtoType), + unsigned, N) { return Node.getNumParams() == N; } @@ -4099,6 +4113,18 @@ /// matches "int (*f)(int)" and the type of "g". AST_TYPE_MATCHER(FunctionType, functionType); +/// \brief Matches \c FunctionProtoType nodes. +/// +/// Given +/// \code +/// int (*f)(int); +/// void g(); +/// \endcode +/// functionProtoType() +/// matches "int (*f)(int)" and the type of "g" in C++ mode. +/// In C mode, "g" is not matched because it does not contain a prototype. +AST_TYPE_MATCHER(FunctionProtoType, functionProtoType); + /// \brief Matches \c ParenType nodes. /// /// Given Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -60,6 +60,17 @@ namespace internal { +/// \brief Unifies obtaining the underlying type of a regular node through +/// `getType` and a TypedefNameDecl node through `getUnderlyingType`. +template +inline QualType getUnderlyingType(const NodeType &Node) { + return Node.getType(); +} + +template <> inline QualType getUnderlyingType(const TypedefDecl &Node) { + return Node.getUnderlyingType(); +} + /// \brief Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -182,6 +182,7 @@ REGISTER_MATCHER(forStmt); REGISTER_MATCHER(friendDecl); REGISTER_MATCHER(functionDecl); + REGISTER_MATCHER(functionProtoType); REGISTER_MATCHER(functionTemplateDecl); REGISTER_MATCHER(functionType); REGISTER_MATCHER(gotoStmt); Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1091,6 +1091,16 @@ notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX)))); } +TEST(HasType, MatchesTypedefDecl) { + EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int"))))); + EXPECT_TRUE(matches("typedef const int T;", + typedefDecl(hasType(asString("const int"))))); + EXPECT_TRUE(notMatches("typedef const int T;", + typedefDecl(hasType(asString("int"))))); + EXPECT_TRUE(matches("typedef int foo; typedef foo bar;", + typedefDecl(hasType(asString("foo")), hasName("bar")))); +} + TEST(HasTypeLoc, MatchesDeclaratorDecls) { EXPECT_TRUE(matches("int x;", varDecl(hasName("x"), hasTypeLoc(loc(asString("int")))))); @@ -1563,6 +1573,9 @@ functionDecl(isVariadic()))); EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic()))); EXPECT_TRUE(notMatchesC("void f();", functionDecl(isVariadic()))); + EXPECT_TRUE(matches("void f(...);", functionDecl(parameterCountIs(0)))); + EXPECT_TRUE(matchesC("void f();", functionDecl(parameterCountIs(0)))); + EXPECT_TRUE(matches("void f(int, ...);", functionDecl(parameterCountIs(1)))); } TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) { @@ -1719,6 +1732,7 @@ EXPECT_TRUE(matches("class X { void f(int i) {} };", Function1Arg)); EXPECT_TRUE(notMatches("void f() {}", Function1Arg)); EXPECT_TRUE(notMatches("void f(int i, int j, int k) {}", Function1Arg)); + EXPECT_TRUE(matches("void f(int i, ...) {};", Function1Arg)); } TEST(Matcher, References) { @@ -4447,6 +4461,15 @@ EXPECT_TRUE(matches("void f(int i) {}", functionType())); } +TEST(TypeMatching, MatchesFunctionProtoTypes) { + EXPECT_TRUE(matches("int (*f)(int);", functionProtoType())); + EXPECT_TRUE(matches("void f(int i);", functionProtoType())); + EXPECT_TRUE(matches("void f();", functionProtoType(parameterCountIs(0)))); + EXPECT_TRUE(notMatchesC("void f();", functionProtoType())); + EXPECT_TRUE( + matchesC("void f(void);", functionProtoType(parameterCountIs(0)))); +} + TEST(TypeMatching, MatchesParenType) { EXPECT_TRUE( matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType()))))); @@ -5148,7 +5171,8 @@ namespaceDecl(isInline(), hasName("m")))); } -// FIXME: Figure out how to specify paths so the following tests pass on Windows. +// FIXME: Figure out how to specify paths so the following tests pass on +// Windows. #ifndef LLVM_ON_WIN32 TEST(Matcher, IsExpansionInMainFileMatcher) { Index: unittests/ASTMatchers/Dynamic/RegistryTest.cpp =================================================================== --- unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -421,7 +421,7 @@ constructMatcher("parameterCountIs", 3), Error.get()) .isNull()); EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher) != " - "(Actual = Matcher)", + "(Actual = Matcher)", Error->toString()); // Bad argument type with variadic.