PR c++/71193 - incomplete types in templates
authorJason Merrill <jason@redhat.com>
Mon, 6 Feb 2017 21:12:13 +0000 (16:12 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 6 Feb 2017 21:12:13 +0000 (16:12 -0500)
* parser.c (cp_parser_postfix_dot_deref_expression): In a template
handle incomplete type by pedwarning and then treating as dependent.

From-SVN: r245223

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/template/incomplete8.C [new file with mode: 0644]

index 0e3e38cef0831465032d61be2a16dae1365f491e..80f1113d8379fa4e669d2e8796f29e08141f0c27 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-06  Jason Merrill  <jason@redhat.com>
+
+       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.
+
 2017-02-06  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/79379
index 592f903a6f98be64a289ab3efcd4bf4b2c7f1ad5..d2df777f344d8d7987437c7b91cc351f1a7d9b04 100644 (file)
@@ -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 (file)
index 0000000..d6cde6a
--- /dev/null
@@ -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" }
+};