r328409 - [C++17] Fix class template argument deduction for default constructors without an initializer

Zhihao Yuan via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 23 21:32:12 PDT 2018


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




More information about the cfe-commits mailing list