[clang] [clang] Accept lambdas in C++03 as an extensions (PR #73376)
Nikolas Klauser via cfe-commits
cfe-commits at lists.llvm.org
Sat Dec 2 05:56:54 PST 2023
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/73376
>From 563f86bddc0ec59b63c6aeffee2342f027c09119 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 1 Dec 2023 18:16:36 +0100
Subject: [PATCH 1/2] [clang] Fix crash when declaring invalid lambda member
---
clang/lib/AST/DeclCXX.cpp | 7 +++----
clang/test/SemaCXX/lambda-expressions.cpp | 16 +++++++++-------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index c944862fcefee..e9e62fea9fb37 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1526,10 +1526,9 @@ bool CXXRecordDecl::isGenericLambda() const {
#ifndef NDEBUG
static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
- for (auto *D : R)
- if (!declaresSameEntity(D, R.front()))
- return false;
- return true;
+ return llvm::all_of(R, [&](NamedDecl *D) {
+ return D->isInvalidDecl() || declaresSameEntity(D, R.front());
+ });
}
#endif
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 1797eef320b86..1921d02b1a9cf 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,expected-cxx14,cxx11 -fblocks %s
// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -verify=expected-cxx14 -fblocks %s
// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify -ast-dump -fblocks %s | FileCheck %s
@@ -558,8 +559,8 @@ struct B {
int x;
A a = [&] { int y = x; };
A b = [&] { [&] { [&] { int y = x; }; }; };
- A d = [&](auto param) { int y = x; };
- A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; };
+ A d = [&](auto param) { int y = x; }; // cxx11-error {{'auto' not allowed in lambda parameter}}
+ A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx11-error 2 {{'auto' not allowed in lambda parameter}}
};
B<int> b;
@@ -589,6 +590,7 @@ struct S1 {
void foo1() {
auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}}
auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}}
+ // cxx11-warning at -1 {{initialized lambda captures are a C++14 extension}}
}
}
@@ -604,7 +606,7 @@ namespace PR25627_dont_odr_use_local_consts {
namespace ConversionOperatorDoesNotHaveDeducedReturnType {
auto x = [](int){};
- auto y = [](auto &v) -> void { v.n = 0; };
+ auto y = [](auto &v) -> void { v.n = 0; }; // cxx11-error {{'auto' not allowed in lambda parameter}} cxx11-note {{candidate function not viable}} cxx11-note {{conversion candidate}}
using T = decltype(x);
using U = decltype(y);
using ExpectedTypeT = void (*)(int);
@@ -624,14 +626,14 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
template<typename T>
friend constexpr U::operator ExpectedTypeU<T>() const noexcept;
#else
- friend auto T::operator()(int) const;
+ friend auto T::operator()(int) const; // cxx11-error {{'auto' return without trailing return type; deduced return types are a C++14 extension}}
friend T::operator ExpectedTypeT() const;
template<typename T>
- friend void U::operator()(T&) const;
+ friend void U::operator()(T&) const; // cxx11-error {{friend declaration of 'operator()' does not match any declaration}}
// FIXME: This should not match, as above.
template<typename T>
- friend U::operator ExpectedTypeU<T>() const;
+ friend U::operator ExpectedTypeU<T>() const; // cxx11-error {{friend declaration of 'operator void (*)(type-parameter-0-0 &)' does not match any declaration}}
#endif
private:
@@ -639,7 +641,7 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
};
// Should be OK: lambda's call operator is a friend.
- void use(X &x) { y(x); }
+ void use(X &x) { y(x); } // cxx11-error {{no matching function for call to object}}
// This used to crash in return type deduction for the conversion opreator.
struct A { int n; void f() { +[](decltype(n)) {}; } };
>From b566ad7128fac43d991d773eae60545ed49566e6 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 25 Nov 2023 04:00:57 +0100
Subject: [PATCH 2/2] [clang] Accept lambdas in C++03 as an extensions
This is a fairly simple extension, but makes the life for people who
have to support C++03 a lot easier. As a nice bonus, this also improves
diagnostics, since lambdas are now properly recognized when parsing
C++03 code.
---
clang/docs/LanguageExtensions.rst | 71 ++++++-----
.../clang/Basic/DiagnosticParseKinds.td | 1 +
clang/include/clang/Basic/Features.def | 1 +
clang/lib/Parse/ParseExpr.cpp | 2 +-
clang/lib/Parse/ParseExprCXX.cpp | 9 +-
clang/lib/Parse/ParseInit.cpp | 2 +-
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaDeclCXX.cpp | 3 +-
clang/test/Lexer/has_extension_cxx.cpp | 5 +
.../OpenMP/declare_reduction_messages.cpp | 14 +--
clang/test/OpenMP/openmp_check.cpp | 2 +-
clang/test/Parser/cxx03-lambda-extension.cpp | 5 +
.../test/Parser/cxx0x-lambda-expressions.cpp | 116 +++++++-----------
clang/test/Parser/cxx2b-lambdas.cpp | 43 +++++--
.../Parser/objcxx-lambda-expressions-neg.mm | 9 +-
clang/test/ParserHLSL/group_shared.hlsl | 4 +-
clang/test/SemaCXX/cxx2a-template-lambdas.cpp | 26 ++--
clang/test/SemaCXX/lambda-expressions.cpp | 66 +++++-----
.../SemaCXX/lambda-implicit-this-capture.cpp | 1 +
clang/test/SemaCXX/lambda-invalid-capture.cpp | 1 +
clang/test/SemaCXX/new-delete.cpp | 7 +-
21 files changed, 209 insertions(+), 181 deletions(-)
create mode 100644 clang/test/Parser/cxx03-lambda-extension.cpp
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 294210c6ac140..52b3086198772 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1455,39 +1455,44 @@ More information could be found `here <https://clang.llvm.org/docs/Modules.html>
Language Extensions Back-ported to Previous Standards
=====================================================
-====================================== ================================ ============= =============
-Feature Feature Test Macro Introduced In Backported To
-====================================== ================================ ============= =============
-variadic templates __cpp_variadic_templates C++11 C++03
-Alias templates __cpp_alias_templates C++11 C++03
-Non-static data member initializers __cpp_nsdmi C++11 C++03
-Range-based ``for`` loop __cpp_range_based_for C++11 C++03
-RValue references __cpp_rvalue_references C++11 C++03
-Attributes __cpp_attributes C++11 C++03
-variable templates __cpp_variable_templates C++14 C++03
-Binary literals __cpp_binary_literals C++14 C++03
-Relaxed constexpr __cpp_constexpr C++14 C++11
-``if constexpr`` __cpp_if_constexpr C++17 C++11
-fold expressions __cpp_fold_expressions C++17 C++03
-Lambda capture of \*this by value __cpp_capture_star_this C++17 C++11
-Attributes on enums __cpp_enumerator_attributes C++17 C++11
-Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03
-Hexadecimal floating literals __cpp_hex_float C++17 C++03
-``inline`` variables __cpp_inline_variables C++17 C++03
-Attributes on namespaces __cpp_namespace_attributes C++17 C++11
-Structured bindings __cpp_structured_bindings C++17 C++03
-template template arguments __cpp_template_template_args C++17 C++03
-``static operator[]`` __cpp_multidimensional_subscript C++20 C++03
-Designated initializers __cpp_designated_initializers C++20 C++03
-Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03
-``using enum`` __cpp_using_enum C++20 C++03
-``if consteval`` __cpp_if_consteval C++23 C++20
-``static operator()`` __cpp_static_call_operator C++23 C++03
--------------------------------------- -------------------------------- ------------- -------------
-Designated initializers (N494) C99 C89
-Array & element qualification (N2607) C23 C89
-Attributes (N2335) C23 C89
-====================================== ================================ ============= =============
+============================================ ================================ ============= =============
+Feature Feature Test Macro Introduced In Backported To
+============================================ ================================ ============= =============
+variadic templates __cpp_variadic_templates C++11 C++03
+Alias templates __cpp_alias_templates C++11 C++03
+Non-static data member initializers __cpp_nsdmi C++11 C++03
+Range-based ``for`` loop __cpp_range_based_for C++11 C++03
+RValue references __cpp_rvalue_references C++11 C++03
+Attributes __cpp_attributes C++11 C++03
+Lambdas __cpp_lambdas C++11 C++03
+Generalized lambda captures __cpp_init_captures C++14 C++03
+Generic lambda expressions __cpp_generic_lambdas C++14 C++03
+variable templates __cpp_variable_templates C++14 C++03
+Binary literals __cpp_binary_literals C++14 C++03
+Relaxed constexpr __cpp_constexpr C++14 C++11
+Pack expansion in generalized lambda-capture __cpp_init_captures C++17 C++03
+``if constexpr`` __cpp_if_constexpr C++17 C++11
+fold expressions __cpp_fold_expressions C++17 C++03
+Lambda capture of \*this by value __cpp_capture_star_this C++17 C++03
+Attributes on enums __cpp_enumerator_attributes C++17 C++11
+Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03
+Hexadecimal floating literals __cpp_hex_float C++17 C++03
+``inline`` variables __cpp_inline_variables C++17 C++03
+Attributes on namespaces __cpp_namespace_attributes C++17 C++11
+Structured bindings __cpp_structured_bindings C++17 C++03
+template template arguments __cpp_template_template_args C++17 C++03
+Familiar template syntax for generic lambdas __cpp_generic_lambdas C++20 C++03
+``static operator[]`` __cpp_multidimensional_subscript C++20 C++03
+Designated initializers __cpp_designated_initializers C++20 C++03
+Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03
+``using enum`` __cpp_using_enum C++20 C++03
+``if consteval`` __cpp_if_consteval C++23 C++20
+``static operator()`` __cpp_static_call_operator C++23 C++03
+-------------------------------------------- -------------------------------- ------------- -------------
+Designated initializers (N494) C99 C89
+Array & element qualification (N2607) C23 C89
+Attributes (N2335) C23 C89
+============================================ ================================ ============= =============
Type Trait Primitives
=====================
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 54b5ba6e6414b..c1b378304b331 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1023,6 +1023,7 @@ def err_expected_lambda_body : Error<"expected body of lambda expression">;
def warn_cxx98_compat_lambda : Warning<
"lambda expressions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def ext_lambda : ExtWarn<"lambdas are a C++11 extension">, InGroup<CXX11>;
def err_lambda_decl_specifier_repeated : Error<
"%select{'mutable'|'static'|'constexpr'|'consteval'}0 cannot "
"appear multiple times in a lambda declarator">;
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index adaf2e413f2f6..7f1e243adddeb 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -254,6 +254,7 @@ EXTENSION(cxx_defaulted_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus)
EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus)
+EXTENSION(cxx_lambdas, LangOpts.CPlusPlus)
EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus)
EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus)
EXTENSION(cxx_override_control, LangOpts.CPlusPlus)
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 8978105579761..c453d77329111 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1799,7 +1799,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
}
goto ExpectedExpression;
case tok::l_square:
- if (getLangOpts().CPlusPlus11) {
+ if (getLangOpts().CPlusPlus) {
if (getLangOpts().ObjC) {
// C++11 lambda expressions and Objective-C message sends both start with a
// square bracket. There are three possibilities here:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 79db094e098f8..2b6044f29fdd8 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -751,9 +751,8 @@ ExprResult Parser::ParseLambdaExpression() {
///
/// If we are not looking at a lambda expression, returns ExprError().
ExprResult Parser::TryParseLambdaExpression() {
- assert(getLangOpts().CPlusPlus11
- && Tok.is(tok::l_square)
- && "Not at the start of a possible lambda expression.");
+ assert(getLangOpts().CPlusPlus && Tok.is(tok::l_square) &&
+ "Not at the start of a possible lambda expression.");
const Token Next = NextToken();
if (Next.is(tok::eof)) // Nothing else to lookup here...
@@ -1271,7 +1270,9 @@ static void DiagnoseStaticSpecifierRestrictions(Parser &P,
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro) {
SourceLocation LambdaBeginLoc = Intro.Range.getBegin();
- Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda);
+ Diag(LambdaBeginLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_lambda
+ : diag::ext_lambda);
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
"lambda expression parsing");
diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp
index 637f21176792b..423497bfcb662 100644
--- a/clang/lib/Parse/ParseInit.cpp
+++ b/clang/lib/Parse/ParseInit.cpp
@@ -35,7 +35,7 @@ bool Parser::MayBeDesignationStart() {
return true;
case tok::l_square: { // designator: array-designator
- if (!PP.getLangOpts().CPlusPlus11)
+ if (!PP.getLangOpts().CPlusPlus)
return true;
// C++11 lambda expressions and C99 designators can be ambiguous all the
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 23dd8ae15c165..c96c6c8d9e521 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15877,7 +15877,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FD->setInvalidDecl();
}
}
- } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) {
+ } else if (getLangOpts().CPlusPlus && isLambdaCallOperator(FD)) {
// In C++11, we don't use 'auto' deduction rules for lambda call
// operators because we don't support return type deduction.
auto *LSI = getCurLambda();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3688192e6cbe5..34a88e1d0c1df 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9716,7 +9716,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
return false;
CXXRecordDecl *RD = MD->getParent();
assert(!RD->isDependentType() && "do deletion after instantiation");
- if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl())
+ if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+ RD->isInvalidDecl())
return false;
// C++11 [expr.lambda.prim]p19:
diff --git a/clang/test/Lexer/has_extension_cxx.cpp b/clang/test/Lexer/has_extension_cxx.cpp
index 1ae6a446b300a..df43d75c90114 100644
--- a/clang/test/Lexer/has_extension_cxx.cpp
+++ b/clang/test/Lexer/has_extension_cxx.cpp
@@ -31,6 +31,11 @@ int has_deleted_functions();
int has_inline_namespaces();
#endif
+// CHECK: has_lambdas
+#if __has_extension(cxx_lambdas)
+int has_lambdas();
+#endif
+
// CHECK: has_override_control
#if __has_extension(cxx_override_control)
int has_override_control();
diff --git a/clang/test/OpenMP/declare_reduction_messages.cpp b/clang/test/OpenMP/declare_reduction_messages.cpp
index 38a5d766eeadf..752cc4fb05a12 100644
--- a/clang/test/OpenMP/declare_reduction_messages.cpp
+++ b/clang/test/OpenMP/declare_reduction_messages.cpp
@@ -58,16 +58,10 @@ class Class2 : public Class1<T> {
#pragma omp declare reduction(fun1 : long : omp_out += omp_in) initializer // expected-error {{expected '(' after 'initializer'}}
#pragma omp declare reduction(fun2 : long : omp_out += omp_in) initializer { // expected-error {{expected '(' after 'initializer'}} expected-error {{expected expression}} expected-warning {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
#pragma omp declare reduction(fun3 : long : omp_out += omp_in) initializer[
-#if __cplusplus <= 199711L
-// expected-error at -2 {{expected '(' after 'initializer'}}
-// expected-error at -3 {{expected expression}}
-// expected-warning at -4 {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
-#else
-// expected-error at -6 {{expected '(' after 'initializer'}}
-// expected-error at -7 {{expected variable name or 'this' in lambda capture list}}
-// expected-error at -8 {{expected ')'}}
-// expected-note at -9 {{to match this '('}}
-#endif
+// expected-error at -1 {{expected '(' after 'initializer'}}
+// expected-error at -2 {{expected variable name or 'this' in lambda capture list}}
+// expected-error at -3 {{expected ')'}}
+// expected-note at -4 {{to match this '('}}
#pragma omp declare reduction(fun4 : long : omp_out += omp_in) initializer() // expected-error {{expected expression}}
#pragma omp declare reduction(fun5 : long : omp_out += omp_in) initializer(temp) // expected-error {{only 'omp_priv' or 'omp_orig' variables are allowed in initializer expression}}
#pragma omp declare reduction(fun6 : long : omp_out += omp_in) initializer(omp_orig // expected-error {{expected ')'}} expected-note {{to match this '('}}
diff --git a/clang/test/OpenMP/openmp_check.cpp b/clang/test/OpenMP/openmp_check.cpp
index 6a8dd17fc8367..b52ce0c066922 100644
--- a/clang/test/OpenMP/openmp_check.cpp
+++ b/clang/test/OpenMP/openmp_check.cpp
@@ -18,7 +18,7 @@ int nested(int a) {
auto F = [&]() {
#if __cplusplus <= 199711L
// expected-warning at -2 {{'auto' type specifier is a C++11 extension}}
- // expected-error at -3 {{expected expression}}
+ // expected-warning at -3 {{lambdas are a C++11 extension}}
#endif
#pragma omp parallel
diff --git a/clang/test/Parser/cxx03-lambda-extension.cpp b/clang/test/Parser/cxx03-lambda-extension.cpp
new file mode 100644
index 0000000000000..82ae7da305305
--- /dev/null
+++ b/clang/test/Parser/cxx03-lambda-extension.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++03 %s
+
+void func() {
+ []() {}; // expected-warning {{lambdas are a C++11 extension}}
+}
diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp
index 72b315a497c06..a786a964163e4 100644
--- a/clang/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp
@@ -1,10 +1,15 @@
-// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 -Wno-c99-designator %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++20 -Wno-c99-designator %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++23 -Wno-c99-designator %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++03 -Wno-c99-designator %s -Wno-c++11-extensions
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++11 -Wno-c99-designator %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx17ext,cxx20ext,cxx23ext -std=c++14 -Wno-c99-designator %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx20ext,cxx23ext -std=c++17 -Wno-c99-designator %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx23ext -std=c++20 -Wno-c99-designator %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected -std=c++23 -Wno-c99-designator %s
enum E { e };
+#if __cplusplus >= 201103L
constexpr int id(int n) { return n; }
+#endif
class C {
@@ -19,28 +24,25 @@ class C {
[&,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
[=,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
[] {};
- [=] (int i) {};
- [&] (int) mutable -> void {};
- [foo,bar] () { return 3; };
- [=,&foo] () {};
- [&,foo] () {};
- [this] () {};
+ [=] (int i) {};
+ [&] (int) mutable -> void {};
+ [foo,bar] () { return 3; };
+ [=,&foo] () {};
+ [&,foo] () {};
+ [this] () {};
[] () -> class C { return C(); };
[] () -> enum E { return e; };
- [] -> int { return 0; };
- [] mutable -> int { return 0; };
-#if __cplusplus <= 202002L
- // expected-warning at -3 {{lambda without a parameter clause is a C++23 extension}}
- // expected-warning at -3 {{is a C++23 extension}}
-#endif
+ [] -> int { return 0; }; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}}
+ [] mutable -> int { return 0; }; // cxx23ext-warning {{is a C++23 extension}}
+
[](int) -> {}; // PR13652 expected-error {{expected a type}}
return 1;
}
void designator_or_lambda() {
- typedef int T;
- const int b = 0;
+ typedef int T;
+ const int b = 0;
const int c = 1;
int d;
int a1[1] = {[b] (T()) {}}; // expected-error{{no viable conversion from '(lambda}}
@@ -49,19 +51,18 @@ class C {
int a4[1] = {[&b] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'const int *'}}
int a5[3] = { []{return 0;}() };
int a6[1] = {[this] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'C *'}}
- int a7[1] = {[d(0)] { return d; } ()};
- int a8[1] = {[d = 0] { return d; } ()};
- int a10[1] = {[id(0)] { return id; } ()};
-#if __cplusplus <= 201103L
- // expected-warning at -4{{extension}}
- // expected-warning at -4{{extension}}
- // expected-warning at -4{{extension}}
+ int a7[1] = {[d(0)] { return d; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}}
+ int a8[1] = {[d = 0] { return d; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}}
+#if __cplusplus >= 201103L
+ int a10[1] = {[id(0)] { return id; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}}
#endif
int a9[1] = {[d = 0] = 1}; // expected-error{{is not an integral constant expression}}
#if __cplusplus >= 201402L
// expected-note at -2{{constant expression cannot modify an object that is visible outside that expression}}
#endif
+#if __cplusplus >= 201103L
int a11[1] = {[id(0)] = 1};
+#endif
}
void delete_lambda(int *p) {
@@ -80,43 +81,33 @@ class C {
// We support init-captures in C++11 as an extension.
int z;
void init_capture() {
- [n(0)] () mutable -> int { return ++n; };
- [n{0}] { return; };
- [a([&b = z]{})](){};
- [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}}
- [n = {0}] { return; }; // expected-error {{<initializer_list>}}
-#if __cplusplus <= 201103L
- // expected-warning at -6{{extension}}
- // expected-warning at -6{{extension}}
- // expected-warning at -6{{extension}}
- // expected-warning at -7{{extension}}
- // expected-warning at -7{{extension}}
- // expected-warning at -7{{extension}}
-#endif
+ [n(0)] () mutable -> int { return ++n; }; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}}
+ [n{0}] { return; }; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}}
+ [a([&b = z]{})](){}; // cxx14ext-warning 2 {{initialized lambda captures are a C++14 extension}}
+ [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}}
+ // cxx14ext-warning at -1 {{initialized lambda captures are a C++14 extension}}
+ [n = {0}] { return; }; // expected-error {{<initializer_list>}}
+ // cxx14ext-warning at -1 {{initialized lambda captures are a C++14 extension}}
int x = 4;
- auto y = [&r = x, x = x + 1]() -> int {
-#if __cplusplus <= 201103L
- // expected-warning at -2{{extension}}
- // expected-warning at -3{{extension}}
-#endif
+ auto y = [&r = x, x = x + 1]() -> int { // cxx14ext-warning 2 {{initialized lambda captures are a C++14 extension}}
r += 2;
return x + 2;
} ();
}
void attributes() {
- [] __attribute__((noreturn)){};
-#if __cplusplus <= 202002L
- // expected-warning at -2 {{is a C++23 extension}}
-#endif
+ [] __attribute__((noreturn)){}; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}}
+
[]() [[]]
mutable {}; // expected-error {{expected body of lambda expression}}
[]() [[]] {};
[]() [[]] -> void {};
[]() mutable [[]] -> void {};
+#if __cplusplus >= 201103L
[]() mutable noexcept [[]] -> void {};
+#endif
// Testing GNU-style attributes on lambdas -- the attribute is specified
// before the mutable specifier instead of after (unlike C++11).
@@ -126,28 +117,18 @@ class C {
// Testing support for P2173 on adding attributes to the declaration
// rather than the type.
- [][[]](){};
-#if __cplusplus <= 202002L
- // expected-warning at -2 {{an attribute specifier sequence in this position is a C++23 extension}}
-#endif
-#if __cplusplus > 201703L
- []<typename>[[]](){};
-#if __cplusplus <= 202002L
- // expected-warning at -2 {{an attribute specifier sequence in this position is a C++23 extension}}
-#endif
-#endif
- [][[]]{};
-#if __cplusplus <= 202002L
- // expected-warning at -2 {{an attribute specifier sequence in this position is a C++23 extension}}
-#endif
+ [][[]](){}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}}
+
+ []<typename>[[]](){}; // cxx20ext-warning {{explicit template parameter list for lambdas is a C++20 extension}}
+ // cxx23ext-warning at -1 {{an attribute specifier sequence in this position is a C++23 extension}}
+
+ [][[]]{}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}}
}
void missing_parens() {
- [] mutable {};
- [] noexcept {};
-#if __cplusplus <= 202002L
- // expected-warning at -3 {{is a C++23 extension}}
- // expected-warning at -3 {{is a C++23 extension}}
+ [] mutable {}; // cxx23ext-warning {{is a C++23 extension}}
+#if __cplusplus >= 201103L
+ [] noexcept {}; // cxx23ext-warning {{is a C++23 extension}}
#endif
}
};
@@ -165,10 +146,7 @@ struct A {
};
struct S {
- void mf() { A{[*this]{}}; }
-#if __cplusplus < 201703L
- // expected-warning at -2 {{C++17 extension}}
-#endif
+ void mf() { A(([*this]{})); } // cxx17ext-warning {{'*this' by copy is a C++17 extension}}
};
}
diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp
index bb9ed226afffa..6582679f65029 100644
--- a/clang/test/Parser/cxx2b-lambdas.cpp
+++ b/clang/test/Parser/cxx2b-lambdas.cpp
@@ -1,30 +1,48 @@
+// RUN: %clang_cc1 -std=c++03 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -Wno-c++11-extensions
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11 -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions
+// RUN: %clang_cc1 -std=c++14 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions
+// RUN: %clang_cc1 -std=c++17 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions
+// RUN: %clang_cc1 -std=c++20 %s -verify -Wno-c++23-extensions
// RUN: %clang_cc1 -std=c++23 %s -verify
auto LL0 = [] {};
auto LL1 = []() {};
auto LL2 = []() mutable {};
-auto LL3 = []() constexpr {};
+#if __cplusplus >= 201103L
+auto LL3 = []() constexpr {}; // cxx11-error {{return type 'void' is not a literal type}}
+#endif
-auto L0 = [] constexpr {};
+#if __cplusplus >= 201103L
+auto L0 = [] constexpr {}; // cxx11-error {{return type 'void' is not a literal type}}
+#endif
auto L1 = [] mutable {};
+#if __cplusplus >= 201103L
auto L2 = [] noexcept {};
-auto L3 = [] constexpr mutable {};
-auto L4 = [] mutable constexpr {};
-auto L5 = [] constexpr mutable noexcept {};
+auto L3 = [] constexpr mutable {}; // cxx11-error {{return type 'void' is not a literal type}}
+auto L4 = [] mutable constexpr {}; // cxx11-error {{return type 'void' is not a literal type}}
+auto L5 = [] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}}
+#endif
auto L6 = [s = 1] mutable {};
-auto L7 = [s = 1] constexpr mutable noexcept {};
+#if __cplusplus >= 201103L
+auto L7 = [s = 1] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}}
+#endif
auto L8 = [] -> bool { return true; };
auto L9 = []<typename T> { return true; };
+#if __cplusplus >= 201103L
auto L10 = []<typename T> noexcept { return true; };
+#endif
auto L11 = []<typename T> -> bool { return true; };
+#if __cplusplus >= 202002L
auto L12 = [] consteval {};
auto L13 = []() requires true {}; // expected-error{{non-templated function cannot have a requires clause}}
auto L14 = []<auto> requires true() requires true {};
auto L15 = []<auto> requires true noexcept {};
+#endif
auto L16 = [] [[maybe_unused]]{};
-auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}}
-auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}}
+#if __cplusplus >= 201103L
+auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}}
+auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}}
auto XL2 = []) constexpr mutable constexpr {}; // expected-error{{expected body of lambda expression}}
auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storage class specifier}} \
// expected-error{{function parameter cannot be constexpr}} \
@@ -33,16 +51,23 @@ auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storag
// expected-note{{to match this '('}} \
// expected-error{{expected body}} \
// expected-warning{{duplicate 'constexpr'}}
+#endif
// http://llvm.org/PR49736
auto XL4 = [] requires true {}; // expected-error{{expected body}}
+#if __cplusplus >= 201703L
auto XL5 = []<auto> requires true requires true {}; // expected-error{{expected body}}
auto XL6 = []<auto> requires true noexcept requires true {}; // expected-error{{expected body}}
+#endif
auto XL7 = []() static static {}; // expected-error {{cannot appear multiple times}}
auto XL8 = []() static mutable {}; // expected-error {{cannot be both mutable and static}}
+#if __cplusplus >= 202002L
auto XL9 = []() static consteval {};
-auto XL10 = []() static constexpr {};
+#endif
+#if __cplusplus >= 201103L
+auto XL10 = []() static constexpr {}; // cxx11-error {{return type 'void' is not a literal type}}
+#endif
auto XL11 = [] static {};
auto XL12 = []() static {};
diff --git a/clang/test/Parser/objcxx-lambda-expressions-neg.mm b/clang/test/Parser/objcxx-lambda-expressions-neg.mm
index b2fe39dfbf708..795157816dcfd 100644
--- a/clang/test/Parser/objcxx-lambda-expressions-neg.mm
+++ b/clang/test/Parser/objcxx-lambda-expressions-neg.mm
@@ -1,13 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=cxx03 -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 %s
int main() {
- []{};
-#if __cplusplus <= 199711L
- // expected-error at -2 {{expected expression}}
-#else
+ []{}; // cxx03-warning {{lambdas are a C++11 extension}}
// expected-no-diagnostics
-#endif
-
}
diff --git a/clang/test/ParserHLSL/group_shared.hlsl b/clang/test/ParserHLSL/group_shared.hlsl
index 0b9f28395ee48..44f3a2e5b4505 100644
--- a/clang/test/ParserHLSL/group_shared.hlsl
+++ b/clang/test/ParserHLSL/group_shared.hlsl
@@ -3,8 +3,8 @@ extern groupshared float f;
extern float groupshared f; // Ok, redeclaration?
-// NOTE:lambda is not enabled except for hlsl202x.
-// expected-error at +2 {{expected expression}}
+// expected-warning at +3 {{lambdas are a C++11 extension}}
+// expected-error at +2 {{expected body of lambda expression}}
// expected-warning at +1 {{'auto' type specifier is a C++11 extension}}
auto l = []() groupshared {};
diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
index 7ac4813698914..dd66577236cac 100644
--- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -1,10 +1,14 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
+// RUN: %clang_cc1 -std=c++03 -verify -Dstatic_assert=_Static_assert -Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions %s
+// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11,cxx11-cxx14 -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions %s
+// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx11-cxx14,cxx14 -Wno-c++20-extensions -Wno-c++17-extensions %s
+// RUN: %clang_cc1 -std=c++17 -verify -Wno-c++20-extensions %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
template<typename, typename>
-constexpr bool is_same = false;
+inline const bool is_same = false;
template<typename T>
-constexpr bool is_same<T, T> = true;
+inline const bool is_same<T, T> = true;
template<typename T>
struct DummyTemplate { };
@@ -23,7 +27,7 @@ void func() {
L1.operator()<6>(); // expected-note {{in instantiation}}
auto L2 = []<template<typename> class T, class U>(T<U> &&arg) {
- static_assert(is_same<T<U>, DummyTemplate<float>>); // // expected-error {{static assertion failed}}
+ static_assert(is_same<T<U>, DummyTemplate<float> >); // // expected-error {{static assertion failed}}
};
L2(DummyTemplate<float>());
L2(DummyTemplate<double>()); // expected-note {{in instantiation}}
@@ -36,15 +40,20 @@ struct ShadowMe {
}
};
+#if __cplusplus >= 201102L
template<typename T>
constexpr T outer() {
- return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \
- expected-note {{candidate template ignored}}
+ // FIXME: The C++11 error seems wrong
+ return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \
+ expected-note {{candidate template ignored}} \
+ cxx11-error {{cannot initialize return object of type 'int' with an rvalue of type '<dependent type>'}} \
+ cxx14-note {{non-literal type}}
}
-static_assert(outer<int>() == 123);
+static_assert(outer<int>() == 123); // cxx11-cxx14-error {{not an integral constant expression}} cxx11-note {{in instantiation}} cxx14-note {{in call}}
template int *outer<int *>(); // expected-note {{in instantiation}}
+#endif
-
+#if __cplusplus >= 202002L
namespace GH62611 {
template <auto A = [](auto x){}>
struct C {
@@ -87,3 +96,4 @@ void foo() {
}
}
+#endif
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 1921d02b1a9cf..26efeba9def0f 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,expected-cxx14,cxx11 -fblocks %s
-// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -verify=expected-cxx14 -fblocks %s
-// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify -ast-dump -fblocks %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,cxx03-cxx11,cxx11,expected-cxx14 -fblocks %s
+// RUN: %clang_cc1 -std=c++03 -Wno-unused-value -fsyntax-only -verify=expected,cxx03-fixme,cxx03,cxx03-cxx11,expected-cxx14 -fblocks %s -Ddecltype=__decltype -Dstatic_assert=_Static_assert -Wno-c++11-extensions
+// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,expected-cxx14 -fblocks %s
+// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify=expected,not-cxx03 -ast-dump -fblocks %s | FileCheck %s
namespace std { class type_info; };
@@ -93,14 +94,14 @@ namespace ImplicitCapture {
[] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'ref_i' by}} expected-note 2 {{default capture by}}
static int j;
- int &ref_j = j;
- [] { return ref_j; }; // ok
+ int &ref_j = j; // cxx03-fixme-note {{declared here}}
+ [] { return ref_j; }; // cxx03-fixme-error {{variable 'ref_j' cannot be implicitly captured in a lambda with no capture-default specified}} cxx03-fixme-note 4 {{capture}} cxx03-fixme-note {{lambda expression begins here}}
}
}
namespace SpecialMembers {
void f() {
- auto a = []{}; // expected-note 2{{here}} expected-note 2{{candidate}}
+ auto a = []{}; // expected-note 2{{here}} expected-note {{candidate}} not-cxx03-note {{candidate}}
decltype(a) b; // expected-error {{no matching constructor}}
decltype(a) c = a;
decltype(a) d = static_cast<decltype(a)&&>(a);
@@ -213,7 +214,7 @@ namespace VariadicPackExpansion {
};
template<typename...Ts> void local_class() {
- sink {
+ sink s(
[] (Ts t) {
struct S : Ts {
void f(Ts t) {
@@ -226,7 +227,7 @@ namespace VariadicPackExpansion {
s.f(t);
return s;
} (Ts()).g() ...
- };
+ );
};
struct X {}; struct Y {};
template void local_class<X, Y>();
@@ -296,7 +297,7 @@ namespace PR16708 {
namespace TypeDeduction {
struct S {};
void f() {
- const S s {};
+ const S s = S();
S &&t = [&] { return s; } ();
#if __cplusplus > 201103L
S &&u = [&] () -> auto { return s; } ();
@@ -308,7 +309,7 @@ namespace TypeDeduction {
namespace lambdas_in_NSDMIs {
template<class T>
struct L {
- T t{};
+ T t = T();
T t2 = ([](int a) { return [](int b) { return b; };})(t)(t);
};
L<int> l;
@@ -345,6 +346,7 @@ namespace CaptureIncomplete {
}
}
+#if __cplusplus >= 201103L
namespace CaptureAbstract {
struct S {
virtual void f() = 0; // expected-note {{unimplemented}}
@@ -362,6 +364,7 @@ namespace CaptureAbstract {
[=] { return s.n; }; // expected-error {{abstract}}
}
}
+#endif
namespace PR18128 {
auto l = [=]{}; // expected-error {{non-local lambda expression cannot have a capture-default}}
@@ -372,6 +375,8 @@ namespace PR18128 {
// expected-error at -1 {{non-local lambda expression cannot have a capture-default}}
// expected-error at -2 {{invalid use of non-static data member 'n'}}
// expected-cxx14-error at -3 {{a lambda expression may not appear inside of a constant expression}}
+ // cxx03-error at -4 {{function declaration cannot have variably modified type}}
+ // cxx03-warning at -5 {{variable length arrays in C++ are a Clang extension}}
int g(int k = ([=]{ return n; }(), 0));
// expected-error at -1 {{non-local lambda expression cannot have a capture-default}}
// expected-error at -2 {{invalid use of non-static data member 'n'}}
@@ -434,13 +439,13 @@ struct A {
template <typename F>
void g(F f) {
- auto a = A<decltype(f())>{};
+ auto a = A<decltype(f())>();
// expected-note at -1 {{in instantiation of template class 'PR20731::A<void>' requested here}}
auto xf = [a, f]() {};
int x = sizeof(xf);
};
void f() {
- g([] {});
+ g([] {}); // cxx03-warning {{template argument uses local type}}
// expected-note-re at -1 {{in instantiation of function template specialization 'PR20731::g<(lambda at {{.*}}>' requested here}}
}
@@ -491,8 +496,8 @@ namespace PR21857 {
fun() = default;
using Fn::operator();
};
- template<typename Fn> fun<Fn> wrap(Fn fn);
- auto x = wrap([](){});
+ template<typename Fn> fun<Fn> wrap(Fn fn); // cxx03-warning {{template argument uses unnamed type}}
+ auto x = wrap([](){}); // cxx03-fixme-warning {{template argument uses unnamed type}} cxx03-fixme-note 2 {{unnamed type used in template argument was declared here}}
}
namespace PR13987 {
@@ -559,8 +564,8 @@ struct B {
int x;
A a = [&] { int y = x; };
A b = [&] { [&] { [&] { int y = x; }; }; };
- A d = [&](auto param) { int y = x; }; // cxx11-error {{'auto' not allowed in lambda parameter}}
- A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx11-error 2 {{'auto' not allowed in lambda parameter}}
+ A d = [&](auto param) { int y = x; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}}
+ A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx03-cxx11-error 2 {{'auto' not allowed in lambda parameter}}
};
B<int> b;
@@ -588,9 +593,9 @@ struct S1 {
};
void foo1() {
- auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}}
- auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}}
- // cxx11-warning at -1 {{initialized lambda captures are a C++14 extension}}
+ auto s0 = S1([name=]() {}); // expected-error {{expected expression}}
+ auto s1 = S1([name=name]() {}); // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}}
+ // cxx03-cxx11-warning at -1 {{initialized lambda captures are a C++14 extension}}
}
}
@@ -606,7 +611,7 @@ namespace PR25627_dont_odr_use_local_consts {
namespace ConversionOperatorDoesNotHaveDeducedReturnType {
auto x = [](int){};
- auto y = [](auto &v) -> void { v.n = 0; }; // cxx11-error {{'auto' not allowed in lambda parameter}} cxx11-note {{candidate function not viable}} cxx11-note {{conversion candidate}}
+ auto y = [](auto &v) -> void { v.n = 0; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}} cxx03-cxx11-note {{candidate function not viable}} cxx03-cxx11-note {{conversion candidate}}
using T = decltype(x);
using U = decltype(y);
using ExpectedTypeT = void (*)(int);
@@ -626,14 +631,15 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
template<typename T>
friend constexpr U::operator ExpectedTypeU<T>() const noexcept;
#else
- friend auto T::operator()(int) const; // cxx11-error {{'auto' return without trailing return type; deduced return types are a C++14 extension}}
+ friend auto T::operator()(int) const; // cxx11-error {{'auto' return without trailing return type; deduced return types are a C++14 extension}} \
+ cxx03-error {{'auto' not allowed in function return type}}
friend T::operator ExpectedTypeT() const;
template<typename T>
- friend void U::operator()(T&) const; // cxx11-error {{friend declaration of 'operator()' does not match any declaration}}
+ friend void U::operator()(T&) const; // cxx03-cxx11-error {{friend declaration of 'operator()' does not match any declaration}}
// FIXME: This should not match, as above.
template<typename T>
- friend U::operator ExpectedTypeU<T>() const; // cxx11-error {{friend declaration of 'operator void (*)(type-parameter-0-0 &)' does not match any declaration}}
+ friend U::operator ExpectedTypeU<T>() const; // cxx03-cxx11-error {{friend declaration of 'operator void (*)(type-parameter-0-0 &)' does not match any declaration}}
#endif
private:
@@ -641,7 +647,7 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
};
// Should be OK: lambda's call operator is a friend.
- void use(X &x) { y(x); } // cxx11-error {{no matching function for call to object}}
+ void use(X &x) { y(x); } // cxx03-cxx11-error {{no matching function for call to object}}
// This used to crash in return type deduction for the conversion opreator.
struct A { int n; void f() { +[](decltype(n)) {}; } };
@@ -682,20 +688,20 @@ namespace GH60518 {
// function parameters that are used in enable_if
struct StringLiteral {
template <int N>
-StringLiteral(const char (&array)[N])
- __attribute__((enable_if(__builtin_strlen(array) == 2,
+StringLiteral(const char (&array)[N]) // cxx03-note {{declared here}}
+ __attribute__((enable_if(__builtin_strlen(array) == 2, // cxx03-error {{'enable_if' attribute expression never produces a constant expression}} cxx03-note {{read of variable}}
"invalid string literal")));
};
namespace cpp_attribute {
struct StringLiteral {
template <int N>
-StringLiteral(const char (&array)[N]) [[clang::annotate_type("test", array)]];
+StringLiteral(const char (&array)[N]) [[clang::annotate_type("test", array)]]; // cxx03-fixme-error {{'annotate_type' attribute takes at least 1 argument}}
};
}
void Func1() {
- [[maybe_unused]] auto y = [&](decltype(StringLiteral("xx"))) {};
+ [[maybe_unused]] auto y = [&](decltype(StringLiteral("xx"))) {}; // cxx03-note {{in instantiation of function template specialization}}
[[maybe_unused]] auto z = [&](decltype(cpp_attribute::StringLiteral("xx"))) {};
}
@@ -718,6 +724,7 @@ static_assert([]() constexpr {
// Call operator attributes refering to a variable should
// be properly handled after D124351
+#if __cplusplus >= 201103L
constexpr int i = 2;
void foo() {
(void)[=][[gnu::aligned(i)]] () {}; // expected-warning{{C++23 extension}}
@@ -725,12 +732,15 @@ void foo() {
// CHECK-NEXT: ConstantExpr
// CHECK-NEXT: value: Int 2
}
+#endif
void GH48527() {
auto a = []()__attribute__((b(({ return 0; })))){}; // expected-warning {{unknown attribute 'b' ignored}}
}
+#if __cplusplus >= 201103L
void GH67492() {
constexpr auto test = 42;
auto lambda = (test, []() noexcept(true) {});
}
+#endif
diff --git a/clang/test/SemaCXX/lambda-implicit-this-capture.cpp b/clang/test/SemaCXX/lambda-implicit-this-capture.cpp
index 7e0e347a8fee7..eb1f9e880aec0 100644
--- a/clang/test/SemaCXX/lambda-implicit-this-capture.cpp
+++ b/clang/test/SemaCXX/lambda-implicit-this-capture.cpp
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -std=c++03 -verify=cxx11 %s -Wno-c++11-extensions
// RUN: %clang_cc1 -std=c++11 -verify=cxx11 %s
// RUN: %clang_cc1 -std=c++2a -verify=cxx2a %s
// RUN: %clang_cc1 -std=c++2a -verify=cxx2a-no-deprecated %s -Wno-deprecated
diff --git a/clang/test/SemaCXX/lambda-invalid-capture.cpp b/clang/test/SemaCXX/lambda-invalid-capture.cpp
index 236753871d701..5be8c8c5078f2 100644
--- a/clang/test/SemaCXX/lambda-invalid-capture.cpp
+++ b/clang/test/SemaCXX/lambda-invalid-capture.cpp
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++03 -Wno-c++11-extensions %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// Don't crash.
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 0270e42b7389f..96122cfe87b4f 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -165,12 +165,7 @@ void good_deletes()
void bad_deletes()
{
delete 0; // expected-error {{cannot delete expression of type 'int'}}
- delete [0] (int*)0;
-#if __cplusplus <= 199711L
- // expected-error at -2 {{expected expression}}
-#else
- // expected-error at -4 {{expected variable name or 'this' in lambda capture list}}
-#endif
+ delete [0] (int*)0; // expected-error {{expected variable name or 'this' in lambda capture list}}
delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}}
delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
::S::delete (int*)0; // expected-error {{expected unqualified-id}}
More information about the cfe-commits
mailing list