aaronpuchert created this revision. aaronpuchert added a reviewer: rsmith. aaronpuchert requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This is explicitly allowed via [expr.type.conv], if the initialization list is empty. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D113838 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaInit.cpp clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp clang/test/SemaCXX/attr-annotate.cpp clang/test/SemaCXX/cxx2a-explicit-bool.cpp Index: clang/test/SemaCXX/cxx2a-explicit-bool.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -73,8 +73,8 @@ template <typename T> struct E { // expected-note@-1+ {{candidate constructor}} - explicit((T{}, false)) - // expected-error@-1 {{illegal initializer type 'void'}} + explicit(((T&&)T{}, false)) + // expected-error@-1 {{cannot form a reference to 'void'}} E(int); }; Index: clang/test/SemaCXX/attr-annotate.cpp =================================================================== --- clang/test/SemaCXX/attr-annotate.cpp +++ clang/test/SemaCXX/attr-annotate.cpp @@ -42,8 +42,8 @@ template<typename T> struct B { - [[clang::annotate("test", ((void)T{}, 9))]] void t() {} - // expected-error@-1 {{illegal initializer type 'void'}} + [[clang::annotate("test", ((void)T{1}, 9))]] void t() {} + // expected-error@-1 {{initializer list for 'void' must be empty}} }; B<int> b; B<void> b1; Index: clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp =================================================================== --- /dev/null +++ clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +void paren_list() { + return void(); +} + +void brace_list() { + return void{}; +} + +void brace_list_nonempty() { + return void{1}; // expected-error {{initializer list for 'void' must be empty}} +} + +void brace_list_nested_nonempty() { + return void{{}}; // expected-error {{initializer list for 'void' must be empty}} +} Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -1308,7 +1308,16 @@ CheckArrayType(Entity, IList, DeclType, Zero, SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex); - } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { + } else if (DeclType->isVoidType()) { + // [expr.type.conv]p2: Otherwise, if the type is cv void and the + // initializer is () or {} (after pack expansion, if any), the expression + // is a prvalue of type void that performs no initialization. + if (IList->getNumInits() > 0) { + if (!VerifyOnly) + SemaRef.Diag(IList->getBeginLoc(), diag::err_init_list_void_nonempty); + hadError = true; + } + } else if (DeclType->isFunctionType()) { // This type is invalid, issue a diagnostic. ++Index; if (!VerifyOnly) Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5845,6 +5845,8 @@ def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; +def err_init_list_void_nonempty : Error< + "initializer list for 'void' must be empty">; def ext_init_list_type_narrowing : ExtWarn< "type %0 cannot be narrowed to %1 in initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
Index: clang/test/SemaCXX/cxx2a-explicit-bool.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -73,8 +73,8 @@ template <typename T> struct E { // expected-note@-1+ {{candidate constructor}} - explicit((T{}, false)) - // expected-error@-1 {{illegal initializer type 'void'}} + explicit(((T&&)T{}, false)) + // expected-error@-1 {{cannot form a reference to 'void'}} E(int); }; Index: clang/test/SemaCXX/attr-annotate.cpp =================================================================== --- clang/test/SemaCXX/attr-annotate.cpp +++ clang/test/SemaCXX/attr-annotate.cpp @@ -42,8 +42,8 @@ template<typename T> struct B { - [[clang::annotate("test", ((void)T{}, 9))]] void t() {} - // expected-error@-1 {{illegal initializer type 'void'}} + [[clang::annotate("test", ((void)T{1}, 9))]] void t() {} + // expected-error@-1 {{initializer list for 'void' must be empty}} }; B<int> b; B<void> b1; Index: clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp =================================================================== --- /dev/null +++ clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +void paren_list() { + return void(); +} + +void brace_list() { + return void{}; +} + +void brace_list_nonempty() { + return void{1}; // expected-error {{initializer list for 'void' must be empty}} +} + +void brace_list_nested_nonempty() { + return void{{}}; // expected-error {{initializer list for 'void' must be empty}} +} Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -1308,7 +1308,16 @@ CheckArrayType(Entity, IList, DeclType, Zero, SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex); - } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { + } else if (DeclType->isVoidType()) { + // [expr.type.conv]p2: Otherwise, if the type is cv void and the + // initializer is () or {} (after pack expansion, if any), the expression + // is a prvalue of type void that performs no initialization. + if (IList->getNumInits() > 0) { + if (!VerifyOnly) + SemaRef.Diag(IList->getBeginLoc(), diag::err_init_list_void_nonempty); + hadError = true; + } + } else if (DeclType->isFunctionType()) { // This type is invalid, issue a diagnostic. ++Index; if (!VerifyOnly) Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5845,6 +5845,8 @@ def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; +def err_init_list_void_nonempty : Error< + "initializer list for 'void' must be empty">; def ext_init_list_type_narrowing : ExtWarn< "type %0 cannot be narrowed to %1 in initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits