diff options
| author | Eric Liu <ioeric@google.com> | 2016-09-21 15:06:12 +0000 |
|---|---|---|
| committer | Eric Liu <ioeric@google.com> | 2016-09-21 15:06:12 +0000 |
| commit | 68765a848bc4457ab03d5aac6e1f67f3bc4f47a6 (patch) | |
| tree | a5bdf367cf06f7a88d70077040edff053b5c2b31 /clang-tools-extra/change-namespace/ChangeNamespace.cpp | |
| parent | 58db5bb20e7d1c545b3d8c90763e10794d3749ec (diff) | |
| download | bcm5719-llvm-68765a848bc4457ab03d5aac6e1f67f3bc4f47a6.tar.gz bcm5719-llvm-68765a848bc4457ab03d5aac6e1f67f3bc4f47a6.zip | |
[change-namespace] fix name qualifiers in UsingShadowDecl and NestedNameSpecifier.
Reviewers: hokein
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D24784
llvm-svn: 282073
Diffstat (limited to 'clang-tools-extra/change-namespace/ChangeNamespace.cpp')
| -rw-r--r-- | clang-tools-extra/change-namespace/ChangeNamespace.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/clang-tools-extra/change-namespace/ChangeNamespace.cpp b/clang-tools-extra/change-namespace/ChangeNamespace.cpp index 2f6f364b9e3..89ba0bbcf27 100644 --- a/clang-tools-extra/change-namespace/ChangeNamespace.cpp +++ b/clang-tools-extra/change-namespace/ChangeNamespace.cpp @@ -231,9 +231,6 @@ ChangeNamespaceTool::ChangeNamespaceTool( } // FIXME: handle the following symbols: -// - Types in `UsingShadowDecl` (e.g. `using a::b::c;`) which are not matched -// by `typeLoc`. -// - Types in nested name specifier, e.g. "na::X" in "na::X::Nested". // - Function references. // - Variable references. void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) { @@ -266,7 +263,6 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) { // Match TypeLocs on the declaration. Carefully match only the outermost // TypeLoc that's directly linked to the old class and don't handle nested // name specifier locs. - // FIXME: match and handle nested name specifier locs. Finder->addMatcher( typeLoc(IsInMovedNs, loc(qualType(hasDeclaration(DeclMatcher.bind("from_decl")))), @@ -276,6 +272,17 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) { hasAncestor(decl().bind("dc"))) .bind("type"), this); + // Types in `UsingShadowDecl` is not matched by `typeLoc` above, so we need to + // special case it. + Finder->addMatcher( + usingDecl(hasAnyUsingShadowDecl(IsInMovedNs)).bind("using_decl"), this); + // Handle types in nested name specifier. + Finder->addMatcher(nestedNameSpecifierLoc( + hasAncestor(decl(IsInMovedNs).bind("dc")), + loc(nestedNameSpecifier(specifiesType( + hasDeclaration(DeclMatcher.bind("from_decl")))))) + .bind("nested_specifier_loc"), + this); } void ChangeNamespaceTool::run( @@ -285,6 +292,15 @@ void ChangeNamespaceTool::run( } else if (const auto *FwdDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("fwd_decl")) { moveClassForwardDeclaration(Result, FwdDecl); + } else if (const auto *UsingDeclaration = + Result.Nodes.getNodeAs<UsingDecl>("using_decl")) { + fixUsingShadowDecl(Result, UsingDeclaration); + } else if (const auto *Specifier = + Result.Nodes.getNodeAs<NestedNameSpecifierLoc>( + "nested_specifier_loc")) { + SourceLocation Start = Specifier->getBeginLoc(); + SourceLocation End = EndLocationForType(Specifier->getTypeLoc()); + fixTypeLoc(Result, Start, End, Specifier->getTypeLoc()); } else { const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type"); assert(TLoc != nullptr && "Expecting callback for TypeLoc"); @@ -439,6 +455,26 @@ void ChangeNamespaceTool::fixTypeLoc( FromDecl->getQualifiedNameAsString()); } +void ChangeNamespaceTool::fixUsingShadowDecl( + const ast_matchers::MatchFinder::MatchResult &Result, + const UsingDecl *UsingDeclaration) { + SourceLocation Start = UsingDeclaration->getLocStart(); + SourceLocation End = UsingDeclaration->getLocEnd(); + if (Start.isInvalid() || End.isInvalid()) return; + + assert(UsingDeclaration->shadow_size() > 0); + // FIXME: it might not be always accurate to use the first using-decl. + const NamedDecl *TargetDecl = + UsingDeclaration->shadow_begin()->getTargetDecl(); + std::string TargetDeclName = TargetDecl->getQualifiedNameAsString(); + // 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); + addOrMergeReplacement(R, &FileToReplacements[R.getFilePath()]); +} + void ChangeNamespaceTool::onEndOfTranslationUnit() { // Move namespace blocks and insert forward declaration to old namespace. for (const auto &FileAndNsMoves : MoveNamespaces) { |

