diff mbox

Better location info for "incomplete type" error msg (PR c/70756)

Message ID 20160502164149.GE5348@redhat.com
State New
Headers show

Commit Message

Marek Polacek May 2, 2016, 4:41 p.m. UTC
On Fri, Apr 29, 2016 at 04:04:13PM -0400, Jason Merrill wrote:
> On 04/28/2016 11:59 AM, Marek Polacek wrote:
> > 3) for the C++ FE I used a macro so that I don't have to change all the
> >     cxx_incomplete_type_error calls now,
> 
> How about an inline overload, instead?
 
I realized the macro was already there, but inline overloads should probably
be preferred these days.  So I used them instead.

> It seems sad to discard the location information; could we pass it into
> cxx_incomplete_type_diagnostic?

I suppose I can, though it required another inline overload.  I'm not sure
if the patch will make the C++ diagnostics about incomplete types better,
most likely not :/.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2016-05-02  Marek Polacek  <polacek@redhat.com>

	PR c/70756
	* c-common.c (pointer_int_sum): Call size_in_bytes_loc instead of
	size_in_bytes and pass LOC to it.

	* c-decl.c (build_compound_literal): Pass LOC down to
	c_incomplete_type_error.
	* c-tree.h (require_complete_type): Adjust declaration.
	(c_incomplete_type_error): Likewise.
	* c-typeck.c (require_complete_type): Add location parameter, pass it
	down to c_incomplete_type_error.
	(c_incomplete_type_error): Add location parameter, pass it down to
	error_at.
	(build_component_ref): Pass location down to c_incomplete_type_error.
	(default_conversion): Pass location down to require_complete_type.
	(build_array_ref): Likewise.
	(build_function_call_vec): Likewise.
	(convert_arguments): Likewise.
	(build_unary_op): Likewise.
	(build_c_cast): Likewise.
	(build_modify_expr): Likewise.
	(convert_for_assignment): Likewise.
	(c_finish_omp_clauses): Likewise.

	* cp-tree.h (cxx_incomplete_type_error,
	cxx_incomplete_type_diagnostic): New inline overloads.
	* typeck2.c (cxx_incomplete_type_diagnostic,
	cxx_incomplete_type_error): Add location parameter.

	* langhooks-def.h (lhd_incomplete_type_error): Adjust declaration.
	* langhooks.c (lhd_incomplete_type_error): Add location parameter.
	* langhooks.h (incomplete_type_error): Likewise.
	* tree.c (size_in_bytes_loc): Renamed from size_in_bytes.  Add location
	parameter, pass it down to incomplete_type_error.
	* tree.h (size_in_bytes): New inline overload.
	(size_in_bytes_loc): Renamed from size_in_bytes.

	* gcc.dg/pr70756.c: New test.


	Marek

Comments

Jason Merrill May 2, 2016, 5:34 p.m. UTC | #1
On 05/02/2016 12:41 PM, Marek Polacek wrote:
> On Fri, Apr 29, 2016 at 04:04:13PM -0400, Jason Merrill wrote:
>> On 04/28/2016 11:59 AM, Marek Polacek wrote:
>>> 3) for the C++ FE I used a macro so that I don't have to change all the
>>>      cxx_incomplete_type_error calls now,
>>
>> How about an inline overload, instead?
>
> I realized the macro was already there, but inline overloads should probably
> be preferred these days.  So I used them instead.
>
>> It seems sad to discard the location information; could we pass it into
>> cxx_incomplete_type_diagnostic?
>
> I suppose I can, though it required another inline overload.  I'm not sure
> if the patch will make the C++ diagnostics about incomplete types better,
> most likely not :/.
> +inline void
> +cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
> +				diagnostic_t diag_kind)
> +{
> +  cxx_incomplete_type_diagnostic (input_location, value, type, diag_kind);
> +}
> +

...

> -cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
> -				diagnostic_t diag_kind)
> +cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
>
> -  location_t loc = EXPR_LOC_OR_LOC (value, input_location);

Shouldn't we use EXPR_LOC_OR_LOC in the inline?

Jason
diff mbox

Patch

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index d45bf1b..747d55d 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -4269,7 +4269,7 @@  pointer_int_sum (location_t loc, enum tree_code resultcode,
       size_exp = integer_one_node;
     }
   else
-    size_exp = size_in_bytes (TREE_TYPE (result_type));
+    size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
 
   /* We are manipulating pointer values, so we don't need to warn
      about relying on undefined signed overflow.  We disable the
diff --git gcc/c/c-decl.c gcc/c/c-decl.c
index 7094efc..48fa65c 100644
--- gcc/c/c-decl.c
+++ gcc/c/c-decl.c
@@ -5112,7 +5112,7 @@  build_compound_literal (location_t loc, tree type, tree init, bool non_const)
 
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     {
-      c_incomplete_type_error (NULL_TREE, type);
+      c_incomplete_type_error (loc, NULL_TREE, type);
       return error_mark_node;
     }
 
diff --git gcc/c/c-tree.h gcc/c/c-tree.h
index 4633182..d3a6c4c 100644
--- gcc/c/c-tree.h
+++ gcc/c/c-tree.h
@@ -588,13 +588,13 @@  extern tree c_last_sizeof_arg;
 extern struct c_switch *c_switch_stack;
 
 extern tree c_objc_common_truthvalue_conversion (location_t, tree);
-extern tree require_complete_type (tree);
+extern tree require_complete_type (location_t, tree);
 extern int same_translation_unit_p (const_tree, const_tree);
 extern int comptypes (tree, tree);
 extern int comptypes_check_different_types (tree, tree, bool *);
 extern bool c_vla_type_p (const_tree);
 extern bool c_mark_addressable (tree);
-extern void c_incomplete_type_error (const_tree, const_tree);
+extern void c_incomplete_type_error (location_t, const_tree, const_tree);
 extern tree c_type_promotes_to (tree);
 extern struct c_expr default_function_array_conversion (location_t,
 							struct c_expr);
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 58c2139..32fd504 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -183,11 +183,12 @@  struct tagged_tu_seen_cache {
 static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
 static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
 
-/* Do `exp = require_complete_type (exp);' to make sure exp
-   does not have an incomplete type.  (That includes void types.)  */
+/* Do `exp = require_complete_type (loc, exp);' to make sure exp
+   does not have an incomplete type.  (That includes void types.)
+   LOC is the location of the use.  */
 
 tree
-require_complete_type (tree value)
+require_complete_type (location_t loc, tree value)
 {
   tree type = TREE_TYPE (value);
 
@@ -198,23 +199,24 @@  require_complete_type (tree value)
   if (COMPLETE_TYPE_P (type))
     return value;
 
-  c_incomplete_type_error (value, type);
+  c_incomplete_type_error (loc, value, type);
   return error_mark_node;
 }
 
 /* Print an error message for invalid use of an incomplete type.
    VALUE is the expression that was used (or 0 if that isn't known)
-   and TYPE is the type that was invalid.  */
+   and TYPE is the type that was invalid.  LOC is the location for
+   the error.  */
 
 void
