cor3ntin updated this revision to Diff 414880.
cor3ntin added a comment.
- Rebase
- Update cxx_status as we are now targeting clang 15
- Test the pre-C++2b warnings
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D111400/new/
https://reviews.llvm.org/D111400
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Frontend/InitPreprocessor.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
clang/test/Lexer/cxx-features.cpp
clang/test/SemaCXX/constant-expression-cxx14.cpp
clang/test/SemaCXX/constant-expression-cxx2b.cpp
clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
clang/www/cxx_status.html
Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1361,7 +1361,7 @@
<tr>
<td>Non-literal variables (and labels and gotos) in constexpr functions</td>
<td><a href="https://wg21.link/P2242R3">P2242R3</a></td>
- <td class="none" align="center">No</td>
+ <td class="unreleased" align="center">Clang 15</td>
</tr>
<tr>
<td>Character encoding of diagnostic text</td>
Index: clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -115,11 +115,6 @@
constexpr const char *Str = "abc";
static_assert(fp4(Str) == Str);
-auto NCL = [](int i) { static int j; return j; }; //expected-note{{declared here}}
-constexpr int (*fp5)(int) = NCL;
-constexpr int I = //expected-error{{must be initialized by a constant expression}}
- fp5(5); //expected-note{{non-constexpr function}}
-
namespace test_dont_always_instantiate_constexpr_templates {
auto explicit_return_type = [](auto x) -> int { return x.get(); };
Index: clang/test/SemaCXX/constant-expression-cxx2b.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wpre-c++2b-compat
+
+constexpr int f(int n) { // expected-error {{constexpr function never produces a constant expression}}
+ static const int m = n; // expected-note {{declared here}} \
+ // expected-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m; // expected-note {{initializer of 'm' is not a constant expression}}
+}
+constexpr int g(int n) { // expected-error {{constexpr function never produces a constant expression}}
+ thread_local const int m = n; // expected-note {{declared here}} \
+ // expected-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m; // expected-note {{initializer of 'm' is not a constant expression}}
+}
+
+constexpr int h(int n) {
+ if (!n)
+ return 0;
+ static const int m = n; // expected-warning{{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m;
+}
+constexpr int i(int n) {
+ if (!n)
+ return 0;
+ thread_local const int m = n; // expected-warning{{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m;
+}
Index: clang/test/SemaCXX/constant-expression-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -44,14 +44,6 @@
return 3 * k3 + 5 * k2 + n * k - 20;
}
static_assert(g(2) == 42, "");
-constexpr int h(int n) {
- static const int m = n; // expected-error {{static variable not permitted in a constexpr function}}
- return m;
-}
-constexpr int i(int n) {
- thread_local const int m = n; // expected-error {{thread_local variable not permitted in a constexpr function}}
- return m;
-}
// if-statements can be used in constexpr functions.
constexpr int j(int k) {
@@ -65,7 +57,9 @@
return 2;
}
}
-} // expected-note 2{{control reached end of constexpr function}}
+} // expected-warning {{non-void}} \
+ //expected-note 2{{control reached end of constexpr function}}
+
static_assert(j(0) == -3, "");
static_assert(j(1) == 5, "");
static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
Index: clang/test/Lexer/cxx-features.cpp
===================================================================
--- clang/test/Lexer/cxx-features.cpp
+++ clang/test/Lexer/cxx-features.cpp
@@ -277,7 +277,7 @@
#error "wrong value for __cpp_lambdas"
#endif
-#if check(constexpr, 0, 200704, 201304, 201603, 201907, 201907)
+#if check(constexpr, 0, 200704, 201304, 201603, 201907, 202110)
#error "wrong value for __cpp_constexpr"
#endif
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
===================================================================
--- clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++14-extensions -Werror=c++20-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++14 -DCXX14 -Werror=c++20-extensions %s
-// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++20 -DCXX14 -DCXX20 %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++14-extensions -Werror=c++20-extensions -Werror=c++2b-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++14 -DCXX14 -Werror=c++20-extensions -Werror=c++2b-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++20 -DCXX14 -DCXX20 -Werror=c++2b-extensions %s
+// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2b -DCXX14 -DCXX20 -DCXX2b %s
namespace N {
typedef char C;
@@ -10,7 +11,7 @@
typedef double D;
}
-struct NonLiteral { // expected-note 3{{no constexpr constructors}}
+struct NonLiteral { // expected-note 2{{no constexpr constructors}}
NonLiteral() {}
NonLiteral(int) {}
};
@@ -150,16 +151,25 @@
}
constexpr int DisallowedStmtsCXX14_2() {
// - a goto statement
- goto x; // expected-error {{statement not allowed in constexpr function}}
-x:
+ try {
+ }catch (...){
+ goto x;
+ x: ;
+ }
+#ifndef CXX2b
+ // expected-error@-4 {{use of this statement in a constexpr function is a C++2b extension}}
+#endif
return 0;
}
constexpr int DisallowedStmtsCXX14_2_1() {
try {
- return 0;
} catch (...) {
- merp: goto merp; // expected-error {{statement not allowed in constexpr function}}
+ merp: goto merp;
+#ifndef CXX2b
+ // expected-error@-2 {{use of this statement in a constexpr function is a C++2b extension}}
+#endif
}
+ return 0;
}
constexpr int DisallowedStmtsCXX14_3() {
// - a try-block,
@@ -171,18 +181,35 @@
}
constexpr int DisallowedStmtsCXX14_4() {
// - a definition of a variable of non-literal type
- NonLiteral nl; // expected-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function}}
return 0;
+ NonLiteral nl;
+#ifndef CXX2b
+ // expected-error@-2 {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function before C++2b}}
+ // expected-note@14 {{'NonLiteral' is not literal}}
+#endif
}
+
constexpr int DisallowedStmtsCXX14_5() {
// - a definition of a variable of static storage duration
- static constexpr int n = 123; // expected-error {{static variable not permitted in a constexpr function}}
- return n;
+ static constexpr int n = 123;
+#ifndef CXX2b
+ // expected-error@-2 {{definition of a static variable in a constexpr function is a C++2b extension}}
+#endif
+#if !defined(CXX14)
+ // expected-error@-5 {{variable declaration in a constexpr function is a C++14 extension}}
+#endif
+ return 0;
}
constexpr int DisallowedStmtsCXX14_6() {
// - a definition of a variable of thread storage duration
- thread_local constexpr int n = 123; // expected-error {{thread_local variable not permitted in a constexpr function}}
- return n;
+ return 0;
+ thread_local constexpr int n = 123;
+#ifndef CXX2b
+ // expected-error@-2 {{definition of a thread_local variable in a constexpr function is a C++2b extension}}
+#endif
+#if !defined(CXX14)
+ // expected-error@-5 {{variable declaration in a constexpr function is a C++14 extension}}
+#endif
}
constexpr int DisallowedStmtsCXX14_7() {
// - a definition of a variable for which no initialization is performed
@@ -317,8 +344,14 @@
return x;
}
constexpr int first(int n) {
- static int value = n; // expected-error {{static variable not permitted}}
- return value;
+ return 0;
+ static int value = n;
+#ifndef CXX2b
+ // expected-error@-2 {{definition of a static variable in a constexpr function is a C++2b extension}}
+#endif
+#ifndef CXX14
+ // expected-error@-5 {{C++14}}
+#endif
}
constexpr int uninit() {
int a;
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -verify -std=c++2b -Wpre-c++2b-compat %s
+
+constexpr int h(int n) {
+ if (!n)
+ return 0;
+ static const int m = n; // expected-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m;
+}
+
+constexpr int i(int n) {
+ if (!n)
+ return 0;
+ thread_local const int m = n; // expected-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
+ return m;
+}
+
+constexpr int f(int x) {
+ if(x) {
+ return 0;
+ }
+ else {
+ goto test; // expected-note {{subexpression not valid in a constant expression}} \
+ // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++2b}}
+ }
+ test: return 0;
+}
+
+constexpr int g() { //expected-error {{constexpr function never produces a constant expression}}
+goto test; // expected-note {{subexpression not valid in a constant expression}} \
+ // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++2b}}
+test:
+return 0;
+}
+
+
+int x = f(0);
+constexpr int y = f(0); //expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{in call to 'f(0)'}}
+
+constexpr void h() {
+label:; // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++2b}}
+}
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
===================================================================
--- clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
// p3: if the function is a constructor or destructor, its class shall not have
// any virtual base classes;
@@ -9,40 +9,42 @@
};
}
-// p3: its function-body shall not enclose
-// -- a goto statement
-// -- an identifier label
-// -- a variable of non-literal type or of static or thread storage duration
namespace contents {
struct A {
constexpr ~A() {
- goto x; // expected-error {{statement not allowed in constexpr function}}
+ return;
+ goto x;
x: ;
}
};
struct B {
constexpr ~B() {
- x: ; // expected-error {{statement not allowed in constexpr function}}
+ x: ;
}
};
- struct Nonlit { Nonlit(); }; // expected-note {{not literal}}
+ struct Nonlit { Nonlit(); };
struct C {
constexpr ~C() {
- Nonlit nl; // expected-error {{non-literal}}
+ return;
+ Nonlit nl;
}
};
struct D {
constexpr ~D() {
- static int a; // expected-error {{static variable}}
+ return;
+ static int a;
}
};
struct E {
constexpr ~E() {
- thread_local int e; // expected-error {{thread_local variable}}
+ return;
+ thread_local int e;
+
}
};
struct F {
constexpr ~F() {
+ return;
extern int f;
}
};
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -1892,13 +1892,17 @@
if (VD->isStaticLocal()) {
if (Kind == Sema::CheckConstexprKind::Diagnose) {
SemaRef.Diag(VD->getLocation(),
- diag::err_constexpr_local_var_static)
- << isa<CXXConstructorDecl>(Dcl)
- << (VD->getTLSKind() == VarDecl::TLS_Dynamic);
+ SemaRef.getLangOpts().CPlusPlus2b
+ ? diag::warn_cxx20_compat_constexpr_static_var
+ : diag::ext_constexpr_static_var)
+ << isa<CXXConstructorDecl>(Dcl)
+ << (VD->getTLSKind() == VarDecl::TLS_Dynamic);
+ } else if (!SemaRef.getLangOpts().CPlusPlus2b) {
+ return false;
}
- return false;
}
- if (CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(),
+ if (!SemaRef.LangOpts.CPlusPlus2b &&
+ CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(),
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
@@ -2021,6 +2025,7 @@
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
SmallVectorImpl<SourceLocation> &ReturnStmts,
SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc,
+ SourceLocation &Cxx2bLoc,
Sema::CheckConstexprKind Kind) {
// - its function-body shall be [...] a compound-statement that contains only
switch (S->getStmtClass()) {
@@ -2053,9 +2058,9 @@
case Stmt::AttributedStmtClass:
// Attributes on a statement don't affect its formal kind and hence don't
// affect its validity in a constexpr function.
- return CheckConstexprFunctionStmt(SemaRef, Dcl,
- cast<AttributedStmt>(S)->getSubStmt(),
- ReturnStmts, Cxx1yLoc, Cxx2aLoc, Kind);
+ return CheckConstexprFunctionStmt(
+ SemaRef, Dcl, cast<AttributedStmt>(S)->getSubStmt(), ReturnStmts,
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind);
case Stmt::CompoundStmtClass: {
// C++1y allows compound-statements.
@@ -2065,7 +2070,7 @@
CompoundStmt *CompStmt = cast<CompoundStmt>(S);
for (auto *BodyIt : CompStmt->body()) {
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
}
return true;
@@ -2078,11 +2083,11 @@
IfStmt *If = cast<IfStmt>(S);
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
if (If->getElse() &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
return true;
}
@@ -2101,7 +2106,7 @@
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
return true;
@@ -2116,7 +2121,18 @@
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
+ return false;
+ return true;
+
+ case Stmt::LabelStmtClass:
+ case Stmt::GotoStmtClass:
+ if (!Cxx2bLoc.isValid())
+ Cxx2bLoc = S->getBeginLoc();
+ for (Stmt *SubStmt : S->children())
+ if (SubStmt &&
+ !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
return true;
@@ -2129,7 +2145,7 @@
for (Stmt *SubStmt : S->children()) {
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
}
return true;
@@ -2137,9 +2153,9 @@
case Stmt::CXXCatchStmtClass:
// Do not bother checking the language mode (already covered by the
// try block check).
- if (!CheckConstexprFunctionStmt(SemaRef, Dcl,
- cast<CXXCatchStmt>(S)->getHandlerBlock(),
- ReturnStmts, Cxx1yLoc, Cxx2aLoc, Kind))
+ if (!CheckConstexprFunctionStmt(
+ SemaRef, Dcl, cast<CXXCatchStmt>(S)->getHandlerBlock(), ReturnStmts,
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
return true;
@@ -2204,20 +2220,27 @@
//
// Note that walking the children here is enough to properly check for
// CompoundStmt and CXXTryStmt body.
- SourceLocation Cxx1yLoc, Cxx2aLoc;
+ SourceLocation Cxx1yLoc, Cxx2aLoc, Cxx2bLoc;
for (Stmt *SubStmt : Body->children()) {
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
- Cxx1yLoc, Cxx2aLoc, Kind))
+ Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind))
return false;
}
if (Kind == Sema::CheckConstexprKind::CheckValid) {
// If this is only valid as an extension, report that we don't satisfy the
// constraints of the current language.
- if ((Cxx2aLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus20) ||
+ if ((Cxx2bLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus2b) ||
+ (Cxx2aLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus20) ||
(Cxx1yLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus17))
return false;
+ } else if (Cxx2bLoc.isValid()) {
+ SemaRef.Diag(Cxx2bLoc,
+ SemaRef.getLangOpts().CPlusPlus2b
+ ? diag::warn_cxx20_compat_constexpr_body_invalid_stmt
+ : diag::ext_constexpr_body_invalid_stmt_cxx2b)
+ << isa<CXXConstructorDecl>(Dcl);
} else if (Cxx2aLoc.isValid()) {
SemaRef.Diag(Cxx2aLoc,
SemaRef.getLangOpts().CPlusPlus20
Index: clang/lib/Frontend/InitPreprocessor.cpp
===================================================================
--- clang/lib/Frontend/InitPreprocessor.cpp
+++ clang/lib/Frontend/InitPreprocessor.cpp
@@ -561,10 +561,11 @@
Builder.defineMacro("__cpp_unicode_literals", "200710L");
Builder.defineMacro("__cpp_user_defined_literals", "200809L");
Builder.defineMacro("__cpp_lambdas", "200907L");
- Builder.defineMacro("__cpp_constexpr",
- LangOpts.CPlusPlus20 ? "201907L" :
- LangOpts.CPlusPlus17 ? "201603L" :
- LangOpts.CPlusPlus14 ? "201304L" : "200704");
+ Builder.defineMacro("__cpp_constexpr", LangOpts.CPlusPlus2b ? "202110L"
+ : LangOpts.CPlusPlus20 ? "201907L"
+ : LangOpts.CPlusPlus17 ? "201603L"
+ : LangOpts.CPlusPlus14 ? "201304L"
+ : "200704");
Builder.defineMacro("__cpp_constexpr_in_decltype", "201711L");
Builder.defineMacro("__cpp_range_based_for",
LangOpts.CPlusPlus17 ? "201603L" : "200907");
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2689,6 +2689,13 @@
"use of this statement in a constexpr %select{function|constructor}0 "
"is incompatible with C++ standards before C++20">,
InGroup<CXXPre20Compat>, DefaultIgnore;
+def ext_constexpr_body_invalid_stmt_cxx2b : ExtWarn<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is a C++2b extension">, InGroup<CXX2b>;
+def warn_cxx20_compat_constexpr_body_invalid_stmt : Warning<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++2b">,
+ InGroup<CXXPre2bCompat>, DefaultIgnore;
def ext_constexpr_type_definition : ExtWarn<
"type definition in a constexpr %select{function|constructor}0 "
"is a C++14 extension">, InGroup<CXX14>;
@@ -2706,12 +2713,18 @@
"variable declaration in a constexpr %select{function|constructor}0 "
"is incompatible with C++ standards before C++14">,
InGroup<CXXPre14Compat>, DefaultIgnore;
-def err_constexpr_local_var_static : Error<
- "%select{static|thread_local}1 variable not permitted in a constexpr "
- "%select{function|constructor}0">;
+def ext_constexpr_static_var : ExtWarn<
+ "definition of a %select{static|thread_local}1 variable "
+ "in a constexpr %select{function|constructor}0 "
+ "is a C++2b extension">, InGroup<CXX2b>;
+def warn_cxx20_compat_constexpr_static_var : Warning<
+ "definition of a %select{static|thread_local}1 variable "
+ "in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++2b">,
+ InGroup<CXXPre2bCompat>, DefaultIgnore;
def err_constexpr_local_var_non_literal_type : Error<
"variable of non-literal type %1 cannot be defined in a constexpr "
- "%select{function|constructor}0">;
+ "%select{function|constructor}0 before C++2b">;
def ext_constexpr_local_var_no_init : ExtWarn<
"uninitialized variable in a constexpr %select{function|constructor}0 "
"is a C++20 extension">, InGroup<CXX20>;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -127,6 +127,7 @@
- Implemented `P2128R6: Multidimensional subscript operator <https://wg21.link/P2128R6>`_.
- Implemented `P0849R8: auto(x): decay-copy in the language <https://wg21.link/P0849R8>`_.
+- Implemented `P2242R3: Non-literal variables (and labels and gotos) in constexpr functions <https://wg21.link/P2242R3>`_.
CUDA Language Changes in Clang
------------------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits