[pushed] c++: Immediately deduce auto member [PR94926].

Message ID 20200528185903.22414-1-jason@redhat.com
State New
Headers show
Series
  • [pushed] c++: Immediately deduce auto member [PR94926].
Related show

Commit Message

Kewen.Lin via Gcc-patches May 28, 2020, 6:59 p.m.
In r9-297 I was trying to be more flexible and treat static data members of
class templates more like variable templates, where the type need not be
determined until the variable is instantiated, but I suppose that in a class
the types of all the non-template members need to be determined at the time
of class instantiation.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	PR c++/94926
	* decl.c (cp_finish_decl): Revert r9-297 change.
	(check_static_variable_definition): Likewise.
	* constexpr.c (ensure_literal_type_for_constexpr_object): Likewise.
	* pt.c (instantiate_decl): Return early on type error.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/pr86648.C: Expect error.
	* g++.dg/cpp1z/static2.C: Expect error.
	* g++.dg/cpp0x/nsdmi16.C: New test.
---
 gcc/cp/constexpr.c                   |  2 --
 gcc/cp/decl.c                        | 21 +++++++++++++--------
 gcc/cp/pt.c                          |  1 +
 gcc/testsuite/g++.dg/cpp0x/nsdmi16.C | 11 +++++++++++
 gcc/testsuite/g++.dg/cpp1z/pr86648.C |  4 +++-
 gcc/testsuite/g++.dg/cpp1z/static2.C |  2 +-
 6 files changed, 29 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi16.C


base-commit: c83027f32d9cca84959c7d6a1e519a0129731501
-- 
2.18.1

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4e441ac8d2f..4b1f92f989c 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -96,8 +96,6 @@  ensure_literal_type_for_constexpr_object (tree decl)
       if (CLASS_TYPE_P (stype) && !COMPLETE_TYPE_P (complete_type (stype)))
 	/* Don't complain here, we'll complain about incompleteness
 	   when we try to initialize the variable.  */;
-      else if (type_uses_auto (type))
-	/* We don't know the actual type yet.  */;
       else if (!literal_type_p (type))
 	{
 	  if (DECL_DECLARED_CONSTEXPR_P (decl))
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 56571e39570..b0de90630d7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7467,18 +7467,24 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       && (DECL_INITIAL (decl) || init))
     DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
 
-  /* Do auto deduction unless decl is a function or an uninstantiated
-     template specialization.  */
   if (TREE_CODE (decl) != FUNCTION_DECL
-      && !(init == NULL_TREE
-	   && DECL_LANG_SPECIFIC (decl)
-	   && DECL_TEMPLATE_INSTANTIATION (decl)
-	   && !DECL_TEMPLATE_INSTANTIATED (decl))
       && (auto_node = type_uses_auto (type)))
     {
       tree d_init;
       if (init == NULL_TREE)
-	gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node));
+	{
+	  if (DECL_LANG_SPECIFIC (decl)
+	      && DECL_TEMPLATE_INSTANTIATION (decl)
+	      && !DECL_TEMPLATE_INSTANTIATED (decl))
+	    {
+	      /* init is null because we're deferring instantiating the
+		 initializer until we need it.  Well, we need it now.  */
+	      instantiate_decl (decl, /*defer_ok*/true, /*expl*/false);
+	      return;
+	    }
+
+	  gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node));
+	}
       d_init = init;
       if (d_init)
 	{
@@ -10171,7 +10177,6 @@  check_static_variable_definition (tree decl, tree type)
      in check_initializer.  Similarly for inline static data members.  */
   else if (DECL_P (decl)
       && (DECL_DECLARED_CONSTEXPR_P (decl)
-	  || undeduced_auto_decl (decl)
 	  || DECL_VAR_DECLARED_INLINE_P (decl)))
     ;
   else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d9651acee6..90dafff3aa7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25293,6 +25293,7 @@  instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
     d = DECL_CLONED_FUNCTION (d);
 
   if (DECL_TEMPLATE_INSTANTIATED (d)
+      || TREE_TYPE (d) == error_mark_node
       || (TREE_CODE (d) == FUNCTION_DECL
 	  && DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
       || DECL_TEMPLATE_SPECIALIZATION (d))
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C
new file mode 100644
index 00000000000..07bc198e691
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C
@@ -0,0 +1,11 @@ 
+// PR c++/94926
+// { dg-do compile { target c++11 } }
+
+template<typename>
+struct A {
+    static auto self_reference = A{}; // { dg-error "incomplete" }
+};
+
+int main() {
+    A<void>{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/pr86648.C b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
index 20ee4c8c0d4..58c611c985f 100644
--- a/gcc/testsuite/g++.dg/cpp1z/pr86648.C
+++ b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
@@ -1,5 +1,7 @@ 
 // { dg-do compile { target c++17 } }
 
 template <typename> class A;
-template <class T> struct B { static A a{T::a}; };
+template <class T> struct B {
+  static A a{T::a};		// { dg-error "int" }
+};
 void foo () { B<int> a; }
diff --git a/gcc/testsuite/g++.dg/cpp1z/static2.C b/gcc/testsuite/g++.dg/cpp1z/static2.C
index 9462e0355c8..5d93a0e7242 100644
--- a/gcc/testsuite/g++.dg/cpp1z/static2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/static2.C
@@ -3,7 +3,7 @@ 
 template <class T>
 struct A
 {
-  static constexpr auto x = T::x;
+  static constexpr auto x = T::x; // { dg-error "incomplete" }
 };
 
 struct B;