-c_incomplete_type_error (const_tree value, const_tree type)
+c_incomplete_type_error (location_t loc, const_tree value, const_tree type)
 {
   /* Avoid duplicate error message.  */
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
   if (value != 0 && (VAR_P (value) || TREE_CODE (value) == PARM_DECL))
-    error ("%qD has an incomplete type %qT", value, type);
+    error_at (loc, "%qD has an incomplete type %qT", value, type);
   else
     {
     retry:
@@ -228,7 +230,7 @@  c_incomplete_type_error (const_tree value, const_tree type)
 	  break;
 
 	case VOID_TYPE:
-	  error ("invalid use of void expression");
+	  error_at (loc, "invalid use of void expression");
 	  return;
 
 	case ARRAY_TYPE:
@@ -236,13 +238,13 @@  c_incomplete_type_error (const_tree value, const_tree type)
 	    {
 	      if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
 		{
-		  error ("invalid use of flexible array member");
+		  error_at (loc, "invalid use of flexible array member");
 		  return;
 		}
 	      type = TREE_TYPE (type);
 	      goto retry;
 	    }
-	  error ("invalid use of array with unspecified bounds");
+	  error_at (loc, "invalid use of array with unspecified bounds");
 	  return;
 
 	default:
@@ -250,10 +252,10 @@  c_incomplete_type_error (const_tree value, const_tree type)
 	}
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-	error ("invalid use of undefined type %qT", type);
+	error_at (loc, "invalid use of undefined type %qT", type);
       else
 	/* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
-	error ("invalid use of incomplete typedef %qT", type);
+	error_at (loc, "invalid use of incomplete typedef %qT", type);
     }
 }
 
@@ -2117,7 +2119,7 @@  default_conversion (tree exp)
       return error_mark_node;
     }
 
-  exp = require_complete_type (exp);
+  exp = require_complete_type (EXPR_LOC_OR_LOC (exp, input_location), exp);
   if (exp == error_mark_node)
     return error_mark_node;
 
@@ -2334,7 +2336,7 @@  build_component_ref (location_t loc, tree datum, tree component)
     {
       if (!COMPLETE_TYPE_P (type))
 	{
-	  c_incomplete_type_error (NULL_TREE, type);
+	  c_incomplete_type_error (loc, NULL_TREE, type);
 	  return error_mark_node;
 	}
 
@@ -2642,7 +2644,7 @@  build_array_ref (location_t loc, tree array, tree index)
 	       in an inline function.
 	       Hope it doesn't break something else.  */
 	    | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type (rval);
+      ret = require_complete_type (loc, rval);
       protected_set_expr_location (ret, loc);
       if (non_lvalue)
 	ret = non_lvalue_loc (loc, ret);
@@ -3087,7 +3089,7 @@  build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 		 "function with qualified void return type called");
       return result;
     }
-  return require_complete_type (result);
+  return require_complete_type (loc, result);
 }
 
 /* Like build_function_call_vec, but call also resolve_overloaded_builtin.  */
@@ -3238,7 +3240,7 @@  convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
       val = c_fully_fold (val, false, NULL);
       STRIP_TYPE_NOPS (val);
 
