[llvm] Stop abusing Twine in DiagnosticInfo (PR #136371)

Justin Bogner via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 21 00:55:22 PDT 2025


https://github.com/bogner updated https://github.com/llvm/llvm-project/pull/136371

>From 7327ce46e221207e0ffb66ec7b2dc16aed4ead3c Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Fri, 18 Apr 2025 14:20:28 -0700
Subject: [PATCH 1/5] Stop abusing Twine in DiagnosticInfo

This switches the various DiagnosticInfo subclasses that store an un-owned
string to use StringRef for this instead of Twine.

Storing a `Twine &` like most of these were doing makes it very easy to
introduce memory corruption bugs:

```c++
void f(std::string &Msg) {
  auto Diag = DiagnosticInfoGeneric(Msg);
  Ctx.diagnose(Diag); // Bug! We're referring to the temporary Twine!
  Ctx.diagnose(DiagnosticInfoGeneric(Msg); // this works, I guess...
};
```

This was sort of mitigated in DiagnosticInfoUnsupported, which actually copies
the Twine, but copying Twines is always a questionable practice.

Instead, we store a StringRef, which makes it much more explicit that ownership
of the storage is the caller's problem.
---
 llvm/include/llvm/IR/DiagnosticInfo.h         | 81 ++++++++---------
 .../llvm/ProfileData/SampleProfReader.h       |  5 +-
 .../Utils/SampleProfileLoaderBaseImpl.h       | 33 ++++---
 .../AsmPrinter/AsmPrinterInlineAsm.cpp        |  7 +-
 llvm/lib/CodeGen/MachineInstr.cpp             |  8 +-
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 10 +-
 llvm/lib/IR/DiagnosticInfo.cpp                | 11 +--
 llvm/lib/IR/LLVMContext.cpp                   |  7 +-
 llvm/lib/Target/DirectX/DXILRootSignature.cpp |  5 +-
 .../Instrumentation/PGOInstrumentation.cpp    | 91 +++++++++----------
 llvm/lib/Transforms/Utils/MisExpect.cpp       |  9 +-
 11 files changed, 137 insertions(+), 130 deletions(-)

diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 8743f8058c382..151f323447bfb 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -18,7 +18,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -139,22 +138,22 @@ class DiagnosticInfo {
 using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>;
 
 class DiagnosticInfoGeneric : public DiagnosticInfo {
-  const Twine &MsgStr;
+  StringRef MsgStr;
   const Instruction *Inst = nullptr;
 
 public:
   /// \p MsgStr is the message to be reported to the frontend.
   /// This class does not copy \p MsgStr, therefore the reference must be valid
   /// for the whole life time of the Diagnostic.
-  DiagnosticInfoGeneric(const Twine &MsgStr,
+  DiagnosticInfoGeneric(StringRef MsgStr,
                         DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Generic, Severity), MsgStr(MsgStr) {}
 
-  DiagnosticInfoGeneric(const Instruction *I, const Twine &ErrMsg,
+  DiagnosticInfoGeneric(const Instruction *I, StringRef ErrMsg,
                         DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Generic, Severity), MsgStr(ErrMsg), Inst(I) {}
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  StringRef getMsgStr() const { return MsgStr; }
   const Instruction *getInstruction() const { return Inst; }
 
   /// \see DiagnosticInfo::print.
@@ -172,7 +171,7 @@ class DiagnosticInfoInlineAsm : public DiagnosticInfo {
   /// Optional line information. 0 if not set.
   uint64_t LocCookie = 0;
   /// Message to be reported.
-  const Twine &MsgStr;
+  StringRef MsgStr;
   /// Optional origin of the problem.
   const Instruction *Instr = nullptr;
 
@@ -181,7 +180,7 @@ class DiagnosticInfoInlineAsm : public DiagnosticInfo {
   /// \p MsgStr gives the message.
   /// This class does not copy \p MsgStr, therefore the reference must be valid
   /// for the whole life time of the Diagnostic.
-  DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr,
+  DiagnosticInfoInlineAsm(uint64_t LocCookie, StringRef MsgStr,
                           DiagnosticSeverity Severity = DS_Error);
 
   /// \p Instr gives the original instruction that triggered the diagnostic.
@@ -189,11 +188,11 @@ class DiagnosticInfoInlineAsm : public DiagnosticInfo {
   /// This class does not copy \p MsgStr, therefore the reference must be valid
   /// for the whole life time of the Diagnostic.
   /// Same for \p I.
-  DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
+  DiagnosticInfoInlineAsm(const Instruction &I, StringRef MsgStr,
                           DiagnosticSeverity Severity = DS_Error);
 
   uint64_t getLocCookie() const { return LocCookie; }
-  const Twine &getMsgStr() const { return MsgStr; }
+  StringRef getMsgStr() const { return MsgStr; }
   const Instruction *getInstruction() const { return Instr; }
 
   /// \see DiagnosticInfo::print.
@@ -258,15 +257,15 @@ class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
 class DiagnosticInfoSampleProfile : public DiagnosticInfo {
 public:
   DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
-                              const Twine &Msg,
+                              StringRef Msg,
                               DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
         LineNum(LineNum), Msg(Msg) {}
-  DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
+  DiagnosticInfoSampleProfile(StringRef FileName, StringRef Msg,
                               DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
         Msg(Msg) {}
-  DiagnosticInfoSampleProfile(const Twine &Msg,
+  DiagnosticInfoSampleProfile(StringRef Msg,
                               DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {}
 
@@ -279,7 +278,7 @@ class DiagnosticInfoSampleProfile : public DiagnosticInfo {
 
   StringRef getFileName() const { return FileName; }
   unsigned getLineNum() const { return LineNum; }
-  const Twine &getMsg() const { return Msg; }
+  StringRef getMsg() const { return Msg; }
 
 private:
   /// Name of the input file associated with this diagnostic.
@@ -290,13 +289,13 @@ class DiagnosticInfoSampleProfile : public DiagnosticInfo {
   unsigned LineNum = 0;
 
   /// Message to report.
-  const Twine &Msg;
+  StringRef Msg;
 };
 
 /// Diagnostic information for the PGO profiler.
 class DiagnosticInfoPGOProfile : public DiagnosticInfo {
 public:
-  DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
+  DiagnosticInfoPGOProfile(const char *FileName, StringRef Msg,
                            DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {}
 
@@ -308,14 +307,14 @@ class DiagnosticInfoPGOProfile : public DiagnosticInfo {
   }
 
   const char *getFileName() const { return FileName; }
-  const Twine &getMsg() const { return Msg; }
+  StringRef getMsg() const { return Msg; }
 
 private:
   /// Name of the input file associated with this diagnostic.
   const char *FileName;
 
   /// Message to report.
-  const Twine &Msg;
+  StringRef Msg;
 };
 
 class DiagnosticLocation {
@@ -364,7 +363,7 @@ class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
 
   /// Return the absolute path tot the file.
   std::string getAbsolutePath() const;
-  
+
   const Function &getFunction() const { return Fn; }
   DiagnosticLocation getLocation() const { return Loc; }
 
@@ -379,19 +378,19 @@ class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
 class DiagnosticInfoGenericWithLoc : public DiagnosticInfoWithLocationBase {
 private:
   /// Message to be reported.
-  const Twine &MsgStr;
+  StringRef MsgStr;
 
 public:
   /// \p MsgStr is the message to be reported to the frontend.
   /// This class does not copy \p MsgStr, therefore the reference must be valid
   /// for the whole life time of the Diagnostic.
-  DiagnosticInfoGenericWithLoc(const Twine &MsgStr, const Function &Fn,
+  DiagnosticInfoGenericWithLoc(StringRef MsgStr, const Function &Fn,
                                const DiagnosticLocation &Loc,
                                DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfoWithLocationBase(DK_GenericWithLoc, Severity, Fn, Loc),
         MsgStr(MsgStr) {}
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  StringRef getMsgStr() const { return MsgStr; }
 
   /// \see DiagnosticInfo::print.
   void print(DiagnosticPrinter &DP) const override;
@@ -404,20 +403,20 @@ class DiagnosticInfoGenericWithLoc : public DiagnosticInfoWithLocationBase {
 class DiagnosticInfoRegAllocFailure : public DiagnosticInfoWithLocationBase {
 private:
   /// Message to be reported.
-  const Twine &MsgStr;
+  StringRef MsgStr;
 
 public:
   /// \p MsgStr is the message to be reported to the frontend.
   /// This class does not copy \p MsgStr, therefore the reference must be valid
   /// for the whole life time of the Diagnostic.
-  DiagnosticInfoRegAllocFailure(const Twine &MsgStr, const Function &Fn,
+  DiagnosticInfoRegAllocFailure(StringRef MsgStr, const Function &Fn,
                                 const DiagnosticLocation &DL,
                                 DiagnosticSeverity Severity = DS_Error);
 
-  DiagnosticInfoRegAllocFailure(const Twine &MsgStr, const Function &Fn,
+  DiagnosticInfoRegAllocFailure(StringRef MsgStr, const Function &Fn,
                                 DiagnosticSeverity Severity = DS_Error);
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  StringRef getMsgStr() const { return MsgStr; }
 
   /// \see DiagnosticInfo::print.
   void print(DiagnosticPrinter &DP) const override;
@@ -707,7 +706,7 @@ class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
                                enum DiagnosticSeverity Severity,
                                const char *PassName, const Function &Fn,
-                               const DiagnosticLocation &Loc, const Twine &Msg)
+                               const DiagnosticLocation &Loc, StringRef Msg)
       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
     *this << Msg.str();
   }
@@ -764,7 +763,7 @@ class OptimizationRemark : public DiagnosticInfoIROptimization {
   /// Note that this class does not copy this message, so this reference
   /// must be valid for the whole life time of the diagnostic.
   OptimizationRemark(const char *PassName, const Function &Fn,
-                     const DiagnosticLocation &Loc, const Twine &Msg)
+                     const DiagnosticLocation &Loc, StringRef Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
                                      Fn, Loc, Msg) {}
 };
@@ -810,7 +809,7 @@ class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
   /// Note that this class does not copy this message, so this reference
   /// must be valid for the whole life time of the diagnostic.
   OptimizationRemarkMissed(const char *PassName, const Function &Fn,
-                           const DiagnosticLocation &Loc, const Twine &Msg)
+                           const DiagnosticLocation &Loc, StringRef Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
                                      PassName, Fn, Loc, Msg) {}
 };
@@ -863,7 +862,7 @@ class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
 protected:
   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
                              const Function &Fn, const DiagnosticLocation &Loc,
-                             const Twine &Msg)
+                             StringRef Msg)
       : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
 
   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
@@ -882,7 +881,7 @@ class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
   /// this class does not copy this message, so this reference must be valid for
   /// the whole life time of the diagnostic.
   OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
-                             const DiagnosticLocation &Loc, const Twine &Msg)
+                             const DiagnosticLocation &Loc, StringRef Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
                                      PassName, Fn, Loc, Msg) {}
 };
@@ -924,7 +923,7 @@ class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
   /// diagnostic.
   OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
                                       const DiagnosticLocation &Loc,
-                                      const Twine &Msg)
+                                      StringRef Msg)
       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
                                    PassName, Fn, Loc, Msg) {}
 };
@@ -965,7 +964,7 @@ class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
   /// diagnostic.
   OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
                                      const DiagnosticLocation &Loc,
-                                     const Twine &Msg)
+                                     StringRef Msg)
       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
                                    PassName, Fn, Loc, Msg) {}
 };
@@ -991,10 +990,10 @@ class DiagnosticInfoMIRParser : public DiagnosticInfo {
 
 /// Diagnostic information for IR instrumentation reporting.
 class DiagnosticInfoInstrumentation : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 
 public:
-  DiagnosticInfoInstrumentation(const Twine &DiagMsg,
+  DiagnosticInfoInstrumentation(StringRef DiagMsg,
                                 DiagnosticSeverity Severity = DS_Warning)
       : DiagnosticInfo(DK_Instrumentation, Severity), Msg(DiagMsg) {}
 
@@ -1038,7 +1037,7 @@ class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
   /// of the diagnostic.
   DiagnosticInfoOptimizationFailure(const Function &Fn,
                                     const DiagnosticLocation &Loc,
-                                    const Twine &Msg)
+                                    StringRef Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
                                      nullptr, Fn, Loc, Msg) {}
 
@@ -1062,7 +1061,7 @@ class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
 /// Diagnostic information for unsupported feature in backend.
 class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
 private:
-  Twine Msg;
+  StringRef Msg;
 
 public:
   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
@@ -1072,7 +1071,7 @@ class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
   /// copy this message, so this reference must be valid for the whole life time
   /// of the diagnostic.
   DiagnosticInfoUnsupported(
-      const Function &Fn, const Twine &Msg,
+      const Function &Fn, StringRef Msg,
       const DiagnosticLocation &Loc = DiagnosticLocation(),
       DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
@@ -1082,7 +1081,7 @@ class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
     return DI->getKind() == DK_Unsupported;
   }
 
-  const Twine &getMessage() const { return Msg; }
+  const StringRef getMessage() const { return Msg; }
 
   void print(DiagnosticPrinter &DP) const override;
 };
@@ -1090,7 +1089,7 @@ class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
 /// Diagnostic information for MisExpect analysis.
 class DiagnosticInfoMisExpect : public DiagnosticInfoWithLocationBase {
 public:
-  DiagnosticInfoMisExpect(const Instruction *Inst, Twine &Msg);
+  DiagnosticInfoMisExpect(const Instruction *Inst, StringRef Msg);
 
   /// \see DiagnosticInfo::print.
   void print(DiagnosticPrinter &DP) const override;
@@ -1099,11 +1098,11 @@ class DiagnosticInfoMisExpect : public DiagnosticInfoWithLocationBase {
     return DI->getKind() == DK_MisExpect;
   }
 
-  const Twine &getMsg() const { return Msg; }
+  StringRef getMsg() const { return Msg; }
 
 private:
   /// Message to report.
-  const Twine &Msg;
+  StringRef Msg;
 };
 
 static DiagnosticSeverity getDiagnosticSeverity(SourceMgr::DiagKind DK) {
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index 76c7cecded629..d3f29d52f0c4b 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -449,8 +449,9 @@ class SampleProfileReader {
 
   /// Report a parse error message.
   void reportError(int64_t LineNumber, const Twine &Msg) const {
-    Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
-                                             LineNumber, Msg));
+    SmallString<128> Storage;
+    Ctx.diagnose(DiagnosticInfoSampleProfile(
+        Buffer->getBufferIdentifier(), LineNumber, Msg.toStringRef(Storage)));
   }
 
   /// Create a sample profile reader appropriate to the file format.
diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h
index d714dba4a9687..1a63d3ed96438 100644
--- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h
+++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LoopInfo.h"
@@ -39,6 +40,7 @@
 #include "llvm/ProfileData/SampleProf.h"
 #include "llvm/ProfileData/SampleProfReader.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/GenericDomTree.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/SampleProfileInference.h"
@@ -1104,12 +1106,13 @@ void SampleProfileLoaderBaseImpl<BT>::emitCoverageRemarks(FunctionT &F) {
     unsigned Used = CoverageTracker.countUsedRecords(Samples, PSI);
     unsigned Total = CoverageTracker.countBodyRecords(Samples, PSI);
     unsigned Coverage = CoverageTracker.computeCoverage(Used, Total);
+    SmallString<128> Msg =
+        formatv("{0} of {1} available profile records ({2}%) were applied",
+                Used, Total, Coverage);
     if (Coverage < SampleProfileRecordCoverage) {
-      Func.getContext().diagnose(DiagnosticInfoSampleProfile(
-          Func.getSubprogram()->getFilename(), getFunctionLoc(F),
-          Twine(Used) + " of " + Twine(Total) + " available profile records (" +
-              Twine(Coverage) + "%) were applied",
-          DS_Warning));
+      Func.getContext().diagnose(
+          DiagnosticInfoSampleProfile(Func.getSubprogram()->getFilename(),
+                                      getFunctionLoc(F), Msg, DS_Warning));
     }
   }
 
@@ -1117,12 +1120,13 @@ void SampleProfileLoaderBaseImpl<BT>::emitCoverageRemarks(FunctionT &F) {
     uint64_t Used = CoverageTracker.getTotalUsedSamples();
     uint64_t Total = CoverageTracker.countBodySamples(Samples, PSI);
     unsigned Coverage = CoverageTracker.computeCoverage(Used, Total);
+    SmallString<128> Msg =
+        formatv("{0} of {1} available profile samples ({2}%) were applied",
+                Used, Total, Coverage);
     if (Coverage < SampleProfileSampleCoverage) {
-      Func.getContext().diagnose(DiagnosticInfoSampleProfile(
-          Func.getSubprogram()->getFilename(), getFunctionLoc(F),
-          Twine(Used) + " of " + Twine(Total) + " available profile samples (" +
-              Twine(Coverage) + "%) were applied",
-          DS_Warning));
+      Func.getContext().diagnose(
+          DiagnosticInfoSampleProfile(Func.getSubprogram()->getFilename(),
+                                      getFunctionLoc(F), Msg, DS_Warning));
     }
   }
 }
@@ -1149,10 +1153,11 @@ unsigned SampleProfileLoaderBaseImpl<BT>::getFunctionLoc(FunctionT &F) {
 
   // If the start of \p F is missing, emit a diagnostic to inform the user
   // about the missed opportunity.
-  Func.getContext().diagnose(DiagnosticInfoSampleProfile(
-      "No debug information found in function " + Func.getName() +
-          ": Function profile not used",
-      DS_Warning));
+  SmallString<128> Msg = formatv(
+      "No debug information found in function {0}: Function profile not used",
+      Func.getName());
+
+  Func.getContext().diagnose(DiagnosticInfoSampleProfile(Msg, DS_Warning));
   return 0;
 }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 59fc4cfc23e10..217ce0a298e19 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -34,6 +34,7 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
@@ -313,9 +314,9 @@ static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
         }
         if (Error) {
           const Function &Fn = MI->getMF()->getFunction();
-          Fn.getContext().diagnose(DiagnosticInfoInlineAsm(
-              LocCookie,
-              "invalid operand in inline asm: '" + Twine(AsmStr) + "'"));
+          SmallString<128> Msg =
+              formatv("invalid operand in inline asm: '{0}'", AsmStr);
+          Fn.getContext().diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg));
         }
       }
       break;
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 33910d0ec6aeb..70e0314f3d281 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2332,13 +2332,15 @@ void MachineInstr::emitInlineAsmError(const Twine &Msg) const {
           ? mdconst::extract<ConstantInt>(LocMD->getOperand(0))->getZExtValue()
           : 0;
   LLVMContext &Ctx = getMF()->getFunction().getContext();
-  Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg));
+  SmallString<128> Storage;
+  Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg.toStringRef(Storage)));
 }
 
 void MachineInstr::emitGenericError(const Twine &Msg) const {
   const Function &Fn = getMF()->getFunction();
-  Fn.getContext().diagnose(
-      DiagnosticInfoGenericWithLoc(Msg, Fn, getDebugLoc()));
+  SmallString<128> Storage;
+  Fn.getContext().diagnose(DiagnosticInfoGenericWithLoc(
+      Msg.toStringRef(Storage), Fn, getDebugLoc()));
 }
 
 MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index d7a67cca3c197..ef253d938739e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -316,15 +316,16 @@ getCopyFromParts(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts,
 }
 
 static void diagnosePossiblyInvalidConstraint(LLVMContext &Ctx, const Value *V,
-                                              const Twine &ErrMsg) {
+                                              StringRef ErrMsg) {
   const Instruction *I = dyn_cast_or_null<Instruction>(V);
   if (!I)
     return Ctx.emitError(ErrMsg);
 
   if (const CallInst *CI = dyn_cast<CallInst>(I))
     if (CI->isInlineAsm()) {
-      return Ctx.diagnose(DiagnosticInfoInlineAsm(
-          *CI, ErrMsg + ", possible invalid constraint for vector type"));
+      SmallString<128> Msg(
+          {ErrMsg, ", possible invalid constraint for vector type"});
+      return Ctx.diagnose(DiagnosticInfoInlineAsm(*CI, Msg));
     }
 
   return Ctx.emitError(I, ErrMsg);
@@ -10445,7 +10446,8 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
 void SelectionDAGBuilder::emitInlineAsmError(const CallBase &Call,
                                              const Twine &Message) {
   LLVMContext &Ctx = *DAG.getContext();
-  Ctx.diagnose(DiagnosticInfoInlineAsm(Call, Message));
+  SmallString<128> Storage;
+  Ctx.diagnose(DiagnosticInfoInlineAsm(Call, Message.toStringRef(Storage)));
 
   // Make sure we leave the DAG in a valid state
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp
index 0e526ada4b405..938d8642ff14c 100644
--- a/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/llvm/lib/IR/DiagnosticInfo.cpp
@@ -13,7 +13,6 @@
 
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Twine.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Demangle/Demangle.h"
 #include "llvm/IR/BasicBlock.h"
@@ -57,13 +56,13 @@ void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const {
 }
 
 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie,
-                                                 const Twine &MsgStr,
+                                                 StringRef MsgStr,
                                                  DiagnosticSeverity Severity)
     : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
       MsgStr(MsgStr) {}
 
 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
-                                                 const Twine &MsgStr,
+                                                 StringRef MsgStr,
                                                  DiagnosticSeverity Severity)
     : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
   if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
