void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const NamedDecl *Parent, const DeclContext *DC) { if (!NNS) return; if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) indexNestedNameSpecifierLoc(Prefix, Parent, DC); if (!DC) DC = Parent->getLexicalDeclContext(); SourceLocation Loc = NNS.getSourceRange().getBegin(); switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: break; case NestedNameSpecifier::Namespace: handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), Loc, Parent, DC, SymbolRoleSet()); break; case NestedNameSpecifier::NamespaceAlias: handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Loc, Parent, DC, SymbolRoleSet()); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: indexTypeLoc(NNS.getTypeLoc(), Parent, DC); break; } }
bool RemoveNamespaceRewriteVisitor::VisitUsingDecl(UsingDecl *D) { if (ConsumerInstance->isForUsingNamedDecls) return true; if (ConsumerInstance->UselessUsingDecls.count(D)) { ConsumerInstance->RewriteHelper->removeDecl(D); return true; } // check if this UsingDecl refers to the namespaced being removed NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); TransAssert(QualifierLoc && "Bad QualifierLoc!"); NestedNameSpecifierLoc PrefixLoc = QualifierLoc.getPrefix(); const NestedNameSpecifier *NNS = D->getQualifier(); TransAssert(NNS && "Bad NameSpecifier!"); if (ConsumerInstance->isTheNamespaceSpecifier(NNS) && (!PrefixLoc || ConsumerInstance->isGlobalNamespace(PrefixLoc))) { ConsumerInstance->RewriteHelper->removeDecl(D); SkipTraverseNestedNameSpecifier = true; } return true; }
SourceLocation ReplaceDependentName::getElaboratedTypeLocBegin( const ElaboratedTypeLoc &TLoc) { SourceLocation Loc = TLoc.getElaboratedKeywordLoc(); if (Loc.isValid()) return Loc; NestedNameSpecifierLoc SpecLoc = TLoc.getQualifierLoc(); NestedNameSpecifierLoc Prefix = SpecLoc.getPrefix(); while (Prefix.getBeginLoc().isValid()) { SpecLoc = Prefix; Prefix = Prefix.getPrefix(); } Loc = SpecLoc.getBeginLoc(); TransAssert(Loc.isValid() && "Failed to get ElaboratedTypeLoc!"); return Loc; }
SourceRange NestedNameSpecifierLoc::getSourceRange() const { if (!Qualifier) return SourceRange(); NestedNameSpecifierLoc First = *this; while (NestedNameSpecifierLoc Prefix = First.getPrefix()) First = Prefix; return SourceRange(First.getLocalSourceRange().getBegin(), getLocalSourceRange().getEnd()); }
// fix the "B" part of names like A::B::C if B is our target void TypeRenameTransform::processQualifierLoc(NestedNameSpecifierLoc NNSL, bool forceRewriteMacro) { while (NNSL) { auto NNS = NNSL.getNestedNameSpecifier(); auto NNSK = NNS->getKind(); if (NNSK == NestedNameSpecifier::TypeSpec || NNSK == NestedNameSpecifier::TypeSpecWithTemplate) { processTypeLoc(NNSL.getTypeLoc(), forceRewriteMacro); } else if (NNSK == NestedNameSpecifier::Namespace) { std::string newName; if (nameMatches(NNS->getAsNamespace(), newName, true)) { renameLocation(NNSL.getLocalBeginLoc(), newName); } processTypeLoc(NNSL.getTypeLoc(), forceRewriteMacro); } else if (NNSK == NestedNameSpecifier::NamespaceAlias) { std::string newName; if (nameMatches(NNS->getAsNamespaceAlias(), newName, true)) { renameLocation(NNSL.getLocalBeginLoc(), newName); } processTypeLoc(NNSL.getTypeLoc(), forceRewriteMacro); } // else { // auto srcrange = NNSL.getSourceRange(); // llvm::errs() << indent() // << "==> ??? (" << ii << ") " // << " range=[" << range(srcrange) // << "\n"; // break; // } NNSL = NNSL.getPrefix(); } }
// It handles two cases: // * remove the specifier if it refers to TheNamespaceDecl // * replace the specifier with a new name if the corresponding namespace // has a name conflicts, e.g., // namespace NS1 { } // namespace NS2 { // namespace NS1 { // void foo() {} // } // namespace NS3 { // using NS1::foo; // void bar() { foo(); } // } // } // If we remove NS2, then the inner namespace NS1 conflicts with // the global NS1, but "using NS1::foo" refers to the conflicting NS1. bool RemoveNamespaceRewriteVisitor::TraverseNestedNameSpecifierLoc( NestedNameSpecifierLoc QualifierLoc) { SkipRewriteName = false; // Reset the flag if (SkipTraverseNestedNameSpecifier) { SkipTraverseNestedNameSpecifier = false; return true; } if (!QualifierLoc || QualifierLoc.getBeginLoc().isInvalid()) return true; SmallVector<NestedNameSpecifierLoc, 8> QualifierLocs; for (; QualifierLoc; QualifierLoc = QualifierLoc.getPrefix()) QualifierLocs.push_back(QualifierLoc); while (!QualifierLocs.empty()) { NestedNameSpecifierLoc Loc = QualifierLocs.pop_back_val(); NestedNameSpecifier *NNS = Loc.getNestedNameSpecifier(); NestedNameSpecifier::SpecifierKind Kind = NNS->getKind(); const NamespaceDecl *ND = NULL; switch (Kind) { case NestedNameSpecifier::Namespace: { ND = NNS->getAsNamespace()->getCanonicalDecl(); break; } case NestedNameSpecifier::NamespaceAlias: { const NamespaceAliasDecl *NAD = NNS->getAsNamespaceAlias(); if (!NAD->getQualifier()) ND = NAD->getNamespace()->getCanonicalDecl(); break; } case NestedNameSpecifier::TypeSpec: // Fall-through case NestedNameSpecifier::TypeSpecWithTemplate: TraverseTypeLoc(Loc.getTypeLoc()); break; default: break; } if (!ND) continue; if (ND == ConsumerInstance->TheNamespaceDecl) { ConsumerInstance->RewriteHelper->removeSpecifier(Loc); continue; } std::string SpecifierName; if (Loc.getBeginLoc().isInvalid()) continue; ConsumerInstance->RewriteHelper->getSpecifierAsString(Loc, SpecifierName); std::string NDName = ND->getNameAsString(); std::string Name = ""; ConsumerInstance->getNewName(ND, Name); // Skip it if this specifier is the same as ND's name. // Note that the above case could only happen for UsingNamedDecls if (ConsumerInstance->isForUsingNamedDecls && (SpecifierName == NDName)) { // It could happen for example: // namespace NS1 { } // namespace NS2 { // using namespace NS1; // void bar() { NS1::foo(); } // } // If we remove NS2, then the guard below avoids renaming // NS1::foo to NS1::foo::foo. if (Name.empty()) { SkipRewriteName = true; return true; } // another case to handle: // namespace NS1 { // namespace NS2 { // void foo() {} // } // } // namespace NS3 { // using namespace NS1; // void bar() { NS2::foo(); } // } // If we remove NS3, we do need to rename NS2::foo as NS1::NS2::foo if (!ConsumerInstance->isSuffix(Name, SpecifierName)) { SkipRewriteName = true; return true; } } if (!Name.empty()) { ConsumerInstance->RewriteHelper->replaceSpecifier(Loc, Name); SkipRewriteName = true; return true; } } return true; }