Author: lichray Date: Fri Mar 23 21:32:11 2018 New Revision: 328409 URL: http://llvm.org/viewvc/llvm-project?rev=328409&view=rev Log: [C++17] Fix class template argument deduction for default constructors without an initializer
Summary: As the title says, this makes following code compile: ``` template<typename> struct Foo {}; Foo() -> Foo<void>; Foo f; // ok ``` Thanks Nicolas Lesser for coining the fix. Reviewers: rsmith, lichray Reviewed By: rsmith, lichray Subscribers: lichray, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D38216 Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=328409&r1=328408&r2=328409&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Mar 23 21:32:11 2018 @@ -10396,12 +10396,22 @@ QualType Sema::deduceVarTypeFromInitiali // C++11 [dcl.spec.auto]p3 if (!Init) { assert(VDecl && "no init for init capture deduction?"); - Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) - << VDecl->getDeclName() << Type; - return QualType(); + + // Except for class argument deduction, and then for an initializing + // declaration only, i.e. no static at class scope or extern. + if (!isa<DeducedTemplateSpecializationType>(Deduced) || + VDecl->hasExternalStorage() || + VDecl->isStaticDataMember()) { + Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) + << VDecl->getDeclName() << Type; + return QualType(); + } } - ArrayRef<Expr*> DeduceInits = Init; + ArrayRef<Expr*> DeduceInits; + if (Init) + DeduceInits = Init; + if (DirectInit) { if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init)) DeduceInits = PL->exprs(); Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp?rev=328409&r1=328408&r2=328409&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp Fri Mar 23 21:32:11 2018 @@ -5,8 +5,7 @@ A() -> A<int>; A(int) -> A<char>; static constexpr inline const volatile A a = {}; // ok, specifiers are permitted -// FIXME: There isn't really a good reason to reject this. -A b; // expected-error {{requires an initializer}} +A b; A c [[]] {}; A d = {}, e = {}; @@ -16,3 +15,5 @@ struct B { static A a; // expected-error {{requires an initializer}} }; extern A x; // expected-error {{requires an initializer}} +static A y; + Modified: cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp?rev=328409&r1=328408&r2=328409&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp (original) +++ cfe/trunk/test/Parser/cxx1z-class-template-argument-deduction.cpp Fri Mar 23 21:32:11 2018 @@ -137,7 +137,6 @@ namespace expr { (void)A{n}; (void)new A(n); (void)new A{n}; - // FIXME: We should diagnose the lack of an initializer here. (void)new A; } } @@ -150,7 +149,7 @@ namespace decl { auto k() -> A; // expected-error{{requires template arguments}} - A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}} + A a; A b = 0; const A c = 0; A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits