[change-namespace] Fix crash when injected base-class name is used in friend declarations.

Reviewers: hokein

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D41001

llvm-svn: 320139
This commit is contained in:
Eric Liu 2017-12-08 10:06:16 +00:00
parent f5f0fffea5
commit 5a6d57c75f
2 changed files with 58 additions and 0 deletions

View File

@ -552,6 +552,10 @@ void ChangeNamespaceTool::run(
if (Loc.getTypeLocClass() == TypeLoc::Elaborated) {
NestedNameSpecifierLoc NestedNameSpecifier =
Loc.castAs<ElaboratedTypeLoc>().getQualifierLoc();
// This happens for friend declaration of a base class with injected class
// name.
if (!NestedNameSpecifier.getNestedNameSpecifier())
return;
const Type *SpecifierType =
NestedNameSpecifier.getNestedNameSpecifier()->getAsType();
if (SpecifierType && SpecifierType->isRecordType())

View File

@ -2154,6 +2154,60 @@ TEST_F(ChangeNamespaceTest, DefaultMoveConstructors) {
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
}
TEST_F(ChangeNamespaceTest, InjectedClassNameInFriendDecl) {
OldNamespace = "d";
NewNamespace = "e";
std::string Code = "namespace a{\n"
"template <typename T>\n"
"class Base {\n"
" public:\n"
" void f() {\n"
" T t;\n"
" t.priv();\n"
" }\n"
"};\n"
"} // namespace a\n"
"namespace d {\n"
"class D : public a::Base<D> {\n"
" private:\n"
" friend class Base<D>;\n"
" void priv() {}\n"
" Base b;\n"
"};\n"
"\n"
"void f() {\n"
" D d;\n"
" a:: Base<D> b;\n"
" b.f();\n"
"}\n"
"} // namespace d\n";
std::string Expected = "namespace a{\n"
"template <typename T>\n"
"class Base {\n"
" public:\n"
" void f() {\n"
" T t;\n"
" t.priv();\n"
" }\n"
"};\n"
"} // namespace a\n"
"\n"
"namespace e {\n"
"class D : public a::Base<D> {\n"
" private:\n"
" friend class Base<D>;\n"
" void priv() {}\n"
" a::Base b;\n"
"};\n"
"\n"
"void f() {\n"
" D d;\n"
" a::Base<D> b;\n"
" b.f();\n"
"}\n"
"} // namespace e\n";
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
}
} // anonymous namespace
} // namespace change_namespace