https://github.com/TPPPP72 created 
https://github.com/llvm/llvm-project/pull/218264

Fixed a FIXME in `Decl.h` and removed the existing heap allocation API.

This is the first time making such extensive changes, so it might take some 
time to adjust.

Assisted by Claude.

>From 5778afe6c44e53f707ff96adc3e1f36231beafa4 Mon Sep 17 00:00:00 2001
From: Shengxin Pei <[email protected]>
Date: Mon, 24 Aug 2026 01:16:02 +0800
Subject: [PATCH] [clang][AST][NFC] Tree-wide removal of deprecated
 getQualifiedNameAsString()

---
 .../CapturingThisInMemberVariableCheck.cpp    |  4 +-
 .../bugprone/DanglingHandleCheck.cpp          |  2 +-
 .../DerivedMethodShadowingBaseMethodCheck.cpp |  2 +-
 .../bugprone/StandaloneEmptyCheck.cpp         |  4 +-
 .../bugprone/VirtualNearMissCheck.cpp         |  3 +-
 .../fuchsia/TemporaryObjectsCheck.cpp         |  8 +-
 .../clang-tidy/modernize/AvoidBindCheck.cpp   |  7 +-
 .../clang-tidy/modernize/LoopConvertCheck.cpp | 18 +++--
 .../MinMaxUseInitializerListCheck.cpp         | 13 +++-
 .../clang-tidy/modernize/UseAutoCheck.cpp     | 16 ++--
 .../clang-tidy/modernize/UseEmplaceCheck.cpp  | 17 +++--
 .../readability/EnumInitialValueCheck.cpp     |  5 +-
 .../readability/NamedParameterCheck.cpp       | 21 +++--
 clang-tools-extra/clang-tidy/utils/Matchers.h | 21 ++++-
 clang-tools-extra/clangd/refactor/Rename.cpp  | 11 ++-
 .../clangd/refactor/tweaks/DefineOutline.cpp  | 22 ++++--
 .../include-cleaner/lib/Types.cpp             | 15 ++--
 clang/include/clang/AST/Decl.h                |  3 -
 clang/include/clang/AST/StmtDataCollectors.td | 22 ++++--
 clang/include/clang/ASTMatchers/ASTMatchers.h |  8 +-
 .../Analysis/Analyses/ThreadSafetyTraverse.h  |  4 +-
 .../StaticAnalyzer/Checkers/SValExplainer.h   | 76 +++++++++++--------
 clang/lib/AST/ASTDiagnostic.cpp               | 24 ++++--
 clang/lib/AST/ByteCode/Function.h             |  6 +-
 clang/lib/AST/Decl.cpp                        | 28 ++++---
 clang/lib/AST/DeclPrinter.cpp                 |  4 +-
 clang/lib/AST/VTableBuilder.cpp               | 17 ++++-
 clang/lib/Analysis/AnalysisDeclContext.cpp    |  4 +-
 clang/lib/Analysis/CFG.cpp                    |  4 +-
 clang/lib/Analysis/IssueHash.cpp              | 38 ++++++----
 clang/lib/Analysis/LifetimeSafety/Facts.cpp   |  7 +-
 .../LifetimeSafety/LifetimeSafety.cpp         | 27 ++++---
 clang/lib/Analysis/ProgramPoint.cpp           | 17 +++--
 clang/lib/CodeGen/CGClass.cpp                 | 25 ++++--
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 14 ++--
 clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp |  9 ++-
 clang/lib/Frontend/ASTConsumers.cpp           |  8 +-
 .../Interpreter/InterpreterValuePrinter.cpp   |  9 +--
 clang/lib/Parse/ParseDeclCXX.cpp              | 22 +++---
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 13 +---
 clang/lib/Sema/SemaAccess.cpp                 |  3 +-
 clang/lib/Sema/SemaBoundsSafety.cpp           | 14 ++--
 clang/lib/Sema/SemaChecking.cpp               | 14 +++-
 clang/lib/Sema/SemaExpr.cpp                   |  3 +-
 clang/lib/Sema/SemaOverload.cpp               | 13 +++-
 clang/lib/Sema/SemaTemplate.cpp               | 10 ++-
 .../Checkers/AnalysisOrderChecker.cpp         | 22 ++++--
 .../StaticAnalyzer/Checkers/MallocChecker.cpp | 15 ++--
 .../StaticAnalyzer/Checkers/MoveChecker.cpp   | 24 +++---
 .../Checkers/NoOwnershipChangeVisitor.cpp     |  8 +-
 .../RetainCountDiagnostics.cpp                |  8 +-
 clang/lib/StaticAnalyzer/Core/MemRegion.cpp   | 12 +--
 clang/lib/StaticAnalyzer/Core/SVals.cpp       |  2 +-
 .../Frontend/AnalysisConsumer.cpp             | 13 +++-
 clang/lib/Tooling/ASTDiff/ASTDiff.cpp         | 55 +++++++++-----
 clang/lib/Tooling/Refactoring/Lookup.cpp      | 23 ++++--
 .../Tooling/Refactoring/Rename/USRFinder.cpp  | 17 ++++-
 .../Clang/CxxModuleHandler.cpp                | 14 +++-
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  7 +-
 .../NativePDB/PdbAstBuilderClang.cpp          | 24 ++++--
 60 files changed, 571 insertions(+), 308 deletions(-)

diff --git 
a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp
index a78af8aa2fea3..9b8ff04707b12 100644
--- 
a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp
+++ 
b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp
@@ -133,7 +133,7 @@ void CapturingThisInMemberVariableCheck::check(
          "'this' captured by a '%0' call and stored in a class member "
          "variable; disable implicit class copying/moving to prevent potential 
"
          "use-after-free")
-        << Callee->getQualifiedNameAsString();
+        << Callee;
   }
 
   const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field");
@@ -142,7 +142,7 @@ void CapturingThisInMemberVariableCheck::check(
   diag(Field->getLocation(),
        "class member of type '%0' that stores captured 'this'",
        DiagnosticIDs::Note)
-      << Field->getType().getAsString();
+      << Field->getType();
 }
 
 } // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
index c95ad2beed3a9..00d16a4b025e1 100644
--- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
@@ -172,7 +172,7 @@ void DanglingHandleCheck::check(const 
MatchFinder::MatchResult &Result) {
   auto *Handle = Result.Nodes.getNodeAs<CXXRecordDecl>("handle");
   diag(Result.Nodes.getNodeAs<Stmt>("bad_stmt")->getBeginLoc(),
        "%0 outlives its value")
-      << Handle->getQualifiedNameAsString();
+      << Handle;
 }
 
 } // namespace clang::tidy::bugprone
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp
 
b/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp
index 904685cb8416d..bb861bb810f81 100644
--- 
a/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp
+++ 
b/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp
@@ -121,7 +121,7 @@ void DerivedMethodShadowingBaseMethodCheck::check(
 
   diag(ShadowingMethod->getBeginLoc(),
        "'%0' shadows method with the same name in class %1")
-      << ShadowingMethod->getQualifiedNameAsString() << 
BaseMethod->getParent();
+      << ShadowingMethod << BaseMethod->getParent();
   diag(BaseMethod->getBeginLoc(), "previous definition of %0 is here",
        DiagnosticIDs::Note)
       << ShadowingMethod;
diff --git a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp
index 1d72f3e9f387b..4fcb8b84c7444 100644
--- a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp
@@ -200,15 +200,13 @@ void StandaloneEmptyCheck::check(const 
MatchFinder::MatchResult &Result) {
         diag(NonMemberLoc,
              "ignoring the result of '%0'; did you mean 'clear()'?")
             << dyn_cast<NamedDecl>(NonMemberCall->getCalleeDecl())
-                   ->getQualifiedNameAsString()
             << FixItHint::CreateReplacement(ReplacementRange, ReplacementText);
         return;
       }
     }
 
     diag(NonMemberLoc, "ignoring the result of '%0'")
-        << dyn_cast<NamedDecl>(NonMemberCall->getCalleeDecl())
-               ->getQualifiedNameAsString();
+        << dyn_cast<NamedDecl>(NonMemberCall->getCalleeDecl());
   }
 }
 
diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
index 07dc77b5dee0a..fa9d213f546ef 100644
--- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -253,8 +253,7 @@ void VirtualNearMissCheck::check(const 
MatchFinder::MatchResult &Result) {
               diag(DerivedMD->getBeginLoc(),
                    "method '%0' has a similar name and the same signature as "
                    "virtual method '%1'; did you mean to override it?")
-              << DerivedMD->getQualifiedNameAsString()
-              << BaseMD->getQualifiedNameAsString();
+              << DerivedMD << BaseMD;
           if (ApplyFix)
             Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
         }
