diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -310,6 +310,14 @@ void printQualifiedName(raw_ostream &OS) const; void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; + /// Print only the nested name specifier part of a fully-qualified name, + /// including the '::' at the end. E.g. + /// when `printQualifiedName(D)` prints "A::B::i", + /// this function prints "A::B::". + void printNestedNameSpecifier(raw_ostream &OS) const; + void printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &Policy) const; + // FIXME: Remove string version. std::string getQualifiedNameAsString() const; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1558,6 +1558,19 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { + printNestedNameSpecifier(OS, P); + if (getDeclName() || isa(this)) + OS << *this; + else + OS << "(anonymous)"; +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const { + printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); // For ObjC methods and properties, look through categories and use the @@ -1571,10 +1584,8 @@ Ctx = ID; } - if (Ctx->isFunctionOrMethod()) { - printName(OS); + if (Ctx->isFunctionOrMethod()) return; - } using ContextsTy = SmallVector; ContextsTy Contexts; @@ -1644,11 +1655,6 @@ } OS << "::"; } - - if (getDeclName() || isa(this)) - OS << *this; - else - OS << "(anonymous)"; } void NamedDecl::getNameForDiagnostic(raw_ostream &OS,