@@ -81,14 +80,14 @@ void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
 }
 
 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
-    const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,
+    StringRef MsgStr, const Function &Fn, const DiagnosticLocation &DL,
     DiagnosticSeverity Severity)
     : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
                                      DL.isValid() ? DL : Fn.getSubprogram()),
       MsgStr(MsgStr) {}
 
 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(
-    const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)
+    StringRef MsgStr, const Function &Fn, DiagnosticSeverity Severity)
     : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,
                                      Fn.getSubprogram()),
       MsgStr(MsgStr) {}
@@ -443,7 +442,7 @@ std::string DiagnosticInfoOptimizationBase::getMsg() const {
 }
 
 DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,
-                                                 Twine &Msg)
+                                                 StringRef Msg)
     : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,
                                      *Inst->getParent()->getParent(),
                                      Inst->getDebugLoc()),
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 447e5d92e0b99..1000d22435337 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/IR/LLVMContext.h"
 #include "LLVMContextImpl.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -204,12 +205,14 @@ void LLVMContext::yield() {
 }
 
 void LLVMContext::emitError(const Twine &ErrorStr) {
-  diagnose(DiagnosticInfoGeneric(ErrorStr));
+  SmallString<128> Storage;
+  diagnose(DiagnosticInfoGeneric(ErrorStr.toStringRef(Storage)));
 }
 
 void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
   assert(I && "Invalid instruction");
-  diagnose(DiagnosticInfoGeneric(I, ErrorStr));
+  SmallString<128> Storage;
+  diagnose(DiagnosticInfoGeneric(I, ErrorStr.toStringRef(Storage)));
 }
 
 static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 3ba0535e0114b..ab701da324355 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -34,9 +34,8 @@
 using namespace llvm;
 using namespace llvm::dxil;
 
-static bool reportError(LLVMContext *Ctx, Twine Message,
-                        DiagnosticSeverity Severity = DS_Error) {
-  Ctx->diagnose(DiagnosticInfoGeneric(Message, Severity));
+static bool reportError(LLVMContext *Ctx, Twine Message) {
+  Ctx->emitError(Message);
   return true;
 }
 
diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
index 7c73c16db02c8..a319635aa18e9 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
@@ -404,6 +404,13 @@ class FunctionInstrumenter final {
 };
 } // namespace
 
+static void emitDiagnostic(LLVMContext &Ctx, StringRef Filename,
+                           const Twine &Msg, DiagnosticSeverity Severity) {
+  SmallString<128> Storage;
+  Ctx.diagnose(DiagnosticInfoPGOProfile(Filename.data(),
+                                        Msg.toStringRef(Storage), Severity));
+}
+
 // Return a string describing the branch condition that can be
 // used in static branch probability heuristics:
 static std::string getBranchCondString(Instruction *TI) {
@@ -1434,8 +1441,7 @@ void PGOUseFunc::handleInstrProfError(Error Err, uint64_t MismatchedFuncSum) {
         std::string(" up to ") + std::to_string(MismatchedFuncSum) +
         std::string(" count discarded");
 
-    Ctx.diagnose(
-        DiagnosticInfoPGOProfile(M->getName().data(), Msg, DS_Warning));
+    emitDiagnostic(Ctx, M->getName(), Msg, DS_Warning);
   });
 }
 
@@ -1478,12 +1484,12 @@ bool PGOUseFunc::readCounters(IndexedInstrProfReader *PGOReader, bool &AllZeros,
   if (!setInstrumentedCounts(CountFromProfile)) {
     LLVM_DEBUG(
         dbgs() << "Inconsistent number of counts, skipping this function");
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        M->getName().data(),
+    emitDiagnostic(
+        Ctx, M->getName(),
         Twine("Inconsistent number of counts in ") + F.getName().str() +
             Twine(": the profile may be stale or there is a function name "
                   "collision."),
-        DS_Warning));
+        DS_Warning);
     return false;
   }
   ProgramMaxCount = PGOReader->getMaximumFunctionCount(IsCS);
@@ -1590,12 +1596,11 @@ void PGOUseFunc::populateCoverage(IndexedInstrProfReader *PGOReader) {
       ++NumCoveredBlocks;
   }
   if (PGOVerifyBFI && NumCorruptCoverage) {
-    auto &Ctx = M->getContext();
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        M->getName().data(),
-        Twine("Found inconsistent block coverage for function ") + F.getName() +
-            " in " + Twine(NumCorruptCoverage) + " blocks.",
-        DS_Warning));
+    emitDiagnostic(M->getContext(), M->getName(),
+                   Twine("Found inconsistent block coverage for function ") +
+                       F.getName() + " in " + Twine(NumCorruptCoverage) +
+                       " blocks.",
+                   DS_Warning);
   }
   if (PGOViewBlockCoverageGraph)
     FuncInfo.BCI->viewBlockCoverageGraph(&Coverage);
@@ -1729,13 +1734,11 @@ void PGOUseFunc::setBranchWeights() {
       // A zero MaxCount can come about when we have a BB with a positive
       // count, and whose successor blocks all have 0 count. This can happen
       // when there is no exit block and the code exits via a noreturn function.
-      auto &Ctx = M->getContext();
-      Ctx.diagnose(DiagnosticInfoPGOProfile(
-          M->getName().data(),
-          Twine("Profile in ") + F.getName().str() +
-              Twine(" partially ignored") +
-              Twine(", possibly due to the lack of a return path."),
-          DS_Warning));
+      emitDiagnostic(M->getContext(), M->getName(),
+                     Twine("Profile in ") + F.getName().str() +
+                         Twine(" partially ignored") +
+                         Twine(", possibly due to the lack of a return path."),
+                     DS_Warning);
     }
   }
 }
@@ -1865,14 +1868,12 @@ void PGOUseFunc::annotateValueSites(uint32_t Kind) {
     FuncInfo.ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget);
   auto &ValueSites = FuncInfo.ValueSites[Kind];
   if (NumValueSites != ValueSites.size()) {
-    auto &Ctx = M->getContext();
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        M->getName().data(),
-        Twine("Inconsistent number of value sites for ") +
-            Twine(ValueProfKindDescr[Kind]) + Twine(" profiling in \"") +
-            F.getName().str() +
-            Twine("\", possibly due to the use of a stale profile."),
-        DS_Warning));
+    emitDiagnostic(M->getContext(), M->getName(),
+                   Twine("Inconsistent number of value sites for ") +
+                       Twine(ValueProfKindDescr[Kind]) +
+                       Twine(" profiling in \"") + F.getName().str() +
+                       Twine("\", possibly due to the use of a stale profile."),
+                   DS_Warning);
     return;
   }
 
@@ -1962,13 +1963,11 @@ static bool InstrumentAllFunctions(
     createIRLevelProfileFlagVar(M, InstrumentationType);
 
   Triple TT(M.getTargetTriple());
-  LLVMContext &Ctx = M.getContext();
   if (!TT.isOSBinFormatELF() && EnableVTableValueProfiling)
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        M.getName().data(),
-        Twine("VTable value profiling is presently not "
-              "supported for non-ELF object formats"),
-        DS_Warning));
+    emitDiagnostic(M.getContext(), M.getName(),
+                   Twine("VTable value profiling is presently not "
+                         "supported for non-ELF object formats"),
+                   DS_Warning);
   std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
   collectComdatMembers(M, ComdatMembers);
 
@@ -2161,8 +2160,7 @@ static bool annotateAllFunctions(
                                                     ProfileRemappingFileName);
   if (Error E = ReaderOrErr.takeError()) {
     handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
-      Ctx.diagnose(
-          DiagnosticInfoPGOProfile(ProfileFileName.data(), EI.message()));
+      emitDiagnostic(Ctx, ProfileFileName, EI.message(), DS_Error);
     });
     return false;
   }
@@ -2170,8 +2168,7 @@ static bool annotateAllFunctions(
   std::unique_ptr<IndexedInstrProfReader> PGOReader =
       std::move(ReaderOrErr.get());
   if (!PGOReader) {
-    Ctx.diagnose(DiagnosticInfoPGOProfile(ProfileFileName.data(),
-                                          StringRef("Cannot get PGOReader")));
+    emitDiagnostic(Ctx, ProfileFileName, "Cannot get PGOReader", DS_Error);
     return false;
   }
   if (!PGOReader->hasCSIRLevelProfile() && IsCS)
@@ -2179,14 +2176,15 @@ static bool annotateAllFunctions(
 
   // TODO: might need to change the warning once the clang option is finalized.
   if (!PGOReader->isIRLevelProfile()) {
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        ProfileFileName.data(), "Not an IR level instrumentation profile"));
+    emitDiagnostic(Ctx, ProfileFileName,
+                   "Not an IR level instrumentation profile", DS_Error);
     return false;
   }
   if (PGOReader->functionEntryOnly()) {
-    Ctx.diagnose(DiagnosticInfoPGOProfile(
-        ProfileFileName.data(),
-        "Function entry profiles are not yet supported for optimization"));
+    emitDiagnostic(
+        Ctx, ProfileFileName,
+        "Function entry profiles are not yet supported for optimization",
+        DS_Error);
     return false;
   }
 
