[clang-tools-extra] r289672 - [change-namespace] don't crash when type reference is in function type parameter list.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 14 09:01:53 PST 2016


Author: ioeric
Date: Wed Dec 14 11:01:52 2016
New Revision: 289672

URL: http://llvm.org/viewvc/llvm-project?rev=289672&view=rev
Log:
[change-namespace] don't crash when type reference is in function type parameter list.

Reviewers: hokein

Subscribers: cfe-commits

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

Modified:
    clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
    clang-tools-extra/trunk/test/change-namespace/lambda-function.cpp

Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=289672&r1=289671&r2=289672&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Wed Dec 14 11:01:52 2016
@@ -172,6 +172,16 @@ tooling::Replacement createReplacement(S
       ReplacementText);
 }
 
+void addReplacementOrDie(
+    SourceLocation Start, SourceLocation End, llvm::StringRef ReplacementText,
+    const SourceManager &SM,
+    std::map<std::string, tooling::Replacements> *FileToReplacements) {
+  const auto R = createReplacement(Start, End, ReplacementText, SM);
+  auto Err = (*FileToReplacements)[R.getFilePath()].add(R);
+  if (Err)
+    llvm_unreachable(llvm::toString(std::move(Err)).c_str());
+}
+
 tooling::Replacement createInsertion(SourceLocation Loc,
                                      llvm::StringRef InsertText,
                                      const SourceManager &SM) {
@@ -574,11 +584,8 @@ void ChangeNamespaceTool::moveClassForwa
   if (AfterSemi.isValid())
     End = AfterSemi.getLocWithOffset(-1);
   // Delete the forward declaration from the code to be moved.
-  const auto Deletion =
-      createReplacement(Start, End, "", *Result.SourceManager);
-  auto Err = FileToReplacements[Deletion.getFilePath()].add(Deletion);
-  if (Err)
-    llvm_unreachable(llvm::toString(std::move(Err)).c_str());
+  addReplacementOrDie(Start, End, "", *Result.SourceManager,
+                      &FileToReplacements);
   llvm::StringRef Code = Lexer::getSourceText(
       CharSourceRange::getTokenRange(
           Result.SourceManager->getSpellingLoc(Start),
@@ -608,6 +615,18 @@ void ChangeNamespaceTool::replaceQualifi
     const DeclContext *DeclCtx, SourceLocation Start, SourceLocation End,
     const NamedDecl *FromDecl) {
   const auto *NsDeclContext = DeclCtx->getEnclosingNamespaceContext();
+  if (llvm::isa<TranslationUnitDecl>(NsDeclContext)) {
+    // This should not happen in usual unless the TypeLoc is in function type
+    // parameters, e.g `std::function<void(T)>`. In this case, DeclContext of
+    // `T` will be the translation unit. We simply use fully-qualified name
+    // here.
+    // Note that `FromDecl` must not be defined in the old namespace (according
+    // to `DeclMatcher`), so its fully-qualified name will not change after
+    // changing the namespace.
+    addReplacementOrDie(Start, End, FromDecl->getQualifiedNameAsString(),
+                        *Result.SourceManager, &FileToReplacements);
+    return;
+  }
   const auto *NsDecl = llvm::cast<NamespaceDecl>(NsDeclContext);
   // Calculate the name of the `NsDecl` after it is moved to new namespace.
   std::string OldNs = NsDecl->getQualifiedNameAsString();
@@ -667,10 +686,8 @@ void ChangeNamespaceTool::replaceQualifi
   // NewNamespace is the global namespace.
   if (ReplaceName == FromDeclName && !NewNamespace.empty())
     ReplaceName = "::" + ReplaceName;
-  auto R = createReplacement(Start, End, ReplaceName, *Result.SourceManager);
-  auto Err = FileToReplacements[R.getFilePath()].add(R);
-  if (Err)
-    llvm_unreachable(llvm::toString(std::move(Err)).c_str());
+  addReplacementOrDie(Start, End, ReplaceName, *Result.SourceManager,
+                      &FileToReplacements);
 }
 
 // Replace the [Start, End] of `Type` with the shortest qualified name when the
@@ -731,11 +748,8 @@ void ChangeNamespaceTool::fixUsingShadow
   // FIXME: check if target_decl_name is in moved ns, which doesn't make much
   // sense. If this happens, we need to use name with the new namespace.
   // Use fully qualified name in UsingDecl for now.
-  auto R = createReplacement(Start, End, "using ::" + TargetDeclName,
-                             *Result.SourceManager);
-  auto Err = FileToReplacements[R.getFilePath()].add(R);
-  if (Err)
-    llvm_unreachable(llvm::toString(std::move(Err)).c_str());
+  addReplacementOrDie(Start, End, "using ::" + TargetDeclName,
+                      *Result.SourceManager, &FileToReplacements);
 }
 
 void ChangeNamespaceTool::fixDeclRefExpr(

Modified: clang-tools-extra/trunk/test/change-namespace/lambda-function.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/change-namespace/lambda-function.cpp?rev=289672&r1=289671&r2=289672&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/change-namespace/lambda-function.cpp (original)
+++ clang-tools-extra/trunk/test/change-namespace/lambda-function.cpp Wed Dec 14 11:01:52 2016
@@ -10,12 +10,27 @@ public:
   R operator()(ArgTypes...) const {}
 };
 
+namespace x {
 // CHECK: namespace x {
-// CHECK-NEXT: namespace y {
+class X {};
+}
+
 namespace na {
 namespace nb {
+// CHECK: namespace x {
+// CHECK-NEXT: namespace y {
 void f(function<void(int)> func, int param) { func(param); }
 void g() { f([](int x) {}, 1); }
+
+// x::X in function type parameter list will have translation unit context, so
+// we simply replace it with fully-qualified name.
+using TX = function<x::X(x::X)>;
+// CHECK: using TX = function<X(x::X)>;
+
+class A {};
+using TA = function<A(A)>;
+// CHECK: using TA = function<A(A)>;
+
 // CHECK: } // namespace y
 // CHECK-NEXT: } // namespace x
 }




More information about the cfe-commits mailing list