lichray updated this revision to Diff 385454.
lichray added a comment.

C++2y -> C++2b


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,8 @@
     // 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 +3416,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 +3427,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 +3505,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

Reply via email to