[C++] Improve throw, sizeof, and alignof locations & more

Message ID 496be035-3db4-a944-0e09-f207180a2fd4@oracle.com
State New
Headers show
Series
  • [C++] Improve throw, sizeof, and alignof locations & more
Related show

Commit Message

Paolo Carlini Dec. 16, 2019, 11:06 p.m.
Hi,

another batch of work. Primarily, more of the idea of moving up the 
construction of the compound location thus passing it to the 
cxx_sizeof_or_alignof* and build_throw functions to obtain better 
locations for all the diagnostics issued by the latter. During the work 
a few mildly interesting nits (eg, for sizeof and alignof we want to set 
whenever possible the location inside the cxx_* functions and that 
allows to avoid set_location in cp_parser_unary_expression, but 
minimally we have to pass it to the cp_expr constructor, otherwise 
plugin testcases badly fail; noticed that in cxx_sizeof_expr and 
cxx_alignof_expr having a single cp_expr_loc_or_input_loc on top 
actually implies better locations (4 testcases) because below, before 
the diagnostic calls, we have STRIP_ANY_LOCATION_WRAPPER uses; in fact I 
changed those cp_expr_loc_or_input_loc to cp_expr_loc_or_loc because for 
expressions we still want to try fetching the locations but we do have a 
meaningful fallback in the location argument of the function; in 
build_throw, an error should be an inform, because in such cases we 
already issued an error (tested in ctor1.C)) but nothing major. The 
below includes a few other minor changes, like two additional uses of 
DECL_SOURCE_LOCATION, cp_expr_loc_or_input_loc, removal of an unused 
function.

Tested x86_64-linux.

Thanks, Paolo.

//////////////////////////////
/gcc/cp
2019-12-16  Paolo Carlini  <paolo.carlini@oracle.com>

	* typeck.c (cxx_sizeof_or_alignof_type): Add location_t parameter
	and use it throughout.
	(cxx_sizeof_expr): Likewise.
	(cxx_alignof_expr): Likewise.
	(cxx_sizeof_or_alignof_expr): Likewise.
	(cxx_alignas_expr): Update call.
	* decl.c (fold_sizeof_expr): Likewise.
	* pt.c (tsubst_copy): Likewise.
	(tsubst_copy_and_build): Likewise.
	* except.c (build_throw): Add location_t parameter and use it.
	(expand_end_catch_block): Update call.
	* parser.c (cp_parser_unary_expression): Update
	cxx_sizeof_or_alignof_type and cxx_sizeof_or_alignof_expr calls,
	pass the compound location.
	(cp_parser_throw_expression): Likewise pass the combined location
	to build_throw.
	* cp-tree.h: Update declarations.

	* semantics.c (finish_handler_parms): Use DECL_SOURCE_LOCATION.
	* decl2.c (check_classfn): Likewise.

	* except.c (is_admissible_throw_operand_or_catch_parameter):
	Exploit cp_expr_loc_or_input_loc in one place.

	* except.c (create_try_catch_expr): Remove, unused.

/libcc1
2019-12-16  Paolo Carlini  <paolo.carlini@oracle.com>

	* libcp1plugin.cc (plugin_build_unary_expr): Update build_throw
	and cxx_sizeof_or_alignof_expr calls.
	(plugin_build_unary_type_expr): Likewise for
	cxx_sizeof_or_alignof_type.

/gcc/testsuite
2019-12-16  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/alignof2.C: New.
	* g++.dg/diagnostic/alignof3.C: Likewise.
	* g++.dg/diagnostic/incomplete-type-1.C: Likewise.
	* g++.dg/warn/Wcatch-value-3b.C: Likewise.
	* g++.dg/cpp0x/alignof3.C: Check location(s) too.
	* g++.dg/cpp1z/decomp-bitfield1.C: Likewise.
	* g++.dg/cpp1z/has-unique-obj-representations2.C: Likewise.
	* g++.dg/expr/sizeof3.C: Likewise.
	* g++.dg/ext/flexary6.C: Likewise.
	* g++.dg/ext/vla4.C: Likewise.
	* g++.dg/template/sizeof11.C: Likewise.
	* g++.dg/warn/Wcatch-value-1.C: Likewise.
	* g++.dg/warn/Wcatch-value-2.C: Likewise.
	* g++.dg/warn/Wcatch-value-3.C: Likewise.
	* g++.old-deja/g++.brendan/sizeof1.C: Likewise.
	* g++.old-deja/g++.brendan/sizeof3.C: Likewise.
	* g++.old-deja/g++.brendan/sizeof4.C: Likewise.
	* g++.old-deja/g++.eh/ctor1.C: Likewise.
	* g++.old-deja/g++.jason/ambig1.C: Likewise.
	* g++.old-deja/g++.other/sizeof4.C: Likewise.

Comments

Jason Merrill Dec. 18, 2019, 12:45 p.m. | #1
On 12/16/19 6:06 PM, Paolo Carlini wrote:
> Hi,

> 

> another batch of work. Primarily, more of the idea of moving up the 

> construction of the compound location thus passing it to the 

> cxx_sizeof_or_alignof* and build_throw functions to obtain better 

> locations for all the diagnostics issued by the latter. During the work 

> a few mildly interesting nits (eg, for sizeof and alignof we want to set 

> whenever possible the location inside the cxx_* functions and that 

> allows to avoid set_location in cp_parser_unary_expression, but 

> minimally we have to pass it to the cp_expr constructor, otherwise 

> plugin testcases badly fail; noticed that in cxx_sizeof_expr and 

> cxx_alignof_expr having a single cp_expr_loc_or_input_loc on top 

> actually implies better locations (4 testcases) because below, before 

> the diagnostic calls, we have STRIP_ANY_LOCATION_WRAPPER uses; in fact I 

> changed those cp_expr_loc_or_input_loc to cp_expr_loc_or_loc because for 

> expressions we still want to try fetching the locations but we do have a 

> meaningful fallback in the location argument of the function; in 

> build_throw, an error should be an inform, because in such cases we 

> already issued an error (tested in ctor1.C)) but nothing major. The 

> below includes a few other minor changes, like two additional uses of 

> DECL_SOURCE_LOCATION, cp_expr_loc_or_input_loc, removal of an unused 

> function.


OK.

Jason

Patch

Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 279371)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6657,7 +6657,7 @@  extern void init_exception_processing		(void);
 extern tree expand_start_catch_block		(tree);
 extern void expand_end_catch_block		(void);
 extern tree build_exc_ptr			(void);
-extern tree build_throw				(tree);
+extern tree build_throw				(location_t, tree);
 extern int nothrow_libfn_p			(const_tree);
 extern void check_handlers			(tree);
 extern tree finish_noexcept_expr		(tree, tsubst_flags_t);
@@ -6674,7 +6674,6 @@  extern tree begin_eh_spec_block			(void);
 extern void finish_eh_spec_block		(tree, tree);
 extern tree build_eh_type_type			(tree);
 extern tree cp_protect_cleanup_actions		(void);
-extern tree create_try_catch_expr               (tree, tree);
 extern tree template_parms_to_args		(tree);
 extern tree template_parms_level_to_args	(tree);
 extern tree generic_targs_for			(tree);
@@ -7487,8 +7486,10 @@  extern bool compparms				(const_tree, const_tree);
 extern int comp_cv_qualification		(const_tree, const_tree);
 extern int comp_cv_qualification		(int, int);
 extern int comp_cv_qual_signature		(tree, tree);
-extern tree cxx_sizeof_or_alignof_expr		(tree, enum tree_code, bool);
-extern tree cxx_sizeof_or_alignof_type		(tree, enum tree_code, bool, bool);
+extern tree cxx_sizeof_or_alignof_expr		(location_t, tree,
+						 enum tree_code, bool);
+extern tree cxx_sizeof_or_alignof_type		(location_t, tree,
+						 enum tree_code, bool, bool);
 extern tree cxx_alignas_expr                    (tree);
 extern tree cxx_sizeof_nowarn                   (tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
@@ -7603,7 +7604,7 @@  extern tree cp_build_binary_op                  (c
 extern tree build_x_vec_perm_expr               (location_t,
 						 tree, tree, tree,
 						 tsubst_flags_t);
-#define cxx_sizeof(T)  cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false, true)
+#define cxx_sizeof(T)  cxx_sizeof_or_alignof_type (input_location, T, SIZEOF_EXPR, false, true)
 extern tree build_simple_component_ref		(tree, tree);
 extern tree build_ptrmemfunc_access_expr	(tree, tree);
 extern tree build_address			(tree);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 279371)
+++ gcc/cp/decl.c	(working copy)
@@ -10225,13 +10225,16 @@  fold_sizeof_expr (tree t)
 {
   tree r;
   if (SIZEOF_EXPR_TYPE_P (t))
-    r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+    r = cxx_sizeof_or_alignof_type (EXPR_LOCATION (t),
+				    TREE_TYPE (TREE_OPERAND (t, 0)),
 				    SIZEOF_EXPR, false, false);
   else if (TYPE_P (TREE_OPERAND (t, 0)))
-    r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+    r = cxx_sizeof_or_alignof_type (EXPR_LOCATION (t),
+				    TREE_OPERAND (t, 0), SIZEOF_EXPR,
 				    false, false);
   else
-    r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+    r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t),
+				    TREE_OPERAND (t, 0), SIZEOF_EXPR,
 				    false);
   if (r == error_mark_node)
     r = size_one_node;
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 279371)
+++ gcc/cp/decl2.c	(working copy)
@@ -698,7 +698,8 @@  check_classfn (tree ctype, tree function, tree tem
   if (!matched)
     {
       if (!COMPLETE_TYPE_P (ctype))
-	cxx_incomplete_type_error (function, ctype);
+	cxx_incomplete_type_error (DECL_SOURCE_LOCATION (function),
+				   function, ctype);
       else
 	{
 	  if (DECL_CONV_FN_P (function))
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	(revision 279371)
+++ gcc/cp/except.c	(working copy)
@@ -507,7 +507,7 @@  expand_end_catch_block (void)
       && (DECL_CONSTRUCTOR_P (current_function_decl)
 	  || DECL_DESTRUCTOR_P (current_function_decl)))
     {
-      tree rethrow = build_throw (NULL_TREE);
+      tree rethrow = build_throw (input_location, NULL_TREE);
       TREE_NO_WARNING (rethrow) = true;
       finish_expr_stmt (rethrow);
     }
@@ -627,7 +627,7 @@  wrap_cleanups_r (tree *tp, int *walk_subtrees, voi
 /* Build a throw expression.  */
 
 tree
-build_throw (tree exp)
+build_throw (location_t loc, tree exp)
 {
   if (exp == error_mark_node)
     return exp;
@@ -637,12 +637,13 @@  tree
       if (cfun)
 	current_function_returns_abnormally = 1;
       exp = build_min (THROW_EXPR, void_type_node, exp);
-      SET_EXPR_LOCATION (exp, input_location);
+      SET_EXPR_LOCATION (exp, loc);
       return exp;
     }
 
   if (exp && null_node_p (exp))
-    warning (0, "throwing NULL, which has integral, not pointer type");
+    warning_at (loc, 0,
+		"throwing NULL, which has integral, not pointer type");
 
   if (exp != NULL_TREE)
     {
@@ -758,6 +759,7 @@  tree
 	{
 	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
 	  bool converted = false;
+	  location_t exp_loc = cp_expr_loc_or_loc (exp, loc);
 
 	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
 	     treated as an rvalue for the purposes of overload resolution
@@ -790,7 +792,7 @@  tree
 
 	  if (exp == error_mark_node)
 	    {
-	      error ("  in thrown expression");
+	      inform (exp_loc, "  in thrown expression");
 	      return error_mark_node;
 	    }
 	}
@@ -867,8 +869,7 @@  tree
       exp = cp_build_function_call_vec (rethrow_fn, NULL, tf_warning_or_error);
     }
 
-  exp = build1 (THROW_EXPR, void_type_node, exp);
-  SET_EXPR_LOCATION (exp, input_location);
+  exp = build1_loc (loc, THROW_EXPR, void_type_node, exp);
 
   return exp;
 }
@@ -948,8 +949,9 @@  is_admissible_throw_operand_or_catch_parameter (tr
   else if (variably_modified_type_p (type, NULL_TREE))
     {
       if (is_throw)
-	error ("cannot throw expression of type %qT because it involves "
-	       "types of variable size", type);
+	error_at (cp_expr_loc_or_input_loc (expr),
+		  "cannot throw expression of type %qT because it involves "
+		  "types of variable size", type);
       else
 	error ("cannot catch type %qT because it involves types of "
 	       "variable size", type);
@@ -1321,22 +1323,4 @@  build_noexcept_spec (tree expr, tsubst_flags_t com
     }
 }
 
-/* Returns a TRY_CATCH_EXPR that will put TRY_LIST and CATCH_LIST in the
-   TRY and CATCH locations.  CATCH_LIST must be a STATEMENT_LIST */
-
-tree
-create_try_catch_expr (tree try_expr, tree catch_list)
-{
-  location_t loc = EXPR_LOCATION (try_expr);
- 
-  append_to_statement_list (do_begin_catch (), &catch_list);
-  append_to_statement_list (build_throw (NULL_TREE), &catch_list);
-  tree catch_tf_expr = build_stmt (loc, TRY_FINALLY_EXPR, catch_list, 
-				   do_end_catch (NULL_TREE));
-  catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE,
-		       catch_tf_expr);
-  tree try_catch_expr = build_stmt (loc, TRY_CATCH_EXPR, try_expr, catch_list);
-  return try_catch_expr;
-}
-
 #include "gt-cp-except.h"
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 279371)
+++ gcc/cp/parser.c	(working copy)
@@ -8169,9 +8169,17 @@  cp_parser_unary_expression (cp_parser *parser, cp_
 	    /* Parse the operand.  */
 	    operand = cp_parser_sizeof_operand (parser, keyword);
 
+	    /* Construct a location e.g. :
+              alignof (expr)
+              ^~~~~~~~~~~~~~
+              with start == caret at the start of the "alignof"/"sizeof"
+              token, with the endpoint at the final closing paren.  */
+	    location_t compound_loc
+	      = make_location (start_loc, start_loc, parser->lexer);
+
 	    if (TYPE_P (operand))
-	      ret = cxx_sizeof_or_alignof_type (operand, op, std_alignof,
-						true);
+	      ret = cxx_sizeof_or_alignof_type (compound_loc, operand, op,
+						std_alignof, true);
 	    else
 	      {
 		/* ISO C++ defines alignof only with types, not with
@@ -8182,7 +8190,8 @@  cp_parser_unary_expression (cp_parser *parser, cp_
 			   "ISO C++ does not allow %<alignof%> "
 			   "with a non-type");
 
-		ret = cxx_sizeof_or_alignof_expr (operand, op, true);
+		ret = cxx_sizeof_or_alignof_expr (compound_loc,
+						  operand, op, true);
 	      }
 	    /* For SIZEOF_EXPR, just issue diagnostics, but keep
 	       SIZEOF_EXPR with the original operand.  */
@@ -8201,19 +8210,11 @@  cp_parser_unary_expression (cp_parser *parser, cp_
 		      ret = build_min (SIZEOF_EXPR, size_type_node, operand);
 		    TREE_SIDE_EFFECTS (ret) = 0;
 		    TREE_READONLY (ret) = 1;
+		    SET_EXPR_LOCATION (ret, compound_loc);
 		  }
 	      }
 
-	    /* Construct a location e.g. :
-	       alignof (expr)
-	       ^~~~~~~~~~~~~~
-	       with start == caret at the start of the "alignof"/"sizeof"
-	       token, with the endpoint at the final closing paren.  */
-	    location_t compound_loc
-	      = make_location (start_loc, start_loc, parser->lexer);
-
-	    cp_expr ret_expr (ret);
-	    ret_expr.set_location (compound_loc);
+	    cp_expr ret_expr (ret, compound_loc);
 	    ret_expr = ret_expr.maybe_add_location_wrapper ();
 	    return ret_expr;
 	  }
@@ -26045,8 +26046,7 @@  cp_parser_throw_expression (cp_parser* parser)
      the end at the end of the final token we consumed.  */
   location_t combined_loc = make_location (start_loc, start_loc,
 					   parser->lexer);
-  expression = build_throw (expression);
-  protected_set_expr_location (expression, combined_loc);
+  expression = build_throw (combined_loc, expression);
 
   return expression;
 }
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 279371)
+++ gcc/cp/pt.c	(working copy)
@@ -16395,11 +16395,13 @@  tsubst_copy (tree t, tree args, tsubst_flags_t com
 		expanded = make_argument_pack (expanded);
 
 	      if (TYPE_P (expanded))
-		return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+		return cxx_sizeof_or_alignof_type (input_location,
+						   expanded, SIZEOF_EXPR,
 						   false,
 						   complain & tf_error);
 	      else
-		return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+		return cxx_sizeof_or_alignof_expr (input_location,
+						   expanded, SIZEOF_EXPR,
                                                    complain & tf_error);
 	    }
 	  else
@@ -19189,10 +19191,12 @@  tsubst_copy_and_build (tree t,
 	    --c_inhibit_evaluation_warnings;
 	  }
         if (TYPE_P (op1))
-	  r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), std_alignof,
+	  r = cxx_sizeof_or_alignof_type (input_location,
+					  op1, TREE_CODE (t), std_alignof,
 					  complain & tf_error);
 	else
-	  r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+	  r = cxx_sizeof_or_alignof_expr (input_location,
+					  op1, TREE_CODE (t),
 					  complain & tf_error);
 	if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
 	  {
@@ -19954,7 +19958,7 @@  tsubst_copy_and_build (tree t,
 
     case THROW_EXPR:
       RETURN (build_throw
-	(RECUR (TREE_OPERAND (t, 0))));
+       (input_location, RECUR (TREE_OPERAND (t, 0))));
 
     case CONSTRUCTOR:
       {
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 279371)
+++ gcc/cp/semantics.c	(working copy)
@@ -1429,15 +1429,19 @@  finish_handler_parms (tree decl, tree handler)
 	  if (CLASS_TYPE_P (orig_type))
 	    {
 	      if (TYPE_POLYMORPHIC_P (orig_type))
-		warning (OPT_Wcatch_value_,
-			 "catching polymorphic type %q#T by value", orig_type);
+		warning_at (DECL_SOURCE_LOCATION (decl),
+			    OPT_Wcatch_value_,
+			    "catching polymorphic type %q#T by value",
+			    orig_type);
 	      else if (warn_catch_value > 1)
-		warning (OPT_Wcatch_value_,
-			 "catching type %q#T by value", orig_type);
+		warning_at (DECL_SOURCE_LOCATION (decl),
+			    OPT_Wcatch_value_,
+			    "catching type %q#T by value", orig_type);
 	    }
 	  else if (warn_catch_value > 2)
-	    warning (OPT_Wcatch_value_,
-		     "catching non-reference type %q#T", orig_type);
+	    warning_at (DECL_SOURCE_LOCATION (decl),
+			OPT_Wcatch_value_,
+			"catching non-reference type %q#T", orig_type);
 	}
     }
   HANDLER_TYPE (handler) = type;
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 279371)
+++ gcc/cp/typeck.c	(working copy)
@@ -1663,8 +1663,8 @@  compparms (const_tree parms1, const_tree parms2)
    SIZEOF_EXPR.  */
 
 tree
-cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool std_alignof,
-			    bool complain)
+cxx_sizeof_or_alignof_type (location_t loc, tree type, enum tree_code op,
+			    bool std_alignof, bool complain)
 {
   gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
   if (type == error_mark_node)
@@ -1675,7 +1675,7 @@  tree
     {
       if (complain)
 	{
-	  pedwarn (input_location, OPT_Wpointer_arith,
+	  pedwarn (loc, OPT_Wpointer_arith,
 		   "invalid application of %qs to a member function",
 		   OVL_OP_INFO (false, op)->name);
 	  return size_one_node;
@@ -1702,10 +1702,11 @@  tree
       TREE_READONLY (value) = 1;
       if (op == ALIGNOF_EXPR && std_alignof)
 	ALIGNOF_EXPR_STD_P (value) = true;
+      SET_EXPR_LOCATION (value, loc);
       return value;
     }
 
-  return c_sizeof_or_alignof_type (input_location, complete_type (type),
+  return c_sizeof_or_alignof_type (loc, complete_type (type),
 				   op == SIZEOF_EXPR, std_alignof,
 				   complain);
 }
@@ -1724,13 +1725,14 @@  cxx_sizeof_nowarn (tree type)
   else if (!COMPLETE_TYPE_P (type))
     return size_zero_node;
   else
-    return cxx_sizeof_or_alignof_type (type, SIZEOF_EXPR, false, false);
+    return cxx_sizeof_or_alignof_type (input_location, type,
+				       SIZEOF_EXPR, false, false);
 }
 
 /* Process a sizeof expression where the operand is an expression.  */
 
 static tree
-cxx_sizeof_expr (tree e, tsubst_flags_t complain)
+cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain)
 {
   if (e == error_mark_node)
     return error_mark_node;
@@ -1740,10 +1742,12 @@  static tree
       e = build_min (SIZEOF_EXPR, size_type_node, e);
       TREE_SIDE_EFFECTS (e) = 0;
       TREE_READONLY (e) = 1;
+      SET_EXPR_LOCATION (e, loc);
 
       return e;
     }
 
+  location_t e_loc = cp_expr_loc_or_loc (e, loc);
   STRIP_ANY_LOCATION_WRAPPER (e);
 
   /* To get the size of a static data member declared as an array of
@@ -1758,8 +1762,9 @@  static tree
       && (complain & tf_warning))
     {
       auto_diagnostic_group d;
-      if (warning (OPT_Wsizeof_array_argument, "%<sizeof%> on array function "
-		   "parameter %qE will return size of %qT", e, TREE_TYPE (e)))
+      if (warning_at (e_loc, OPT_Wsizeof_array_argument,
+		      "%<sizeof%> on array function parameter %qE "
+		      "will return size of %qT", e, TREE_TYPE (e)))
 	inform (DECL_SOURCE_LOCATION (e), "declared here");
     }
 
@@ -1768,7 +1773,7 @@  static tree
   if (bitfield_p (e))
     {
       if (complain & tf_error)
-	error_at (cp_expr_loc_or_input_loc (e),
+	error_at (e_loc,
 		  "invalid application of %<sizeof%> to a bit-field");
       else
         return error_mark_node;
@@ -1777,9 +1782,8 @@  static tree
   else if (is_overloaded_fn (e))
     {
       if (complain & tf_error)
-	permerror (cp_expr_loc_or_input_loc (e),
-		   "ISO C++ forbids applying %<sizeof%> to an expression "
-		   "of function type");
+	permerror (e_loc, "ISO C++ forbids applying %<sizeof%> to "
+		   "an expression of function type");
       else
         return error_mark_node;
       e = char_type_node;
@@ -1787,7 +1791,7 @@  static tree
   else if (type_unknown_p (e))
     {
       if (complain & tf_error)
-        cxx_incomplete_type_error (e, TREE_TYPE (e));
+        cxx_incomplete_type_error (e_loc, e, TREE_TYPE (e));
       else
         return error_mark_node;
       e = char_type_node;
@@ -1795,7 +1799,8 @@  static tree
   else
     e = TREE_TYPE (e);
 
-  return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, false, complain & tf_error);
+  return cxx_sizeof_or_alignof_type (loc, e, SIZEOF_EXPR, false,
+				     complain & tf_error);
 }
 
 /* Implement the __alignof keyword: Return the minimum required
@@ -1804,7 +1809,7 @@  static tree
    "aligned" __attribute__ specification).  */
 
 static tree
-cxx_alignof_expr (tree e, tsubst_flags_t complain)
+cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
 {
   tree t;
 
@@ -1816,15 +1821,17 @@  static tree
       e = build_min (ALIGNOF_EXPR, size_type_node, e);
       TREE_SIDE_EFFECTS (e) = 0;
       TREE_READONLY (e) = 1;
+      SET_EXPR_LOCATION (e, loc);
 
       return e;
     }
 
+  location_t e_loc = cp_expr_loc_or_loc (e, loc);
   STRIP_ANY_LOCATION_WRAPPER (e);
 
   e = mark_type_use (e);
 
-  if (!verify_type_context (input_location, TCTX_ALIGNOF, TREE_TYPE (e),
+  if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (e),
 			    !(complain & tf_error)))
     {
       if (!(complain & tf_error))
@@ -1836,7 +1843,7 @@  static tree
   else if (bitfield_p (e))
     {
       if (complain & tf_error)
-	error_at (cp_expr_loc_or_input_loc (e),
+	error_at (e_loc,
 		  "invalid application of %<__alignof%> to a bit-field");
       else
         return error_mark_node;
@@ -1848,9 +1855,8 @@  static tree
   else if (is_overloaded_fn (e))
     {
       if (complain & tf_error)
-	permerror (cp_expr_loc_or_input_loc (e),
-		   "ISO C++ forbids applying %<__alignof%> to an expression "
-		   "of function type");
+	permerror (e_loc, "ISO C++ forbids applying %<__alignof%> to "
+		   "an expression of function type");
       else
         return error_mark_node;
       if (TREE_CODE (e) == FUNCTION_DECL)
@@ -1861,16 +1867,17 @@  static tree
   else if (type_unknown_p (e))
     {
       if (complain & tf_error)
-        cxx_incomplete_type_error (e, TREE_TYPE (e));
+        cxx_incomplete_type_error (e_loc, e, TREE_TYPE (e));
       else
         return error_mark_node;
       t = size_one_node;
     }
   else
-    return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, false,
+    return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e),
+				       ALIGNOF_EXPR, false,
                                        complain & tf_error);
 
-  return fold_convert (size_type_node, t);
+  return fold_convert_loc (loc, size_type_node, t);
 }
 
 /* Process a sizeof or alignof expression E with code OP where the operand
@@ -1877,12 +1884,13 @@  static tree
    is an expression.  */
 
 tree
-cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain)
+cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op,
+			    bool complain)
 {
   if (op == SIZEOF_EXPR)
-    return cxx_sizeof_expr (e, complain? tf_warning_or_error : tf_none);
+    return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none);
   else
-    return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none);
+    return cxx_alignof_expr (loc, e, complain? tf_warning_or_error : tf_none);
 }
 
 /*  Build a representation of an expression 'alignas(E).'  Return the
@@ -1906,7 +1914,8 @@  cxx_alignas_expr (tree e)
 	   alignas(type-id ), it shall have the same effect as
 	   alignas(alignof(type-id )).  */
 
