forked from OSchip/llvm-project
Traversing template paramter lists of DeclaratorDecls and/or TagDecls.
The unit tests in this patch demonstrate the need to traverse template parameter lists of DeclaratorDecls (e.g. VarDecls, CXXMethodDecls) and TagDecls (e.g. EnumDecls, RecordDecls). Fixes PR29042. https://reviews.llvm.org/D24268 Patch from Lukasz Łukasz Anforowicz <lukasza@chromium.org>! llvm-svn: 281345
This commit is contained in:
parent
2574d15c5b
commit
6339f1a028
|
@ -482,6 +482,11 @@ public:
|
|||
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)
|
||||
|
@ -1533,6 +1538,16 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
|
|||
return true;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1694,6 +1709,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
|
|||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(EnumDecl, {
|
||||
TRY_TO(TraverseDeclTemplateParameterLists(D));
|
||||
|
||||
if (D->getTypeForDecl())
|
||||
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
|
||||
|
||||
|
@ -1708,6 +1725,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
|
|||
// 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;
|
||||
}
|
||||
|
@ -1802,6 +1820,7 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
|
|||
|
||||
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()));
|
||||
|
@ -1848,6 +1867,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, {
|
|||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
|
||||
TRY_TO(TraverseDeclTemplateParameterLists(D));
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
|
||||
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
|
||||
|
||||
|
|
|
@ -641,6 +641,89 @@ TEST(TemplateArgument, Matches) {
|
|||
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(
|
||||
|
|
Loading…
Reference in New Issue