@@ -2335,12 +2333,11 @@ static bool annotateAllFunctions(
     // Only set when there is no Attribute::Hot set by the user. For Hot
     // attribute, user's annotation has the precedence over the profile.
     if (F->hasFnAttribute(Attribute::Hot)) {
-      auto &Ctx = M.getContext();
-      std::string Msg = std::string("Function ") + F->getName().str() +
-                        std::string(" is annotated as a hot function but"
-                                    " the profile is cold");
-      Ctx.diagnose(
-          DiagnosticInfoPGOProfile(M.getName().data(), Msg, DS_Warning));
+      emitDiagnostic(M.getContext(), M.getName(),
+                     Twine("Function ") + F->getName().str() +
+                         Twine(" is annotated as a hot function but"
+                               " the profile is cold"),
+                     DS_Warning);
       continue;
     }
     F->addFnAttr(Attribute::Cold);
diff --git a/llvm/lib/Transforms/Utils/MisExpect.cpp b/llvm/lib/Transforms/Utils/MisExpect.cpp
index 7074376feed9c..9d195a86a5d76 100644
--- a/llvm/lib/Transforms/Utils/MisExpect.cpp
+++ b/llvm/lib/Transforms/Utils/MisExpect.cpp
@@ -100,18 +100,17 @@ Instruction *getInstCondition(Instruction *I) {
 void emitMisexpectDiagnostic(Instruction *I, LLVMContext &Ctx,
                              uint64_t ProfCount, uint64_t TotalCount) {
   double PercentageCorrect = (double)ProfCount / TotalCount;
-  auto PerString =
+  SmallString<32> PerString =
       formatv("{0:P} ({1} / {2})", PercentageCorrect, ProfCount, TotalCount);
-  auto RemStr = formatv(
+  SmallString<128> RemStr = formatv(
       "Potential performance regression from use of the llvm.expect intrinsic: "
       "Annotation was correct on {0} of profiled executions.",
       PerString);
-  Twine Msg(PerString);
   Instruction *Cond = getInstCondition(I);
   if (isMisExpectDiagEnabled(Ctx))
-    Ctx.diagnose(DiagnosticInfoMisExpect(Cond, Msg));
+    Ctx.diagnose(DiagnosticInfoMisExpect(Cond, PerString));
   OptimizationRemarkEmitter ORE(I->getParent()->getParent());
-  ORE.emit(OptimizationRemark(DEBUG_TYPE, "misexpect", Cond) << RemStr.str());
+  ORE.emit(OptimizationRemark(DEBUG_TYPE, "misexpect", Cond) << RemStr);
 }
 
 } // namespace

>From 1695f8810917a9e61113ba05db276e15d2e48a6e Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Mon, 21 Apr 2025 01:10:49 -0600
Subject: [PATCH 2/5] fixup: Fix target specific diags that were missed

---
 llvm/include/llvm/IR/DiagnosticPrinter.h      |  3 ---
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  | 25 +++++++++++--------
 llvm/lib/IR/DiagnosticPrinter.cpp             |  5 ----
 llvm/lib/LTO/LTOCodeGenerator.cpp             |  4 +--
 llvm/lib/LTO/ThinLTOCodeGenerator.cpp         |  4 +--
 llvm/lib/Linker/IRMover.cpp                   |  6 +++--
 llvm/lib/Linker/LinkDiagnosticInfo.h          |  4 +--
 llvm/lib/Linker/LinkModules.cpp               |  5 +++-
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp   | 22 ++++++++--------
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 12 ++++-----
 llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp     |  5 ++--
 llvm/lib/Target/BPF/BPFISelLowering.cpp       |  9 ++++---
 .../Target/BPF/BPFPreserveStaticOffset.cpp    | 17 ++++++-------
 .../Target/DirectX/DXILTranslateMetadata.cpp  | 23 +++++++++--------
 llvm/lib/Transforms/Instrumentation/KCFI.cpp  |  4 +--
 15 files changed, 76 insertions(+), 72 deletions(-)

diff --git a/llvm/include/llvm/IR/DiagnosticPrinter.h b/llvm/include/llvm/IR/DiagnosticPrinter.h
index 2df6fc3dfe739..d92164e6a7248 100644
--- a/llvm/include/llvm/IR/DiagnosticPrinter.h
+++ b/llvm/include/llvm/IR/DiagnosticPrinter.h
@@ -24,7 +24,6 @@ class Module;
 class raw_ostream;
 class SMDiagnostic;
 class StringRef;
-class Twine;
 class Value;
 
 /// Interface for custom diagnostic printing.
@@ -47,7 +46,6 @@ class DiagnosticPrinter {
   virtual DiagnosticPrinter &operator<<(unsigned int N) = 0;
   virtual DiagnosticPrinter &operator<<(int N) = 0;
   virtual DiagnosticPrinter &operator<<(double N) = 0;
-  virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0;
 
   // IR related types.
   virtual DiagnosticPrinter &operator<<(const Value &V) = 0;
@@ -80,7 +78,6 @@ class DiagnosticPrinterRawOStream : public DiagnosticPrinter {
   DiagnosticPrinter &operator<<(unsigned int N) override;
   DiagnosticPrinter &operator<<(int N) override;
   DiagnosticPrinter &operator<<(double N) override;
-  DiagnosticPrinter &operator<<(const Twine &Str) override;
 
   // IR related types.
   DiagnosticPrinter &operator<<(const Value &V) override;
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index c9415292e88f7..b8d2a7f6cca9c 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -64,6 +64,7 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/Triple.h"
@@ -706,10 +707,10 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
 
 namespace {
 class LoweringDiagnosticInfo : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 
 public:
-  LoweringDiagnosticInfo(const Twine &DiagMsg,
+  LoweringDiagnosticInfo(StringRef DiagMsg,
                          DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Lowering, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
@@ -869,15 +870,17 @@ static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO,
     // been placed in an incompatible mergeable section. Emit an error if this
     // is the case to avoid creating broken output.
     if ((Section->getFlags() & ELF::SHF_MERGE) &&
-        (Section->getEntrySize() != getEntrySizeForKind(Kind)))
-      GO->getContext().diagnose(LoweringDiagnosticInfo(
-          "Symbol '" + GO->getName() + "' from module '" +
-          (GO->getParent() ? GO->getParent()->getSourceFileName() : "unknown") +
-          "' required a section with entry-size=" +
-          Twine(getEntrySizeForKind(Kind)) + " but was placed in section '" +
-          SectionName + "' with entry-size=" + Twine(Section->getEntrySize()) +
-          ": Explicit assignment by pragma or attribute of an incompatible "
-          "symbol to this section?"));
+        (Section->getEntrySize() != getEntrySizeForKind(Kind))) {
+      SmallString<128> Msg = formatv(
+          "Symbol '{0}' from module '{1}' required a section with "
+          "entry-size={2} but was placed in section '{3}' with entry-size={4}: "
+          "Explicit assignment by pragma or attribute of an incompatible "
+          "symbol to this section?",
+          GO->getName(),
+          GO->getParent() ? GO->getParent()->getSourceFileName() : "unknown",
+          getEntrySizeForKind(Kind), SectionName, Section->getEntrySize());
+      GO->getContext().diagnose(LoweringDiagnosticInfo(Msg));
+    }
   }
 
   return Section;
diff --git a/llvm/lib/IR/DiagnosticPrinter.cpp b/llvm/lib/IR/DiagnosticPrinter.cpp
index 5ded23403b41e..58de06f04ae15 100644
--- a/llvm/lib/IR/DiagnosticPrinter.cpp
+++ b/llvm/lib/IR/DiagnosticPrinter.cpp
@@ -90,11 +90,6 @@ DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(double N) {
   return *this;
 }
 
-DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Twine &Str) {
-  Str.print(Stream);
-  return *this;
-}
-
 // IR related types.
 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Value &V) {
   // Avoid printing '@' prefix for named functions.
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
index 70b7135fcbef0..a0c0ed3e9b8b4 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -744,9 +744,9 @@ LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
 
 namespace {
 class LTODiagnosticInfo : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 public:
-  LTODiagnosticInfo(const Twine &DiagMsg, DiagnosticSeverity Severity=DS_Error)
+  LTODiagnosticInfo(StringRef DiagMsg, DiagnosticSeverity Severity=DS_Error)
       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
 };
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 9e7f8187fe49c..fce154b0da7c8 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -165,9 +165,9 @@ static void promoteModule(Module &TheModule, const ModuleSummaryIndex &Index,
 
 namespace {
 class ThinLTODiagnosticInfo : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 public:
-  ThinLTODiagnosticInfo(const Twine &DiagMsg,
+  ThinLTODiagnosticInfo(StringRef DiagMsg,
                         DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index e732367b5127e..f4a8fff3ef228 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -340,7 +340,7 @@ Type *TypeMapTy::get(Type *Ty, SmallPtrSet<StructType *, 8> &Visited) {
 }
 
 LinkDiagnosticInfo::LinkDiagnosticInfo(DiagnosticSeverity Severity,
-                                       const Twine &Msg)
+                                       StringRef Msg)
     : DiagnosticInfo(DK_Linker, Severity), Msg(Msg) {}
 void LinkDiagnosticInfo::print(DiagnosticPrinter &DP) const { DP << Msg; }
 
@@ -438,7 +438,9 @@ class IRLinker {
   GlobalValue *copyGlobalValueProto(const GlobalValue *SGV, bool ForDefinition);
 
   void emitWarning(const Twine &Message) {
-    SrcM->getContext().diagnose(LinkDiagnosticInfo(DS_Warning, Message));
+    SmallString<128> Storage;
+    SrcM->getContext().diagnose(
+        LinkDiagnosticInfo(DS_Warning, Message.toStringRef(Storage)));
   }
 
   /// Given a global in the source module, return the global in the
diff --git a/llvm/lib/Linker/LinkDiagnosticInfo.h b/llvm/lib/Linker/LinkDiagnosticInfo.h
index 30c16abaf5090..e43ac93cdb8a2 100644
--- a/llvm/lib/Linker/LinkDiagnosticInfo.h
+++ b/llvm/lib/Linker/LinkDiagnosticInfo.h
@@ -13,10 +13,10 @@
 
 namespace llvm {
 class LinkDiagnosticInfo : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 
 public:
-  LinkDiagnosticInfo(DiagnosticSeverity Severity, const Twine &Msg);
+  LinkDiagnosticInfo(DiagnosticSeverity Severity, StringRef Msg);
   void print(DiagnosticPrinter &DP) const override;
 };
 }
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp
index 485ac106d4ebb..c5ad1fe98aa52 100644
--- a/llvm/lib/Linker/LinkModules.cpp
+++ b/llvm/lib/Linker/LinkModules.cpp
@@ -13,6 +13,7 @@
 #include "LinkDiagnosticInfo.h"
 #include "llvm-c/Linker.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/LLVMContext.h"
@@ -58,7 +59,9 @@ class ModuleLinker {
 
   /// Should we have mover and linker error diag info?
   bool emitError(const Twine &Message) {
-    SrcM->getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message));
+    SmallString<128> Storage;
+    SrcM->getContext().diagnose(
+        LinkDiagnosticInfo(DS_Error, Message.toStringRef(Storage)));
     return true;
   }
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index 800e2b9c0e657..a89b41afb1d1c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -31,6 +31,7 @@
 #include "Utils/AMDGPUBaseInfo.h"
 #include "Utils/AMDKernelCodeTUtils.h"
 #include "Utils/SIDefinesUtils.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -43,6 +44,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/AMDHSAKernelDescriptor.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/TargetParser.h"
@@ -466,12 +468,11 @@ void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
           F, "amdgpu-waves-per-eu", {0, 0}, true);
 
       if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
-        DiagnosticInfoOptimizationFailure Diag(
-            F, F.getSubprogram(),
+        SmallString<256> Msg = formatv(
             "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
-            "'" +
-                F.getName() + "': desired occupancy was " + Twine(MinWEU) +
-                ", final occupancy is " + Twine(Occupancy));
+            "'{0}': desired occupancy was {1}, final occupancy is {2}",
+            F.getName(), MinWEU, Occupancy);
+        DiagnosticInfoOptimizationFailure Diag(F, F.getSubprogram(), Msg);
         F.getContext().diagnose(Diag);
         return;
       }
@@ -1261,13 +1262,12 @@ void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
       AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
   uint64_t Occupancy;
   if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
-    DiagnosticInfoOptimizationFailure Diag(
-        F, F.getSubprogram(),
+    SmallString<256> Msg = formatv(
         "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
-        "'" +
-            F.getName() + "': desired occupancy was " + Twine(MinWEU) +
-            ", final occupancy is " + Twine(Occupancy));
-    F.getContext().diagnose(Diag);
+        "'{0}'': desired occupancy was {1}, final occupancy is {2}",
+        F.getName(), MinWEU, Occupancy);
+    F.getContext().diagnose(
+        DiagnosticInfoOptimizationFailure(F, F.getSubprogram(), Msg));
   }
 
   if (isGFX11Plus(STM)) {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 2846405a2538c..1b36f4c93f749 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -1376,15 +1376,15 @@ SDValue AMDGPUTargetLowering::lowerUnhandledCall(CallLoweringInfo &CLI,
 
   const Function &Fn = DAG.getMachineFunction().getFunction();
 
-  StringRef FuncName("<unknown>");
-
+  SmallString<128> Msg = Reason;
   if (const ExternalSymbolSDNode *G = dyn_cast<ExternalSymbolSDNode>(Callee))
-    FuncName = G->getSymbol();
+    Msg.append(G->getSymbol());
   else if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    FuncName = G->getGlobal()->getName();
+    Msg.append(G->getGlobal()->getName());
+  else
+    Msg.append("<unknown>");
 
-  DiagnosticInfoUnsupported NoCalls(
-    Fn, Reason + FuncName, CLI.DL.getDebugLoc());
+  DiagnosticInfoUnsupported NoCalls(Fn, Msg, CLI.DL.getDebugLoc());
   DAG.getContext()->diagnose(NoCalls);
 
   if (!CLI.IsTailCall) {
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index c1ac9491b2363..cbf265875ff01 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -47,8 +47,9 @@ static const std::array<unsigned, 17> SubRegFromChannelTableWidthMap = {
 
 static void emitUnsupportedError(const Function &Fn, const MachineInstr &MI,
                                  const Twine &ErrMsg) {
-  Fn.getContext().diagnose(
-      DiagnosticInfoUnsupported(Fn, ErrMsg, MI.getDebugLoc()));
+  SmallString<128> Storage;
+  Fn.getContext().diagnose(DiagnosticInfoUnsupported(
+      Fn, ErrMsg.toStringRef(Storage), MI.getDebugLoc()));
 }
 
 namespace llvm {
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 6c196309d2d1a..6e688a0ba5b00 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -38,15 +38,16 @@ static cl::opt<bool> BPFExpandMemcpyInOrder("bpf-expand-memcpy-in-order",
 
 static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg,
                  SDValue Val = {}) {
-  std::string Str;
+  SmallString<128> FullMsg;
   if (Val) {
-    raw_string_ostream OS(Str);
+    raw_svector_ostream OS(FullMsg);
     Val->print(OS);
     OS << ' ';
   }
+  Msg.toVector(FullMsg);
   MachineFunction &MF = DAG.getMachineFunction();
-  DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
-      MF.getFunction(), Twine(Str).concat(Msg), DL.getDebugLoc()));
+  DAG.getContext()->diagnose(
+      DiagnosticInfoUnsupported(MF.getFunction(), FullMsg, DL.getDebugLoc()));
 }
 
 BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
diff --git a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp
index 2b890ddccf628..7315001557161 100644
--- a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp
+++ b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp
@@ -393,15 +393,14 @@ static bool foldGEPChainAsU8Access(SmallVector<GetElementPtrInst *> &GEPs,
 }
 
 static void reportNonStaticGEPChain(Instruction *Insn) {
-  auto Msg = DiagnosticInfoUnsupported(
-      *Insn->getFunction(),
-      Twine("Non-constant offset in access to a field of a type marked "
-            "with preserve_static_offset might be rejected by BPF verifier")
-          .concat(Insn->getDebugLoc()
-                      ? ""
-                      : " (pass -g option to get exact location)"),
-      Insn->getDebugLoc(), DS_Warning);
-  Insn->getContext().diagnose(Msg);
+  SmallString<256> Msg(
+      "Non-constant offset in access to a field of a type marked with "
+      "preserve_static_offset might be rejected by BPF verifier");
+  if (Insn->getDebugLoc())
+    Msg.append(" (pass -g option to get exact location)");
+
+  Insn->getContext().diagnose(DiagnosticInfoUnsupported(
+      *Insn->getFunction(), Msg, Insn->getDebugLoc(), DS_Warning));
 }
 
 static bool allZeroIndices(SmallVector<GetElementPtrInst *> &GEPs) {
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index e177fcb0520e8..70851d461bb8d 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -1,3 +1,5 @@
+
+
 //===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata -------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -9,6 +11,7 @@
 #include "DXILTranslateMetadata.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
@@ -26,6 +29,7 @@
 #include "llvm/InitializePasses.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/VersionTuple.h"
 #include "llvm/TargetParser/Triple.h"
 #include <cstdint>
@@ -38,14 +42,14 @@ namespace {
 /// for TranslateMetadata pass
 class DiagnosticInfoTranslateMD : public DiagnosticInfo {
 private:
-  const Twine &Msg;
+  StringRef Msg;
   const Module &Mod;
 
 public:
   /// \p M is the module for which the diagnostic is being emitted. \p Msg is
   /// the message to show. Note that this class does not copy this message, so
   /// this reference must be valid for the whole life time of the diagnostic.
-  DiagnosticInfoTranslateMD(const Module &M, const Twine &Msg,
+  DiagnosticInfoTranslateMD(const Module &M, StringRef Msg,
                             DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Unsupported, Severity), Msg(Msg), Mod(M) {}
 
@@ -358,14 +362,13 @@ static void translateMetadata(Module &M, DXILResourceMap &DRM,
     if (MMDI.ShaderProfile != Triple::EnvironmentType::Library) {
       EntryShaderFlags = EntrySFMask;
       if (EntryProp.ShaderStage != MMDI.ShaderProfile) {
-        M.getContext().diagnose(DiagnosticInfoTranslateMD(
-            M,
-            "Shader stage '" +
-                Twine(getShortShaderStage(EntryProp.ShaderStage) +
-                      "' for entry '" + Twine(EntryProp.Entry->getName()) +
-                      "' different from specified target profile '" +
-                      Twine(Triple::getEnvironmentTypeName(MMDI.ShaderProfile) +
-                            "'"))));
+        SmallString<256> Msg =
+            formatv("Shader stage '{0}' for entry '{1}' different from "
+                    "specified target profile '{2}'",
+                    getShortShaderStage(EntryProp.ShaderStage),
+                    EntryProp.Entry->getName(),
+                    Triple::getEnvironmentTypeName(MMDI.ShaderProfile));
+        M.getContext().diagnose(DiagnosticInfoTranslateMD(M, Msg));
       }
     }
     EntryFnMDNodes.emplace_back(emitEntryMD(EntryProp, Signatures, ResourceMD,
diff --git a/llvm/lib/Transforms/Instrumentation/KCFI.cpp b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
index bfed678854943..cde87d910d9a5 100644
--- a/llvm/lib/Transforms/Instrumentation/KCFI.cpp
+++ b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
@@ -34,10 +34,10 @@ STATISTIC(NumKCFIChecks, "Number of kcfi operands transformed into checks");
 
 namespace {
 class DiagnosticInfoKCFI : public DiagnosticInfo {
-  const Twine &Msg;
+  StringRef Msg;
 
 public:
-  DiagnosticInfoKCFI(const Twine &DiagMsg,
+  DiagnosticInfoKCFI(StringRef DiagMsg,
                      DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }

>From c454daff38b3f11dca566055c9054d053551b0f4 Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Mon, 21 Apr 2025 01:46:36 -0600
Subject: [PATCH 3/5] fixup: clean up uses where the string *was* copied

These uses were fine, but the comment that claimed the string isn't
copied are just incorrect.
---
 llvm/include/llvm/IR/DiagnosticInfo.h       | 40 +++++++--------------
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 24 +++++++------
 2 files changed, 26 insertions(+), 38 deletions(-)

diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 151f323447bfb..e3973b38bb16d 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -700,13 +700,11 @@ class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
   /// the location information to use in the diagnostic. If line table
   /// information is available, the diagnostic will include the source code
-  /// location. \p Msg is the message to show. Note that this class does not
-  /// copy this message, so this reference must be valid for the whole life time
-  /// of the diagnostic.
+  /// location. \p Msg is the message to show.
   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
                                enum DiagnosticSeverity Severity,
                                const char *PassName, const Function &Fn,
-                               const DiagnosticLocation &Loc, StringRef Msg)
+                               const DiagnosticLocation &Loc, const Twine &Msg)
       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
     *this << Msg.str();
   }
@@ -760,10 +758,8 @@ class OptimizationRemark : public DiagnosticInfoIROptimization {
   /// is being emitted. \p Loc is the location information to use in the
   /// diagnostic. If line table information is available, the diagnostic
   /// will include the source code location. \p Msg is the message to show.
-  /// Note that this class does not copy this message, so this reference
-  /// must be valid for the whole life time of the diagnostic.
   OptimizationRemark(const char *PassName, const Function &Fn,
-                     const DiagnosticLocation &Loc, StringRef Msg)
+                     const DiagnosticLocation &Loc, const Twine &Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
                                      Fn, Loc, Msg) {}
 };
@@ -806,10 +802,8 @@ class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
   /// is being emitted. \p Loc is the location information to use in the
   /// diagnostic. If line table information is available, the diagnostic
   /// will include the source code location. \p Msg is the message to show.
-  /// Note that this class does not copy this message, so this reference
-  /// must be valid for the whole life time of the diagnostic.
   OptimizationRemarkMissed(const char *PassName, const Function &Fn,
-                           const DiagnosticLocation &Loc, StringRef Msg)
+                           const DiagnosticLocation &Loc, const Twine &Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
                                      PassName, Fn, Loc, Msg) {}
 };
@@ -862,7 +856,7 @@ class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
 protected:
   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
                              const Function &Fn, const DiagnosticLocation &Loc,
-                             StringRef Msg)
+                             const Twine &Msg)
       : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
 
   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
@@ -877,11 +871,9 @@ class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
   /// is being emitted. \p Loc is the location information to use in the
   /// diagnostic. If line table information is available, the diagnostic will
-  /// include the source code location. \p Msg is the message to show. Note that
-  /// this class does not copy this message, so this reference must be valid for
-  /// the whole life time of the diagnostic.
+  /// include the source code location. \p Msg is the message to show.
   OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
-                             const DiagnosticLocation &Loc, StringRef Msg)
+                             const DiagnosticLocation &Loc, const Twine &Msg)
       : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
                                      PassName, Fn, Loc, Msg) {}
 };
@@ -918,12 +910,10 @@ class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
   /// diagnostic. If line table information is available, the diagnostic will
   /// include the source code location. \p Msg is the message to show. The
   /// front-end will append its own message related to options that address
-  /// floating-point non-commutativity. Note that this class does not copy this
-  /// message, so this reference must be valid for the whole life time of the
-  /// diagnostic.
+  /// floating-point non-commutativity.
   OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
                                       const DiagnosticLocation &Loc,
-                                      StringRef Msg)
+                                      const Twine &Msg)
       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
                                    PassName, Fn, Loc, Msg) {}
 };
