diff mbox

C++ PATCH for c++/71193 (incomplete error in template)

Message ID CADzB+2=6C=BYE6u4_fDQfvYT4wdDxiQWg-NCMYSLH3Av3W0+YQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Feb. 6, 2017, 9:11 p.m. UTC
71193 is a case where we now properly treat as non-dependent some
expressions that we previously considered type-dependent, and as a
result try to resolve their containing expressions, which can lead to
incomplete type errors that weren't seen before even though the code
was ill-formed.

This patch adjusts one situation this might occur to catch the
problem, give a pedwarn instead of an error, and treat the expression
as type-dependent.  This doesn't help the testcase for 71773, where
the access is more complicated.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit debb4f99e55e5c0b8c64fd1957d41417dc951870
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 6 14:50:03 2017 -0500

            PR c++/71193 - incomplete types in templates
    
            * parser.c (cp_parser_postfix_dot_deref_expression): In a template
            handle incomplete type by pedwarning and then treating as dependent.
diff mbox

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0aa738b..1813adb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7309,7 +7309,7 @@  cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 
   /* Enter the scope corresponding to the type of the object
      given by the POSTFIX_EXPRESSION.  */
-  if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
+  if (!dependent_p)
     {
       scope = TREE_TYPE (postfix_expression);
       /* According to the standard, no expression should ever have
@@ -7324,26 +7324,50 @@  cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 required to be of complete type for purposes of class member
 	 access (5.2.5) outside the member function body.  */
       if (postfix_expression != current_class_ref
+	  && scope != error_mark_node
 	  && !(processing_template_decl
 	       && current_class_type
 	       && (same_type_ignoring_top_level_qualifiers_p
 		   (scope, current_class_type))))
-	scope = complete_type_or_else (scope, postfix_expression);
-      /* Let the name lookup machinery know that we are processing a
-	 class member access expression.  */
-      parser->context->object_type = scope;
-      /* If something went wrong, we want to be able to discern that case,
-	 as opposed to the case where there was no SCOPE due to the type
-	 of expression being dependent.  */
-      if (!scope)
-	scope = error_mark_node;
-      /* If the SCOPE was erroneous, make the various semantic analysis
-	 functions exit quickly -- and without issuing additional error
-	 messages.  */
-      if (scope == error_mark_node)
-	postfix_expression = error_mark_node;
+	{
+	  scope = complete_type (scope);
+	  if (!COMPLETE_TYPE_P (scope))
+	    {
+	      /* In a template, be permissive by treating an object expression
+		 of incomplete type as dependent (after a pedwarn).  */
+	      diagnostic_t kind = (processing_template_decl
+				   ? DK_PEDWARN
+				   : DK_ERROR);
+	      cxx_incomplete_type_diagnostic
+		(location_of (postfix_expression),
+		 postfix_expression, scope, kind);
+	      if (processing_template_decl)
+		{
+		  dependent_p = true;
+		  scope = TREE_TYPE (postfix_expression) = NULL_TREE;
+		}
+	    }
+	}
+
+      if (!dependent_p)
+	{
+	  /* Let the name lookup machinery know that we are processing a
+	     class member access expression.  */
+	  parser->context->object_type = scope;
+	  /* If something went wrong, we want to be able to discern that case,
+	     as opposed to the case where there was no SCOPE due to the type
+	     of expression being dependent.  */
+	  if (!scope)
+	    scope = error_mark_node;
+	  /* If the SCOPE was erroneous, make the various semantic analysis
+	     functions exit quickly -- and without issuing additional error
+	     messages.  */
+	  if (scope == error_mark_node)
+	    postfix_expression = error_mark_node;
+	}
     }
-  else
+
+  if (dependent_p)
     /* Tell cp_parser_lookup_name that there was an object, even though it's
        type-dependent.  */
     parser->context->object_type = unknown_type_node;
diff --git a/gcc/testsuite/g++.dg/template/incomplete8.C b/gcc/testsuite/g++.dg/template/incomplete8.C
new file mode 100644
index 0000000..d6cde6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/incomplete8.C
@@ -0,0 +1,11 @@ 
+// PR c++/71193
+// { dg-options "" }
+
+class Heap;
+class A {
+public:  
+  Heap *m_fn1();
+};
+template <typename> class B : A {
+  void m_fn2() { m_fn1()->HashSeed; } // { dg-warning "incomplete" }
+};