diff options
author | Eric Liu <ioeric@google.com> | 2016-12-15 10:42:35 +0000 |
---|---|---|
committer | Eric Liu <ioeric@google.com> | 2016-12-15 10:42:35 +0000 |
commit | 7fde8055cc5d0525244aaa0f580bd7f9400b9fbb (patch) | |
tree | c94ccbe9b60652b151f6efcb4a49199cc0e9263b /clang-tools-extra/change-namespace | |
parent | 4bba002c52c4bc9338a4c98614657f835c2bdc10 (diff) |
[change-namespace] handling templated type aliases correctly.
Summary: This fixes templated type aliases and templated type aliases in classes.
Reviewers: hokein
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D27801
Diffstat (limited to 'clang-tools-extra/change-namespace')
-rw-r--r-- | clang-tools-extra/change-namespace/ChangeNamespace.cpp | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/clang-tools-extra/change-namespace/ChangeNamespace.cpp b/clang-tools-extra/change-namespace/ChangeNamespace.cpp index b3588aaf689..b620b42e21f 100644 --- a/clang-tools-extra/change-namespace/ChangeNamespace.cpp +++ b/clang-tools-extra/change-namespace/ChangeNamespace.cpp @@ -454,6 +454,17 @@ void ChangeNamespaceTool::run( BaseCtorInitializerTypeLocs.push_back( BaseInitializer->getTypeSourceInfo()->getTypeLoc()); } else if (const auto *TLoc = Result.Nodes.getNodeAs<TypeLoc>("type")) { + // This avoids fixing types with record types as qualifier, which is not + // filtered by matchers in some cases, e.g. the type is templated. We should + // handle the record type qualifier instead. + if (TLoc->getTypeLocClass() == TypeLoc::Elaborated) { + NestedNameSpecifierLoc NestedNameSpecifier = + TLoc->castAs<ElaboratedTypeLoc>().getQualifierLoc(); + const Type *SpecifierType = + NestedNameSpecifier.getNestedNameSpecifier()->getAsType(); + if (SpecifierType && SpecifierType->isRecordType()) + return; + } fixTypeLoc(Result, startLocationForType(*TLoc), endLocationForType(*TLoc), *TLoc); } else if (const auto *VarRef = @@ -705,27 +716,32 @@ void ChangeNamespaceTool::fixTypeLoc( const auto *FromDecl = Result.Nodes.getNodeAs<NamedDecl>("from_decl"); // `hasDeclaration` gives underlying declaration, but if the type is // a typedef type, we need to use the typedef type instead. + auto IsInMovedNs = [&](const NamedDecl *D) { + if (!llvm::StringRef(D->getQualifiedNameAsString()) + .startswith(OldNamespace + "::")) + return false; + auto ExpansionLoc = Result.SourceManager->getExpansionLoc(D->getLocStart()); + if (ExpansionLoc.isInvalid()) + return false; + llvm::StringRef Filename = Result.SourceManager->getFilename(ExpansionLoc); + return FilePatternRE.match(Filename); + }; + // Make `FromDecl` the immediate declaration that `Type` refers to, i.e. if + // `Type` is an alias type, we make `FromDecl` the type alias declaration. + // Also, don't fix the \p Type if it refers to a type alias decl in the moved + // namespace since the alias decl will be moved along with the type reference. if (auto *Typedef = Type.getType()->getAs<TypedefType>()) { FromDecl = Typedef->getDecl(); - auto IsInMovedNs = [&](const NamedDecl *D) { - if (!llvm::StringRef(D->getQualifiedNameAsString()) - .startswith(OldNamespace + "::")) - return false; - auto ExpansionLoc = - Result.SourceManager->getExpansionLoc(D->getLocStart()); - if (ExpansionLoc.isInvalid()) - return false; - llvm::StringRef Filename = - Result.SourceManager->getFilename(ExpansionLoc); - return FilePatternRE.match(Filename); - }; - // Don't fix the \p Type if it refers to a type alias decl in the moved - // namespace since the alias decl will be moved along with the type - // reference. if (IsInMovedNs(FromDecl)) return; + } else if (auto *TemplateType = + Type.getType()->getAs<TemplateSpecializationType>()) { + if (TemplateType->isTypeAlias()) { + FromDecl = TemplateType->getTemplateName().getAsTemplateDecl(); + if (IsInMovedNs(FromDecl)) + return; + } } - const auto *DeclCtx = Result.Nodes.getNodeAs<Decl>("dc"); assert(DeclCtx && "Empty decl context."); replaceQualifiedSymbolInDeclContext(Result, DeclCtx->getDeclContext(), Start, |