-    return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, true, false);
+    return cxx_sizeof_or_alignof_type (input_location,
+				       e, ALIGNOF_EXPR, true, false);
   
   /* If we reach this point, it means the alignas expression if of
      the form "alignas(assignment-expression)", so we should follow
Index: gcc/testsuite/g++.dg/cpp0x/alignof3.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/alignof3.C	(revision 279371)
+++ gcc/testsuite/g++.dg/cpp0x/alignof3.C	(working copy)
@@ -2,5 +2,5 @@ 
 // { dg-options "-pedantic" }
 int main(void)
 {
-  alignof(void (void));   // { dg-warning "function type" }
+  alignof(void (void));   // { dg-warning "3:ISO C\\+\\+ does not permit .alignof. applied to a function type" }
 }
Index: gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C	(revision 279371)
+++ gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C	(working copy)
@@ -15,5 +15,5 @@  void f()
 
   long &r = x;			// { dg-error "bit" }
   &x;				// { dg-error "bit" }
-  sizeof(x);			// { dg-error "bit" }
+  sizeof(x);			// { dg-error "10:invalid application of .sizeof. to a bit-field" }
 }
Index: gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C
===================================================================
--- gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(revision 279371)
+++ gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(working copy)
@@ -1,6 +1,6 @@ 
 struct S;
-struct T { S t; };					// { dg-error "incomplete type" }
-struct U { int u[sizeof (S)]; };			// { dg-error "incomplete type" }
+struct T { S t; };					// { dg-error "14:field .t. has incomplete type" }
+struct U { int u[sizeof (S)]; };			// { dg-error "18:invalid application of .sizeof. to incomplete type" }
 union V { char c; char d[]; };				// { dg-error "24:flexible array member in union" }
 bool a = __has_unique_object_representations (S);	// { dg-error "incomplete type" }
 bool b = __has_unique_object_representations (T);
Index: gcc/testsuite/g++.dg/diagnostic/alignof2.C
===================================================================
--- gcc/testsuite/g++.dg/diagnostic/alignof2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/diagnostic/alignof2.C	(working copy)
@@ -0,0 +1,2 @@ 
+void f();
+int i = __alignof(f); // { dg-error "19:ISO C\\+\\+ forbids applying .__alignof." }
Index: gcc/testsuite/g++.dg/diagnostic/alignof3.C
===================================================================
--- gcc/testsuite/g++.dg/diagnostic/alignof3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/diagnostic/alignof3.C	(working copy)
@@ -0,0 +1,5 @@ 
+struct A { long i: 2; };
+void f()
+{
+  __alignof(A::i); // { dg-error "16:invalid application of .__alignof. to a bit-field" }
+}
Index: gcc/testsuite/g++.dg/diagnostic/incomplete-type-1.C
===================================================================
--- gcc/testsuite/g++.dg/diagnostic/incomplete-type-1.C	(nonexistent)
+++ gcc/testsuite/g++.dg/diagnostic/incomplete-type-1.C	(working copy)
@@ -0,0 +1,2 @@ 
+template<typename> struct A; // { dg-message "27:declaration" }
+template<typename T> A<T>::A(); // { dg-error "22:invalid use of incomplete type" }
Index: gcc/testsuite/g++.dg/expr/sizeof3.C
===================================================================
--- gcc/testsuite/g++.dg/expr/sizeof3.C	(revision 279371)
+++ gcc/testsuite/g++.dg/expr/sizeof3.C	(working copy)
@@ -1,4 +1,4 @@ 
 // PR c++/15337
 
 class CCC; 
-int main() { sizeof(CCC); return 0; } // { dg-error ".*CCC.*" }
+int main() { sizeof(CCC); return 0; } // { dg-error "14:invalid application of .sizeof. to incomplete type .CCC." }
Index: gcc/testsuite/g++.dg/ext/flexary6.C
===================================================================
--- gcc/testsuite/g++.dg/ext/flexary6.C	(revision 279371)
+++ gcc/testsuite/g++.dg/ext/flexary6.C	(working copy)
@@ -9,7 +9,7 @@  struct A {
   int n;
   int a[];
   enum {
-    e = sizeof a   // { dg-error "invalid application of .sizeof. to incomplete type" }
+    e = sizeof a   // { dg-error "9:invalid application of .sizeof. to incomplete type" }
   };
 };
 
@@ -18,6 +18,6 @@  struct B {
   typedef int A[];
   A a;
   enum {
-    e = sizeof a   // { dg-error "invalid application of .sizeof. to incomplete type" }
+    e = sizeof a   // { dg-error "9:invalid application of .sizeof. to incomplete type" }
   };
 };
Index: gcc/testsuite/g++.dg/ext/vla4.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vla4.C	(revision 279371)
+++ gcc/testsuite/g++.dg/ext/vla4.C	(working copy)
@@ -6,7 +6,7 @@ 
 void f(int i) {
   try {
     int a[i];
-    throw &a; // { dg-error "int \\(\\*\\)\\\[i\\\]" }
+    throw &a; // { dg-error "11:cannot throw expression of type .int \\(\\*\\)\\\[i\\\]." }
   } catch (int (*)[i]) { // { dg-error "variable size" }
   }
 }
Index: gcc/testsuite/g++.dg/template/sizeof11.C
===================================================================
--- gcc/testsuite/g++.dg/template/sizeof11.C	(revision 279371)
+++ gcc/testsuite/g++.dg/template/sizeof11.C	(working copy)
@@ -9,6 +9,6 @@  template < int> void g()
 template < class T > struct B;
 template < int> void f()
 {
-  sizeof (B<int>); // { dg-error "incomplete" }
+  sizeof (B<int>); // { dg-error "3:invalid application of .sizeof. to incomplete type" }
 }
 
Index: gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcatch-value-1.C	(revision 279371)
+++ gcc/testsuite/g++.dg/warn/Wcatch-value-1.C	(working copy)
@@ -10,8 +10,8 @@  void foo()
   try {}
   catch (D)    {}
   catch (C)    {}
-  catch (B)    {}  // { dg-warning "catching polymorphic type" }
-  catch (A)    {}  // { dg-warning "catching polymorphic type" }
+  catch (B)    {}  // { dg-warning "10:catching polymorphic type" }
+  catch (A)    {}  // { dg-warning "10:catching polymorphic type" }
   catch (A*)   {}
   catch (int)  {}
 
@@ -27,7 +27,7 @@  void foo()
 template<typename T> void foo1()
 {
   try {}
-  catch (T) {}  // { dg-warning "catching polymorphic type" }
+  catch (T) {}  // { dg-warning "10:catching polymorphic type" }
 }
 
 template<typename T> void foo2()
Index: gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcatch-value-2.C	(revision 279371)
+++ gcc/testsuite/g++.dg/warn/Wcatch-value-2.C	(working copy)
@@ -8,10 +8,10 @@  struct D : C {};
 void foo()
 {
   try {}
-  catch (D)    {}  // { dg-warning "catching type" }
-  catch (C)    {}  // { dg-warning "catching type" }
-  catch (B)    {}  // { dg-warning "catching polymorphic type" }
-  catch (A)    {}  // { dg-warning "catching polymorphic type" }
+  catch (D)    {}  // { dg-warning "10:catching type" }
+  catch (C)    {}  // { dg-warning "10:catching type" }
+  catch (B)    {}  // { dg-warning "10:catching polymorphic type" }
+  catch (A)    {}  // { dg-warning "10:catching polymorphic type" }
   catch (A*)   {}
   catch (int)  {}
 
@@ -27,7 +27,7 @@  void foo()
 template<typename T> void foo1()
 {
   try {}
-  catch (T) {}  // { dg-warning "catching" }
+  catch (T) {}  // { dg-warning "10:catching" }
 }
 
 template<typename T> void foo2()
Index: gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcatch-value-3.C	(revision 279371)
+++ gcc/testsuite/g++.dg/warn/Wcatch-value-3.C	(working copy)
@@ -8,12 +8,12 @@  struct D : C {};
 void foo()
 {
   try {}
-  catch (D)    {}  // { dg-warning "catching type" }
-  catch (C)    {}  // { dg-warning "catching type" }
-  catch (B)    {}  // { dg-warning "catching polymorphic type" }
-  catch (A)    {}  // { dg-warning "catching polymorphic type" }
+  catch (D)    {}  // { dg-warning "10:catching type" }
+  catch (C)    {}  // { dg-warning "10:catching type" }
+  catch (B)    {}  // { dg-warning "10:catching polymorphic type" }
+  catch (A)    {}  // { dg-warning "10:catching polymorphic type" }
   catch (A*)   {}  // { dg-warning "catching non-reference type" }
-  catch (int)  {}  // { dg-warning "catching non-reference type" }
+  catch (int)  {}  // { dg-warning "10:catching non-reference type" }
 
   try {}
   catch (D&)   {}
@@ -27,7 +27,7 @@  void foo()
 template<typename T> void foo1()
 {
   try {}
-  catch (T) {}  // { dg-warning "catching" }
+  catch (T) {}  // { dg-warning "10:catching" }
 }
 
 template<typename T> void foo2()
Index: gcc/testsuite/g++.dg/warn/Wcatch-value-3b.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcatch-value-3b.C	(nonexistent)
+++ gcc/testsuite/g++.dg/warn/Wcatch-value-3b.C	(working copy)
@@ -0,0 +1,64 @@ 
+// { dg-options "-Wcatch-value=3" }
+
+struct A { virtual ~A() {} };
+struct B : A {};
+struct C {};
+struct D : C {};
+
+void foo()
+{
+  try {}
+  catch (D d)    {}  // { dg-warning "12:catching type" }
+  catch (C c)    {}  // { dg-warning "12:catching type" }
+  catch (B b)    {}  // { dg-warning "12:catching polymorphic type" }
+  catch (A a)    {}  // { dg-warning "12:catching polymorphic type" }
+  catch (A* a)   {}  // { dg-warning "13:catching non-reference type" }
+  catch (int i)  {}  // { dg-warning "14:catching non-reference type" }
+
+  try {}
+  catch (D& d)   {}
+  catch (C& c)   {}
+  catch (B& b)   {}
+  catch (A& a)   {}
+  catch (A* a)   {}  // { dg-warning "13:catching non-reference type" }
+  catch (int& i) {}
+}
+
+template<typename T> void foo1()
+{
+  try {}
+  catch (T t) {}  // { dg-warning "12:catching" }
+}
+
+template<typename T> void foo2()
+{
+  try {}
+  catch (T* t) {}  // { dg-warning "13:catching non-reference type" }
+
+  try {}
+  catch (T&) {}
+
+  try {}
+  catch (const T&) {}
+}
+
+void bar()
+{
+  foo1<int&>();
+  foo1<const A&>();
+  foo1<B&>();
+  foo1<const C&>();
+  foo1<D&>();
+
+  foo1<int>();  // { dg-message "required" }
+  foo1<A>();    // { dg-message "required" }
+  foo1<B>();    // { dg-message "required" }
+  foo1<C>();    // { dg-message "required" }
+  foo1<D>();    // { dg-message "required" }
+
+  foo2<int>();  // { dg-message "required" }
+  foo2<A>();    // { dg-message "required" }
+  foo2<B>();    // { dg-message "required" }
+  foo2<C>();    // { dg-message "required" }
+  foo2<D>();    // { dg-message "required" }
+}
Index: gcc/testsuite/g++.old-deja/g++.brendan/sizeof1.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.brendan/sizeof1.C	(revision 279371)
+++ gcc/testsuite/g++.old-deja/g++.brendan/sizeof1.C	(working copy)
@@ -9,7 +9,7 @@  int
 main()
 {
   // sizeof may not be applied to a function
-  int i = sizeof( f);// { dg-error "" } .*
+  int i = sizeof( f);// { dg-error "19:ISO C\\+\\+ forbids applying .sizeof." } .*
 
   return 0;
 }
Index: gcc/testsuite/g++.old-deja/g++.brendan/sizeof3.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.brendan/sizeof3.C	(revision 279371)
+++ gcc/testsuite/g++.old-deja/g++.brendan/sizeof3.C	(working copy)
@@ -9,7 +9,7 @@  int
 main()
 {
   // sizeof may not be applied to an undefined class
-  int k = sizeof (bar);// { dg-error "" } .*
+  int k = sizeof (bar);// { dg-error "11:invalid application of .sizeof. to incomplete type" } .*
 
   return 0;
 }
Index: gcc/testsuite/g++.old-deja/g++.brendan/sizeof4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.brendan/sizeof4.C	(revision 279371)
+++ gcc/testsuite/g++.old-deja/g++.brendan/sizeof4.C	(working copy)
@@ -7,7 +7,7 @@  int
 main()
 {
   // sizeof may not be applied to the type void
-  int l = sizeof (void);// { dg-error "" } .*
+  int l = sizeof (void);// { dg-error "11:invalid application of .sizeof. to a void type" } .*
 
   return 0;
 }
Index: gcc/testsuite/g++.old-deja/g++.eh/ctor1.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.eh/ctor1.C	(revision 279371)
+++ gcc/testsuite/g++.old-deja/g++.eh/ctor1.C	(working copy)
@@ -11,7 +11,7 @@  main ()
   try
     {
       throw A();		// { dg-error "rvalue" "" { target c++14_down } } can't copy
-      // { dg-error "thrown expression" "expr" { target c++14_down } .-1 }
+      // { dg-message "13:thrown expression" "expr" { target c++14_down } .-1 }
     }
   catch (...) { }
 }
Index: gcc/testsuite/g++.old-deja/g++.jason/ambig1.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.jason/ambig1.C	(revision 279371)
+++ gcc/testsuite/g++.old-deja/g++.jason/ambig1.C	(working copy)
@@ -3,5 +3,5 @@ 
 // Testcase for ambiguity between functional cast and abstract declarator.
 // This ambiguity accounts for 6 of the r/r conflicts.
 
-int i = sizeof (int ());	// { dg-error "" } sizeof applied to fn type
+int i = sizeof (int ());	// { dg-error "9:invalid application of .sizeof. to a function type" } sizeof applied to fn type
 int j = sizeof (int () + 1);
Index: gcc/testsuite/g++.old-deja/g++.other/sizeof4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.other/sizeof4.C	(revision 279442)
+++ gcc/testsuite/g++.old-deja/g++.other/sizeof4.C	(working copy)
@@ -17,21 +17,21 @@  void fn () {}
 
 int main (int argc, char **argv)
 {
-  sizeof (s);           // { dg-error "" } incomplete
-  sizeof (0, s);        // { dg-error "" } incomplete
-  sizeof (argc ? s : s); // { dg-error "" } incomplete
+  sizeof (s);           // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (0, s);        // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (argc ? s : s); // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
 
-  sizeof (arys);        // { dg-error "" } incomplete
-  sizeof (0, arys);     // { dg-error "" } incomplete
-  sizeof (argc ? arys : arys); // { dg-error "" } incomplete
+  sizeof (arys);        // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (0, arys);     // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (argc ? arys : arys); // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
 
-  sizeof (aryt);        // { dg-error "" } incomplete
-  sizeof (0, aryt);     // { dg-error "" } incomplete
-  sizeof (argc ? aryt : aryt); // { dg-error "" } incomplete
+  sizeof (aryt);        // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (0, aryt);     // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
+  sizeof (argc ? aryt : aryt); // { dg-error "3:invalid application of .sizeof. to incomplete type" } incomplete
   
-  sizeof (fn);            // { dg-error "" } cannot take size of function
-  sizeof (0, fn);         // { dg-error "" } cannot take size of function
-  sizeof (argc ? fn : fn); // { dg-error "" } cannot take size of function
+  sizeof (fn);            // { dg-error "11:ISO C\\+\\+ forbids applying .sizeof." } cannot take size of function
+  sizeof (0, fn);         // { dg-error "3:invalid application of .sizeof. to a function type" } cannot take size of function
+  sizeof (argc ? fn : fn); // { dg-error "3:invalid application of .sizeof. to a function type" } cannot take size of function
   
   sizeof (&fn);       // ok
   sizeof (0, &fn);    // ok
Index: libcc1/libcp1plugin.cc
===================================================================
--- libcc1/libcp1plugin.cc	(revision 279371)
+++ libcc1/libcp1plugin.cc	(working copy)
@@ -2797,7 +2797,7 @@  plugin_build_unary_expr (cc1_plugin::connection *s
       break;
 
     case THROW_EXPR:
-      result = build_throw (op0);
+      result = build_throw (input_location, op0);
       break;
 
     case TYPEID_EXPR:
@@ -2806,7 +2806,8 @@  plugin_build_unary_expr (cc1_plugin::connection *s
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
-      result = cxx_sizeof_or_alignof_expr (op0, opcode, true);
+      result = cxx_sizeof_or_alignof_expr (input_location,
+					   op0, opcode, true);
       break;
 
     case DELETE_EXPR:
@@ -3048,7 +3049,8 @@  plugin_build_unary_type_expr (cc1_plugin::connecti
 
     default:
       /* Use the C++11 alignof semantics.  */
-      result = cxx_sizeof_or_alignof_type (type, opcode, true, true);
+      result = cxx_sizeof_or_alignof_type (input_location, type,
+					   opcode, true, true);
     }
 
   if (template_dependent_p)