diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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, DefaultError, SFINAEFailure; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/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) diff --git a/clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp b/clang/test/CXX/expr/expr.post/expr.type.conv/p2.cpp new file mode 100644 --- /dev/null +++ b/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}} +} diff --git a/clang/test/SemaCXX/attr-annotate.cpp b/clang/test/SemaCXX/attr-annotate.cpp --- a/clang/test/SemaCXX/attr-annotate.cpp +++ b/clang/test/SemaCXX/attr-annotate.cpp @@ -42,8 +42,8 @@ template 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 b; B b1; diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp --- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -73,8 +73,8 @@ template 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); };