diff --git a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp 
b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp
index a29eda7289aa2..b0d9e4626e728 100644
--- a/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/fuchsia/TemporaryObjectsCheck.cpp
@@ -20,8 +20,12 @@ namespace clang::tidy::fuchsia {
 namespace {
 
 AST_MATCHER_P(CXXRecordDecl, matchesAnyName, ArrayRef<StringRef>, Names) {
-  const std::string QualifiedName = Node.getQualifiedNameAsString();
-  return llvm::is_contained(Names, QualifiedName);
+  SmallString<128> QualifiedName;
+  {
+    llvm::raw_svector_ostream OS(QualifiedName);
+    Node.printQualifiedName(OS);
+  }
+  return llvm::is_contained(Names, QualifiedName.str());
 }
 
 } // namespace
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
index 3cf0173aaa002..f3c309a1c5a00 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
@@ -147,7 +147,12 @@ static bool isCallExprNamed(const Expr *E, StringRef Name) 
{
   const auto *ND = dyn_cast<NamedDecl>(CE->getCalleeDecl());
   if (!ND)
     return false;
-  return ND->getQualifiedNameAsString() == Name;
+  SmallString<128> QName;
+  {
+    llvm::raw_svector_ostream OS(QName);
+    ND->printQualifiedName(OS);
+  }
+  return QName.str() == Name;
 }
 
 static void
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 75bf2a7325900..a25ab6b7f19a1 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -382,21 +382,25 @@ static std::optional<ContainerCall> 
getContainerExpr(const Expr *Call) {
     if (TheCall->getNumArgs() != 1)
       return std::nullopt;
 
+    const FunctionDecl *Callee = TheCall->getDirectCallee();
+    if (!Callee)
+      return std::nullopt;
+
     if (TheCall->usesADL()) {
-      if (TheCall->getDirectCallee() == nullptr ||
-          !ADLNames.contains(TheCall->getDirectCallee()->getName()))
+      if (!ADLNames.contains(Callee->getName()))
         return std::nullopt;
       CallKind = IteratorCallKind::ICK_ADL;
     } else {
-      if (!StdNames.contains(
-              TheCall->getDirectCallee()->getQualifiedNameAsString()))
+      SmallString<128> QName;
+      {
+        llvm::raw_svector_ostream OS(QName);
+        Callee->printQualifiedName(OS);
+      }
+      if (!StdNames.contains(QName.str()))
         return std::nullopt;
       CallKind = IteratorCallKind::ICK_Std;
     }
 
-    if (TheCall->getDirectCallee() == nullptr)
-      return std::nullopt;
-
     return ContainerCall{TheCall->getArg(0),
                          TheCall->getDirectCallee()->getName(), false,
                          CallKind};
diff --git 
a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
index 55f0886d12dee..a3b2e7c473ad2 100644
--- a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
@@ -133,9 +133,16 @@ generateReplacements(const MatchFinder::MatchResult &Match,
       continue;
     }
 
-    // if the nested call is not the same as the top call
-    if (InnerCall->getDirectCallee()->getQualifiedNameAsString() !=
-        TopCall->getDirectCallee()->getQualifiedNameAsString())
+    SmallString<128> InnerName, TopName;
+    {
+      llvm::raw_svector_ostream InnerOS(InnerName);
+      InnerCall->getDirectCallee()->printQualifiedName(InnerOS);
+
+      llvm::raw_svector_ostream TopOS(TopName);
+      TopCall->getDirectCallee()->printQualifiedName(TopOS);
+    }
+
+    if (InnerName.str() != TopName.str())
       continue;
 
     const FindArgsResult InnerResult = findArgs(InnerCall);
diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
index 6c873e3f80004..8d211b39b52f6 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp
@@ -432,11 +432,17 @@ void UseAutoCheck::replaceExpr(
   const StringRef Auto = ShouldReplenishVariableName
                              ? (RemoveStars ? "auto " : "auto *")
                              : (RemoveStars ? "auto " : "auto");
-  const std::string ReplenishedVariableName =
-      ShouldReplenishVariableName ? FirstDecl->getQualifiedNameAsString() : "";
-  const std::string Replacement =
-      (Auto + StringRef{ReplenishedVariableName}).str();
-  Diag << FixItHint::CreateReplacement(Range, Replacement) << StarRemovals;
+
+  SmallString<128> Replacement;
+  {
+    llvm::raw_svector_ostream OS(Replacement);
+    OS << Auto;
+    if (ShouldReplenishVariableName)
+      FirstDecl->printQualifiedName(OS);
+  }
+
+  Diag << FixItHint::CreateReplacement(Range, Replacement.str())
+       << StarRemovals;
 }
 
 void UseAutoCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
index 8ec123fc476ff..bb685b6569498 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -23,20 +23,25 @@ AST_MATCHER_P(InitListExpr, initCountLeq, unsigned, N) {
 // containers.
 AST_MATCHER_P(NamedDecl, hasAnyNameIgnoringTemplates, std::vector<StringRef>,
               Names) {
-  const std::string FullName = "::" + Node.getQualifiedNameAsString();
+  SmallString<128> FullName;
+  {
+    llvm::raw_svector_ostream OS(FullName);
+    OS << "::";
+    Node.printQualifiedName(OS);
+  }
 
   // This loop removes template specifiers by only keeping characters not 
within
   // template brackets. We keep a depth count to handle nested templates. For
   // example, it'll transform a::b<c<d>>::e<f> to simply a::b::e.
-  std::string FullNameTrimmed;
+  SmallString<128> FullNameTrimmed;
   int Depth = 0;
-  for (const auto &Character : FullName)
-    if (Character == '<')
+  for (char C : FullName)
+    if (C == '<')
       ++Depth;
-    else if (Character == '>')
+    else if (C == '>')
       --Depth;
     else if (Depth == 0)
-      FullNameTrimmed.append(1, Character);
+      FullNameTrimmed.push_back(C);
 
   // This loop is taken from HasNameMatcher::matchesNodeFullSlow in
   // clang/lib/ASTMatchers/ASTMatchersInternal.cpp and checks whether
diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
index 620c5bece4eba..2b97c813c72b9 100644
--- a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
@@ -153,7 +153,10 @@ static std::string getName(const EnumDecl *Decl) {
   if (!Decl->getDeclName())
     return "<unnamed>";
 
-  return Decl->getQualifiedNameAsString();
+  SmallString<128> Name;
+  llvm::raw_svector_ostream OS(Name);
+  Decl->printQualifiedName(OS);
+  return std::string(Name.str());
 }
 
 EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
diff --git a/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp
index 07d1bbeccbc16..0195e174003ef 100644
--- a/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp
@@ -100,10 +100,15 @@ void NamedParameterCheck::check(const 
MatchFinder::MatchResult &Result) {
       continue;
 
     // Skip gmock testing::Unused parameters.
-    if (const auto *Typedef = Parm->getType()->getAs<TypedefType>();
-        Typedef &&
-        Typedef->getDecl()->getQualifiedNameAsString() == "testing::Unused")
-      continue;
+    if (const auto *Typedef = Parm->getType()->getAs<TypedefType>()) {
+      SmallString<64> TypedefQName;
+      {
+        llvm::raw_svector_ostream OS(TypedefQName);
+        Typedef->getDecl()->printQualifiedName(OS);
+      }
+      if (TypedefQName.str() == "testing::Unused")
+        continue;
+    }
 
     // Skip std::nullptr_t.
     if (Parm->getType().getCanonicalType()->isNullPtrType())
@@ -113,8 +118,12 @@ void NamedParameterCheck::check(const 
MatchFinder::MatchResult &Result) {
     // tag dispatch types).
     if (const auto *Record =
             Parm->getType().getCanonicalType()->getAsCXXRecordDecl()) {
-      const std::string QName = Record->getQualifiedNameAsString();
-      if (llvm::is_contained(IgnoredTypes, QName))
+      SmallString<128> QName;
+      {
+        llvm::raw_svector_ostream OS(QName);
+        Record->printQualifiedName(OS);
+      }
+      if (llvm::is_contained(IgnoredTypes, QName.str()))
         continue;
     }
 
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h 
b/clang-tools-extra/clang-tidy/utils/Matchers.h
index e04da47322623..2e37d03cb31f4 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.h
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -107,10 +107,23 @@ class MatchesAnyListedRegexNameMatcher
 
     bool match(const NamedDecl &ND) const {
       switch (Mode) {
-      case MatchMode::MatchQualified:
-        return Regex.match(ND.getQualifiedNameAsString());
-      case MatchMode::MatchFullyQualified:
-        return Regex.match("::" + ND.getQualifiedNameAsString());
+      case MatchMode::MatchQualified: {
+        SmallString<128> QName;
+        {
+          llvm::raw_svector_ostream OS(QName);
+          ND.printQualifiedName(OS);
+        }
+        return Regex.match(QName.str());
+      }
+      case MatchMode::MatchFullyQualified: {
+        SmallString<128> QName;
+        {
+          llvm::raw_svector_ostream OS(QName);
+          OS << "::";
+          ND.printQualifiedName(OS);
+        }
+        return Regex.match(QName.str());
+      }
       default:
         if (const IdentifierInfo *II = ND.getIdentifier())
           return Regex.match(II->getName());
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp 
b/clang-tools-extra/clangd/refactor/Rename.cpp
index c56375b1a98d3..cccdc73b055ae 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -898,9 +898,14 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl,
   if (AffectedFiles.size() >= MaxLimitFiles)
     return error("The number of affected files exceeds the max limit {0}",
                  MaxLimitFiles);
-  if (HasMore)
-    return error("The symbol {0} has too many occurrences",
-                 RenameDecl.getQualifiedNameAsString());
+  if (HasMore) {
+    SmallString<128> QName;
+    {
+      llvm::raw_svector_ostream OS(QName);
+      RenameDecl.printQualifiedName(OS);
+    }
+    return error("The symbol {0} has too many occurrences", QName.str());
+  }
   // Sort and deduplicate the results, in case that index returns duplications.
   for (auto &FileAndOccurrences : AffectedFiles) {
     auto &Ranges = FileAndOccurrences.getValue();
diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
index dcc417b5f7d8c..613e0d2cb039c 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
@@ -84,13 +84,14 @@ findContextForNS(llvm::StringRef TargetNS, const 
DeclContext *CurContext) {
   }
   // Otherwise we need to drop any trailing namespaces from CurContext until
   // we reach TargetNS.
-  std::string TargetContextNS =
-      CurContext->isNamespace()
-          ? llvm::cast<NamespaceDecl>(CurContext)->getQualifiedNameAsString()
-          : "";
-  TargetContextNS.append("::");
+  SmallString<128> TargetContextNSBuf;
+  if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(CurContext)) {
+    llvm::raw_svector_ostream OS(TargetContextNSBuf);
+    NS->printQualifiedName(OS);
+  }
+  TargetContextNSBuf.append("::");
 
-  llvm::StringRef CurrentContextNS(TargetContextNS);
+  llvm::StringRef CurrentContextNS(TargetContextNSBuf.str());
   // If TargetNS is not a prefix of CurrentContext, there's no way to reach
   // it.
   if (!CurrentContextNS.starts_with(TargetNS))
@@ -600,8 +601,13 @@ class DefineOutline : public Tweak {
       Offset = P->Offset;
       EnclosingNamespace = P->EnclosingNamespace;
     } else {
-      auto Region = getEligiblePoints(
-          Contents, Source->getQualifiedNameAsString(), 
Sel.AST->getLangOpts());
+      SmallString<128> SourceQName;
+      {
+        llvm::raw_svector_ostream OS(SourceQName);
+        Source->printQualifiedName(OS);
+      }
+      auto Region = getEligiblePoints(Contents, SourceQName.str(),
+                                      Sel.AST->getLangOpts());
       assert(!Region.EligiblePoints.empty());
       EnclosingNamespaceName = Region.EnclosingNamespace;
       InsertionPos = Region.EligiblePoints.back();
diff --git a/clang-tools-extra/include-cleaner/lib/Types.cpp 
b/clang-tools-extra/include-cleaner/lib/Types.cpp
index d7635c258e522..715d9d2a631b0 100644
--- a/clang-tools-extra/include-cleaner/lib/Types.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Types.cpp
@@ -25,9 +25,12 @@ std::string Symbol::name() const {
   switch (kind()) {
   case include_cleaner::Symbol::Macro:
     return macro().Name->getName().str();
-  case include_cleaner::Symbol::Declaration:
-    return llvm::dyn_cast<NamedDecl>(&declaration())
-        ->getQualifiedNameAsString();
+  case include_cleaner::Symbol::Declaration: {
+    SmallString<128> Name;
+    llvm::raw_svector_ostream OS(Name);
+    llvm::cast<NamedDecl>(&declaration())->printQualifiedName(OS);
+    return std::string(Name.str());
+  }
   }
   llvm_unreachable("Unknown symbol kind");
 }
@@ -35,8 +38,10 @@ std::string Symbol::name() const {
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
   switch (S.kind()) {
   case Symbol::Declaration:
-    if (const auto *ND = llvm::dyn_cast<NamedDecl>(&S.declaration()))
-      return OS << ND->getQualifiedNameAsString();
+    if (const auto *ND = llvm::dyn_cast<NamedDecl>(&S.declaration())) {
+      ND->printQualifiedName(OS);
+      return OS;
+    }
     return OS << S.declaration().getDeclKindName();
   case Symbol::Macro:
     return OS << S.macro().Name->getName();
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 92050d635e2e0..bfdafb32a9306 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -361,9 +361,6 @@ class NamedDecl : public Decl {
   void printNestedNameSpecifier(raw_ostream &OS,
                                 const PrintingPolicy &Policy) const;
 
-  // FIXME: Remove string version.
-  std::string getQualifiedNameAsString() const;
-
   /// Appends a human-readable name for this declaration into the given stream.
   ///
   /// This is the method invoked by Sema when displaying a NamedDecl
diff --git a/clang/include/clang/AST/StmtDataCollectors.td 
b/clang/include/clang/AST/StmtDataCollectors.td
index abf4b5f34d349..ce6e20b0629c7 100644
--- a/clang/include/clang/AST/StmtDataCollectors.td
+++ b/clang/include/clang/AST/StmtDataCollectors.td
@@ -46,19 +46,22 @@ class CallExpr {
       // If the function is a template specialization, we also need to handle
       // the template arguments as they are not included in the qualified name.
       if (auto Args = D->getTemplateSpecializationArgs()) {
-        std::string ArgString;
-
-        // Print all template arguments into ArgString
-        llvm::raw_string_ostream OS(ArgString);
+        SmallString<256> ArgString;
+        llvm::raw_svector_ostream OS(ArgString);
         for (unsigned i = 0; i < Args->size(); ++i) {
           Args->get(i).print(Context.getLangOpts(), OS, /*IncludeType*/ true);
           // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
           OS << '\n';
         }
 
-        addData(ArgString);
+        addData(ArgString.str());
+      }
+      SmallString<128> QualName;
+      {
+        llvm::raw_svector_ostream OS(QualName);
+        D->printQualifiedName(OS);
       }
-      addData(D->getQualifiedNameAsString());
+      addData(QualName.str());
     }
   }];
 }
@@ -66,7 +69,12 @@ class CallExpr {
 //--- Value references ---------------------------------------------------//
 class DeclRefExpr {
   code Code = [{
-    addData(S->getDecl()->getQualifiedNameAsString());
+    SmallString<128> QualName;
+    {
+      llvm::raw_svector_ostream OS(QualName);
+      S->getDecl()->printQualifiedName(OS);
+    }
+    addData(QualName.str());
   }];
 }
 class MemberExpr {
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h 
b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 43cbeb3b40eac..39140dd657bb4 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -58,7 +58,6 @@
 #include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/LambdaCapture.h"
-#include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/ParentMapContext.h"
@@ -76,7 +75,6 @@
 #include "clang/Basic/AttrKinds.h"
 #include "clang/Basic/BuiltinTraits.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
-#include "clang/Basic/FileManager.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceManager.h"
@@ -86,7 +84,6 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Regex.h"
 #include <cassert>
@@ -3247,7 +3244,10 @@ extern const 
internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
 ///   namespace foo { namespace bar { class X; } }
 /// \endcode
 AST_MATCHER_REGEX(NamedDecl, matchesName, RegExp) {
-  std::string FullNameString = "::" + Node.getQualifiedNameAsString();
+  SmallString<128> FullNameString;
+  llvm::raw_svector_ostream OS(FullNameString);
+  OS << "::";
+  Node.printQualifiedName(OS);
   return RegExp->match(FullNameString);
 }
 
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h 
b/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 3c14716ff7156..160f906ab024e 100644
--- a/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -22,9 +22,7 @@
 #include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
 #include <cstdint>
-#include <ostream>
 
 namespace clang {
 namespace threadSafety {
@@ -659,7 +657,7 @@ class PrettyPrinter {
       if (isa<Wildcard>(E->record())) {
         // handle existentials
         SS << "&";
-        SS << E->clangDecl()->getQualifiedNameAsString();
+        E->clangDecl()->printQualifiedName(SS);
         return;
       }
     }
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 6c1025ecc7f4d..a8223276cb3e2 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -114,9 +114,15 @@ class SValExplainer : public 
FullSValVisitor<SValExplainer, std::string> {
   std::string VisitSymbolRegionValue(const SymbolRegionValue *S) {
     const MemRegion *R = S->getRegion();
     // Special handling for argument values.
-    if (auto V = dyn_cast<VarRegion>(R))
-      if (auto D = dyn_cast<ParmVarDecl>(V->getDecl()))
-        return "argument '" + D->getQualifiedNameAsString() + "'";
+    if (const auto *V = dyn_cast<VarRegion>(R)) {
+      if (const auto *D = dyn_cast<ParmVarDecl>(V->getDecl())) {
+        SmallString<128> QualName;
+        llvm::raw_svector_ostream OS(QualName);
+        D->printQualifiedName(OS);
+        return "argument '" + std::string(QualName.str()) + "'";
+      }
+    }
+
     return "initial value of " + Visit(R);
   }
 
@@ -216,19 +222,20 @@ class SValExplainer : public 
FullSValVisitor<SValExplainer, std::string> {
 
   std::string VisitNonParamVarRegion(const NonParamVarRegion *R) {
     const VarDecl *VD = R->getDecl();
-    std::string Name = VD->getQualifiedNameAsString();
+    SmallString<128> QualName;
+    llvm::raw_svector_ostream OS(QualName);
+    VD->printQualifiedName(OS);
     if (isa<ParmVarDecl>(VD))
-      return "parameter '" + Name + "'";
-    else if (VD->hasAttr<BlocksAttr>())
-      return "block variable '" + Name + "'";
-    else if (VD->hasLocalStorage())
-      return "local variable '" + Name + "'";
-    else if (VD->isStaticLocal())
-      return "static local variable '" + Name + "'";
-    else if (VD->hasGlobalStorage())
-      return "global variable '" + Name + "'";
-    else
-      llvm_unreachable("A variable is either local or global");
+      return "parameter '" + std::string(QualName.str()) + "'";
+    if (VD->hasAttr<BlocksAttr>())
+      return "block variable '" + std::string(QualName.str()) + "'";
+    if (VD->hasLocalStorage())
+      return "local variable '" + std::string(QualName.str()) + "'";
+    if (VD->isStaticLocal())
+      return "static local variable '" + std::string(QualName.str()) + "'";
+    if (VD->hasGlobalStorage())
+      return "global variable '" + std::string(QualName.str()) + "'";
+    llvm_unreachable("A variable is either local or global");
   }
 
   std::string VisitObjCIvarRegion(const ObjCIvarRegion *R) {
@@ -247,8 +254,11 @@ class SValExplainer : public 
FullSValVisitor<SValExplainer, std::string> {
   }
 
   std::string VisitCXXBaseObjectRegion(const CXXBaseObjectRegion *R) {
-    return "base object '" + R->getDecl()->getQualifiedNameAsString() +
-           "' inside " + Visit(R->getSuperRegion());
+    SmallString<128> QualName;
+    llvm::raw_svector_ostream OS(QualName);
+    R->getDecl()->printQualifiedName(OS);
+    return "base object '" + std::string(QualName) + "' inside " +
+           Visit(R->getSuperRegion());
   }
 
   std::string VisitParamVarRegion(const ParamVarRegion *R) {
@@ -256,24 +266,30 @@ class SValExplainer : public 
FullSValVisitor<SValExplainer, std::string> {
     llvm::raw_string_ostream OS(Str);
 
     const ParmVarDecl *PVD = R->getDecl();
-    std::string Name = PVD->getQualifiedNameAsString();
-    if (!Name.empty()) {
-      OS << "parameter '" << Name << "'";
-      return std::string(OS.str());
+    if (!PVD->getDeclName().isEmpty()) {
+      SmallString<64> Str;
+      llvm::raw_svector_ostream OS(Str);
+      OS << "parameter '";
+      PVD->printQualifiedName(OS);
+      OS << "'";
+      return std::string(Str);
     }
 
     unsigned Index = R->getIndex() + 1;
     OS << Index << llvm::getOrdinalSuffix(Index) << " parameter of ";
     const Decl *Parent = R->getStackFrame()->getDecl();
-    if (const auto *FD = dyn_cast<FunctionDecl>(Parent))
-      OS << "function '" << FD->getQualifiedNameAsString() << "()'";
-    else if (const auto *CD = dyn_cast<CXXConstructorDecl>(Parent))
-      OS << "C++ constructor '" << CD->getQualifiedNameAsString() << "()'";
-    else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Parent)) {
-      if (MD->isClassMethod())
-        OS << "Objective-C method '+" << MD->getQualifiedNameAsString() << "'";
-      else
-        OS << "Objective-C method '-" << MD->getQualifiedNameAsString() << "'";
+    if (const auto *FD = dyn_cast<FunctionDecl>(Parent)) {
+      OS << "function '";
+      FD->printQualifiedName(OS);
+      OS << "()'";
+    } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(Parent)) {
+      OS << "C++ constructor '";
+      CD->printQualifiedName(OS);
+      OS << "()'";
+    } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Parent)) {
+      OS << "Objective-C method '" << (MD->isClassMethod() ? '+' : '-');
+      MD->printQualifiedName(OS);
+      OS << "'";
     } else if (isa<BlockDecl>(Parent)) {
       if (cast<BlockDecl>(Parent)->isConversionFromLambda())
         OS << "lambda";
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 0925fbdcbaeb7..66228956e92ff 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1805,12 +1805,26 @@ class TemplateDiff {
                              bool FromDefault, bool ToDefault, bool Same) {
     assert((FromTD || ToTD) && "Only one template argument may be missing.");
 
-    std::string FromName =
-        std::string(FromTD ? FromTD->getName() : "(no argument)");
-    std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
+    SmallString<128> FromNameBuffer, ToNameBuffer;
+    StringRef FromName = "(no argument)";
+    StringRef ToName = "(no argument)";
+
+    if (FromTD)
+      FromName = FromTD->getName();
+    if (ToTD)
+      ToName = ToTD->getName();
+
     if (FromTD && ToTD && FromName == ToName) {
-      FromName = FromTD->getQualifiedNameAsString();
-      ToName = ToTD->getQualifiedNameAsString();
+      {
+        llvm::raw_svector_ostream OS(FromNameBuffer);
+        FromTD->printQualifiedName(OS);
+      }
+      {
+        llvm::raw_svector_ostream OS(ToNameBuffer);
+        ToTD->printQualifiedName(OS);
+      }
+      FromName = FromNameBuffer;
+      ToName = ToNameBuffer;
     }
 
     if (Same) {
diff --git a/clang/lib/AST/ByteCode/Function.h 
b/clang/lib/AST/ByteCode/Function.h
index 9742a16b50f2c..1b0739fdd7a39 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -144,7 +144,11 @@ class Function final {
     if (!Source || !getDecl())
       return "<<expr>>";
 
-    return getDecl()->getQualifiedNameAsString();
+    SmallString<128> Buffer;
+    llvm::raw_svector_ostream OS(Buffer);
+    getDecl()->printQualifiedName(OS);
+
+    return std::string(Buffer.str());
   }
 
   /// Returns a parameter descriptor.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 0894097333d73..814fe8731f5ec 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1681,13 +1681,6 @@ void NamedDecl::printName(raw_ostream &OS) const {
   printName(OS, getASTContext().getPrintingPolicy());
 }
 
-std::string NamedDecl::getQualifiedNameAsString() const {
-  std::string QualName;
-  llvm::raw_string_ostream OS(QualName);
-  printQualifiedName(OS, getASTContext().getPrintingPolicy());
-  return QualName;
-}
-
 void NamedDecl::printQualifiedName(raw_ostream &OS) const {
   printQualifiedName(OS, getASTContext().getPrintingPolicy());
 }
@@ -5446,21 +5439,32 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) 
const {
   else if (NoSanitizeList.containsLocation(EnabledAsanMask, getLocation(),
                                            "field-padding"))
     ReasonToReject = 6;  // is in an excluded file.
-  else if (NoSanitizeList.containsType(
-               EnabledAsanMask, getQualifiedNameAsString(), "field-padding"))
-    ReasonToReject = 7;  // The type is excluded.
+
+  SmallString<128> QualifiedName;
+  auto getQualName = [this, &QualifiedName]() -> StringRef {
+    if (QualifiedName.empty()) {
+      llvm::raw_svector_ostream OS(QualifiedName);
+      printQualifiedName(OS);
+    }
+    return QualifiedName;
+  };
+
+  if (ReasonToReject < 0 &&
+      NoSanitizeList.containsType(EnabledAsanMask, getQualName(),
+                                  "field-padding"))
+    ReasonToReject = 7; // The type is excluded.
 
   if (EmitRemark) {
     if (ReasonToReject >= 0)
       Context.getDiagnostics().Report(
           getLocation(),
           diag::remark_sanitize_address_insert_extra_padding_rejected)
-          << getQualifiedNameAsString() << ReasonToReject;
+          << getQualName() << ReasonToReject;
     else
       Context.getDiagnostics().Report(
           getLocation(),
           diag::remark_sanitize_address_insert_extra_padding_accepted)
-          << getQualifiedNameAsString();
+          << getQualName();
   }
   return ReasonToReject < 0;
 }
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 1312ffd080342..14c45ab00c808 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -716,10 +716,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   SubPolicy.SuppressSpecifiers = false;
   std::string Proto;
 
+  llvm::raw_string_ostream OS(Proto);
   if (Policy.FullyQualifiedName) {
-    Proto += D->getQualifiedNameAsString();
+    D->printQualifiedName(OS, SubPolicy);
   } else {
-    llvm::raw_string_ostream OS(Proto);
     if (!Policy.SuppressScope)
       D->getQualifier().print(OS, Policy);
     D->getNameInfo().printName(OS, Policy);
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 3c05d4b22b03e..c9d9f0a6fbeda 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -2132,7 +2132,13 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
           assert(I.second.getBaseOffset() == BaseOffset &&
                  "Invalid base offset!");
           const CXXRecordDecl *RD = I.second.getBase();
-          ClassNames.insert(RD->getQualifiedNameAsString());
+
+          SmallString<128> NameBuffer;
+          {
+            llvm::raw_svector_ostream OS(NameBuffer);
+            RD->printQualifiedName(OS);
+          }
+          ClassNames.emplace(NameBuffer.str());
         }
 
         for (const std::string &Name : ClassNames) {
@@ -2154,9 +2160,12 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
 
     std::map<std::string, CharUnits> ClassNamesAndOffsets;
     for (const auto &I : VBaseOffsetOffsets) {
-      std::string ClassName = I.first->getQualifiedNameAsString();
-      CharUnits OffsetOffset = I.second;
-      ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
+      SmallString<128> ClassNameBuffer;
+      {
+        llvm::raw_svector_ostream OS(ClassNameBuffer);
+        I.first->printQualifiedName(OS);
+      }
+      ClassNamesAndOffsets.emplace(ClassNameBuffer.str(), I.second);
     }
 
     Out << "Virtual base offset offsets for '";
diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp 
b/clang/lib/Analysis/AnalysisDeclContext.cpp
index 649035c46d019..17dd7a3d6f411 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -340,7 +340,7 @@ std::string AnalysisDeclContext::getFunctionName(const Decl 
*D) {
   const ASTContext &Ctx = D->getASTContext();
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    OS << FD->getQualifiedNameAsString();
+    FD->printQualifiedName(OS);
 
     // In C++, there are overloads.
 
@@ -474,7 +474,7 @@ void StackFrame::printJson(
         << "{ \"lctx_id\": " << SF.getID() << ", \"location_context\": \"";
     Out << '#' << Idx << " Call\", \"calling\": \"";
     if (const auto *D = dyn_cast<NamedDecl>(SF.getDecl()))
-      Out << D->getQualifiedNameAsString();
+      D->printQualifiedName(Out, PP);
     else
       Out << "anonymous code";
 
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 5263114ebca28..ce80c4951bc45 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -6116,14 +6116,14 @@ static void print_elem(raw_ostream &OS, 
StmtPrinterHelper &Helper,
   case CFGElement::Kind::ScopeBegin:
     OS << "CFGScopeBegin(";
     if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
-      OS << VD->getQualifiedNameAsString();
+      VD->printQualifiedName(OS);
     OS << ")";
     break;
 
   case CFGElement::Kind::ScopeEnd:
     OS << "CFGScopeEnd(";
     if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
-      OS << VD->getQualifiedNameAsString();
+      VD->printQualifiedName(OS);
     OS << ")";
     break;
 
diff --git a/clang/lib/Analysis/IssueHash.cpp b/clang/lib/Analysis/IssueHash.cpp
index 6f97b1964550f..a3d9f49ff4d74 100644
--- a/clang/lib/Analysis/IssueHash.cpp
+++ b/clang/lib/Analysis/IssueHash.cpp
@@ -29,6 +29,7 @@ static std::string GetSignature(const FunctionDecl *Target) {
   if (!Target)
     return "";
   std::string Signature;
+  llvm::raw_string_ostream OS(Signature);
 
   // When a flow sensitive bug happens in templated code we should not generate
   // distinct hash value for every instantiation. Use the signature from the
@@ -38,19 +39,25 @@ static std::string GetSignature(const FunctionDecl *Target) 
{
     Target = InstantiatedFrom;
 
   if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
-      !isa<CXXConversionDecl>(Target))
-    Signature.append(Target->getReturnType().getAsString()).append(" ");
-  Signature.append(Target->getQualifiedNameAsString()).append("(");
+      !isa<CXXConversionDecl>(Target)) {
+    Target->getReturnType().print(
+        OS, PrintingPolicy(Target->getASTContext().getLangOpts()));
+    OS << ' ';
+  }
+
+  Target->printQualifiedName(OS);
+  OS << '(';
 
   for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
     if (i)
-      Signature.append(", ");
-    Signature.append(Target->getParamDecl(i)->getType().getAsString());
+      OS << ", ";
+    Target->getParamDecl(i)->getType().print(
+        OS, PrintingPolicy(Target->getASTContext().getLangOpts()));
   }
 
   if (Target->isVariadic())
-    Signature.append(", ...");
-  Signature.append(")");
+    OS << ", ...";
+  OS << ')';
 
   const auto *TargetT =
       llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());
@@ -59,20 +66,20 @@ static std::string GetSignature(const FunctionDecl *Target) 
{
     return Signature;
 
   if (TargetT->isConst())
-    Signature.append(" const");
+    OS << " const";
   if (TargetT->isVolatile())
-    Signature.append(" volatile");
+    OS << " volatile";
   if (TargetT->isRestrict())
-    Signature.append(" restrict");
+    OS << " restrict";
 
   if (const auto *TargetPT =
           dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) 
{
     switch (TargetPT->getRefQualifier()) {
     case RQ_LValue:
-      Signature.append(" &");
+      OS << " &";
       break;
     case RQ_RValue:
-      Signature.append(" &&");
+      OS << " &&";
       break;
     default:
       break;
@@ -87,7 +94,12 @@ static std::string GetEnclosingDeclContextSignature(const 
Decl *EnclosingDecl) {
     if (const auto *FD = dyn_cast<FunctionDecl>(ND))
       // To distinguish overloads we need to use the signature.
       return GetSignature(FD);
-    return ND->getQualifiedNameAsString();
+    SmallString<128> QualName;
+    {
+      llvm::raw_svector_ostream OS(QualName);
+      ND->printQualifiedName(OS);
+    }
+    return std::string(QualName.str());
   }
   return "";
 }
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp 
b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index a56774327731c..bacce14a61f30 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -213,8 +213,11 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext 
&AC,
   llvm::dbgs() << "       Lifetime Analysis Facts:\n";
   llvm::dbgs() << "==========================================\n";
   if (const Decl *D = AC.getDecl())
-    if (const auto *ND = dyn_cast<NamedDecl>(D))
-      llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
+    if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+      llvm::dbgs() << "Function: ";
+      ND->printQualifiedName(llvm::dbgs());
+      llvm::dbgs() << "\n";
+    }
   // Print blocks in the order as they appear in code for a stable ordering.
   for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
     llvm::dbgs() << "  Block B" << B->getBlockID() << ":\n";
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
index 798812327d3ab..8fce2c8a0cad2 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
@@ -37,11 +37,14 @@ namespace internal {
 static void DebugOnlyFunction(AnalysisDeclContext &AC, const CFG &Cfg,
                               FactManager &FactMgr,
                               const LoanPropagationAnalysis *LPA) {
-  std::string Name;
+  SmallString<128> Name;
   if (const Decl *D = AC.getDecl()) {
-    if (const auto *ND = dyn_cast<NamedDecl>(D))
-      Name = ND->getQualifiedNameAsString();
-  };
+    if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+      llvm::raw_svector_ostream OS(Name);
+      ND->printQualifiedName(OS);
+    }
+  }
+
   DEBUG_WITH_TYPE(Name.c_str(), AC.getDecl()->dumpColor());
   DEBUG_WITH_TYPE(Name.c_str(), Cfg.dump(AC.getASTContext().getLangOpts(),
                                          /*ShowColors=*/true));
@@ -60,13 +63,15 @@ void LifetimeSafetyAnalysis::run() {
   const CFG &Cfg = *AC.getCFG();
   if (LSOpts.MaxCFGBlocks > 0 && Cfg.getNumBlockIDs() > LSOpts.MaxCFGBlocks) {
     DEBUG_WITH_TYPE(
-        "LifetimeSafety", std::string FuncName = "<unknown>";
-        if (const Decl *D = AC.getDecl()) if (const auto *ND =
-                                                  dyn_cast<NamedDecl>(D))
-            FuncName = ND->getQualifiedNameAsString();
-        llvm::dbgs() << "LifetimeSafety: Skipping function " << FuncName
-                     << "due to large CFG: " << Cfg.getNumBlockIDs()
-                     << " blocks (threshold: " << LSOpts.MaxCFGBlocks << 
")\n");
+        "LifetimeSafety", llvm::dbgs() << "LifetimeSafety: Skipping function ";
+        if (const Decl *D = AC.getDecl()) {
+          if (const auto *ND = dyn_cast<NamedDecl>(D))
+            ND->printQualifiedName(llvm::dbgs());
+          else
+            llvm::dbgs() << "<unknown>";
+        } else { llvm::dbgs() << "<unknown>"; } llvm::dbgs()
+        << " due to large CFG: " << Cfg.getNumBlockIDs()
+        << " blocks (threshold: " << LSOpts.MaxCFGBlocks << ")\n");
     return;
   }
 
diff --git a/clang/lib/Analysis/ProgramPoint.cpp 
b/clang/lib/Analysis/ProgramPoint.cpp
index bca2581d923b6..6acae66564700 100644
--- a/clang/lib/Analysis/ProgramPoint.cpp
+++ b/clang/lib/Analysis/ProgramPoint.cpp
@@ -224,24 +224,25 @@ void ProgramPoint::printJson(llvm::raw_ostream &Out, 
const char *NL) const {
     break;
 
   case ProgramPoint::LifetimeEndKind:
-    Out << "LifetimeEnd\", \"var\": \""
-        << castAs<LifetimeEnd>().getDecl()->getNameAsString() << '\"';
+    Out << "LifetimeEnd\", \"var\": \"";
+    castAs<LifetimeEnd>().getDecl()->printName(Out);
+    Out << '\"';
     break;
 
   case ProgramPoint::PreImplicitCallKind: {
     ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
-    Out << "PreCall\", \"decl\": \""
-        << PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
-        << "\", \"location\": ";
+    Out << "PreCall\", \"decl\": \"";
+    PC.getDecl()->getAsFunction()->printQualifiedName(Out, PP);
+    Out << "\", \"location\": ";
     printSourceLocationAsJson(Out, PC.getLocation(), SM);
     break;
   }
 
   case ProgramPoint::PostImplicitCallKind: {
     ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
-    Out << "PostCall\", \"decl\": \""
-        << PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
-        << "\", \"location\": ";
+    Out << "PostCall\", \"decl\": \"";
+    PC.getDecl()->getAsFunction()->printQualifiedName(Out, PP);
+    Out << "\", \"location\": ";
     printSourceLocationAsJson(Out, PC.getLocation(), SM);
     break;
   }
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 9c0c1cbdeb219..946e5860474c5 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -3033,9 +3033,14 @@ void CodeGenFunction::EmitVTablePtrCheck(const 
CXXRecordDecl *RD,
 
   auto [M, SSK] = SanitizerInfoFromCFICheckKind(TCK);
 
-  std::string TypeName = RD->getQualifiedNameAsString();
+  SmallString<128> TypeName;
+  {
+    llvm::raw_svector_ostream OS(TypeName);
+    RD->printQualifiedName(OS);
+  }
+
   if (getContext().getNoSanitizeList().containsType(
-          SanitizerMask::bitPosToMask(M), TypeName))
+          SanitizerMask::bitPosToMask(M), TypeName.str()))
     return;
 
   EmitSanitizerStatReport(SSK);
@@ -3087,9 +3092,13 @@ bool 
CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
       !CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
     return false;
 
-  std::string TypeName = RD->getQualifiedNameAsString();
+  SmallString<128> TypeName;
+  {
+    llvm::raw_svector_ostream OS(TypeName);
+    RD->printQualifiedName(OS);
+  }
   return 
!getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
-                                                        TypeName);
+                                                        TypeName.str());
 }
 
 llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
@@ -3114,10 +3123,14 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
 
   llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
 
-  std::string TypeName = RD->getQualifiedNameAsString();
+  SmallString<128> TypeName;
+  {
+    llvm::raw_svector_ostream OS(TypeName);
+    RD->printQualifiedName(OS);
+  }
   if (SanOpts.has(SanitizerKind::CFIVCall) &&
       !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
-                                                     TypeName)) {
+                                                     TypeName.str())) {
     EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
   }
 
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp 
b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 26aaef9d331c0..7235f23bfa35e 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1376,7 +1376,7 @@ static StringRef 
getIdentStringFromSourceLocation(CodeGenFunction &CGF,
     OS << PLoc.getFilename();
   OS << ";";
   if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
-    OS << FD->getQualifiedNameAsString();
+    FD->printQualifiedName(OS);
   OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
   return OS.str();
 }
@@ -1391,15 +1391,19 @@ llvm::Value 
*CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
       Loc.isInvalid()) {
     SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
   } else {
-    std::string FunctionName;
-    std::string FileName;
-    if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
-      FunctionName = FD->getQualifiedNameAsString();
+    SmallString<128> FunctionName;
+    if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
+      llvm::raw_svector_ostream OS(FunctionName);
+      FD->printQualifiedName(OS);
+    }
+
     PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
+    std::string FileName;
     if (auto *DbgInfo = CGF.getDebugInfo())
       FileName = DbgInfo->remapDIPath(PLoc.getFilename());
     else
       FileName = PLoc.getFilename();
+
     unsigned Line = PLoc.getLine();
     unsigned Column = PLoc.getColumn();
     SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName, FileName, Line,
diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp 
b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
index b09fc4c91df2a..c7b660fb8d2ec 100644
--- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
@@ -96,8 +96,13 @@ HLSLBufferLayoutBuilder::layOutStruct(const RecordType *RT,
   // Create the layout struct type; anonymous structs have empty name but
   // non-empty qualified name
   const auto *Decl = RT->castAsCXXRecordDecl();
-  std::string Name =
-      Decl->getName().empty() ? "anon" : Decl->getQualifiedNameAsString();
+  SmallString<64> Name;
+  if (Decl->getName().empty()) {
+    Name = "anon";
+  } else {
+    llvm::raw_svector_ostream OS(Name);
+    Decl->printQualifiedName(OS);
+  }
 
   llvm::StructType *NewTy = llvm::StructType::create(Layout, Name,
                                                      /*isPacked=*/true);
diff --git a/clang/lib/Frontend/ASTConsumers.cpp 
b/clang/lib/Frontend/ASTConsumers.cpp
index 40995e32b67fa..adb9b766b10a8 100644
--- a/clang/lib/Frontend/ASTConsumers.cpp
+++ b/clang/lib/Frontend/ASTConsumers.cpp
@@ -79,8 +79,12 @@ namespace {
 
   private:
     std::string getName(Decl *D) {
-      if (isa<NamedDecl>(D))
-        return cast<NamedDecl>(D)->getQualifiedNameAsString();
+      if (auto *ND = dyn_cast_or_null<NamedDecl>(D)) {
+        SmallString<64> Name;
+        llvm::raw_svector_ostream OS(Name);
+        ND->printQualifiedName(OS);
+        return std::string(Name.str());
+      }
       return "";
     }
     bool filterMatches(Decl *D) {
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp 
b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index 79f1e2b6571c6..b9bb100e07de9 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -21,14 +21,11 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
-
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
-
 #include <cassert>
 #include <cmath>
 #include <cstdarg>
-#include <sstream>
 #include <string>
 
 #define DEBUG_TYPE "interp-value"
@@ -40,7 +37,7 @@ static std::string DeclTypeToString(const QualType &QT, 
NamedDecl *D) {
   llvm::raw_string_ostream SS(Str);
   if (QT.hasQualifiers())
     SS << QT.getQualifiers().getAsString() << " ";
-  SS << D->getQualifiedNameAsString();
+  D->printQualifiedName(SS);
   return Str;
 }
 
@@ -109,7 +106,9 @@ static std::string EnumToString(const Value &V) {
     if (I->getInitVal() == AP) {
       if (!IsFirst)
         SS << " ? ";
-      SS << "(" + I->getQualifiedNameAsString() << ")";
+      SS << "(";
+      I->printQualifiedName(SS);
+      SS << ")";
       IsFirst = false;
     }
   }
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 0bdea354c2406..ed55c0efc72f1 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3510,11 +3510,15 @@ void Parser::ParseCXXMemberSpecification(SourceLocation 
RecordLoc,
           TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) &&
          "Invalid TagType!");
 
-  llvm::TimeTraceScope TimeScope("ParseClass", [&]() {
-    if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl))
-      return TD->getQualifiedNameAsString();
-    return std::string("<anonymous>");
-  });
+  SmallString<128> NameBuf;
+  if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl)) {
+    llvm::raw_svector_ostream OS(NameBuf);
+    TD->printQualifiedName(OS);
+  } else {
+    NameBuf = "<anonymous>";
+  }
+
+  llvm::TimeTraceScope TimeScope("ParseClass", NameBuf);
 
   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
                                       "parsing struct/union/class body");
@@ -3529,13 +3533,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation 
RecordLoc,
         NonNestedClass = false;
 
         // The Microsoft extension __interface does not permit nested classes.
-        if (getCurrentClass().IsInterface) {
+        if (getCurrentClass().IsInterface)
           Diag(RecordLoc, diag::err_invalid_member_in_interface)
-              << /*ErrorType=*/6
-              << (isa<NamedDecl>(TagDecl)
-                      ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()
-                      : "(anonymous)");
-        }
+              << /*ErrorType=*/6 << dyn_cast_or_null<NamedDecl>(TagDecl);
         break;
       }
 
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index d0500a6defd64..afa18ad632d7b 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -14,7 +14,6 @@
 
 #include "clang/Sema/AnalysisBasedWarnings.h"
 #include "SemaLifetimeSafety.h"
-#include "TypeLocBuilder.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
@@ -47,7 +46,6 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/ScopeInfo.h"
-#include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
@@ -2595,14 +2593,11 @@ class UnsafeBufferUsageReporter : public 
UnsafeBufferUsageHandler {
     Loc = CtorExpr->getLocation();
     Range = CtorExpr->getSourceRange();
 
-    std::string ContainerName = "std::span";
-    if (auto *TD = CtorExpr->getConstructor()->getParent()) {
-      // This will provide "std::span" if it's in the std namespace
-      ContainerName = TD->getQualifiedNameAsString();
-    }
-
     // FIX: Pass the container name to fill the %0 parameter
-    S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container) << ContainerName;
+    if (const auto *TD = CtorExpr->getConstructor()->getParent())
+      S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container) << TD;
+    else
+      S.Diag(Loc, diag::warn_unsafe_buffer_usage_in_container) << "std::span";
 
     if (IsRelatedToDecl) {
       assert(!SuggestSuggestions &&
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index cc2af8feb3794..acf2ba04b2b06 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1876,8 +1876,7 @@ static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
           (OrigDecl->getAccess() == AS_public ||
            OrigDecl->getAccess() == AS_protected)) {
         S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
-            << UD->getQualifiedNameAsString()
-            << OrigDecl->getQualifiedNameAsString();
+            << UD << OrigDecl;
         return true;
       }
     }
diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp 
b/clang/lib/Sema/SemaBoundsSafety.cpp
index 066dab2f0bef2..7dc80b8b35037 100644
--- a/clang/lib/Sema/SemaBoundsSafety.cpp
+++ b/clang/lib/Sema/SemaBoundsSafety.cpp
@@ -320,17 +320,17 @@ static bool 
CheckAssignmentToCountAttrPtrWithIncompletePointeeTy(
   if (!CATy)
     return true;
 
-  std::string AssigneeStr;
+  SmallString<64> AssigneeBuf;
   if (Assignee) {
-    if (ShowFullyQualifiedAssigneeName) {
-      AssigneeStr = Assignee->getQualifiedNameAsString();
-    } else {
-      AssigneeStr = Assignee->getNameAsString();
-    }
+    llvm::raw_svector_ostream OS(AssigneeBuf);
+    if (ShowFullyQualifiedAssigneeName)
+      Assignee->printQualifiedName(OS);
+    else
+      Assignee->printName(OS);
   }
 
   S.Diag(Loc, diag::err_counted_by_on_incomplete_type_on_assign)
-      << static_cast<int>(Action) << AssigneeStr << (AssigneeStr.size() > 0)
+      << static_cast<int>(Action) << AssigneeBuf << !AssigneeBuf.empty()
       << isa<ImplicitValueInitExpr>(RHSExpr) << LHSTy
       << CATy->getAttributeName(/*WithMacroPrefix=*/true) << PointeeTy
       << CATy->isOrNull() << RHSExpr->getSourceRange();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7f3ccea82e8af..30568c4da03ca 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11578,8 +11578,14 @@ void CheckFreeArgumentsCast(Sema &S, const std::string 
&CalleeName,
 } // namespace
 
 void Sema::CheckFreeArguments(const CallExpr *E) {
-  const std::string CalleeName =
-      cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString();
+  const auto *FD = cast<FunctionDecl>(E->getCalleeDecl());
+
+  SmallString<64> CalleeNameBuf;
+  {
+    llvm::raw_svector_ostream OS(CalleeNameBuf);
+    FD->printQualifiedName(OS);
+  }
+  std::string CalleeName = CalleeNameBuf.str().str();
 
   { // Prefer something that doesn't involve a cast to make things simpler.
     const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
@@ -11599,13 +11605,13 @@ void Sema::CheckFreeArguments(const CallExpr *E) {
 
     if (const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
       Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
-          << CalleeName << 0 /*object: */ << 
Label->getLabel()->getIdentifier();
+          << FD << 0 /*object: */ << Label->getLabel()->getIdentifier();
       return;
     }
 
     if (isa<BlockExpr>(Arg)) {
       Diag(Arg->getBeginLoc(), diag::warn_free_nonheap_object)
-          << CalleeName << 1 /*object: block*/;
+          << FD << 1 /*object: block*/;
       return;
     }
   }
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2b524a956ecc4..0d5aed12544ee 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6760,8 +6760,7 @@ static void DiagnosedUnqualifiedCallsToStdFunctions(Sema 
&S,
     return;
 
   S.Diag(DRE->getLocation(), diag::warn_unqualified_call_to_std_cast_function)
-      << FD->getQualifiedNameAsString()
-      << FixItHint::CreateInsertion(DRE->getLocation(), "std::");
+      << FD << FixItHint::CreateInsertion(DRE->getLocation(), "std::");
 }
 
 ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation 
LParenLoc,
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 81bc6c68f377d..80b0ae6c08f0d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12,7 +12,6 @@
 
 #include "CheckExprLifetime.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
@@ -14681,9 +14680,15 @@ static bool DiagnoseTwoPhaseLookup(
           // Never suggest declaring a function within a namespace with a
           // reserved name, like __gnu_cxx.
           NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it);
-          if (NS &&
-              NS->getQualifiedNameAsString().find("__") != std::string::npos)
-            continue;
+          if (NS) {
+            SmallString<64> QualName;
+            {
+              llvm::raw_svector_ostream OS(QualName);
+              NS->printQualifiedName(OS);
+            }
+            if (QualName.str().contains("__"))
+              continue;
+          }
 
           SuggestedNamespaces.insert(*it);
         }
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 67289855685db..512052c0f3d96 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3379,11 +3379,15 @@ static bool isInVkNamespace(const RecordType *RT) {
   if (!DC)
     return false;
 
-  NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
-  if (!ND)
+  const auto *VkND = dyn_cast<NamespaceDecl>(DC);
+  if (!VkND || VkND->getName() != "vk")
     return false;
 
-  return ND->getQualifiedNameAsString() == "hlsl::vk";
+  const auto *HlslND = dyn_cast<NamespaceDecl>(VkND->getDeclContext());
+  if (!HlslND || HlslND->getName() != "hlsl")
+    return false;
+
+  return HlslND->getDeclContext()->isTranslationUnit();
 }
 
 static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef,
diff --git a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
index d3e4a3a634764..0ce9780cf3fa0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -124,8 +124,12 @@ class AnalysisOrderChecker
   bool evalCall(const CallEvent &Call, CheckerContext &C) const {
     if (isCallbackEnabled(C, "EvalCall")) {
       llvm::errs() << "EvalCall";
-      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
-        llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) {
+        llvm::errs() << " (";
+        ND->printQualifiedName(llvm::errs());
+        llvm::errs() << ')';
+      }
+
       llvm::errs() << " {argno: " << Call.getNumArgs() << '}';
       llvm::errs() << " [" << Call.getKindAsString() << ']';
       llvm::errs() << '\n';
@@ -138,8 +142,11 @@ class AnalysisOrderChecker
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
     if (isCallbackEnabled(C, "PreCall")) {
       llvm::errs() << "PreCall";
-      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
-        llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) {
+        llvm::errs() << " (";
+        ND->printQualifiedName(llvm::errs());
+        llvm::errs() << ')';
+      }
       llvm::errs() << " [" << Call.getKindAsString() << ']';
       llvm::errs() << '\n';
     }
@@ -148,8 +155,11 @@ class AnalysisOrderChecker
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
     if (isCallbackEnabled(C, "PostCall")) {
       llvm::errs() << "PostCall";
-      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl()))
-        llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')';
+      if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) {
+        llvm::errs() << " (";
+        ND->printQualifiedName(llvm::errs());
+        llvm::errs() << ')';
+      }
       llvm::errs() << " [" << Call.getKindAsString() << ']';
       llvm::errs() << '\n';
     }
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 5ee5601a9319a..029c3df4fdc51 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -3857,18 +3857,21 @@ bool 
MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
     return true;
   }
 
-  if (FName == "postEvent" &&
-      FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
+  auto IsInClass = [](const FunctionDecl *FD, StringRef ClassName) {
+    if (const auto *RD = dyn_cast<CXXRecordDecl>(FD->getDeclContext()))
+      return RD->getName() == ClassName;
+    return false;
+  };
+
+  if (FName == "postEvent" && IsInClass(FD, "QCoreApplication")) {
     return true;
   }
 
-  if (FName == "connectImpl" &&
-      FD->getQualifiedNameAsString() == "QObject::connectImpl") {
+  if (FName == "connectImpl" && IsInClass(FD, "QObject")) {
     return true;
   }
 
-  if (FName == "singleShotImpl" &&
-      FD->getQualifiedNameAsString() == "QTimer::singleShotImpl") {
+  if (FName == "singleShotImpl" && IsInClass(FD, "QTimer")) {
     return true;
   }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
index 9c616a2d17783..e669b25e83a3b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -662,7 +662,7 @@ void MoveChecker::explainObject(ProgramStateRef State, 
llvm::raw_ostream &OS,
                                 MisuseKind MK) const {
   // We may need a leading space every time we actually explain anything,
   // and we never know if we are to explain anything until we try.
-  if (const auto DR =
+  if (const auto *DR =
           dyn_cast_or_null<DeclRegion>(unwrapRValueReferenceIndirection(MR))) {
     const auto *RegionDecl = cast<NamedDecl>(DR->getDecl());
     OS << " '" << RegionDecl->getDeclName() << "'";
@@ -670,18 +670,20 @@ void MoveChecker::explainObject(ProgramStateRef State, 
llvm::raw_ostream &OS,
 
   ObjectKind OK = classifyObject(State, MR, RD);
   switch (OK.StdKind) {
-    case SK_NonStd:
-    case SK_Safe:
+  case SK_NonStd:
+  case SK_Safe:
+    break;
+  case SK_SmartPtr:
+    if (MK != MK_Dereference)
       break;
-    case SK_SmartPtr:
-      if (MK != MK_Dereference)
-        break;
 
-      // We only care about the type if it's a dereference.
-      [[fallthrough]];
-    case SK_Unsafe:
-      OS << " of type '" << RD->getQualifiedNameAsString() << "'";
-      break;
+    // We only care about the type if it's a dereference.
+    [[fallthrough]];
+  case SK_Unsafe:
+    OS << " of type '";
+    RD->printQualifiedName(OS);
+    OS << "'";
+    break;
   };
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/NoOwnershipChangeVisitor.cpp 
b/clang/lib/StaticAnalyzer/Checkers/NoOwnershipChangeVisitor.cpp
index 3583e7b2aa6f8..756f6cf4157f2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NoOwnershipChangeVisitor.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NoOwnershipChangeVisitor.cpp
@@ -63,8 +63,12 @@ LLVM_DUMP_METHOD std::string
 NoOwnershipChangeVisitor::getFunctionName(const ExplodedNode *CallEnterN) {
   if (const CallExpr *CE = llvm::dyn_cast_or_null<CallExpr>(
           CallEnterN->getLocationAs<CallEnter>()->getCallExpr()))
-    if (const FunctionDecl *FD = CE->getDirectCallee())
-      return FD->getQualifiedNameAsString();
+    if (const FunctionDecl *FD = CE->getDirectCallee()) {
+      SmallString<128> Name;
+      llvm::raw_svector_ostream OS(Name);
+      FD->printQualifiedName(OS);
+      return std::string(Name.str());
+    }
   return "";
 }
 
diff --git 
a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
 
b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
index 59d11c4d8ae2c..4b0c6b60f84ed 100644
--- 
a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
+++ 
b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -173,9 +173,13 @@ static void generateDiagnosticsForCallLike(ProgramStateRef 
CurrSt,
       FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
 
     if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
-      os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
+      os << "Call to method '";
+      MD->printQualifiedName(os);
+      os << '\'';
     } else if (FD) {
-      os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
+      os << "Call to function '";
+      FD->printQualifiedName(os);
+      os << '\'';
     } else {
       os << "function call";
     }
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp 
b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 36a71d510b902..7d65ff51f3f7c 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -211,18 +211,20 @@ const ParmVarDecl *ParamVarRegion::getDecl() const {
   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
     assert(Index < FD->param_size());
     return FD->parameters()[Index];
-  } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+  }
+  if (const auto *BD = dyn_cast<BlockDecl>(D)) {
     assert(Index < BD->param_size());
     return BD->parameters()[Index];
-  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+  }
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
     assert(Index < MD->param_size());
     return MD->parameters()[Index];
-  } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+  }
+  if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
     assert(Index < CD->param_size());
     return CD->parameters()[Index];
-  } else {
-    llvm_unreachable("Unexpected Decl kind!");
   }
+  llvm_unreachable("Unexpected Decl kind!");
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Core/SVals.cpp 
b/clang/lib/StaticAnalyzer/Core/SVals.cpp
index 483e62d4a9a7e..6f92683501e3f 100644
--- a/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -355,7 +355,7 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
       const nonloc::PointerToMember &CastRes =
           castAs<nonloc::PointerToMember>();
       if (CastRes.getDecl())
-        os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
+        os << "|" << CastRes.getDecl() << "|";
       bool first = true;
       for (const auto &I : CastRes) {
         if (first) {
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp 
b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index ce44fcd240ffa..2c71769f4b646 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -373,9 +373,16 @@ class AnalysisConsumer : public AnalysisASTConsumer,
 
 std::string timeTraceScopeDeclName(StringRef FunName, const Decl *D) {
   if (llvm::timeTraceProfilerEnabled()) {
-    if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
-      return (FunName + " " + ND->getQualifiedNameAsString()).str();
-    return (FunName + " <anonymous> ").str();
+    SmallString<128> NameBuf;
+    llvm::raw_svector_ostream OS(NameBuf);
+
+    OS << FunName << " ";
+    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
+      ND->printQualifiedName(OS);
+    else
+      OS << "<anonymous>";
+
+    return std::string(NameBuf.str());
   }
   return "";
 }
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp 
b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index 7ca789bba9c02..5466cc55c260f 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -358,23 +358,36 @@ int SyntaxTree::Impl::findPositionInParent(NodeId Id, 
bool Shifted) const {
 std::string
 SyntaxTree::Impl::getRelativeName(const NamedDecl *ND,
                                   const DeclContext *Context) const {
-  std::string Val = ND->getQualifiedNameAsString();
-  std::string ContextPrefix;
-  if (!Context)
-    return Val;
-  if (auto *Namespace = dyn_cast<NamespaceDecl>(Context))
-    ContextPrefix = Namespace->getQualifiedNameAsString();
-  else if (auto *Record = dyn_cast<RecordDecl>(Context))
-    ContextPrefix = Record->getQualifiedNameAsString();
-  else if (AST.getLangOpts().CPlusPlus11)
-    if (auto *Tag = dyn_cast<TagDecl>(Context))
-      ContextPrefix = Tag->getQualifiedNameAsString();
-  // Strip the qualifier, if Val refers to something in the current scope.
-  // But leave one leading ':' in place, so that we know that this is a
-  // relative path.
-  if (!ContextPrefix.empty() && StringRef(Val).starts_with(ContextPrefix))
-    Val = Val.substr(ContextPrefix.size() + 1);
-  return Val;
+  SmallString<128> ValBuf;
+  {
+    llvm::raw_svector_ostream OS(ValBuf);
+    ND->printQualifiedName(OS);
+  }
+
+  if (Context) {
+    if (const auto *ContextND = dyn_cast<NamedDecl>(Context)) {
+      if (isa<NamespaceDecl>(Context) || isa<RecordDecl>(Context) ||
+          (AST.getLangOpts().CPlusPlus11 && isa<TagDecl>(Context))) {
+
+        SmallString<128> ContextPrefixBuf;
+        {
+          llvm::raw_svector_ostream OS(ContextPrefixBuf);
+          ContextND->printQualifiedName(OS);
+        }
+
+        StringRef Val = ValBuf.str();
+        StringRef ContextPrefix = ContextPrefixBuf.str();
+
+        // Strip the qualifier, if Val refers to something in the current 
scope.
+        // But leave one leading ':' in place, so that we know that this is a
+        // relative path.
+        if (!ContextPrefix.empty() && Val.starts_with(ContextPrefix))
+          return std::string(Val.substr(ContextPrefix.size() + 1));
+      }
+    }
+  }
+
+  return std::string(ValBuf.str());
 }
 
 std::string SyntaxTree::Impl::getRelativeName(const NamedDecl *ND) const {
@@ -691,8 +704,12 @@ StringRef Node::getTypeLabel() const { return 
getType().asStringRef(); }
 
 std::optional<std::string> Node::getQualifiedIdentifier() const {
   if (auto *ND = ASTNode.get<NamedDecl>()) {
-    if (ND->getDeclName().isIdentifier())
-      return ND->getQualifiedNameAsString();
+    if (ND->getDeclName().isIdentifier()) {
+      SmallString<128> Buf;
+      llvm::raw_svector_ostream OS(Buf);
+      ND->printQualifiedName(OS);
+      return std::string(Buf.str());
+    }
   }
   return std::nullopt;
 }
diff --git a/clang/lib/Tooling/Refactoring/Lookup.cpp 
b/clang/lib/Tooling/Refactoring/Lookup.cpp
index dedde860516ab..2a6ffc2271518 100644
--- a/clang/lib/Tooling/Refactoring/Lookup.cpp
+++ b/clang/lib/Tooling/Refactoring/Lookup.cpp
@@ -62,11 +62,11 @@ usingFromDifferentCanonicalNamespace(const DeclContext 
*FromContext,
   if (UseNamespaces.size() < FromNamespaces.size())
     return false;
   unsigned Diff = UseNamespaces.size() - FromNamespaces.size();
-  auto FromIter = FromNamespaces.begin();
+  auto *FromIter = FromNamespaces.begin();
   // Only compare `FromNamespaces` with namespaces in `UseNamespaces` that can
   // collide, i.e. the top N namespaces where N is the number of namespaces in
   // `FromNamespaces`.
-  auto UseIter = UseNamespaces.begin() + Diff;
+  auto *UseIter = UseNamespaces.begin() + Diff;
   for (; FromIter != FromNamespaces.end() && UseIter != UseNamespaces.end();
        ++FromIter, ++UseIter) {
     // Literally the same namespace, not a collision.
@@ -96,8 +96,13 @@ static StringRef getBestNamespaceSubstr(const DeclContext 
*DeclA,
     // Otherwise strip off redundant namespace qualifications from the new 
name.
     // We use the fully qualified name of the namespace and remove that part
     // from NewName if it has an identical prefix.
-    std::string NS =
-        "::" + cast<NamespaceDecl>(DeclA)->getQualifiedNameAsString() + "::";
+    SmallString<128> NS;
+    {
+      llvm::raw_svector_ostream OS(NS);
+      OS << "::";
+      cast<NamespaceDecl>(DeclA)->printQualifiedName(OS);
+      OS << "::";
+    }
     if (NewName.consume_front(NS))
       return NewName;
 
@@ -145,15 +150,21 @@ static std::string disambiguateSpellingInScope(StringRef 
Spelling,
     for (const auto *NS : EnclosingNamespaces) {
       auto LookupRes = NS->lookup(DeclarationName(&AST.Idents.get(Head)));
       if (!LookupRes.empty()) {
-        for (const NamedDecl *Res : LookupRes)
+        for (const NamedDecl *Res : LookupRes) {
           // If `Res` is not visible in `UseLoc`, we don't consider it
           // ambiguous. For example, a reference in a header file should not be
           // affected by a potentially ambiguous name in some file that 
includes
           // the header.
-          if (!TrimmedQName.starts_with(Res->getQualifiedNameAsString()) &&
+          SmallString<128> ResQName;
+          {
+            llvm::raw_svector_ostream OS(ResQName);
+            Res->printQualifiedName(OS);
+          }
+          if (!TrimmedQName.starts_with(ResQName.str()) &&
               SM.isBeforeInTranslationUnit(
                   SM.getSpellingLoc(Res->getLocation()), UseLoc))
             return true;
+        }
       }
     }
     return false;
diff --git a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp 
b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
index 66902614488a7..1f52a624aac6d 100644
--- a/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ b/clang/lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -106,10 +106,21 @@ class NamedDeclFindingVisitor
   bool VisitNamedDecl(const NamedDecl *ND) {
     if (!ND)
       return true;
-    // Fully qualified name is used to find the declaration.
-    if (Name != ND->getQualifiedNameAsString() &&
-        Name != "::" + ND->getQualifiedNameAsString())
+
+    SmallString<128> QNameBuf;
+    {
+      llvm::raw_svector_ostream OS(QNameBuf);
+      ND->printQualifiedName(OS);
+    }
+
+    StringRef QName = QNameBuf.str();
+    StringRef TargetName = Name;
+
+    TargetName.consume_front("::");
+
+    if (TargetName != QName)
       return true;
+
     Result = ND;
     return false;
   }
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp 
b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
index 9381a29f56f43..70902f3cdc797 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
@@ -12,6 +12,7 @@
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
 #include "clang/Sema/Lookup.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/Error.h"
 #include <optional>
 
@@ -100,8 +101,8 @@ struct MissingDeclContext : public 
llvm::ErrorInfo<MissingDeclContext> {
 
   static char ID;
 
-  MissingDeclContext(DeclContext *context, std::string error)
-      : m_context(context), m_error(error) {}
+  MissingDeclContext(DeclContext *context, llvm::Twine error)
+      : m_context(context), m_error(error.str()) {}
 
   DeclContext *m_context;
   std::string m_error;
@@ -148,9 +149,14 @@ getEqualLocalDeclContext(Sema &sema, DeclContext 
*foreign_ctxt) {
       if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
         return DC->getPrimaryContext();
     }
+    SmallString<128> Msg;
+    {
+      llvm::raw_svector_ostream OS(Msg);
+      OS << "Couldn't find namespace ";
+      ns->printQualifiedName(OS);
+    }
     return llvm::make_error<MissingDeclContext>(
-        foreign_ctxt,
-        "Couldn't find namespace " + ns->getQualifiedNameAsString());
+        foreign_ctxt, "Couldn't find namespace " + Msg.str());
   }
 
   return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context 
");
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index b60f1d9e41958..92cb4c6faa6fd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2950,9 +2950,14 @@ void DWARFASTParserClang::CreateStaticMemberVariable(
   llvm::Expected<llvm::APInt> const_value_or_err =
       ExtractIntFromFormValue(ct, *attrs.const_value_form);
   if (!const_value_or_err) {
+    clang::SmallString<128> QName;
+    {
+      llvm::raw_svector_ostream OS(QName);
+      v->printQualifiedName(OS);
+    }
     LLDB_LOG_ERROR(log, const_value_or_err.takeError(),
                    "Failed to add const value to variable {1}: {0}",
-                   v->getQualifiedNameAsString());
+                   QName.str());
     return;
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp 
b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
index 6d4af9ec6bf95..02b179ab08c35 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
@@ -1219,11 +1219,13 @@ 
PdbAstBuilderClang::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
   clang::DeclContext *parent = GetParentClangDeclContext(PdbSymUid(func_id));
   if (!parent)
     return nullptr;
-  std::string context_name;
-  if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) 
{
-    context_name = ns->getQualifiedNameAsString();
-  } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {
-    context_name = tag->getQualifiedNameAsString();
+  clang::SmallString<128> context_name_buf;
+  if (const auto *parent_nd = llvm::dyn_cast<clang::NamedDecl>(parent)) {
+    if (llvm::isa<clang::NamespaceDecl>(parent) ||
+        llvm::isa<clang::TagDecl>(parent)) {
+      llvm::raw_svector_ostream OS(context_name_buf);
+      parent_nd->printQualifiedName(OS);
+    }
   }
 
   SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
@@ -1255,8 +1257,9 @@ 
PdbAstBuilderClang::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
   CompilerType func_ct = ToCompilerType(qt);
 
   llvm::StringRef proc_name = proc.Name;
-  if (!context_name.empty() && !(proc_name.consume_front(context_name) &&
-                                 proc_name.consume_front("::"))) {
+  if (!context_name_buf.empty() &&
+      !(proc_name.consume_front(context_name_buf) &&
+        proc_name.consume_front("::"))) {
     // If we have some context, but the function name doesn't start with it, 
use
     // the basename.
     MSVCUndecoratedNameParser parser(proc.Name);
@@ -1516,7 +1519,12 @@ void 
PdbAstBuilderClang::ParseNamespace(clang::DeclContext &context) {
   clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(&context);
   if (m_parsed_namespaces.contains(ns))
     return;
-  std::string qname = ns->getQualifiedNameAsString();
+  clang::SmallString<128> qname_buf;
+  {
+    llvm::raw_svector_ostream OS(qname_buf);
+    ns->printQualifiedName(OS);
+  }
+  llvm::StringRef qname = qname_buf.str();
   SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
       m_clang.GetSymbolFile()->GetBackingSymbolFile());
   PdbIndex &index = pdb->GetIndex();

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to