@@ -959,12 +949,10 @@ class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
   /// diagnostic. If line table information is available, the diagnostic will
   /// include the source code location. \p Msg is the message to show. The
   /// front-end will append its own message related to options that address
-  /// pointer aliasing legality. Note that this class does not copy this
-  /// message, so this reference must be valid for the whole life time of the
-  /// diagnostic.
+  /// pointer aliasing legality.
   OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
                                      const DiagnosticLocation &Loc,
-                                     StringRef Msg)
+                                     const Twine &Msg)
       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
                                    PassName, Fn, Loc, Msg) {}
 };
@@ -1032,12 +1020,10 @@ class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
   /// the location information to use in the diagnostic. If line table
   /// information is available, the diagnostic will include the source code
-  /// location. \p Msg is the message to show. Note that this class does not
-  /// copy this message, so this reference must be valid for the whole life time
-  /// of the diagnostic.
+  /// location. \p Msg is the message to show.
   DiagnosticInfoOptimizationFailure(const Function &Fn,
                                     const DiagnosticLocation &Loc,
-                                    StringRef Msg)
+                                    const Twine &Msg = "")
       : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
                                      nullptr, Fn, Loc, Msg) {}
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index a89b41afb1d1c..483d3b37dbb2b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -468,11 +468,12 @@ void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
           F, "amdgpu-waves-per-eu", {0, 0}, true);
 
       if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
-        SmallString<256> Msg = formatv(
-            "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
-            "'{0}': desired occupancy was {1}, final occupancy is {2}",
-            F.getName(), MinWEU, Occupancy);
-        DiagnosticInfoOptimizationFailure Diag(F, F.getSubprogram(), Msg);
+        DiagnosticInfoOptimizationFailure Diag(F, F.getSubprogram());
+        Diag << "failed to meet occupancy target given by "
+                "'amdgpu-waves-per-eu' in '"
+             << F.getName() << "': desired occupancy was "
+             << std::to_string(MinWEU) << ", final occupancy is "
+             << std::to_string(Occupancy);
         F.getContext().diagnose(Diag);
         return;
       }
@@ -1262,12 +1263,13 @@ void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
       AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
   uint64_t Occupancy;
   if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
-    SmallString<256> Msg = formatv(
-        "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
-        "'{0}'': desired occupancy was {1}, final occupancy is {2}",
-        F.getName(), MinWEU, Occupancy);
-    F.getContext().diagnose(
-        DiagnosticInfoOptimizationFailure(F, F.getSubprogram(), Msg));
+    DiagnosticInfoOptimizationFailure Diag(F, F.getSubprogram());
+    Diag
+        << "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in '"
+        << F.getName(),
+        << "': desired occupancy was " << std::to_string(MinWEU)
+        << ", final occupancy is " << Occupancy;
+    F.getContext().diagnose(Diag);
   }
 
   if (isGFX11Plus(STM)) {

>From 736d2df9c528b50d70bd7a7f5a356ad4c47a593c Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Mon, 21 Apr 2025 01:49:40 -0600
Subject: [PATCH 4/5] fixup: adjacent clang-format to appease the bot

---
 llvm/lib/LTO/LTOCodeGenerator.cpp            | 2 +-
 llvm/lib/Transforms/Instrumentation/KCFI.cpp | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
index a0c0ed3e9b8b4..037344b77efd7 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -746,7 +746,7 @@ namespace {
 class LTODiagnosticInfo : public DiagnosticInfo {
   StringRef Msg;
 public:
-  LTODiagnosticInfo(StringRef DiagMsg, DiagnosticSeverity Severity=DS_Error)
+  LTODiagnosticInfo(StringRef DiagMsg, DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
 };
diff --git a/llvm/lib/Transforms/Instrumentation/KCFI.cpp b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
index cde87d910d9a5..75dbd65d9909b 100644
--- a/llvm/lib/Transforms/Instrumentation/KCFI.cpp
+++ b/llvm/lib/Transforms/Instrumentation/KCFI.cpp
@@ -37,8 +37,7 @@ class DiagnosticInfoKCFI : public DiagnosticInfo {
   StringRef Msg;
 
 public:
-  DiagnosticInfoKCFI(StringRef DiagMsg,
-                     DiagnosticSeverity Severity = DS_Error)
+  DiagnosticInfoKCFI(StringRef DiagMsg, DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
   void print(DiagnosticPrinter &DP) const override { DP << Msg; }
 };

>From 7fe9dc0f7470d57c651a23a90b73c34331087dc9 Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Mon, 21 Apr 2025 01:55:05 -0600
Subject: [PATCH 5/5] fixup: typos

---
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index 483d3b37dbb2b..b6ce2dbd2140b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -1266,9 +1266,8 @@ void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
     DiagnosticInfoOptimizationFailure Diag(F, F.getSubprogram());
     Diag
         << "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in '"
-        << F.getName(),
-        << "': desired occupancy was " << std::to_string(MinWEU)
-        << ", final occupancy is " << Occupancy;
+        << F.getName() << "': desired occupancy was " << std::to_string(MinWEU)
+        << ", final occupancy is " << std::to_string(Occupancy);
     F.getContext().diagnose(Diag);
   }
 



More information about the llvm-commits mailing list