-      val = require_complete_type (val);
+      val = require_complete_type (ploc, val);
 
       if (type != 0)
 	{
@@ -4046,7 +4048,7 @@  build_unary_op (location_t location,
     arg = remove_c_maybe_const_expr (arg);
 
   if (code != ADDR_EXPR)
-    arg = require_complete_type (arg);
+    arg = require_complete_type (location, arg);
 
   typecode = TREE_CODE (TREE_TYPE (arg));
   if (typecode == ERROR_MARK)
@@ -5267,7 +5269,7 @@  build_c_cast (location_t loc, tree type, tree expr)
 
   if (!VOID_TYPE_P (type))
     {
-      value = require_complete_type (value);
+      value = require_complete_type (loc, value);
       if (value == error_mark_node)
 	return error_mark_node;
     }
@@ -5537,7 +5539,7 @@  build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   bool is_atomic_op;
 
   /* Types that aren't fully specified cannot be used in assignments.  */
-  lhs = require_complete_type (lhs);
+  lhs = require_complete_type (location, lhs);
 
   /* Avoid duplicate error messages from operands that had errors.  */
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
@@ -6132,7 +6134,7 @@  convert_for_assignment (location_t location, location_t expr_loc, tree type,
       error_at (location, "void value not ignored as it ought to be");
       return error_mark_node;
     }
-  rhs = require_complete_type (rhs);
+  rhs = require_complete_type (location, rhs);
   if (rhs == error_mark_node)
     return error_mark_node;
 
@@ -12548,7 +12550,7 @@  c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd,
 
 	      t = OMP_CLAUSE_DECL (c);
 	    }
-	  t = require_complete_type (t);
+	  t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
 	  if (t == error_mark_node)
 	    {
 	      remove = true;
@@ -13359,7 +13361,7 @@  c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd,
 
 	  if (need_complete)
 	    {
-	      t = require_complete_type (t);
+	      t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
 	      if (t == error_mark_node)
 		remove = true;
 	    }
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index 8a06609..0a3f060 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -6727,11 +6727,23 @@  extern tree finish_binary_fold_expr          (tree, tree, int);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types	(tree, tree);
-extern void cxx_incomplete_type_diagnostic	(const_tree, const_tree, diagnostic_t);
-#undef cxx_incomplete_type_error
-extern void cxx_incomplete_type_error		(const_tree, const_tree);
-#define cxx_incomplete_type_error(V,T) \
-  (cxx_incomplete_type_diagnostic ((V), (T), DK_ERROR))
+extern void cxx_incomplete_type_diagnostic	(location_t, const_tree,
+						 const_tree, diagnostic_t);
+inline void
+cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
+				diagnostic_t diag_kind)
+{
+  cxx_incomplete_type_diagnostic (input_location, value, type, diag_kind);
+}
+
+extern void cxx_incomplete_type_error		(location_t, const_tree,
+						 const_tree);
+inline void
+cxx_incomplete_type_error (const_tree value, const_tree type)
+{
+  cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
+}
+
 extern void cxx_incomplete_type_inform 	        (const_tree);
 extern tree error_not_base_type			(tree, tree);
 extern tree binfo_or_else			(tree, tree);
diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
index e59ad51..1c4e832 100644
--- gcc/cp/typeck2.c
+++ gcc/cp/typeck2.c
@@ -451,8 +451,8 @@  cxx_incomplete_type_inform (const_tree type)
    type of diagnostic (see diagnostic.def).  */
 
 void
-cxx_incomplete_type_diagnostic (const_tree value, const_tree type, 
-				diagnostic_t diag_kind)
+cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
+				const_tree type, diagnostic_t diag_kind)
 {
   bool is_decl = false, complained = false;
 
@@ -475,8 +475,6 @@  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
  retry:
   /* We must print an error message.  Be clever about what it says.  */
 
-  location_t loc = EXPR_LOC_OR_LOC (value, input_location);
-
   switch (TREE_CODE (type))
     {
     case RECORD_TYPE:
@@ -570,13 +568,14 @@  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
     }
 }
 
-/* Backward-compatibility interface to incomplete_type_diagnostic;
-   required by ../tree.c.  */
-#undef cxx_incomplete_type_error
+/* Print an error message for invalid use of an incomplete type.
+   VALUE is the expression that was used (or 0 if that isn't known)
+   and TYPE is the type that was invalid.  */
+
 void
-cxx_incomplete_type_error (const_tree value, const_tree type)
+cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type)
 {
-  cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
+  cxx_incomplete_type_diagnostic (loc, value, type, DK_ERROR);
 }
 
 
diff --git gcc/langhooks-def.h gcc/langhooks-def.h
index a2566ec..034b3b7 100644
--- gcc/langhooks-def.h
+++ gcc/langhooks-def.h
@@ -52,7 +52,7 @@  extern void lhd_print_error_function (diagnostic_context *,
 				      const char *, struct diagnostic_info *);
 extern void lhd_set_decl_assembler_name (tree);
 extern bool lhd_warn_unused_global_decl (const_tree);
-extern void lhd_incomplete_type_error (const_tree, const_tree);
+extern void lhd_incomplete_type_error (location_t, const_tree, const_tree);
 extern tree lhd_type_promotes_to (tree);
 extern void lhd_register_builtin_type (tree, const char *);
 extern bool lhd_decl_ok_for_sibcall (const_tree);
diff --git gcc/langhooks.c gcc/langhooks.c
index 7c07175..6444631 100644
--- gcc/langhooks.c
+++ gcc/langhooks.c
@@ -199,7 +199,8 @@  lhd_register_builtin_type (tree ARG_UNUSED (type),
 
 /* Invalid use of an incomplete type.  */
 void
-lhd_incomplete_type_error (const_tree ARG_UNUSED (value), const_tree type)
+lhd_incomplete_type_error (location_t ARG_UNUSED (loc),
+			   const_tree ARG_UNUSED (value), const_tree type)
 {
   gcc_assert (TREE_CODE (type) == ERROR_MARK);
   return;
diff --git gcc/langhooks.h gcc/langhooks.h
index bcfd389..0593424 100644
--- gcc/langhooks.h
+++ gcc/langhooks.h
@@ -100,8 +100,9 @@  struct lang_hooks_for_types
   /* This routine is called in tree.c to print an error message for
      invalid use of an incomplete type.  VALUE is the expression that
      was used (or 0 if that isn't known) and TYPE is the type that was
-     invalid.  */
-  void (*incomplete_type_error) (const_tree value, const_tree type);
+     invalid.  LOC is the location of the use.  */
+  void (*incomplete_type_error) (location_t loc, const_tree value,
+				 const_tree type);
 
   /* Called from assign_temp to return the maximum size, if there is one,
      for a type.  */
diff --git gcc/testsuite/gcc.dg/pr70756.c gcc/testsuite/gcc.dg/pr70756.c
index e69de29..e867832 100644
--- gcc/testsuite/gcc.dg/pr70756.c
+++ gcc/testsuite/gcc.dg/pr70756.c
@@ -0,0 +1,23 @@ 
+/* PR c/70756 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+enum E e; /* { dg-error "storage size" } */
+int (*A)[];
+
+void
+fn0 (void)
+{
+  struct
+  {
+    int x;
+    int y[];
+  } s;
+  1234 && &s.y + 1; /* { dg-error "16:invalid use of flexible array member" } */
+}
+
+void
+fn1 (void)
+{
+  1234, A += 1; /* { dg-error "11:invalid use of array with unspecified bounds" } */
+}
diff --git gcc/tree.c gcc/tree.c
index f7366f6..e1e4d63 100644
--- gcc/tree.c
+++ gcc/tree.c
@@ -2939,7 +2939,7 @@  ctor_to_vec (tree ctor)
    make_unsigned_type).  */
 
 tree
-size_in_bytes (const_tree type)
+size_in_bytes_loc (location_t loc, const_tree type)
 {
   tree t;
 
@@ -2951,7 +2951,7 @@  size_in_bytes (const_tree type)
 
   if (t == 0)
     {
-      lang_hooks.types.incomplete_type_error (NULL_TREE, type);
+      lang_hooks.types.incomplete_type_error (loc, NULL_TREE, type);
       return size_zero_node;
     }
 
diff --git gcc/tree.h gcc/tree.h
index 6e52e3d..37324bf 100644
--- gcc/tree.h
+++ gcc/tree.h
@@ -4224,7 +4224,13 @@  extern tree type_hash_canon (unsigned int, tree);
 
 extern tree convert (tree, tree);
 extern unsigned int expr_align (const_tree);
-extern tree size_in_bytes (const_tree);
+extern tree size_in_bytes_loc (location_t, const_tree);
+inline tree
+size_in_bytes (const_tree t)
+{
+  return size_in_bytes_loc (input_location, t);
+}
+
 extern HOST_WIDE_INT int_size_in_bytes (const_tree);
 extern HOST_WIDE_INT max_int_size_in_bytes (const_tree);
 extern tree bit_position (const_tree);