From 4b11d767d52c819894f705353ffb401e71354818 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 12 Mar 2014 17:42:45 +0000 Subject: [PATCH] DR1346: a parenthesized braced-init-list cannot be used as the initializer when performing auto type deduction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203683 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 8 ++++- lib/Sema/SemaDecl.cpp | 5 ++++ lib/Sema/SemaExprCXX.cpp | 7 +++-- lib/Sema/SemaLambda.cpp | 3 ++ .../dcl.spec/dcl.type/dcl.spec.auto/p4.cpp | 25 +++++++++++++++- test/CXX/drs/dr13xx.cpp | 29 +++++++++++++++++++ .../CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp | 2 ++ www/cxx_dr_status.html | 2 +- 8 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 test/CXX/drs/dr13xx.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4f93429a84..49d1d676fa 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1538,12 +1538,15 @@ def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; -def err_auto_new_requires_parens : Error< +def err_auto_new_list_init : Error< "new expression for type %0 cannot use list-initialization">; def err_auto_var_init_no_expression : Error< "initializer for variable %0 with type %1 is empty">; def err_auto_var_init_multiple_expressions : Error< "initializer for variable %0 with type %1 contains multiple expressions">; +def err_auto_var_init_paren_braces : Error< + "cannot deduce type for variable %0 with type %1 from " + "parenthesized initializer list">; def err_auto_new_ctor_multiple_expressions : Error< "new expression for type %0 contains multiple constructor arguments">; def err_auto_missing_trailing_return : Error< @@ -5239,6 +5242,9 @@ let CategoryName = "Lambda Issue" in { "initializer missing for lambda capture %0">; def err_init_capture_multiple_expressions : Error< "initializer for lambda capture %0 contains multiple expressions">; + def err_init_capture_paren_braces : Error< + "cannot deduce type for lambda capture %0 from " + "parenthesized initializer list">; def err_init_capture_deduction_failure : Error< "cannot deduce type for lambda capture %0 from initializer of type %2">; def err_init_capture_deduction_failure_from_init_list : Error< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6419c7f584..521fc3f2cb 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8057,6 +8057,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } else { DeduceInit = CXXDirectInit->getExpr(0); + if (isa(DeduceInit)) + Diag(CXXDirectInit->getLocStart(), + diag::err_auto_var_init_paren_braces) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3fa5de1a77..8b9c0e2cc7 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1188,14 +1188,15 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, else if (Initializer && isa(Initializer)) HaveCompleteInit = true; - // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && AllocType->isUndeducedType()) { if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); - if (initStyle == CXXNewExpr::ListInit) + if (initStyle == CXXNewExpr::ListInit || + (NumInits == 1 && isa(Inits[0]))) return ExprError(Diag(Inits[0]->getLocStart(), - diag::err_auto_new_requires_parens) + diag::err_auto_new_list_init) << AllocType << TypeRange); if (NumInits > 1) { Expr *FirstBad = Inits[1]; diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 158324cb82..cd62ba4b92 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -736,6 +736,9 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, return QualType(); } else { DeduceInit = CXXDirectInit->getExpr(0); + if (isa(DeduceInit)) + Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces) + << DeclarationName(Id) << Loc; } } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp index 84f9f9b829..46c874f605 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-c++1y-extensions // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions template @@ -41,3 +42,25 @@ struct S { }; const int S::b; const auto S::c = 0; + +namespace std { template struct initializer_list { initializer_list(); }; } + +// In an initializer of the form ( expression-list ), the expression-list +// shall be a single assigment-expression. +auto parens1(1); +auto parens2(2, 3); // expected-error {{initializer for variable 'parens2' with type 'auto' contains multiple expressions}} +#if __cplusplus >= 201103L +auto parens3({4, 5, 6}); // expected-error {{cannot deduce type for variable 'parens3' with type 'auto' from parenthesized initializer list}} +auto parens4 = [p4(1)] {}; +auto parens5 = [p5(2, 3)] {}; // expected-error {{initializer for lambda capture 'p5' contains multiple expressions}} +auto parens6 = [p6({4, 5, 6})] {}; // expected-error {{cannot deduce type for lambda capture 'p6' from parenthesized initializer list}} +#endif + +#if __cplusplus >= 201402L +namespace std_example { + // The other half of this example is in p3.cpp + auto f() -> int; + auto g() { return 0.0; } + auto h(); +} +#endif diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp new file mode 100644 index 0000000000..5827291142 --- /dev/null +++ b/test/CXX/drs/dr13xx.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +namespace dr1346 { // dr1346: 3.5 + auto a(1); // expected-error 0-1{{extension}} + auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} +#if __cplusplus >= 201103L + auto c({}); // expected-error {{parenthesized initializer list}} expected-error {{cannot deduce}} + auto d({1}); // expected-error {{parenthesized initializer list}} expected-error {{}} + auto e({1, 2}); // expected-error {{parenthesized initializer list}} expected-error {{}} +#endif + template void f(Ts ...ts) { // expected-error 0-1{{extension}} + auto x(ts...); // expected-error {{empty}} expected-error 0-1{{extension}} + } + template void f(); // expected-note {{instantiation}} + +#if __cplusplus >= 201103L + void init_capture() { + [a(1)] {} (); // expected-error 0-1{{extension}} + [b(1, 2)] {} (); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} +#if __cplusplus >= 201103L + [c({})] {} (); // expected-error {{parenthesized initializer list}} expected-error {{cannot deduce}} expected-error 0-1{{extension}} + [d({1})] {} (); // expected-error {{parenthesized initializer list}} expected-error {{}} expected-error 0-1{{extension}} + [e({1, 2})] {} (); // expected-error {{parenthesized initializer list}} expected-error {{}} expected-error 0-1{{extension}} +#endif + } +#endif +} diff --git a/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp b/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp index 2e99b525b4..7305bd1f53 100644 --- a/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp +++ b/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp @@ -13,6 +13,8 @@ void f() { new auto; // expected-error{{new expression for type 'auto' requires a constructor argument}} new (const auto)(); // expected-error{{new expression for type 'const auto' requires a constructor argument}} new (auto) (1,2,3); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}} + new auto {1,2,3}; // expected-error{{new expression for type 'auto' cannot use list-initialization}} + new auto ({1,2,3}); // expected-error{{new expression for type 'auto' cannot use list-initialization}} } void p2example() { diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index c4420b9414..c431f774c5 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -7891,7 +7891,7 @@ and POD class 1346 CD3 expression-list initializers and the auto specifier - Unknown + SVN 1347 -- 2.40.0