[clang] [clang] Implement CWG3135 - constexpr structured bindings with prvalues from tuples (PR #191880)
Matthias Wippich via cfe-commits
cfe-commits at lists.llvm.org
Mon May 4 20:07:26 PDT 2026
https://github.com/Tsche updated https://github.com/llvm/llvm-project/pull/191880
>From 93a95b86f4f80841d6de67f5e50462c134e41d06 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Mon, 4 May 2026 06:37:02 +0200
Subject: [PATCH] [clang] Implement CWG3135 - constexpr structured bindings
with prvalues from tuples
---
clang/docs/ReleaseNotes.rst | 3 +
clang/lib/Analysis/FlowSensitive/Transfer.cpp | 2 +-
clang/lib/Sema/SemaDeclCXX.cpp | 29 +++++----
clang/test/Analysis/anonymous-decls.cpp | 14 ++---
clang/test/Analysis/live-bindings-test.cpp | 11 ----
clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp | 5 +-
clang/test/CXX/drs/cwg31xx.cpp | 61 ++++++++++++++++---
...egen-for-constexpr-structured-bindings.cpp | 2 +-
clang/test/CodeGenCXX/cxx1z-decomposition.cpp | 13 ++--
.../test/DebugInfo/CXX/structured-binding.cpp | 2 +-
clang/test/SemaCXX/cxx2c-decomposition.cpp | 4 +-
clang/www/cxx_dr_status.html | 21 ++++---
12 files changed, 104 insertions(+), 63 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eb1d926926d9e..fde13bd74e2e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -164,6 +164,9 @@ Resolutions to C++ Defect Reports
- Clang now allows omitting ``typename`` before a template name in a
conversion operator, implementing `CWG2413 <https://wg21.link/cwg2413>`_.
+- Clang now uses non-reference types for structured bindings whose initializer
+ returns a prvalue. This resolves CWG3135.
+
C Language Changes
------------------
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 57ee93f5e156e..d40843ff4ec43 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -255,7 +255,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
// If this is the holding variable for a `BindingDecl`, we may already
// have a storage location set up -- so check. (See also explanation below
// where we process the `BindingDecl`.)
- if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr)
+ if (D.isImplicit() && Env.getStorageLocation(D) != nullptr)
return;
assert(Env.getStorageLocation(D) == nullptr);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 1e339fee29ab8..e7c1984c2f17b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1380,25 +1380,28 @@ static bool checkTupleLikeDecomposition(Sema &S,
return true;
Expr *Init = E.get();
- // Given the type T designated by std::tuple_element<i - 1, E>::type,
+ // Given the type T designated by std::tuple_element<i - 1, E>::type
QualType T = getTupleLikeElementType(S, Loc, I, DecompType);
if (T.isNull())
return true;
- // each vi is a variable of type "reference to T" initialized with the
- // initializer, where the reference is an lvalue reference if the
- // initializer is an lvalue and an rvalue reference otherwise
- QualType RefType =
- S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
- if (RefType.isNull())
+ // C++26 [dcl.struct.bind]p7:
+ // and the type Ui, defined as Ti if the initializer is a prvalue,
+ // as "lvalue reference to Ti" if the initializer is an lvalue,
+ // or as "rvalue reference to Ti" otherwise
+ // "defined as Ti if the initializer is a prvalue" was introduced by CWG3135
+ QualType U = E.get()->isPRValue()
+ ? T
+ : S.BuildReferenceType(T, E.get()->isLValue(), Loc,
+ B->getDeclName());
+ if (U.isNull())
return true;
// Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
// entity and this type was never written in source code.
- auto *RefVD =
- VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
- B->getDeclName().getAsIdentifierInfo(), RefType,
- /*TInfo=*/nullptr, Src->getStorageClass());
+ auto *RefVD = VarDecl::Create(S.Context, Src->getDeclContext(), Loc, Loc,
+ B->getDeclName().getAsIdentifierInfo(), U,
+ /*TInfo=*/nullptr, Src->getStorageClass());
RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
RefVD->setTSCSpec(Src->getTSCSpec());
RefVD->setImplicit();
@@ -1407,7 +1410,9 @@ static bool checkTupleLikeDecomposition(Sema &S,
RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);
InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
- InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
+ InitializationKind Kind =
+ E.get()->isPRValue() ? InitializationKind::CreateDirect(Loc, Loc, Loc)
+ : InitializationKind::CreateCopy(Loc, Loc);
InitializationSequence Seq(S, Entity, Kind, Init);
E = Seq.Perform(S, Entity, Kind, Init);
if (E.isInvalid())
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
index 76e5155b61b67..705273328e6cc 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -77,13 +77,11 @@ int main() {
// CHECK-NEXT: 7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &))
// CHECK-NEXT: 8: decomposition-a-b
// CHECK-NEXT: 9: [B3.7]([B3.8])
-// CHECK-NEXT: 10: [B3.9]
-// CHECK-NEXT: 11: std::tuple_element<0UL, std::pair<int, int>>::type &&a = get<0UL>(decomposition-a-b);
-// CHECK-NEXT: 12: get<1UL>
-// CHECK-NEXT: 13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
-// CHECK-NEXT: 14: decomposition-a-b
-// CHECK-NEXT: 15: [B3.13]([B3.14])
-// CHECK-NEXT: 16: [B3.15]
-// CHECK-NEXT: 17: std::tuple_element<1UL, std::pair<int, int>>::type &&b = get<1UL>(decomposition-a-b);
+// CHECK-NEXT: 10: std::tuple_element<0UL, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
+// CHECK-NEXT: 11: get<1UL>
+// CHECK-NEXT: 12: [B3.11] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT: 13: decomposition-a-b
+// CHECK-NEXT: 14: [B3.12]([B3.13])
+// CHECK-NEXT: 15: std::tuple_element<1UL, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
// CHECK-NEXT: Preds (1): B1
// CHECK-NEXT: Succs (1): B2
diff --git a/clang/test/Analysis/live-bindings-test.cpp b/clang/test/Analysis/live-bindings-test.cpp
index 7660e9c9904d7..eebd928145522 100644
--- a/clang/test/Analysis/live-bindings-test.cpp
+++ b/clang/test/Analysis/live-bindings-test.cpp
@@ -108,19 +108,8 @@ namespace std {
};
}
-void no_warning_on_tuple_types_copy(Mytuple t) {
- auto [a, b] = t; // no-warning
-}
-
Mytuple getMytuple();
-void deconstruct_tuple_types_warning() {
- // The initializers reference the decomposed region, so the warning is not reported
- // FIXME: ideally we want to ignore that the initializers reference the decomposed region, and report the warning,
- // though the first step towards that is to handle DeadCode if the initializer is CXXConstructExpr.
- auto [a, b] = getMytuple(); // no-warning
-}
-
int deconstruct_tuple_types_no_warning() {
auto [a, b] = getMytuple(); // no-warning
return a + b;
diff --git a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
index b9d19c1eb4371..b1e639efc441f 100644
--- a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
@@ -222,9 +222,6 @@ template<> struct std::tuple_size<constant::Q> { static const int value = 3; };
template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; };
namespace constant {
Q q;
- // This creates and lifetime-extends a temporary to hold the result of each get() call.
- auto [a, b, c] = q; // expected-note {{temporary}}
- static_assert(a == 0); // expected-error {{constant expression}} expected-note {{temporary}}
constexpr bool f() {
auto [a, b, c] = q;
@@ -235,7 +232,7 @@ namespace constant {
constexpr int g() {
int *p = nullptr;
{
- auto [a, b, c] = q; // expected-note {{temporary created here}}
+ auto [a, b, c] = q; // expected-note {{declared here}}
p = &c;
}
return *p; // expected-note {{read of object outside its lifetime}}
diff --git a/clang/test/CXX/drs/cwg31xx.cpp b/clang/test/CXX/drs/cwg31xx.cpp
index 3c88d5ff7c607..ee41c77f6f181 100644
--- a/clang/test/CXX/drs/cwg31xx.cpp
+++ b/clang/test/CXX/drs/cwg31xx.cpp
@@ -1,16 +1,61 @@
-// RUN: %clang_cc1 -std=c++98 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++17 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++20 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++23 -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
-// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors %s -verify-directives -verify=expected
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-14,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx98-14
+// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx98-14,cxx11-17,since-cxx11
+// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx98-14,cxx14-17,cxx11-17,since-cxx11,since-cxx14
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14,since-cxx17
+// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -fexperimental-new-constant-interpreter -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20
-// expected-no-diagnostics
+// cxx98-14-no-diagnostics
namespace cwg3106 { // cwg3106: 2.7
#if __cplusplus >= 201103L
const char str[9] = R"(\u{1234})";
#endif
} // namespace cwg3106
+
+namespace cwg3135 { // cwg3135: 23
+#if __cplusplus >= 201703L
+struct Pinned {
+ Pinned(const Pinned&) = delete; // #cwg3135-pinned-ctor
+ Pinned& operator=(const Pinned&) = delete;
+};
+
+struct Source {
+ operator Pinned&&() const;
+
+ template<int>
+ Source get() noexcept;
+};
+} // namespace cwg3135
+
+namespace std {
+ template<typename> struct tuple_size;
+ template<int, typename> struct tuple_element;
+
+ template<>
+ struct tuple_size<cwg3135::Source> {
+ static constexpr int value = 1;
+ };
+
+ template<>
+ struct tuple_element<0, cwg3135::Source> { using type = cwg3135::Pinned; };
+} // namespace std
+
+namespace cwg3135 {
+// CWG3135: `x` is of type Pinned rather than Pinned&&.
+// This leads to the deleted copy ctor being called.
+auto [x] = Source{};
+// since-cxx17-error-re at -1 {{call to deleted constructor of 'std::tuple_element<0U{{L*}}, Source>::type' (aka 'cwg3135::Pinned')}}
+// since-cxx17-note at -2 {{in implicit initialization of binding declaration 'x'}}
+// since-cxx17-note@#cwg3135-pinned-ctor {{'Pinned' has been explicitly marked deleted here}}
+#endif
+} // namespace cwg3135
diff --git a/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
index ce81f7d8d026e..87c2055627aa7 100644
--- a/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
+++ b/clang/test/CodeGenCXX/bad-codegen-for-constexpr-structured-bindings.cpp
@@ -35,6 +35,6 @@ const u8 &f() {
return I;
}
-// CHECK: @[[TMP:_ZGR.*]] = internal constant i8 0, align 1
+// CHECK: @[[TMP:_ZZ1fvE1I]] = internal constant i8 0, align 1
// CHECK-LABEL: define {{.*}} @_Z1fv(
// CHECK: ret ptr @[[TMP]]
diff --git a/clang/test/CodeGenCXX/cxx1z-decomposition.cpp b/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
index 228a6fd910248..a2f5a91aa9b2e 100644
--- a/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
+++ b/clang/test/CodeGenCXX/cxx1z-decomposition.cpp
@@ -33,8 +33,7 @@ template<typename T> T &make();
// CHECK: @_ZDC2a12a2E ={{.*}} global {{.*}} zeroinitializer, align 4
auto [a1, a2] = make<A>();
// CHECK: @_ZDC2b12b2E ={{.*}} global {{.*}} zeroinitializer, align 1
-// CHECK: @b1 ={{.*}} global ptr null, align 8
-// CHECK: @_ZGR2b1_ = internal global {{.*}} zeroinitializer, align 1
+// CHECK: @b1 ={{.*}} global {{.*}} zeroinitializer, align 1
// CHECK: @b2 ={{.*}} global ptr null, align 8
// CHECK: @_ZGR2b2_ = internal global i32 0, align 4
auto [b1, b2] = make<B>();
@@ -50,9 +49,8 @@ auto [e1, e2] = make<E>();
// CHECK: @_Z4makeI1BERT_v()
// CHECK: call i32 @_Z3getILi0EEDa1B()
-// CHECK: call void @_ZN1XC1E1Y(ptr {{[^,]*}} @_ZGR2b1_, i32
-// CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@_ZGR2b1_
-// CHECK: store ptr @_ZGR2b1_,
+// CHECK: call void @_ZN1XC1E1Y(ptr {{[^,]*}} @b1, i32
+// CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@b1
//
// CHECK: call noundef double @_Z3getILi1EEDa1B()
// CHECK: fptosi double %{{.*}} to i32
@@ -149,9 +147,8 @@ int test_static_tuple() {
// CHECK: br i1
// CHECK: @__cxa_guard_acquire({{.*}} @_ZGVZ17test_static_tuplevE2x1)
// CHECK: call {{.*}} @_Z3getILi0EEDa1B(
- // CHECK: call {{.*}} @_ZN1XC1E1Y({{.*}} @_ZGRZ17test_static_tuplevE2x1_,
- // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1XD1Ev, {{.*}} @_ZGRZ17test_static_tuplevE2x1_
- // CHECK: store {{.*}} @_ZGRZ17test_static_tuplevE2x1_, {{.*}} @_ZZ17test_static_tuplevE2x1
+ // CHECK: call {{.*}} @_ZN1XC1E1Y({{.*}} @_ZZ17test_static_tuplevE2x1,
+ // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1XD1Ev, {{.*}} @_ZZ17test_static_tuplevE2x1
// CHECK: call void @__cxa_guard_release({{.*}} @_ZGVZ17test_static_tuplevE2x1)
// Initialization of the secret 'x2' variable.
diff --git a/clang/test/DebugInfo/CXX/structured-binding.cpp b/clang/test/DebugInfo/CXX/structured-binding.cpp
index 51818e7e16f00..e124a53762be6 100644
--- a/clang/test/DebugInfo/CXX/structured-binding.cpp
+++ b/clang/test/DebugInfo/CXX/structured-binding.cpp
@@ -17,7 +17,7 @@
// CHECK: #dbg_declare(ptr %p, ![[VAR_13:[0-9]+]], !DIExpression()
// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg ![[Y1_DEBUG_LOC:[0-9]+]]
// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg ![[Y2_DEBUG_LOC:[0-9]+]]
-// CHECK: load ptr, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]]
+// CHECK: load i32, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]]
// CHECK: getelementptr inbounds [2 x i32], ptr {{.*}}, i{{64|32}} 0, i{{64|32}} 1, !dbg ![[A2_DEBUG_LOC:[0-9]+]]
// CHECK: getelementptr inbounds nuw { i32, i32 }, ptr {{.*}}, i32 0, i32 1, !dbg ![[C2_DEBUG_LOC:[0-9]+]]
// CHECK: extractelement <2 x i32> {{.*}}, i32 1, !dbg ![[V2_DEBUG_LOC:[0-9]+]]
diff --git a/clang/test/SemaCXX/cxx2c-decomposition.cpp b/clang/test/SemaCXX/cxx2c-decomposition.cpp
index 99278c6575ef1..df2e3fa90263a 100644
--- a/clang/test/SemaCXX/cxx2c-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx2c-decomposition.cpp
@@ -66,8 +66,8 @@ void test() {
constexpr auto [a, b] = B{};
static_assert(a.n == 0);
// expected-error at -1 {{static assertion expression is not an integral constant expression}} \
-// expected-note at -1 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}}\
-// expected-note at -2 {{temporary created here}}
+// expected-note at -1 {{read of non-constexpr variable 'a' is not allowed in a constant expression}} \
+// expected-note at -2 {{declared here}}
constinit auto [init1] = Y {42};
constinit auto [init2] = X {}; // expected-error {{variable does not have a constant initializer}} \
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c3571b59ba874..87bf9e08cf65c 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -17575,12 +17575,12 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Unspecified interpretation of <I>numeric-escape-sequence</I></td>
<td class="unknown" align="center">Unknown</td>
</tr>
- <tr class="open" id="2541">
+ <tr id="2541">
<td><a href="https://cplusplus.github.io/CWG/issues/2541.html">2541</a></td>
<td>[<a href="https://wg21.link/module.unit">module.unit</a>]</td>
- <td>open</td>
+ <td>NAD</td>
<td>Linkage specifications, module purview, and module attachment</td>
- <td align="center">Not resolved</td>
+ <td class="unknown" align="center">Unknown</td>
</tr>
<tr id="2542">
<td><a href="https://cplusplus.github.io/CWG/issues/2542.html">2542</a></td>
@@ -21762,7 +21762,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>[<a href="https://wg21.link/dcl.struct.bind">dcl.struct.bind</a>]</td>
<td>accepted</td>
<td>constexpr structured bindings with prvalues from tuples</td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 23</td>
</tr>
<tr id="3136">
<td><a href="https://cplusplus.github.io/CWG/issues/3136.html">3136</a></td>
@@ -21928,7 +21928,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<tr class="open" id="3159">
<td><a href="https://cplusplus.github.io/CWG/issues/3159.html">3159</a></td>
<td>[<a href="https://wg21.link/temp.inst">temp.inst</a>]</td>
- <td>open</td>
+ <td>review</td>
<td>Instantiation of variables with incomplete array types</td>
<td align="center">Not resolved</td>
</tr>
@@ -22068,8 +22068,8 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<tr class="open" id="3179">
<td><a href="https://cplusplus.github.io/CWG/issues/3179.html">3179</a></td>
<td>[<a href="https://wg21.link/dcl.fct">dcl.fct</a>]</td>
- <td>open</td>
- <td>More edge cases for <TT>void</TT> parameters</td>
+ <td>review</td>
+ <td>More edge cases for a <TT>void</TT> function parameter</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="3180">
@@ -22106,6 +22106,13 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>tentatively ready</td>
<td>Pointer arithmetic with similar types</td>
<td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="3185">
+ <td><a href="https://cplusplus.github.io/CWG/issues/3185.html">3185</a></td>
+ <td>[<a href="https://wg21.link/module.interface">module.interface</a>]</td>
+ <td>open</td>
+ <td>Exporting a <I><TT>static_assert</TT>-declaration</I></td>
+ <td align="center">Not resolved</td>
</tr></table>
</div>
More information about the cfe-commits
mailing list