lichray updated this revision to Diff 385564.
lichray added a comment.
Clang-format
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D113393/new/
https://reviews.llvm.org/D113393
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaType.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.type.auto.deduct/p2.cpp
clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
clang/www/cxx_status.html
Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1379,6 +1379,11 @@
<td><a href="https://wg21.link/P2360R0">P2360R0</a></td>
<td class="unreleased" align="center">Clang 14</td>
</tr>
+ <tr>
+ <td>auto(x): decay-copy in the language</td>
+ <td><a href="https://wg21.link/P0849R8">P0849R8</a></td>
+ <td class="unreleased" align="center">Clang 14</td>
+ </tr>
</table>
</details>
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,26 @@
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+template <class T>
+void foo(T);
+
+struct A {
+ int m;
+ char g(int);
+ float g(double);
+} a{1};
+
+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 {{initializer for functional-style cast to 'auto' is empty}}
+
+ foo(auto(a));
+ foo(auto {a});
+ foo(auto(a));
+
+ foo(auto(&A::g)); // expected-error {{functional-style cast to 'auto' has incompatible initializer of type '<overloaded function 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 {{initializer for functional-style cast to 'auto' contains multiple expressions}}
+}
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,56 @@
+// RUN: %clang_cc1 -std=c++2b -verify %s
+// expected-no-diagnostics
+
+void test_decay() {
+ int v[3];
+ static_assert(__is_same(decltype(auto(v)), int *));
+ static_assert(__is_same(decltype(auto("lit")), char const *));
+
+ int fn(char *);
+ static_assert(__is_same(decltype(auto(fn)), int (*)(char *)));
+
+ constexpr long i = 1;
+ static_assert(__is_same(decltype(auto(1L)), long));
+ static_assert(__is_same(decltype(i), long const));
+ static_assert(__is_same(decltype(auto(i)), long));
+
+ class A {
+ } a;
+
+ A &lr = a;
+ A const &lrc = a;
+ A &&rr = static_cast<A &&>(a);
+ A const &&rrc = static_cast<A &&>(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));
+}
+
+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");
+}
+
+class A {
+ int x;
+ friend void f(A &&);
+
+public:
+ A();
+
+ auto test_access() {
+ f(A(*this)); // ok
+ f(auto(*this)); // ok in P0849
+ }
+
+protected:
+ A(const A &);
+};
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<auto*>(&n); // expected-error{{'auto' not allowed here}}
(void)const_cast<auto>(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 <auto a = 10> 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
@@ -3395,6 +3395,7 @@
// class template argument deduction)?
bool IsCXXAutoType =
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
+ bool IsAutoKeyword = (Auto && Auto->getKeyword() == AutoTypeKeyword::Auto);
bool IsDeducedReturnType = false;
switch (D.getContext()) {
@@ -3414,8 +3415,7 @@
InventedTemplateParameterInfo *Info = nullptr;
if (D.getContext() == DeclaratorContext::Prototype) {
// With concepts we allow 'auto' in function parameters.
- if (!SemaRef.getLangOpts().CPlusPlus20 || !Auto ||
- Auto->getKeyword() != AutoTypeKeyword::Auto) {
+ if (!SemaRef.getLangOpts().CPlusPlus20 || !IsAutoKeyword) {
Error = 0;
break;
} else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
@@ -3426,8 +3426,7 @@
Info = &SemaRef.InventedParameterInfos.back();
} else {
// In C++14, generic lambdas allow 'auto' in their parameters.
- if (!SemaRef.getLangOpts().CPlusPlus14 || !Auto ||
- Auto->getKeyword() != AutoTypeKeyword::Auto) {
+ if (!SemaRef.getLangOpts().CPlusPlus14 || !IsAutoKeyword) {
Error = 16;
break;
}
@@ -3505,6 +3504,8 @@
case DeclaratorContext::FunctionalCast:
if (isa<DeducedTemplateSpecializationType>(Deduced))
break;
+ if (SemaRef.getLangOpts().CPlusPlus2b && IsAutoKeyword)
+ break; // 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
@@ -1467,6 +1467,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<DeducedTemplateSpecializationType>(Deduced)) {
Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity,
@@ -1474,6 +1477,33 @@
if (Ty.isNull())
return ExprError();
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
+ } else if (Deduced) {
+ auto Inits = Exprs;
+ if (Exprs.size() == 1) {
+ if (auto p = dyn_cast_or_null<InitListExpr>(Exprs[0])) {
+ Inits = MultiExprArg(p->getInits(), p->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);
+ }
+ Expr *Deduce = Inits[0];
+ 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;
+ Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
}
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -2226,6 +2226,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
@@ -1523,6 +1523,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
@@ -1027,10 +1027,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
@@ -2320,8 +2320,12 @@
"type %0 to use list-initialization">, InGroup<CXX17>;
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">;
@@ -2340,6 +2344,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<
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -153,6 +153,8 @@
^^^^^^^^^^^^^^^^^^^^^
- Implemented `P1938R3: if consteval <https://wg21.link/P1938R3>`_.
- Implemented `P2360R0: Extend init-statement to allow alias-declaration <https://wg21.link/P2360R0>`_.
+- Implemented `P0849R8: auto(x): decay-copy in the language
+ <https://wg21.link/P0849R8>`_.
CUDA Language Changes in Clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits