private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
+
+ // Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
+ template <typename T>
+ bool TraverseDeclTemplateParameterLists(T *D);
+
#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
DEF_TRAVERSE_TMPL_INST(Class)
}
template <typename Derived>
+template <typename T>
+bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) {
+ for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) {
+ TemplateParameterList *TPL = D->getTemplateParameterList(i);
+ TraverseTemplateParameterListHelper(TPL);
+ }
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
ClassTemplateDecl *D) {
for (auto *SD : D->specializations()) {
})
DEF_TRAVERSE_DECL(EnumDecl, {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
+
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the source.
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
functionDecl(hasAnyTemplateArgument(templateArgument()))));
}
+TEST(TemplateTypeParmDecl, CXXMethodDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " void method();\n"
+ "};\n"
+ "template<typename U>\n"
+ "void Class<U>::method() {}\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " static T pi;\n"
+ "};\n"
+ "template<typename U>\n"
+ "U Class<U>::pi = U(3.1415926535897932385);\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "struct Struct {\n"
+ " template<typename T2> static int field;\n"
+ "};\n"
+ "template<typename U>\n"
+ "template<typename U2>\n"
+ "int Struct<U>::field<char> = 123;\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " template<typename T2> struct Struct;\n"
+ "};\n"
+ "template<typename U>\n"
+ "template<typename U2>\n"
+ "struct Class<U>::Struct<int> {};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, EnumDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "struct Struct {\n"
+ " enum class Enum : T;\n"
+ "};\n"
+ "template<typename U>\n"
+ "enum class Struct<U>::Enum : U {\n"
+ " e1,\n"
+ " e2\n"
+ "};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, RecordDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " struct Struct;\n"
+ "};\n"
+ "template<typename U>\n"
+ "struct Class<U>::Struct {\n"
+ " U field;\n"
+ "};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
TEST(RefersToIntegralType, Matches) {
EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
classTemplateSpecializationDecl(