[llvm] [IR] Make succ_iterator compliant with C++20 (PR #188601)

Daniel Hoekwater via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 25 13:50:02 PDT 2026


https://github.com/dhoekwater created https://github.com/llvm/llvm-project/pull/188601

GCC 15.2 enforces the `DefaultConstructible` requirement for
`std::reverse_iterator<llvm::succ_iterator>` causing LLVM to fail to
build with C++20 (see
https://discourse.llvm.org/t/suspicious-usages-of-std-reverse-iterator-and-associated-llvm-build-failures-with-gcc-15-2-1/89426,
issue #182417).

```
$ cmake -G Ninja -S llvm -B llvm/build \
    -DCMAKE_INSTALL_PREFIX=$(mktemp -d) \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_C_COMPILER=gcc \
    -DCMAKE_CXX_COMPILER=g++ \
    -DLLVM_ENABLE_PROJECTS="clang;" \
    -DLLVM_ENABLE_ASSERTIONS=ON \
    -DLLVM_USE_LINKER=lld \
    -DCMAKE_CXX_STANDARD=20 \
    -DLLVM_OPTIMIZED_TABLEGEN=ON \
    -DLLVM_PARALLEL_LINK_JOBS=4

$ ninja -C llvm/build bin/llvm-lib

...
/usr/include/c++/15/bits/stl_iterator.h:182:7: error: no matching function for call to ‘llvm::Instruction::succ_iterator::succ_iterator()’
  182 |       _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator()))
...
```

Adding a default constructor fixes this error.

Fixes #182417.


>From 3465df89057ae2a8479ac010c170c01e506fa82d Mon Sep 17 00:00:00 2001
From: Daniel Hoekwater <hoekwater at google.com>
Date: Wed, 25 Mar 2026 20:11:57 +0000
Subject: [PATCH] [IR] Make succ_iterator compliant with C++20
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

GCC 15.2 enforces the `DefaultConstructible` requirement for
`std::reverse_iterator<llvm::succ_iterator>` causing LLVM to fail to
build with C++20 (see
https://discourse.llvm.org/t/suspicious-usages-of-std-reverse-iterator-and-associated-llvm-build-failures-with-gcc-15-2-1/89426,
issue #182417).

```
$ cmake -G Ninja -S llvm -B llvm/build \
    -DCMAKE_INSTALL_PREFIX=$(mktemp -d) \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_C_COMPILER=gcc \
    -DCMAKE_CXX_COMPILER=g++ \
    -DLLVM_ENABLE_PROJECTS="clang;" \
    -DLLVM_ENABLE_ASSERTIONS=ON \
    -DLLVM_USE_LINKER=lld \
    -DCMAKE_CXX_STANDARD=20 \
    -DLLVM_OPTIMIZED_TABLEGEN=ON \
    -DLLVM_PARALLEL_LINK_JOBS=4

$ ninja -C llvm/build bin/llvm-lib

...
/usr/include/c++/15/bits/stl_iterator.h:182:7: error: no matching function for call to ‘llvm::Instruction::succ_iterator::succ_iterator()’
  182 |       _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator()))
...
```

Adding a default constructor fixes this error.

Fixes #182417.
---
 llvm/include/llvm/IR/Instruction.h | 75 ++++++++++++++++--------------
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 00b63f1e1b060..ed54ee118f833 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -78,6 +78,7 @@ class Instruction : public User,
       : iterator_adaptor_base<succ_iterator, op_iterator,
                               std::random_access_iterator_tag, BasicBlock *,
                               ptrdiff_t, BasicBlock *, BasicBlock *> {
+    succ_iterator() = default;
     explicit succ_iterator(op_iterator I) : iterator_adaptor_base(I) {}
 
     BasicBlock *operator*() const { return cast<BasicBlock>(*I); }
@@ -92,6 +93,7 @@ class Instruction : public User,
                               std::random_access_iterator_tag,
                               const BasicBlock *, ptrdiff_t, const BasicBlock *,
                               const BasicBlock *> {
+    const_succ_iterator() = default;
     explicit const_succ_iterator(const_op_iterator I)
         : iterator_adaptor_base(I) {}
 
@@ -102,7 +104,7 @@ class Instruction : public User,
   };
 
 private:
-  DebugLoc DbgLoc;                         // 'dbg' Metadata cache.
+  DebugLoc DbgLoc; // 'dbg' Metadata cache.
 
   /// Relative order of this instruction in its parent basic block. Used for
   /// O(1) local dominance checks between instructions.
@@ -198,8 +200,10 @@ class Instruction : public User,
 
   /// Specialize the methods defined in Value, as we know that an instruction
   /// can only be used by other instructions.
-  Instruction       *user_back()       { return cast<Instruction>(*user_begin());}
-  const Instruction *user_back() const { return cast<Instruction>(*user_begin());}
+  Instruction *user_back() { return cast<Instruction>(*user_begin()); }
+  const Instruction *user_back() const {
+    return cast<Instruction>(*user_begin());
+  }
 
   /// Return the module owning the function this instruction belongs to
   /// or nullptr it the function does not have a module.
@@ -209,7 +213,7 @@ class Instruction : public User,
   LLVM_ABI const Module *getModule() const;
   Module *getModule() {
     return const_cast<Module *>(
-                           static_cast<const Instruction *>(this)->getModule());
+        static_cast<const Instruction *>(this)->getModule());
   }
 
   /// Return the function this instruction belongs to.
@@ -219,7 +223,7 @@ class Instruction : public User,
   LLVM_ABI const Function *getFunction() const;
   Function *getFunction() {
     return const_cast<Function *>(
-                         static_cast<const Instruction *>(this)->getFunction());
+        static_cast<const Instruction *>(this)->getFunction());
   }
 
   /// Get the data layout of the module this instruction belongs to.
@@ -388,9 +392,7 @@ class Instruction : public User,
   }
 
   /// Return true if this is an arithmetic shift right.
-  inline bool isArithmeticShift() const {
-    return getOpcode() == AShr;
-  }
+  inline bool isArithmeticShift() const { return getOpcode() == AShr; }
 
   /// Determine if the Opcode is and/or/xor.
   static inline bool isBitwiseLogicOp(unsigned Opcode) {
@@ -398,9 +400,7 @@ class Instruction : public User,
   }
 
   /// Return true if this is and/or/xor.
-  inline bool isBitwiseLogicOp() const {
-    return isBitwiseLogicOp(getOpcode());
-  }
+  inline bool isBitwiseLogicOp() const { return isBitwiseLogicOp(getOpcode()); }
 
   /// Determine if the Opcode is one of the CastInst instructions.
   static inline bool isCast(unsigned Opcode) {
@@ -465,7 +465,8 @@ class Instruction : public User,
   /// Get the metadata of given kind attached to this Instruction.
   /// If the metadata is not found then return null.
   MDNode *getMetadata(StringRef Kind) const {
-    if (!hasMetadata()) return nullptr;
+    if (!hasMetadata())
+      return nullptr;
     return getMetadataImpl(Kind);
   }
 
@@ -780,8 +781,8 @@ class Instruction : public User,
   ///
   LLVM_ABI bool isAssociative() const LLVM_READONLY;
   static bool isAssociative(unsigned Opcode) {
-    return Opcode == And || Opcode == Or || Opcode == Xor ||
-           Opcode == Add || Opcode == Mul;
+    return Opcode == And || Opcode == Or || Opcode == Xor || Opcode == Add ||
+           Opcode == Mul;
   }
 
   /// Return true if the instruction is commutative:
@@ -800,13 +801,17 @@ class Instruction : public User,
 
   static bool isCommutative(unsigned Opcode) {
     switch (Opcode) {
-    case Add: case FAdd:
-    case Mul: case FMul:
-    case And: case Or: case Xor:
+    case Add:
+    case FAdd:
+    case Mul:
+    case FMul:
+    case And:
+    case Or:
+    case Xor:
       return true;
     default:
       return false;
-  }
+    }
   }
 
   /// Return true if the instruction is idempotent:
@@ -830,9 +835,7 @@ class Instruction : public User,
   /// In LLVM, the Xor operator is nilpotent.
   ///
   bool isNilpotent() const { return isNilpotent(getOpcode()); }
-  static bool isNilpotent(unsigned Opcode) {
-    return Opcode == Xor;
-  }
+  static bool isNilpotent(unsigned Opcode) { return Opcode == Xor; }
 
   /// Return true if this instruction may modify memory.
   LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY;
@@ -1025,52 +1028,52 @@ class Instruction : public User,
   //----------------------------------------------------------------------
   // Exported enumerations.
   //
-  enum TermOps {       // These terminate basic blocks
-#define  FIRST_TERM_INST(N)             TermOpsBegin = N,
+  enum TermOps { // These terminate basic blocks
+#define FIRST_TERM_INST(N) TermOpsBegin = N,
 #define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_TERM_INST(N)             TermOpsEnd = N+1
+#define LAST_TERM_INST(N) TermOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum UnaryOps {
-#define  FIRST_UNARY_INST(N)             UnaryOpsBegin = N,
+#define FIRST_UNARY_INST(N) UnaryOpsBegin = N,
 #define HANDLE_UNARY_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_UNARY_INST(N)             UnaryOpsEnd = N+1
+#define LAST_UNARY_INST(N) UnaryOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum BinaryOps {
-#define  FIRST_BINARY_INST(N)             BinaryOpsBegin = N,
+#define FIRST_BINARY_INST(N) BinaryOpsBegin = N,
 #define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_BINARY_INST(N)             BinaryOpsEnd = N+1
+#define LAST_BINARY_INST(N) BinaryOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum MemoryOps {
-#define  FIRST_MEMORY_INST(N)             MemoryOpsBegin = N,
+#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N,
 #define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_MEMORY_INST(N)             MemoryOpsEnd = N+1
+#define LAST_MEMORY_INST(N) MemoryOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum CastOps {
-#define  FIRST_CAST_INST(N)             CastOpsBegin = N,
+#define FIRST_CAST_INST(N) CastOpsBegin = N,
 #define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_CAST_INST(N)             CastOpsEnd = N+1
+#define LAST_CAST_INST(N) CastOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum FuncletPadOps {
-#define  FIRST_FUNCLETPAD_INST(N)             FuncletPadOpsBegin = N,
+#define FIRST_FUNCLETPAD_INST(N) FuncletPadOpsBegin = N,
 #define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_FUNCLETPAD_INST(N)             FuncletPadOpsEnd = N+1
+#define LAST_FUNCLETPAD_INST(N) FuncletPadOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 
   enum OtherOps {
-#define  FIRST_OTHER_INST(N)             OtherOpsBegin = N,
+#define FIRST_OTHER_INST(N) OtherOpsBegin = N,
 #define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N,
-#define   LAST_OTHER_INST(N)             OtherOpsEnd = N+1
+#define LAST_OTHER_INST(N) OtherOpsEnd = N + 1
 #include "llvm/IR/Instruction.def"
   };
 



More information about the llvm-commits mailing list