Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1388,6 +1388,11 @@
P2360R0 |
Clang 14 |
+
+ auto(x): decay-copy in the language |
+ P0849R8 |
+ Clang 14 |
+
Attributes on Lambda-Expressions |
Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -442,6 +442,15 @@
B() : decltype(auto)() {} // expected-error {{'decltype(auto)' not allowed here}}
};
}
+
+ namespace Cast {
+ void foo() {
+ (void)decltype(auto)(0); // cxx14_20-error{{'decltype(auto)' not allowed here}} \
+ cxx2b-warning{{ISO C++23 DIS does not allow functional-style cast to 'decltype(auto)'}}
+ (void)decltype(auto){0}; // cxx14_20-error{{'decltype(auto)' not allowed here}} \
+ cxx2b-warning{{ISO C++23 DIS does not allow functional-style cast to 'decltype(auto)'}}
+ }
+ }
}
namespace CurrentInstantiation {
Index: clang/test/Parser/cxx2b-auto-x.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/cxx2b-auto-x.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
+
+void looks_like_decltype_auto() {
+ decltype(auto(42)) b = 42; // cxx20-error {{'auto' not allowed here}} \
+ cxx2b-warning {{'auto' as a functional-style cast is incompatible with C++ standards before C++2b}}
+ decltype(long *) a = 42; // expected-error {{expected '(' for function-style cast or type construction}} \
+ expected-error {{expected expression}}
+ decltype(auto *) a = 42; // expected-error {{expected '(' for function-style cast or type construction}} \
+ expected-error {{expected expression}}
+ decltype(auto()) c = 42; // cxx2b-error {{initializer for functional-style cast to 'auto' is empty}} \
+ cxx20-error {{'auto' not allowed here}}
+}
+
+struct looks_like_declaration {
+ int n;
+} a;
+
+using T = looks_like_declaration *;
+void f() { T(&a)->n = 1; }
+// FIXME: They should be deemed expressions without breaking function pointer
+// parameter declarations with trailing return types.
+// void g() { auto(&a)->n = 0; }
+// void h() { auto{&a}->n = 0; }
Index: clang/test/CXX/expr/expr.unary/expr.new/p2-cxx1z.cpp
===================================================================
--- clang/test/CXX/expr/expr.unary/expr.new/p2-cxx1z.cpp
+++ clang/test/CXX/expr/expr.unary/expr.new/p2-cxx1z.cpp
@@ -1,11 +1,30 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17 -pedantic
+// [expr.new]p2 ... the invented declaration: T x init ;
+// C++2b [dcl.type.auto.deduct]p2.2
+// For a variable declared with a type that contains a placeholder type, T is the declared type of the variable.
void f() {
+ // - If the initializer is a parenthesized expression-list, the expression-list shall be a single assignmentexpression and E is the assignment-expression.
new auto('a');
- new auto {2};
- new auto {1, 2}; // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
- new auto {}; // expected-error{{new expression for type 'auto' requires a constructor argument}}
- new decltype(auto)({1});
- new decltype(auto)({1, 2}); // expected-error{{new expression for type 'decltype(auto)' contains multiple constructor arguments}}
+ new decltype(auto)('a');
+ // - If the initializer is a braced-init-list, it shall consist of a single brace-enclosed assignment-expression and E is the assignment-expression.
+ new auto{2};
+ new decltype(auto){2};
+
+ new auto{}; // expected-error{{new expression for type 'auto' requires a constructor argument}}
+ new auto({}); // expected-error{{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ new auto{{}}; // expected-error{{cannot deduce actual type for 'auto' from nested initializer list}}
+
+ new auto({2}); // expected-error{{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ new auto{{2}}; // expected-error{{cannot deduce actual type for 'auto' from nested initializer list}}
+ new auto{1, 2}; // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
+
+ new decltype(auto){}; // expected-error{{new expression for type 'decltype(auto)' requires a constructor argument}}
+ new decltype(auto)({}); // expected-error{{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ new decltype(auto){{}}; // expected-error{{cannot deduce actual type for 'decltype(auto)' from nested initializer list}}
+
+ new decltype(auto)({1}); // expected-error{{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ new decltype(auto){1, 2}; // expected-error{{new expression for type 'decltype(auto)' contains multiple constructor arguments}}
+ new decltype(auto)({1, 2}); // expected-error{{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
}
Index: clang/test/CXX/expr/expr.unary/expr.new/p2-cxx14.cpp
===================================================================
--- clang/test/CXX/expr/expr.unary/expr.new/p2-cxx14.cpp
+++ clang/test/CXX/expr/expr.unary/expr.new/p2-cxx14.cpp
@@ -5,6 +5,6 @@
new auto {2}; // expected-warning {{ISO C++ standards before C++17 do not allow new expression for type 'auto' to use list-initialization}}
new auto {1, 2}; // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
new auto {}; // expected-error{{new expression for type 'auto' requires a constructor argument}}
- new decltype(auto)({1}); // expected-warning {{ISO C++ standards before C++17 do not allow new expression for type 'decltype(auto)' to use list-initialization}}
- new decltype(auto)({1, 2}); // expected-error{{new expression for type 'decltype(auto)' contains multiple constructor arguments}}
+ new decltype(auto)({1}); // expected-error{{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ new decltype(auto)({1, 2}); // expected-error{{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
}
Index: clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp
===================================================================
--- clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp
+++ clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp
@@ -16,7 +16,7 @@
new (auto) (1,2,3); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
new auto {}; // expected-error{{new expression for type 'auto' requires a constructor argument}}
new auto {1,2,3}; // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
- new auto ({1,2,3}); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
+ new auto ({1,2,3}); // expected-error{{cannot deduce actual type for 'auto' from parenthesized initializer list}}
}
void p2example() {
Index: clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++2b -Wno-decltype-auto-cast -verify %s
+
+template
+void foo(T);
+
+struct A {
+ int m;
+ char g(int);
+ float g(double);
+} a{1};
+
+// C++2b [dcl.type.auto.deduct]p2.3
+// For an explicit type conversion, T is the specified type, which shall be auto.
+void diagnostics() {
+ foo(auto()); // expected-error {{initializer for functional-style cast to 'auto' is empty}}
+ foo(auto{}); // expected-error {{initializer for functional-style cast to 'auto' is empty}}
+ foo(auto({})); // expected-error {{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ foo(auto{{}}); // expected-error {{cannot deduce actual type for 'auto' from nested initializer list}}
+
+ // - If the initializer is a parenthesized expression-list, the expression-list shall be a single assignmentexpression and E is the assignment-expression.
+ foo(auto(a));
+ // - If the initializer is a braced-init-list, it shall consist of a single brace-enclosed assignment-expression and E is the assignment-expression.
+ foo(auto{a});
+ foo(auto({a})); // expected-error {{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ foo(auto{{a}}); // expected-error {{cannot deduce actual type for 'auto' from nested initializer list}}
+
+ foo(auto(&A::g)); // expected-error {{functional-style cast to 'auto' has incompatible initializer of type ''}}
+
+ foo(auto(a, 3.14)); // expected-error {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+ foo(auto{a, 3.14}); // expected-error {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+ foo(auto({a, 3.14})); // expected-error {{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ foo(auto{{a, 3.14}}); // expected-error {{cannot deduce actual type for 'auto' from nested initializer list}}
+ foo(auto({a}, {3.14})); // expected-error {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+ foo(auto{{a}, {3.14}}); // expected-error {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+
+ foo(auto{1, 2}); // expected-error {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+ foo(auto({1, 2})); // expected-error {{cannot deduce actual type for 'auto' from parenthesized initializer list}}
+ foo(auto{{1, 2}}); // expected-error {{cannot deduce actual type for 'auto' from nested initializer list}}
+}
+
+void diagnostics_extension() {
+ foo(decltype(auto)()); // expected-error {{initializer for functional-style cast to 'decltype(auto)' is empty}}
+ foo(decltype(auto){}); // expected-error {{initializer for functional-style cast to 'decltype(auto)' is empty}}
+ foo(decltype(auto)({})); // expected-error {{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ foo(decltype(auto){{}}); // expected-error {{cannot deduce actual type for 'decltype(auto)' from nested initializer list}}
+
+ foo(decltype(auto)({a})); // expected-error {{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ foo(decltype(auto){{a}}); // expected-error {{cannot deduce actual type for 'decltype(auto)' from nested initializer list}}
+
+ foo(decltype(auto)(&A::g)); // expected-error {{reference to overloaded function could not be resolved}}
+
+ foo(decltype(auto)(a, 3.14)); // expected-error {{initializer for functional-style cast to 'decltype(auto)' contains multiple expressions}}
+ foo(decltype(auto){a, 3.14}); // expected-error {{initializer for functional-style cast to 'decltype(auto)' contains multiple expressions}}
+ foo(decltype(auto)({a, 3.14})); // expected-error {{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ foo(decltype(auto){{a, 3.14}}); // expected-error {{cannot deduce actual type for 'decltype(auto)' from nested initializer list}}
+ foo(decltype(auto)({a}, {3.14})); // expected-error {{initializer for functional-style cast to 'decltype(auto)' contains multiple expressions}}
+ foo(decltype(auto){{a}, {3.14}}); // expected-error {{initializer for functional-style cast to 'decltype(auto)' contains multiple expressions}}
+
+ foo(decltype(auto){1, 2}); // expected-error {{initializer for functional-style cast to 'decltype(auto)' contains multiple expressions}}
+ foo(decltype(auto)({1, 2})); // expected-error {{cannot deduce actual type for 'decltype(auto)' from parenthesized initializer list}}
+ foo(decltype(auto){{1, 2}}); // expected-error {{cannot deduce actual type for 'decltype(auto)' from nested initializer list}}
+}
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
@@ -0,0 +1,185 @@
+// RUN: %clang_cc1 -std=c++2b -Wno-decltype-auto-cast -verify %s
+
+// p2.3 allows only T = auto in T(x).
+// As a Clang extension, we also allow T = decltype(auto) to match p2.2 (new T(x)).
+
+void test_decay() {
+ int v[3];
+ static_assert(__is_same(decltype(auto(v)), int *));
+ static_assert(__is_same(decltype(auto{v}), int *));
+ static_assert(__is_same(decltype(auto("lit")), char const *));
+ static_assert(__is_same(decltype(auto{"lit"}), char const *));
+
+ void(decltype(auto)(v)); // expected-error {{functional-style cast}}
+ void(decltype(auto){v}); // expected-error {{cannot initialize an array element}}
+ static_assert(__is_same(decltype(decltype(auto)("lit")), char const(&)[4]));
+ static_assert(__is_same(decltype(decltype(auto){"lit"}), char const(&)[4]));
+
+ int fn(char *);
+ static_assert(__is_same(decltype(auto(fn)), int (*)(char *)));
+ static_assert(__is_same(decltype(auto{fn}), int (*)(char *)));
+
+ void(decltype(auto)(fn)); // expected-error{{functional-style cast}}
+ void(decltype(auto){fn}); // expected-error{{cannot create object of function type}}
+
+ constexpr long i = 1;
+ static_assert(__is_same(decltype(i), long const));
+ static_assert(__is_same(decltype(auto(1L)), long));
+ static_assert(__is_same(decltype(auto{1L}), long));
+ static_assert(__is_same(decltype(auto(i)), long));
+ static_assert(__is_same(decltype(auto{i}), long));
+
+ // scalar prvalue is not cv-qualified
+ static_assert(__is_same(decltype(decltype(auto)(1L)), long));
+ static_assert(__is_same(decltype(decltype(auto){1L}), long));
+ static_assert(__is_same(decltype(decltype(auto)(i)), long));
+ static_assert(__is_same(decltype(decltype(auto){i}), long));
+
+ class A {
+ } a;
+ A const ac;
+
+ static_assert(__is_same(decltype(auto(a)), A));
+ static_assert(__is_same(decltype(auto(ac)), A));
+
+ static_assert(__is_same(decltype(decltype(auto)(a)), A));
+ static_assert(__is_same(decltype(decltype(auto)(ac)), A const));
+
+ static_assert(__is_same(decltype(decltype(auto)((a))), A &));
+ static_assert(__is_same(decltype(decltype(auto)((ac))), A const &));
+
+ static_assert(__is_same(decltype(decltype(auto){a}), A));
+ static_assert(__is_same(decltype(decltype(auto){ac}), A const));
+
+ static_assert(__is_same(decltype(decltype(auto){(a)}), A &));
+ static_assert(__is_same(decltype(decltype(auto){(ac)}), A const &));
+
+ A &lr = a;
+ A const &lrc = a;
+ A &&rr = static_cast(a);
+ A const &&rrc = static_cast(a);
+
+ static_assert(__is_same(decltype(auto(lr)), A));
+ static_assert(__is_same(decltype(auto(lrc)), A));
+ static_assert(__is_same(decltype(auto(rr)), A));
+ static_assert(__is_same(decltype(auto(rrc)), A));
+
+ static_assert(__is_same(decltype(decltype(auto)(lr)), A &));
+ static_assert(__is_same(decltype(decltype(auto)(lrc)), A const &));
+ static_assert(__is_same(decltype(decltype(auto)(rr)), A &&));
+ static_assert(__is_same(decltype(decltype(auto)(rrc)), A const &&));
+}
+
+class cmdline_parser {
+public:
+ cmdline_parser(char const *);
+ auto add_option(char const *, char const *) && -> cmdline_parser &&;
+};
+
+void test_rvalue_fluent_interface() {
+ auto cmdline = cmdline_parser("driver");
+ auto internal = auto{cmdline}.add_option("--dump-full", "do not minimize dump");
+}
+
+template constexpr auto decay_copy(T &&v) { return static_cast(v); } // expected-error {{calling a protected constructor}}
+
+class A {
+ int x;
+ friend void f(A &&);
+
+public:
+ A();
+
+ auto test_access() {
+ static_assert(__is_same(decltype(auto(*this)), A));
+ static_assert(__is_same(decltype(auto(this)), A *));
+
+ f(A(*this)); // ok
+ f(auto(*this)); // ok in P0849
+ f(decay_copy(*this)); // expected-note {{in instantiation of function template specialization}}
+ }
+
+ auto test_access() const {
+ static_assert(__is_same(decltype(auto(*this)), A)); // ditto
+ static_assert(__is_same(decltype(auto(this)), A const *));
+ }
+
+protected:
+ A(const A &); // expected-note {{declared protected here}}
+};
+
+// post-C++17 semantics
+namespace auto_x {
+constexpr struct Uncopyable {
+ constexpr explicit Uncopyable(int) {}
+ constexpr Uncopyable(Uncopyable &&) = delete;
+} u = auto(Uncopyable(auto(Uncopyable(42))));
+} // namespace auto_x
+
+// decltype(auto) is no-op to prvalues
+namespace decltype_auto_x {
+constexpr struct Uncopyable {
+ constexpr explicit Uncopyable(int) {}
+ constexpr Uncopyable(Uncopyable &&) = delete;
+} u = decltype(auto)(Uncopyable(decltype(auto)(Uncopyable(42))));
+} // namespace decltype_auto_x
+
+// Forward with decltype(auto)
+constexpr auto invoke1 = [](auto &&x, auto &&y) {
+ return decltype(auto)(x)(decltype(auto)(y));
+};
+
+struct MoveOnly {
+ MoveOnly() = default;
+ MoveOnly(MoveOnly &&) = default;
+ MoveOnly(MoveOnly const &) = delete;
+};
+
+constexpr MoveOnly getMoveOnly() { return {}; }
+
+struct Fn {
+ constexpr int operator()(MoveOnly &) & { return 0; }
+ constexpr int operator()(MoveOnly &&) & { return 1; }
+
+ constexpr int operator()(MoveOnly &) && { return 2; }
+ constexpr int operator()(MoveOnly &&) && { return 3; }
+
+ constexpr int operator()(MoveOnly &) const & { return 4; }
+ constexpr int operator()(MoveOnly &&) const & { return 5; }
+
+ constexpr int operator()(MoveOnly &) const && { return 6; }
+ constexpr int operator()(MoveOnly &&) const && { return 7; }
+};
+
+constexpr void FwdWithDecltypeAuto() {
+ MoveOnly lv;
+ Fn f;
+ constexpr Fn cf;
+
+ static_assert(invoke1(f, lv) == 0);
+ static_assert(invoke1(f, getMoveOnly()) == 1);
+
+ static_assert(invoke1(Fn{}, lv) == 2);
+ static_assert(invoke1(Fn{}, getMoveOnly()) == 3);
+
+ static_assert(invoke1(cf, lv) == 4);
+ static_assert(invoke1(cf, getMoveOnly()) == 5);
+
+ static_assert(invoke1((Fn const){}, lv) == 6);
+ static_assert(invoke1((Fn const){}, getMoveOnly()) == 7);
+}
+
+struct FnArray {
+ template
+ constexpr int operator()(T (&)[N]) const { return 0; }
+
+ template
+ constexpr int operator()(T (&&)[N]) const { return 1; }
+};
+
+constexpr void FwdArrayWithDecltypeAuto() {
+ FnArray f;
+
+ static_assert(invoke1(f, "foo") == 0);
+ static_assert(invoke1(f, (int[]){1, 2, 3}) == 1);
+}
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
===================================================================
--- clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -51,8 +51,8 @@
(void)reinterpret_cast(&n); // expected-error{{'auto' not allowed here}}
(void)const_cast(n); // expected-error{{'auto' not allowed here}}
(void)*(auto*)(&n); // expected-error{{'auto' not allowed here}}
- (void)auto(n); // expected-error{{expected expression}}
- (void)auto{n}; // expected-error{{expected expression}}
+ (void)auto(n); // expected-error{{'auto' not allowed here}}
+ (void)auto{n}; // expected-error{{'auto' not allowed here}}
}
template class C { }; // expected-error{{'auto' not allowed in template parameter}}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -3506,6 +3506,8 @@
case DeclaratorContext::FunctionalCast:
if (isa(Deduced))
break;
+ if (SemaRef.getLangOpts().CPlusPlus2b && IsCXXAutoType)
+ break; // auto(x) and decltype(auto)(x)
LLVM_FALLTHROUGH;
case DeclaratorContext::TypeName:
Error = 15; // Generic
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1468,6 +1468,9 @@
// C++1z [expr.type.conv]p1:
// If the type is a placeholder for a deduced class type, [...perform class
// template argument deduction...]
+ // C++2b:
+ // Otherwise, if the type contains a placeholder type, it is replaced by the
+ // type determined by placeholder type deduction.
DeducedType *Deduced = Ty->getContainedDeducedType();
if (Deduced && isa(Deduced)) {
Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity,
@@ -1475,6 +1478,50 @@
if (Ty.isNull())
return ExprError();
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
+ } else if (Deduced) {
+ MultiExprArg Inits = Exprs;
+ if (ListInitialization) {
+ auto *ILE = cast(Exprs[0]);
+ Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
+ }
+
+ if (Inits.empty())
+ return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression)
+ << Ty << FullRange);
+ if (Inits.size() > 1) {
+ Expr *FirstBad = Inits[1];
+ return ExprError(Diag(FirstBad->getBeginLoc(),
+ diag::err_auto_expr_init_multiple_expressions)
+ << Ty << FullRange);
+ }
+ if (getLangOpts().CPlusPlus2b) {
+ if (auto *TyAuto = Ty->getAs())
+ Diag(TyBeginLoc, TyAuto->isDecltypeAuto()
+ ? diag::ext_decltype_auto_expr
+ : diag::warn_cxx20_compat_auto_expr)
+ << FullRange;
+ }
+ Expr *Deduce = Inits[0];
+ if (isa(Deduce))
+ return ExprError(
+ Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
+ << ListInitialization << Ty << FullRange);
+ QualType DeducedType;
+ if (DeduceAutoType(TInfo, Deduce, DeducedType) == DAR_Failed)
+ return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure)
+ << Ty << Deduce->getType() << FullRange
+ << Deduce->getSourceRange());
+ if (DeducedType.isNull())
+ return ExprError();
+
+ Ty = DeducedType;
+ if (Ty->isReferenceType()) {
+ // decltype(auto)(x) takes a shortcut; see also P0849R2.
+ return BuildCXXFunctionalCastExpr(SubstAutoTypeSourceInfo(TInfo, Ty), Ty,
+ LParenOrBraceLoc, Deduce,
+ RParenOrBraceLoc);
+ }
+ Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
}
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
@@ -1983,12 +2030,10 @@
return ExprError();
} else if (Deduced) {
bool Braced = (initStyle == CXXNewExpr::ListInit);
- if (NumInits == 1) {
- if (auto p = dyn_cast_or_null(Inits[0])) {
- Inits = p->getInits();
- NumInits = p->getNumInits();
- Braced = true;
- }
+ if (Braced) {
+ auto *ILE = cast(Inits[0]);
+ Inits = ILE->getInits();
+ NumInits = ILE->getNumInits();
}
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
@@ -2004,6 +2049,10 @@
Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init)
<< AllocType << TypeRange;
Expr *Deduce = Inits[0];
+ if (isa(Deduce))
+ return ExprError(
+ Diag(Deduce->getBeginLoc(), diag::err_auto_expr_init_paren_braces)
+ << Braced << AllocType << TypeRange);
QualType DeducedType;
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed)
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -2231,6 +2231,9 @@
case tok::kw_void:
DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw_auto:
+ DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw_char:
DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy);
break;
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1524,6 +1524,7 @@
case tok::kw___float128:
case tok::kw___ibm128:
case tok::kw_void:
+ case tok::kw_auto:
case tok::kw_typename:
case tok::kw_typeof:
case tok::kw___vector:
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1030,10 +1030,9 @@
}
// Check for C++1y 'decltype(auto)'.
- if (Tok.is(tok::kw_auto)) {
- // No need to disambiguate here: an expression can't start with 'auto',
- // because the typename-specifier in a function-style cast operation can't
- // be 'auto'.
+ if (Tok.is(tok::kw_auto) && NextToken().is(tok::r_paren)) {
+ // the typename-specifier in a function-style cast expression may
+ // be 'auto' since C++2b
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_decltype_auto_type_specifier
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2325,13 +2325,23 @@
"type %0 to use list-initialization">, InGroup;
def err_auto_var_init_no_expression : Error<
"initializer for variable %0 with type %1 is empty">;
+def err_auto_expr_init_no_expression : Error<
+ "initializer for functional-style cast to %0 is empty">;
def err_auto_var_init_multiple_expressions : Error<
"initializer for variable %0 with type %1 contains multiple expressions">;
+def err_auto_expr_init_multiple_expressions : Error<
+ "initializer for functional-style cast to %0 contains multiple expressions">;
def err_auto_var_init_paren_braces : Error<
"cannot deduce type for variable %1 with type %2 from "
"%select{parenthesized|nested}0 initializer list">;
def err_auto_new_ctor_multiple_expressions : Error<
"new expression for type %0 contains multiple constructor arguments">;
+def err_auto_expr_init_paren_braces : Error<
+ "cannot deduce actual type for %1 from "
+ "%select{parenthesized|nested}0 initializer list">;
+def warn_cxx20_compat_auto_expr : Warning<
+ "'auto' as a functional-style cast is incompatible with C++ standards "
+ "before C++2b">, InGroup, DefaultIgnore;
def err_auto_missing_trailing_return : Error<
"'auto' return without trailing return type; deduced return types are a "
"C++14 extension">;
@@ -2345,6 +2355,8 @@
"variable %0 with type %1 has incompatible initializer of type %2">;
def err_auto_var_deduction_failure_from_init_list : Error<
"cannot deduce actual type for variable %0 with type %1 from initializer list">;
+def err_auto_expr_deduction_failure : Error<
+ "functional-style cast to %0 has incompatible initializer of type %1">;
def err_auto_new_deduction_failure : Error<
"new expression for type %0 has incompatible constructor argument of type %1">;
def err_auto_inconsistent_deduction : Error<
@@ -2380,6 +2392,9 @@
"cannot form %select{pointer to|reference to|array of}0 'decltype(auto)'">;
def err_decltype_auto_initializer_list : Error<
"cannot deduce 'decltype(auto)' from initializer list">;
+def ext_decltype_auto_expr : ExtWarn<
+ "ISO C++23 DIS does not allow functional-style cast to 'decltype(auto)'">,
+ InGroup>;
// C++17 deduced class template specialization types
def err_deduced_class_template_compound_type : Error<
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -95,6 +95,7 @@
^^^^^^^^^^^^^^^^^^^^^
- Implemented `P2128R6: Multidimensional subscript operator `_.
+- Implemented `P0849R8: auto(x): decay-copy in the language `_.
CUDA Language Changes in Clang
------------------------------