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 <ja...@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 --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" }
+};

Reply via email to