[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