[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

llvm-svn: 328409
This commit is contained in:
Zhihao Yuan 2018-03-24 04:32:11 +00:00
parent 40eb34607c
commit 2c5471ddc7
3 changed files with 18 additions and 8 deletions

View File

@ -10396,12 +10396,22 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
// 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();

View File

@ -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;

View File

@ -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}}