This revision was automatically updated to reflect the committed changes.
Closed by commit rL320139: [change-namespace] Fix crash when injected 
base-class name is used in friend… (authored by ioeric).

Repository:
  rL LLVM

https://reviews.llvm.org/D41001

Files:
  clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
  clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp


Index: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
===================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
@@ -552,6 +552,10 @@
     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())
Index: 
clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
===================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
@@ -2154,6 +2154,60 @@
   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


Index: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
===================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
@@ -552,6 +552,10 @@
     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())
Index: clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
===================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
@@ -2154,6 +2154,60 @@
   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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to