forked from OSchip/llvm-project
RecursiveASTVisitor should visit the nested name qualifiers in
a template specialisation rdar://33123354 Differential Revision: https://reviews.llvm.org/D34981 llvm-svn: 307638
This commit is contained in:
parent
c1ace40bf9
commit
9c171406c6
|
@ -1799,6 +1799,7 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
|
|||
if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \
|
||||
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \
|
||||
\
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \
|
||||
if (!getDerived().shouldVisitTemplateInstantiations() && \
|
||||
D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \
|
||||
/* Returning from here skips traversing the \
|
||||
|
|
|
@ -244,4 +244,62 @@ TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
|
|||
InitListExprPostOrderNoQueueVisitor::Lang_C));
|
||||
}
|
||||
|
||||
// Check to ensure that nested name specifiers are visited.
|
||||
class NestedNameSpecifiersVisitor
|
||||
: public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
|
||||
public:
|
||||
bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
|
||||
if (!RTL)
|
||||
return true;
|
||||
Match(RTL.getDecl()->getName(), RTL.getNameLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
if (!NNS)
|
||||
return true;
|
||||
if (const NamespaceDecl *ND =
|
||||
NNS.getNestedNameSpecifier()->getAsNamespace())
|
||||
Match(ND->getName(), NNS.getLocalBeginLoc());
|
||||
return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(RecursiveASTVisitor,
|
||||
NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
|
||||
StringRef Source = R"(
|
||||
namespace ns {
|
||||
struct Outer {
|
||||
template<typename T, typename U>
|
||||
struct Nested { };
|
||||
|
||||
template<typename T>
|
||||
static T x;
|
||||
};
|
||||
}
|
||||
|
||||
template<>
|
||||
struct ns::Outer::Nested<int, int>;
|
||||
|
||||
template<>
|
||||
struct ns::Outer::Nested<int, int> { };
|
||||
|
||||
template<typename T>
|
||||
struct ns::Outer::Nested<int, T> { };
|
||||
|
||||
template<>
|
||||
int ns::Outer::x<int> = 0;
|
||||
)";
|
||||
NestedNameSpecifiersVisitor Visitor;
|
||||
Visitor.ExpectMatch("ns", 13, 8);
|
||||
Visitor.ExpectMatch("ns", 16, 8);
|
||||
Visitor.ExpectMatch("ns", 19, 8);
|
||||
Visitor.ExpectMatch("ns", 22, 5);
|
||||
Visitor.ExpectMatch("Outer", 13, 12);
|
||||
Visitor.ExpectMatch("Outer", 16, 12);
|
||||
Visitor.ExpectMatch("Outer", 19, 12);
|
||||
Visitor.ExpectMatch("Outer", 22, 9);
|
||||
EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14));
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
Loading…
Reference in New Issue