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

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 21 05:37:14 PDT 2025


arsenm wrote:

> > Can we just get a warning on the bad usage instead?
> 
> I'd be perfectly happy for this to just warn on misuse, but I don't think it's possible. Essentially we'd need to be able to warn on creating any of these `DiagnosticInfo*` classes on the stack, as the problematic pattern is as follows:

Seems to work if we add `[[clang::lifetimebound]]` to all of these constructor parameters 

```
diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 8743f8058c38..badc1cdb6cac 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -146,15 +146,15 @@ 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(const Twine &MsgStr [[clang::lifetimebound]] ,
                         DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Generic, Severity), MsgStr(MsgStr) {}
 
-  DiagnosticInfoGeneric(const Instruction *I, const Twine &ErrMsg,
+  DiagnosticInfoGeneric(const Instruction *I, const Twine &ErrMsg [[clang::lifetimebound]] ,
                         DiagnosticSeverity Severity = DS_Error)
       : DiagnosticInfo(DK_Generic, Severity), MsgStr(ErrMsg), Inst(I) {}
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  const Twine &getMsgStr() const [[clang::lifetimebound]] { return MsgStr; }
   const Instruction *getInstruction() const { return Inst; }
 
   /// \see DiagnosticInfo::print.
@@ -193,7 +193,7 @@ public:
                           DiagnosticSeverity Severity = DS_Error);
 
   uint64_t getLocCookie() const { return LocCookie; }
-  const Twine &getMsgStr() const { return MsgStr; }
+  const Twine &getMsgStr() const [[clang::lifetimebound]] { return MsgStr; }
   const Instruction *getInstruction() const { return Instr; }
 
   /// \see DiagnosticInfo::print.
@@ -364,7 +364,7 @@ public:
 
   /// Return the absolute path tot the file.
   std::string getAbsolutePath() const;
-  
+
   const Function &getFunction() const { return Fn; }
   DiagnosticLocation getLocation() const { return Loc; }
 
@@ -391,7 +391,7 @@ public:
       : DiagnosticInfoWithLocationBase(DK_GenericWithLoc, Severity, Fn, Loc),
         MsgStr(MsgStr) {}
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  const Twine &getMsgStr() const [[clang::lifetimebound]] { return MsgStr; }
 
   /// \see DiagnosticInfo::print.
   void print(DiagnosticPrinter &DP) const override;
@@ -417,7 +417,7 @@ public:
   DiagnosticInfoRegAllocFailure(const Twine &MsgStr, const Function &Fn,
                                 DiagnosticSeverity Severity = DS_Error);
 
-  const Twine &getMsgStr() const { return MsgStr; }
+  const Twine &getMsgStr() const [[clang::lifetimebound]] { return MsgStr; }
 
   /// \see DiagnosticInfo::print.
   void print(DiagnosticPrinter &DP) const override;

```
```
 warning: temporary whose address is used as value of local variable 'Diag' will be destroyed at the end of the full-expression [-Wdangling]
 2863 |     auto Diag = DiagnosticInfoGeneric("bug");
```

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


More information about the llvm-commits mailing list