llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Mital Ashok (MitalAshok) <details> <summary>Changes</summary> As per [CWG2351](https://wg21.link/CWG2351), allow `void{}`, treated the same as `void()`: a prvalue expression of type `void` that performs no initialization. Note that the AST for the expression `T{}` looks like: ``` // using T = int; CXXFunctionalCastExpr 'T':'int' functional cast to T <NoOp> `-InitListExpr 'T':'int' // using T = const int; CXXFunctionalCastExpr 'int' functional cast to T <NoOp> `-InitListExpr 'int' // using T = void; CXXFunctionalCastExpr 'void' functional cast to T <NoOp> `-InitListExpr 'void' // using T = const void; CXXFunctionalCastExpr 'void' functional cast to T <NoOp> `-InitListExpr 'void' ``` (Since the `InitListExpr` already has `void` before anything is done, the type doesn't need to be adjusted) As for `void()`/`T() [T = const void]`, that looked like `CXXScalarValueInitExpr 'void'` and is unchanged after this. For reference, C++98 [5.2.3p2] says: > The expression `T()`, where `T` is a simple-type-specifier (7.1.5.2) for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by default-initialization (8.5; no initialization is done for the `void()` case). [*Note:* if `T` is a non-class type that is *cv-qualified*, the `cv-qualifiers` are ignored when determining the type of the resulting rvalue (3.10). ] Though it is a bit of a misnomer that, for `T = void`, `CXXScalarValueInitExpr` does not perform value initialization, it would be a breaking change to change the AST node for `void()`, so I simply reworded the doc comment. --- Full diff: https://github.com/llvm/llvm-project/pull/78060.diff 5 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/include/clang/AST/ExprCXX.h (+3-2) - (modified) clang/lib/Sema/SemaExprCXX.cpp (+15-6) - (modified) clang/test/CXX/drs/dr23xx.cpp (+31) - (modified) clang/www/cxx_dr_status.html (+1-1) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3cbce1be159437..00e200ea76e5bc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -226,6 +226,8 @@ C++2c Feature Support Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Implemented `CWG2351 <https://wg21.link/CWG2351>`_ which allows ``void{}`` + as a prvalue of type ``void``. C Language Changes ------------------ diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 24278016431837..e7b732e4181127 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2160,8 +2160,9 @@ class LambdaExpr final : public Expr, const_child_range children() const; }; -/// An expression "T()" which creates a value-initialized rvalue of type -/// T, which is a non-class type. See (C++98 [5.2.3p2]). +/// An expression "T()" which creates an rvalue of type T, which is a +/// non-class type. For non-void T, the rvalue is value-initialized. +/// See (C++98 [5.2.3p2]). class CXXScalarValueInitExpr : public Expr { friend class ASTStmtReader; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 4ae04358d5df7c..1792ec6bb292d5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1600,12 +1600,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type) << Ty << FullRange); - // C++17 [expr.type.conv]p2: - // If the type is cv void and the initializer is (), the expression is a - // prvalue of the specified type that performs no initialization. - if (!Ty->isVoidType() && - RequireCompleteType(TyBeginLoc, ElemTy, - diag::err_invalid_incomplete_type_use, FullRange)) + // C++17 [expr.type.conv]p2, per DR2351: + // If the type is cv void and the initializer is () or {}, the expression is + // a prvalue of the specified type that performs no initialization. + if (Ty->isVoidType()) { + if (Exprs.empty()) + return new (Context) CXXScalarValueInitExpr(Context.VoidTy, TInfo, + Kind.getRange().getEnd()); + if (ListInitialization && cast<InitListExpr>(Exprs[0])->getNumInits() == 0) + return CXXFunctionalCastExpr::Create( + Context, Context.VoidTy, VK_PRValue, TInfo, CK_NoOp, Exprs[0], + /*Path=*/nullptr, CurFPFeatureOverrides(), Exprs[0]->getBeginLoc(), + Exprs[0]->getEndLoc()); + } else if (RequireCompleteType(TyBeginLoc, ElemTy, + diag::err_invalid_incomplete_type_use, + FullRange)) return ExprError(); // Otherwise, the expression is a prvalue of the specified type whose diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index d2f4e7652ab568..1bf30a80f743e5 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -69,6 +69,37 @@ namespace dr2346 { // dr2346: 11 } } +namespace dr2351 { // dr2351: 18 +#if __cplusplus >= 201103L + static_assert((void{}, true), ""); + // since-cxx11-warning@-1 {{left operand of comma operator has no effect}} + + void f() { + return void{}; + } + + template<typename T> + void g() { + return T{}; + } + template void g<void>(); + + void h() { + return {}; + // since-cxx11-error@-1 {{void function 'h' must not return a value}} + } + + template<typename T, int... I> + T i() { + return T{I...}; + } + template void i<void>(); + + static_assert((void({}), true), ""); + // since-cxx11-error@-1 {{cannot initialize non-class type 'void' with a parenthesized initializer list}} +#endif +} + namespace dr2352 { // dr2352: 10 int **p; const int *const *const &f1() { return p; } diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 4a3ed19161f9a5..207f032a5d45e4 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -13914,7 +13914,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/2351.html">2351</a></td> <td>CD5</td> <td><TT>void{}</TT></td> - <td class="unknown" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 18</td> </tr> <tr id="2352"> <td><a href="https://cplusplus.github.io/CWG/issues/2352.html">2352</a></td> `````````` </details> https://github.com/llvm/llvm-project/pull/78060 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits