[llvm] [Diagnostics] Return rvalue reference from temporary argument (PR #127400)

Jonas Hahnfeld via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 12 15:03:41 PDT 2025


https://github.com/hahnjo updated https://github.com/llvm/llvm-project/pull/127400

>From 3b0573bb84a604e1c65fd23f3f99d2f473d685ef Mon Sep 17 00:00:00 2001
From: Jonas Hahnfeld <hahnjo at hahnjo.de>
Date: Sun, 16 Feb 2025 14:54:15 +0100
Subject: [PATCH 1/4] Return rvalue reference from temporary argument

This fixes compilation issues with GCC and C++23:
```
error: cannot bind non-const lvalue reference of type
'llvm::OptimizationRemarkMissed&' to an rvalue of type
'llvm::OptimizationRemarkMissed'
```

Closes #105778
---
 .../llvm/Analysis/OptimizationRemarkEmitter.h |  5 ++++
 llvm/include/llvm/IR/DiagnosticInfo.h         | 24 ++++++++++++++-----
 llvm/lib/Analysis/InlineAdvisor.cpp           |  9 +++++--
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
index 7b14e55782adb..2640bb9194010 100644
--- a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
+++ b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
@@ -69,6 +69,11 @@ class OptimizationRemarkEmitter {
   /// Output the remark via the diagnostic handler and to the
   /// optimization record file.
   void emit(DiagnosticInfoOptimizationBase &OptDiag);
+  /// Also allow r-value for OptDiag to allow emitting a temporarily-constructed
+  /// diagnostic.
+  void emit(DiagnosticInfoOptimizationBase &&OptDiag) {
+    emit(static_cast<DiagnosticInfoOptimizationBase &>(OptDiag));
+  }
 
   /// Take a lambda that returns a remark which will be emitted.  Second
   /// argument is only used to restrict this to functions.
diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 694785317af04..1e26cfdd17b5f 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -30,6 +30,7 @@
 #include <iterator>
 #include <optional>
 #include <string>
+#include <utility>
 
 namespace llvm {
 
@@ -625,14 +626,14 @@ operator<<(RemarkT &R,
 /// Also allow r-value for the remark to allow insertion into a
 /// temporarily-constructed remark.
 template <class RemarkT>
-RemarkT &
+RemarkT &&
 operator<<(RemarkT &&R,
            std::enable_if_t<
                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
                StringRef>
                S) {
   R.insert(S);
-  return R;
+  return std::move(R);
 }
 
 template <class RemarkT>
@@ -647,14 +648,14 @@ operator<<(RemarkT &R,
 }
 
 template <class RemarkT>
-RemarkT &
+RemarkT &&
 operator<<(RemarkT &&R,
            std::enable_if_t<
                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
                DiagnosticInfoOptimizationBase::Argument>
                A) {
   R.insert(A);
-  return R;
+  return std::move(R);
 }
 
 template <class RemarkT>
@@ -669,14 +670,14 @@ operator<<(RemarkT &R,
 }
 
 template <class RemarkT>
-RemarkT &
+RemarkT &&
 operator<<(RemarkT &&R,
            std::enable_if_t<
                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
                DiagnosticInfoOptimizationBase::setIsVerbose>
                V) {
   R.insert(V);
-  return R;
+  return std::move(R);
 }
 
 template <class RemarkT>
@@ -690,6 +691,17 @@ operator<<(RemarkT &R,
   return R;
 }
 
+template <class RemarkT>
+RemarkT &&
+operator<<(RemarkT &&R,
+           std::enable_if_t<
+               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
+               DiagnosticInfoOptimizationBase::setExtraArgs>
+               EA) {
+  R.insert(EA);
+  return std::move(R);
+}
+
 /// Common features for diagnostics dealing with optimization remarks
 /// that are used by IR passes.
 class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
index 12553dd446a61..6cf6f10f20392 100644
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
@@ -337,8 +337,7 @@ static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
   return R << Arg.Val;
 }
 
-template <class RemarkT>
-RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
+template <class RemarkT> RemarkT &operator<<(RemarkT &R, const InlineCost &IC) {
   using namespace ore;
   if (IC.isAlways()) {
     R << "(cost=always)";
@@ -352,6 +351,12 @@ RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
     R << ": " << ore::NV("Reason", Reason);
   return R;
 }
+
+template <class RemarkT>
+RemarkT &&operator<<(RemarkT &&R, const InlineCost &IC) {
+  static_cast<RemarkT &>(R) << IC;
+  return std::move(R);
+}
 } // namespace llvm
 
 std::string llvm::inlineCostStr(const InlineCost &IC) {

>From 824936ca9f51b70fcfd61e443a441be082f144e2 Mon Sep 17 00:00:00 2001
From: Jonas Hahnfeld <hahnjo at hahnjo.de>
Date: Tue, 11 Mar 2025 20:37:28 +0100
Subject: [PATCH 2/4] Remove unneeded cast

---
 llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
index 2640bb9194010..64e6442bb92f8 100644
--- a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
+++ b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h
@@ -71,9 +71,7 @@ class OptimizationRemarkEmitter {
   void emit(DiagnosticInfoOptimizationBase &OptDiag);
   /// Also allow r-value for OptDiag to allow emitting a temporarily-constructed
   /// diagnostic.
-  void emit(DiagnosticInfoOptimizationBase &&OptDiag) {
-    emit(static_cast<DiagnosticInfoOptimizationBase &>(OptDiag));
-  }
+  void emit(DiagnosticInfoOptimizationBase &&OptDiag) { emit(OptDiag); }
 
   /// Take a lambda that returns a remark which will be emitted.  Second
   /// argument is only used to restrict this to functions.

>From 0a8055149ed044e667530aaf6e35e593c44ca01c Mon Sep 17 00:00:00 2001
From: Jonas Hahnfeld <hahnjo at hahnjo.de>
Date: Wed, 12 Mar 2025 19:36:08 +0100
Subject: [PATCH 3/4] Unify duplicated template functions

---
 llvm/include/llvm/IR/DiagnosticInfo.h | 102 +++++++-------------------
 llvm/lib/Analysis/InlineAdvisor.cpp   |  11 +--
 2 files changed, 31 insertions(+), 82 deletions(-)

diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 1e26cfdd17b5f..0ab9f5a87e41b 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -613,93 +613,47 @@ class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
 /// common base class.  This allows returning the result of the insertion
 /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
 template <class RemarkT>
-RemarkT &
-operator<<(RemarkT &R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               StringRef>
-               S) {
+decltype(auto) operator<<(
+    RemarkT &&R,
+    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
+                                     std::remove_reference_t<RemarkT>>::value,
+                     StringRef>
+        S) {
   R.insert(S);
-  return R;
+  return std::forward<RemarkT>(R);
 }
 
-/// Also allow r-value for the remark to allow insertion into a
-/// temporarily-constructed remark.
 template <class RemarkT>
-RemarkT &&
-operator<<(RemarkT &&R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               StringRef>
-               S) {
-  R.insert(S);
-  return std::move(R);
-}
-
-template <class RemarkT>
-RemarkT &
-operator<<(RemarkT &R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::Argument>
-               A) {
-  R.insert(A);
-  return R;
-}
-
-template <class RemarkT>
-RemarkT &&
-operator<<(RemarkT &&R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::Argument>
-               A) {
+decltype(auto) operator<<(
+    RemarkT &&R,
+    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
+                                     std::remove_reference_t<RemarkT>>::value,
+                     DiagnosticInfoOptimizationBase::Argument>
+        A) {
   R.insert(A);
-  return std::move(R);
+  return std::forward<RemarkT>(R);
 }
 
 template <class RemarkT>
-RemarkT &
-operator<<(RemarkT &R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::setIsVerbose>
-               V) {
+decltype(auto) operator<<(
+    RemarkT &&R,
+    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
+                                     std::remove_reference_t<RemarkT>>::value,
+                     DiagnosticInfoOptimizationBase::setIsVerbose>
+        V) {
   R.insert(V);
-  return R;
-}
-
-template <class RemarkT>
-RemarkT &&
-operator<<(RemarkT &&R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::setIsVerbose>
-               V) {
-  R.insert(V);
-  return std::move(R);
-}
-
-template <class RemarkT>
-RemarkT &
-operator<<(RemarkT &R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::setExtraArgs>
-               EA) {
-  R.insert(EA);
-  return R;
+  return std::forward<RemarkT>(R);
 }
 
 template <class RemarkT>
-RemarkT &&
-operator<<(RemarkT &&R,
-           std::enable_if_t<
-               std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
-               DiagnosticInfoOptimizationBase::setExtraArgs>
-               EA) {
+decltype(auto) operator<<(
+    RemarkT &&R,
+    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
+                                     std::remove_reference_t<RemarkT>>::value,
+                     DiagnosticInfoOptimizationBase::setExtraArgs>
+        EA) {
   R.insert(EA);
-  return std::move(R);
+  return std::forward<RemarkT>(R);
 }
 
 /// Common features for diagnostics dealing with optimization remarks
diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
index 6cf6f10f20392..5b2f0479e2b41 100644
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
@@ -337,7 +337,8 @@ static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
   return R << Arg.Val;
 }
 
-template <class RemarkT> RemarkT &operator<<(RemarkT &R, const InlineCost &IC) {
+template <class RemarkT>
+decltype(auto) operator<<(RemarkT &&R, const InlineCost &IC) {
   using namespace ore;
   if (IC.isAlways()) {
     R << "(cost=always)";
@@ -349,13 +350,7 @@ template <class RemarkT> RemarkT &operator<<(RemarkT &R, const InlineCost &IC) {
   }
   if (const char *Reason = IC.getReason())
     R << ": " << ore::NV("Reason", Reason);
-  return R;
-}
-
-template <class RemarkT>
-RemarkT &&operator<<(RemarkT &&R, const InlineCost &IC) {
-  static_cast<RemarkT &>(R) << IC;
-  return std::move(R);
+  return std::forward<RemarkT>(R);
 }
 } // namespace llvm
 

>From 60c7cae624b4c5d6d87744fd8b6e9f4aabb459eb Mon Sep 17 00:00:00 2001
From: Jonas Hahnfeld <hahnjo at hahnjo.de>
Date: Wed, 12 Mar 2025 23:03:18 +0100
Subject: [PATCH 4/4] Use is_base_of_v

---
 llvm/include/llvm/IR/DiagnosticInfo.h | 48 +++++++++++++--------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 0ab9f5a87e41b..779c88993b71c 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -613,45 +613,45 @@ class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
 /// common base class.  This allows returning the result of the insertion
 /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
 template <class RemarkT>
-decltype(auto) operator<<(
-    RemarkT &&R,
-    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
-                                     std::remove_reference_t<RemarkT>>::value,
-                     StringRef>
-        S) {
+decltype(auto)
+operator<<(RemarkT &&R,
+           std::enable_if_t<std::is_base_of_v<DiagnosticInfoOptimizationBase,
+                                              std::remove_reference_t<RemarkT>>,
+                            StringRef>
+               S) {
   R.insert(S);
   return std::forward<RemarkT>(R);
 }
 
 template <class RemarkT>
-decltype(auto) operator<<(
-    RemarkT &&R,
-    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
-                                     std::remove_reference_t<RemarkT>>::value,
-                     DiagnosticInfoOptimizationBase::Argument>
-        A) {
+decltype(auto)
+operator<<(RemarkT &&R,
+           std::enable_if_t<std::is_base_of_v<DiagnosticInfoOptimizationBase,
+                                              std::remove_reference_t<RemarkT>>,
+                            DiagnosticInfoOptimizationBase::Argument>
+               A) {
   R.insert(A);
   return std::forward<RemarkT>(R);
 }
 
 template <class RemarkT>
-decltype(auto) operator<<(
-    RemarkT &&R,
-    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
-                                     std::remove_reference_t<RemarkT>>::value,
-                     DiagnosticInfoOptimizationBase::setIsVerbose>
-        V) {
+decltype(auto)
+operator<<(RemarkT &&R,
+           std::enable_if_t<std::is_base_of_v<DiagnosticInfoOptimizationBase,
+                                              std::remove_reference_t<RemarkT>>,
+                            DiagnosticInfoOptimizationBase::setIsVerbose>
+               V) {
   R.insert(V);
   return std::forward<RemarkT>(R);
 }
 
 template <class RemarkT>
-decltype(auto) operator<<(
-    RemarkT &&R,
-    std::enable_if_t<std::is_base_of<DiagnosticInfoOptimizationBase,
-                                     std::remove_reference_t<RemarkT>>::value,
-                     DiagnosticInfoOptimizationBase::setExtraArgs>
-        EA) {
+decltype(auto)
+operator<<(RemarkT &&R,
+           std::enable_if_t<std::is_base_of_v<DiagnosticInfoOptimizationBase,
+                                              std::remove_reference_t<RemarkT>>,
+                            DiagnosticInfoOptimizationBase::setExtraArgs>
+               EA) {
   R.insert(EA);
   return std::forward<RemarkT>(R);
 }



More information about the llvm-commits mailing list