[C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)

Jakub Jelinek jakub@redhat.com
Tue Oct 2 12:57:00 GMT 2012


On Tue, Sep 25, 2012 at 05:36:40PM +0200, Jakub Jelinek wrote:
> Here is the current patch.  One issue already mentioned on IRC is
> that generic code like contains_placeholder_p, save_expr etc.
> got confused by SIZEOF_EXPR having type as argument instead of expression.
> So for !processing_template_decl this patch uses instead NOP_EXPR with
> error_mark_node operand and type on the NOP_EXPR, plus SIZEOF_EXPR_TYPE_P
> bit set on the SIZEOF_EXPR (we need location on the sizeof expression, so
> it should be expression).  The patch solves that thing.
> 
> The remaining unsolved issues are two regressions, one is error
> FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++98 (test for excess errors)
> FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++11 (test for excess errors)
> on the
>   int* r = sizeof(char) / 2;
> line.  Is that even valid C++11?  C++03?  The thing is that we previously
> immediately folded sizeof(char) to 1, and 1/2 into 0 and considered that as
> null_ptr_cst_p.  With the patch we don't fold it anymore right away, we

This patch uses maybe_constant_value for C++98/03, and makes the above an
error for C++11 (where the standard says that only literal 0 is null pointer
constant?).

> The other issue is Obj-C++ ICE, in cp_build_binary_op I've added
...
> No idea what to do about that unfortunately, we don't have any handy macro
> to tell us the ObjC tree code range, we'd need to enumerate the Obj-C++ tree
> codes which we don't want to ICE on (and just set *non_constant_p on them
> instead).  We have objc_is_property_ref predicate, but not sure about the
> other ObjC trees.

And this is solved by saying objc_is_property_ref is not a
potential_constant_expression and removing the early return for C++98/03.

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

2012-10-02  Jakub Jelinek  <jakub@redhat.com>

cp/
	* cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
	* tree.c (cp_tree_equal): Handle SIZEOF_EXPR with
	SIZEOF_EXPR_TYPE_P.
	* mangle.c (write_expression): Likewise.
	* cxx-pretty-print.c (pp_cxx_unary_expression): Likewise.
	* error.c (dump_expr): Likewise.
	* parser.c (cp_parser_unary_expression): For sizeof call
	cxx_sizeof_or_alignof_{type,expr} just for diagnostics and
	return SIZEOF_EXPR with the operand.
	* pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR,
	call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but
	return SIZEOF_EXPR with tsubsted operand.
	(value_dependent_expression_p): Handle SIZEOF_EXPR with
	SIZEOF_EXPR_TYPE_P.
	(instantiation_dependent_r): Likewise.
	* call.c (null_ptr_cst_p): Call maybe_constant_value for C++98.
	* semantics.c (finish_call_expr): Call
	sizeof_pointer_memaccess_warning if needed.
	(cxx_eval_constant_expression): Handle SIZEOF_EXPR.
	(potential_constant_expression_1): Remove early exit for
	C++98.  Handle PROPERTY_REF.
	* decl.c (duplicate_decls): When redeclaring a builtin function,
	keep the merged decl builtin also if newdecl is a gnu_inline
	inline definition.
	(fold_sizeof_expr_r): New function.
	(compute_array_index_type): Fold SIZEOF_EXPRs in itype.
	* cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR.
	* typeck.c (cp_build_binary_op): For warn_for_sign_compare
	try harder using maybe_constant_value to get INTEGER_CSTs.

	* decl.c (stabilize_vla_size): Call pointer_set_destroy
	at the end.
testsuite/
	* g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test.
	* g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test.
	* g++.dg/warn/Wsign-compare-5.C: New test.
	* g++.dg/warn/Wsizeof-pointer-memaccess-1.C: New test.
	* g++.dg/warn/Wnull-conversion-1.C: For c++11 add dg-error.
	* g++.dg/ext/builtin30.C: New test.
	* g++.dg/ext/vla12.C: New test.
	* gcc.dg/builtins-85.c: New test.
libstdc++-v3/
	* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line
	numbers.

--- gcc/cp/cp-tree.h.jj	2012-10-01 10:08:40.447237104 +0200
+++ gcc/cp/cp-tree.h	2012-10-01 17:38:18.506576783 +0200
@@ -79,6 +79,7 @@ c-common.h, not after.
       OVL_ARG_DEPENDENT (in OVERLOAD)
       PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
       TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO)
+      SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -4044,6 +4045,10 @@ more_aggr_init_expr_args_p (const aggr_i
 #define CONVERT_EXPR_VBASE_PATH(NODE) \
   TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE))
 
+/* True if SIZEOF_EXPR argument is type.  */
+#define SIZEOF_EXPR_TYPE_P(NODE) \
+  TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE))
+
 /* An enumeration of the kind of tags that C++ accepts.  */
 enum tag_types {
   none_type = 0, /* Not a tag type.  */
--- gcc/cp/cp-gimplify.c.jj	2012-09-27 12:45:49.060392494 +0200
+++ gcc/cp/cp-gimplify.c	2012-10-01 17:38:18.507576775 +0200
@@ -1119,6 +1119,22 @@ cp_genericize_r (tree *stmt_p, int *walk
     genericize_break_stmt (stmt_p);
   else if (TREE_CODE (stmt) == OMP_FOR)
     genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
+  else if (TREE_CODE (stmt) == SIZEOF_EXPR)
+    {
+      if (SIZEOF_EXPR_TYPE_P (stmt))
+	*stmt_p
+	  = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
+					SIZEOF_EXPR, false);
+      else if (TYPE_P (TREE_OPERAND (stmt, 0)))
+	*stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
+					      SIZEOF_EXPR, false);
+      else
+	*stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
+					      SIZEOF_EXPR, false);
+      if (*stmt_p == error_mark_node)
+	*stmt_p = size_one_node;
+      return NULL;
+    }    
 
   pointer_set_insert (p_set, *stmt_p);
 
--- gcc/cp/call.c.jj	2012-09-27 12:45:49.000000000 +0200
+++ gcc/cp/call.c	2012-10-01 17:53:17.594609236 +0200
@@ -557,7 +557,10 @@ null_ptr_cst_p (tree t)
     {
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
       if (cxx_dialect < cxx0x)
-	t = integral_constant_value (t);
+	{
+	  t = integral_constant_value (t);
+	  t = maybe_constant_value (t);
+	}
       STRIP_NOPS (t);
       if (integer_zerop (t) && !TREE_OVERFLOW (t))
 	return true;
--- gcc/cp/semantics.c.jj	2012-09-27 12:45:49.296391214 +0200
+++ gcc/cp/semantics.c	2012-10-01 17:50:27.088550744 +0200
@@ -2170,8 +2170,25 @@ finish_call_expr (tree fn, VEC(tree,gc)
 	result = resolve_overloaded_builtin (input_location, fn, *args);
 
       if (!result)
-	/* A call to a namespace-scope function.  */
-	result = build_new_function_call (fn, args, koenig_p, complain);
+	{
+	  if (warn_sizeof_pointer_memaccess
+	      && !VEC_empty(tree, *args)
+	      && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR
+	      && !processing_template_decl)
+	    {
+	      tree sizeof_arg = VEC_last(tree, *args);
+	      if (SIZEOF_EXPR_TYPE_P (sizeof_arg))
+		sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0));
+	      else
+		sizeof_arg = TREE_OPERAND (sizeof_arg, 0);
+	      sizeof_pointer_memaccess_warning
+		(EXPR_LOCATION (VEC_last(tree, *args)), fn, *args,
+		 sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
+	    }
+
+	  /* A call to a namespace-scope function.  */
+	  result = build_new_function_call (fn, args, koenig_p, complain);
+	}
     }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
@@ -7723,6 +7740,21 @@ cxx_eval_constant_expression (const cons
 				     non_constant_p);
       break;
 
+    case SIZEOF_EXPR:
+      if (SIZEOF_EXPR_TYPE_P (t))
+	r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+					SIZEOF_EXPR, false);
+      else if (TYPE_P (TREE_OPERAND (t, 0)))
+	r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+					false);
+      else
+	r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+					false);
+      if (r == error_mark_node)
+	r = size_one_node;
+      VERIFY_CONSTANT (r);
+      break;
+
     case COMPOUND_EXPR:
       {
 	/* check_return_expr sometimes wraps a TARGET_EXPR in a
@@ -8106,12 +8138,6 @@ potential_constant_expression_1 (tree t,
   int i;
   tree tmp;
 
-  /* C++98 has different rules for the form of a constant expression that
-     are enforced in the parser, so we can assume that anything that gets
-     this far is suitable.  */
-  if (cxx_dialect < cxx0x)
-    return true;
-
   if (t == error_mark_node)
     return false;
   if (t == NULL_TREE)
@@ -8632,6 +8658,9 @@ potential_constant_expression_1 (tree t,
       return false;
 
     default:
+      if (objc_is_property_ref (t))
+	return false;
+
       sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
       gcc_unreachable();
       return false;
--- gcc/cp/tree.c.jj	2012-09-27 12:45:49.083392369 +0200
+++ gcc/cp/tree.c	2012-10-01 17:38:18.512576744 +0200
@@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2)
 	tree o1 = TREE_OPERAND (t1, 0);
 	tree o2 = TREE_OPERAND (t2, 0);
 
+	if (SIZEOF_EXPR_TYPE_P (t1))
+	  o1 = TREE_TYPE (o1);
+	if (SIZEOF_EXPR_TYPE_P (t2))
+	  o2 = TREE_TYPE (o2);
 	if (TREE_CODE (o1) != TREE_CODE (o2))
 	  return false;
 	if (TYPE_P (o1))
--- gcc/cp/mangle.c.jj	2012-09-27 12:45:49.111392217 +0200
+++ gcc/cp/mangle.c	2012-10-01 17:38:18.513576740 +0200
@@ -2581,6 +2581,12 @@ write_expression (tree expr)
       write_char ('E');
     }
   else if (TREE_CODE (expr) == SIZEOF_EXPR
+	   && SIZEOF_EXPR_TYPE_P (expr))
+    {
+      write_string ("st");
+      write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
+    }
+  else if (TREE_CODE (expr) == SIZEOF_EXPR
 	   && TYPE_P (TREE_OPERAND (expr, 0)))
     {
       write_string ("st");
--- gcc/cp/decl.c.jj	2012-10-01 10:08:40.429237206 +0200
+++ gcc/cp/decl.c	2012-10-01 17:38:18.516576724 +0200
@@ -2160,39 +2160,40 @@ duplicate_decls (tree newdecl, tree oldd
 	  DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
 	  DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
 	}
+      /* If redeclaring a builtin function, it stays built in
+	 if newdecl is a gnu_inline definition, or if newdecl is just
+	 a declaration.  */
+      if (DECL_BUILT_IN (olddecl)
+	  && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
+	{
+	  DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+	  DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+	  /* If we're keeping the built-in definition, keep the rtl,
+	     regardless of declaration matches.  */
+	  COPY_DECL_RTL (olddecl, newdecl);
+	  if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+	    {
+	      enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+	      switch (fncode)
+		{
+		  /* If a compatible prototype of these builtin functions
+		     is seen, assume the runtime implements it with the
+		     expected semantics.  */
+		case BUILT_IN_STPCPY:
+		  if (builtin_decl_explicit_p (fncode))
+		    set_builtin_decl_implicit_p (fncode, true);
+		  break;
+		default:
+		  break;
+		}
+	    }
+	}
       if (new_defines_function)
 	/* If defining a function declared with other language
 	   linkage, use the previously declared language linkage.  */
 	SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
       else if (types_match)
 	{
-	  /* If redeclaring a builtin function, and not a definition,
-	     it stays built in.  */
-	  if (DECL_BUILT_IN (olddecl))
-	    {
-	      DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
-	      DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
-	      /* If we're keeping the built-in definition, keep the rtl,
-		 regardless of declaration matches.  */
-	      COPY_DECL_RTL (olddecl, newdecl);
-	      if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-		{
-		  enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
-		  switch (fncode)
-		    {
-		      /* If a compatible prototype of these builtin functions
-			 is seen, assume the runtime implements it with the
-			 expected semantics.  */
-		    case BUILT_IN_STPCPY:
-		      if (builtin_decl_explicit_p (fncode))
-			set_builtin_decl_implicit_p (fncode, true);
-		      break;
-		    default:
-		      break;
-		    }
-		}
-	    }
-
 	  DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
 	  /* Don't clear out the arguments if we're just redeclaring a
 	     function.  */
@@ -7928,6 +7929,36 @@ stabilize_vla_size (tree size)
   struct pointer_set_t *pset = pointer_set_create ();
   /* Break out any function calls into temporary variables.  */
   cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
+  pointer_set_destroy (pset);
+}
+
+/* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
+   not inside of SAVE_EXPR and fold them.  */
+
+static tree
+fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
+{
+  tree expr = *expr_p;
+  if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
+    *walk_subtrees = 0;
+  else if (TREE_CODE (expr) == SIZEOF_EXPR)
+    {
+      *(bool *)data = true;
+      if (SIZEOF_EXPR_TYPE_P (expr))
+	expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
+					   SIZEOF_EXPR, false);
+      else if (TYPE_P (TREE_OPERAND (expr, 0)))
+	expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+					   false);
+      else
+        expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+					   false);
+      if (expr == error_mark_node)
+        expr = size_one_node;
+      *expr_p = expr;
+      *walk_subtrees = 0;
+    }
+  return NULL;
 }
 
 /* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8123,8 +8154,21 @@ compute_array_index_type (tree name, tre
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
-	/* A variable sized array.  */
-	itype = variable_size (itype);
+	{
+	  /* A variable sized array.  */
+	  itype = variable_size (itype);
+	  if (TREE_CODE (itype) != SAVE_EXPR)
+	    {
+	      /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
+		 they might survive till gimplification.  */
+	      tree newitype = itype;
+	      bool found = false;
+	      cp_walk_tree_without_duplicates (&newitype,
+					       fold_sizeof_expr_r, &found);
+	      if (found)
+		itype = variable_size (fold (newitype));
+	    }
+	}
       /* Make sure that there was no overflow when creating to a signed
 	 index type.  (For example, on a 32-bit machine, an array with
 	 size 2^32 - 1 is too big.)  */
--- gcc/cp/cxx-pretty-print.c.jj	2012-09-27 12:45:49.118392179 +0200
+++ gcc/cp/cxx-pretty-print.c	2012-10-01 17:38:18.518576711 +0200
@@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_prin
     case ALIGNOF_EXPR:
       pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
       pp_cxx_whitespace (pp);
-      if (TYPE_P (TREE_OPERAND (t, 0)))
+      if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+	{
+	  pp_cxx_left_paren (pp);
+	  pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0)));
+	  pp_cxx_right_paren (pp);
+	}
+      else if (TYPE_P (TREE_OPERAND (t, 0)))
 	{
 	  pp_cxx_left_paren (pp);
 	  pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
--- gcc/cp/typeck.c.jj	2012-09-27 12:45:49.208391691 +0200
+++ gcc/cp/typeck.c	2012-10-01 17:38:18.519576704 +0200
@@ -4624,7 +4624,14 @@ cp_build_binary_op (location_t location,
 	  && !enum_cast_to_int (orig_op0)
 	  && !enum_cast_to_int (orig_op1))
 	{
-	  warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, 
+	  tree oop0 = maybe_constant_value (orig_op0);
+	  tree oop1 = maybe_constant_value (orig_op1);
+
+	  if (TREE_CODE (oop0) != INTEGER_CST)
+	    oop0 = orig_op0;
+	  if (TREE_CODE (oop1) != INTEGER_CST)
+	    oop1 = orig_op1;
+	  warn_for_sign_compare (location, oop0, oop1, op0, op1, 
 				 result_type, resultcode);
 	}
     }
--- gcc/cp/parser.c.jj	2012-10-01 10:08:40.447237104 +0200
+++ gcc/cp/parser.c	2012-10-01 17:38:18.524576680 +0200
@@ -6383,17 +6383,19 @@ cp_parser_unary_expression (cp_parser *p
 	case RID_ALIGNOF:
 	case RID_SIZEOF:
 	  {
-	    tree operand;
+	    tree operand, ret;
 	    enum tree_code op;
+	    location_t first_loc;
 
 	    op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
 	    /* Consume the token.  */
 	    cp_lexer_consume_token (parser->lexer);
+	    first_loc = cp_lexer_peek_token (parser->lexer)->location;
 	    /* Parse the operand.  */
 	    operand = cp_parser_sizeof_operand (parser, keyword);
 
 	    if (TYPE_P (operand))
-	      return cxx_sizeof_or_alignof_type (operand, op, true);
+	      ret = cxx_sizeof_or_alignof_type (operand, op, true);
 	    else
 	      {
 		/* ISO C++ defines alignof only with types, not with
@@ -6404,8 +6406,29 @@ cp_parser_unary_expression (cp_parser *p
 			   "ISO C++ does not allow %<alignof%> "
 			   "with a non-type");
 
-		return cxx_sizeof_or_alignof_expr (operand, op, true);
+		ret = cxx_sizeof_or_alignof_expr (operand, op, true);
 	      }
+	    /* For SIZEOF_EXPR, just issue diagnostics, but keep
+	       SIZEOF_EXPR with the original operand.  */
+	    if (op == SIZEOF_EXPR && ret != error_mark_node)
+	      {
+		if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand))
+		  {
+		    if (!processing_template_decl && TYPE_P (operand))
+		      {
+			ret = build_min (SIZEOF_EXPR, size_type_node,
+					 build1 (NOP_EXPR, operand,
+						 error_mark_node));
+			SIZEOF_EXPR_TYPE_P (ret) = 1;
+		      }
+		    else
+		      ret = build_min (SIZEOF_EXPR, size_type_node, operand);
+		    TREE_SIDE_EFFECTS (ret) = 0;
+		    TREE_READONLY (ret) = 1;
+		  }
+		SET_EXPR_LOCATION (ret, first_loc);
+	      }
+	    return ret;
 	  }
 
 	case RID_NEW:
--- gcc/cp/pt.c.jj	2012-10-01 10:08:40.445237116 +0200
+++ gcc/cp/pt.c	2012-10-01 17:38:18.529576651 +0200
@@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_f
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
         {
 
-          tree expanded;
+          tree expanded, op = TREE_OPERAND (t, 0);
 	  int len = 0;
 
+	  if (SIZEOF_EXPR_TYPE_P (t))
+	    op = TREE_TYPE (op);
+
 	  ++cp_unevaluated_operand;
 	  ++c_inhibit_evaluation_warnings;
 	  /* We only want to compute the number of arguments.  */
-	  expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
-					    complain, in_decl);
+	  expanded = tsubst_pack_expansion (op, args, complain, in_decl);
 	  --cp_unevaluated_operand;
 	  --c_inhibit_evaluation_warnings;
 
@@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_f
 	  else
 	    return build_int_cst (size_type_node, len);
         }
+      if (SIZEOF_EXPR_TYPE_P (t))
+	{
+	  r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)),
+			   args, complain, in_decl);
+	  r = build1 (NOP_EXPR, r, error_mark_node);
+	  r = build1 (SIZEOF_EXPR,
+		      tsubst (TREE_TYPE (t), args, complain, in_decl), r);
+	  SIZEOF_EXPR_TYPE_P (r) = 1;
+	  return r;
+	}
       /* Fall through */
 
     case INDIRECT_REF:
@@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t,
       /* Fall through */
       
     case ALIGNOF_EXPR:
-      op1 = TREE_OPERAND (t, 0);
-      if (!args)
-	{
-	  /* When there are no ARGS, we are trying to evaluate a
-	     non-dependent expression from the parser.  Trying to do
-	     the substitutions may not work.  */
-	  if (!TYPE_P (op1))
-	    op1 = TREE_TYPE (op1);
-	}
-      else
-	{
-	  ++cp_unevaluated_operand;
-	  ++c_inhibit_evaluation_warnings;
-	  op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
-				       /*function_p=*/false,
-				       /*integral_constant_expression_p=*/false);
-	  --cp_unevaluated_operand;
-	  --c_inhibit_evaluation_warnings;
-	}
-      if (TYPE_P (op1))
-	RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
-                                           complain & tf_error));
-      else
-	RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
-                                           complain & tf_error));
+      {
+	tree r;
+
+	op1 = TREE_OPERAND (t, 0);
+	if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+	  op1 = TREE_TYPE (op1);
+        if (!args)
+	  {
+	    /* When there are no ARGS, we are trying to evaluate a
+	       non-dependent expression from the parser.  Trying to do
+	       the substitutions may not work.  */
+	    if (!TYPE_P (op1))
+	      op1 = TREE_TYPE (op1);
+	  }
+	else
+	  {
+	    ++cp_unevaluated_operand;
+	    ++c_inhibit_evaluation_warnings;
+	    op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+					 /*function_p=*/false,
+					 /*integral_constant_expression_p=*/
+					 false);
+	    --cp_unevaluated_operand;
+	    --c_inhibit_evaluation_warnings;
+	  }
+        if (TYPE_P (op1))
+	  r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+					  complain & tf_error);
+	else
+	  r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+					  complain & tf_error);
+	if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
+	  {
+	    if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1))
+	      {
+		if (TYPE_P (op1))
+		  {
+		    r = build_min (SIZEOF_EXPR, size_type_node,
+				   build1 (NOP_EXPR, op1, error_mark_node));
+		    SIZEOF_EXPR_TYPE_P (r) = 1;
+		  }
+		else
+		  r = build_min (SIZEOF_EXPR, size_type_node, op1);
+		TREE_SIDE_EFFECTS (r) = 0;
+		TREE_READONLY (r) = 1;
+	      }
+	    SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+	  }
+	RETURN (r);
+      }
 
     case AT_ENCODE_EXPR:
       {
@@ -19288,6 +19325,9 @@ value_dependent_expression_p (tree expre
       }
 
     case SIZEOF_EXPR:
+      if (SIZEOF_EXPR_TYPE_P (expression))
+	return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+      /* FALLTHRU */
     case ALIGNOF_EXPR:
     case TYPEID_EXPR:
       /* A `sizeof' expression is value-dependent if the operand is
@@ -19627,6 +19667,8 @@ instantiation_dependent_r (tree *tp, int
     case TRAIT_EXPR:
       {
 	tree op = TREE_OPERAND (*tp, 0);
+	if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
+	  op = TREE_TYPE (op);
 	if (TYPE_P (op))
 	  {
 	    if (dependent_type_p (op)
--- gcc/cp/error.c.jj	2012-09-27 12:45:49.151391999 +0200
+++ gcc/cp/error.c	2012-10-01 17:38:18.532576635 +0200
@@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags)
 	}
       pp_cxx_whitespace (cxx_pp);
       pp_cxx_left_paren (cxx_pp);
-      if (TYPE_P (TREE_OPERAND (t, 0)))
+      if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+	dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags);
+      else if (TYPE_P (TREE_OPERAND (t, 0)))
 	dump_type (TREE_OPERAND (t, 0), flags);
       else
 	dump_expr (TREE_OPERAND (t, 0), flags);
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C.jj	2012-10-01 17:38:18.549576540 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C	2012-10-01 17:38:18.549576540 +0200
@@ -0,0 +1,716 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
+// { dg-skip-if "" { *-*-* }  { "*" } { "-O0" "-O2" } }
+// { dg-skip-if "" { *-*-* }  { "-flto" } { "" } }
+
+extern "C" {
+
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *, int, size_t);
+extern void *memcpy (void *__restrict, const void *__restrict, size_t);
+extern void *memmove (void *__restrict, const void *__restrict, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strncpy (char *__restrict, const char *__restrict, size_t);
+extern char *strncat (char *__restrict, const char *__restrict, size_t);
+extern char *strndup (const char *, size_t);
+extern int strncmp (const char *, const char *, size_t);
+extern int strncasecmp (const char *, const char *, size_t);
+
+#ifdef __OPTIMIZE__
+# define bos(ptr) __builtin_object_size (ptr, 1)
+# define bos0(ptr) __builtin_object_size (ptr, 0)
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memset (void *dest, int c, size_t len)
+{
+  return __builtin___memset_chk (dest, c, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memcpy (void *__restrict dest, const void *__restrict src, size_t len)
+{
+  return __builtin___memcpy_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memmove (void *dest, const void *src, size_t len)
+{
+  return __builtin___memmove_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncpy (char *__restrict dest, const char *__restrict src, size_t len)
+{
+  return __builtin___strncpy_chk (dest, src, len, bos (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncat (char *dest, const char *src, size_t len)
+{
+  return __builtin___strncat_chk (dest, src, len, bos (dest));
+}
+#endif
+
+}
+
+struct A { short a, b; int c, d; long e, f; };
+typedef struct A TA;
+typedef struct A *PA;
+typedef TA *PTA;
+struct B {};
+typedef struct B TB;
+typedef struct B *PB;
+typedef TB *PTB;
+typedef int X[3][3][3];
+
+template <int N>
+int
+f1 (void *x, int z)
+{
+  struct A a, *pa1 = &a;
+  TA *pa2 = &a;
+  PA pa3 = &a;
+  PTA pa4 = &a;
+  memset (&a, 0, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (pa1, 0, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa2, 0, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa3, 0, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa4, 0, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa1, 0, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa2, 0, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa3, 0, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (&a, x, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa2, x, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa4, x, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa1, x, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa2, x, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa3, x, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (x, &a, sizeof (&a));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa2, sizeof pa2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa4, sizeof pa4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa1, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa2, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa3, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (&a, x, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa2, x, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa4, x, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa1, x, sizeof (struct A *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa2, x, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa3, x, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (x, &a, sizeof (&a));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa2, sizeof pa2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa4, sizeof pa4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa1, sizeof (struct A *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa2, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa3, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (&a, x, sizeof (&a));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa2, x, sizeof pa2);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa4, x, sizeof pa4);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pa2, x, sizeof (PTA));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pa3, x, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (x, &a, sizeof (&a));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa2, sizeof pa2);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa4, sizeof pa4);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pa2, sizeof (PTA));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pa3, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  // These are correct, no warning. 
+  memset (&a, 0, sizeof a);
+  memset (&a, 0, sizeof (a));
+  memset (&a, 0, sizeof (struct A));
+  memset (&a, 0, sizeof (const struct A));
+  memset (&a, 0, sizeof (volatile struct A));
+  memset (&a, 0, sizeof (volatile const struct A));
+  memset (&a, 0, sizeof (TA));
+  memset (&a, 0, sizeof (__typeof (*&a)));
+  memset (pa1, 0, sizeof (*pa1));
+  memset (pa2, 0, sizeof (*pa3));
+  memset (pa3, 0, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) &a, 0, sizeof (&a));
+  memset ((char *) &a, 0, sizeof (&a));
+  memset (&a, 0, sizeof (&a) + 0);
+  memset (&a, 0, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memcpy (&a, x, sizeof a);
+  memcpy (&a, x, sizeof (a));
+  memcpy (&a, x, sizeof (struct A));
+  memcpy (&a, x, sizeof (const struct A));
+  memcpy (&a, x, sizeof (volatile struct A));
+  memcpy (&a, x, sizeof (volatile const struct A));
+  memcpy (&a, x, sizeof (TA));
+  memcpy (&a, x, sizeof (__typeof (*&a)));
+  memcpy (pa1, x, sizeof (*pa1));
+  memcpy (pa2, x, sizeof (*pa3));
+  memcpy (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) &a, x, sizeof (&a));
+  memcpy ((char *) &a, x, sizeof (&a));
+  memcpy (&a, x, sizeof (&a) + 0);
+  memcpy (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memcpy (x, &a, sizeof a);
+  memcpy (x, &a, sizeof (a));
+  memcpy (x, &a, sizeof (struct A));
+  memcpy (x, &a, sizeof (const struct A));
+  memcpy (x, &a, sizeof (volatile struct A));
+  memcpy (x, &a, sizeof (volatile const struct A));
+  memcpy (x, &a, sizeof (TA));
+  memcpy (x, &a, sizeof (__typeof (*&a)));
+  memcpy (x, pa1, sizeof (*pa1));
+  memcpy (x, pa2, sizeof (*pa3));
+  memcpy (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) &a, sizeof (&a));
+  memcpy (x, (char *) &a, sizeof (&a));
+  memcpy (x, &a, sizeof (&a) + 0);
+  memcpy (x, &a, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memmove (&a, x, sizeof a);
+  memmove (&a, x, sizeof (a));
+  memmove (&a, x, sizeof (struct A));
+  memmove (&a, x, sizeof (const struct A));
+  memmove (&a, x, sizeof (volatile struct A));
+  memmove (&a, x, sizeof (volatile const struct A));
+  memmove (&a, x, sizeof (TA));
+  memmove (&a, x, sizeof (__typeof (*&a)));
+  memmove (pa1, x, sizeof (*pa1));
+  memmove (pa2, x, sizeof (*pa3));
+  memmove (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) &a, x, sizeof (&a));
+  memmove ((char *) &a, x, sizeof (&a));
+  memmove (&a, x, sizeof (&a) + 0);
+  memmove (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memmove (x, &a, sizeof a);
+  memmove (x, &a, sizeof (a));
+  memmove (x, &a, sizeof (struct A));
+  memmove (x, &a, sizeof (const struct A));
+  memmove (x, &a, sizeof (volatile struct A));
+  memmove (x, &a, sizeof (volatile const struct A));
+  memmove (x, &a, sizeof (TA));
+  memmove (x, &a, sizeof (__typeof (*&a)));
+  memmove (x, pa1, sizeof (*pa1));
+  memmove (x, pa2, sizeof (*pa3));
+  memmove (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) &a, sizeof (&a));
+  memmove (x, (char *) &a, sizeof (&a));
+  memmove (x, &a, sizeof (&a) + 0);
+  memmove (x, &a, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  z += memcmp (&a, x, sizeof a);
+  z += memcmp (&a, x, sizeof (a));
+  z += memcmp (&a, x, sizeof (struct A));
+  z += memcmp (&a, x, sizeof (const struct A));
+  z += memcmp (&a, x, sizeof (volatile struct A));
+  z += memcmp (&a, x, sizeof (volatile const struct A));
+  z += memcmp (&a, x, sizeof (TA));
+  z += memcmp (&a, x, sizeof (__typeof (*&a)));
+  z += memcmp (pa1, x, sizeof (*pa1));
+  z += memcmp (pa2, x, sizeof (*pa3));
+  z += memcmp (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) &a, x, sizeof (&a));
+  z += memcmp ((char *) &a, x, sizeof (&a));
+  z += memcmp (&a, x, sizeof (&a) + 0);
+  z += memcmp (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  z += memcmp (x, &a, sizeof a);
+  z += memcmp (x, &a, sizeof (a));
+  z += memcmp (x, &a, sizeof (struct A));
+  z += memcmp (x, &a, sizeof (const struct A));
+  z += memcmp (x, &a, sizeof (volatile struct A));
+  z += memcmp (x, &a, sizeof (volatile const struct A));
+  z += memcmp (x, &a, sizeof (TA));
+  z += memcmp (x, &a, sizeof (__typeof (*&a)));
+  z += memcmp (x, pa1, sizeof (*pa1));
+  z += memcmp (x, pa2, sizeof (*pa3));
+  z += memcmp (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) &a, sizeof (&a));
+  z += memcmp (x, (char *) &a, sizeof (&a));
+  z += memcmp (x, &a, sizeof (&a) + 0);
+  z += memcmp (x, &a, 0 + sizeof (&a));
+
+  return z;
+}
+
+template <int N>
+int
+f2 (void *x, int z)
+{
+  struct B b, *pb1 = &b;
+  TB *pb2 = &b;
+  PB pb3 = &b;
+  PTB pb4 = &b;
+  memset (&b, 0, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (pb1, 0, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb2, 0, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb3, 0, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb4, 0, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb1, 0, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb2, 0, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb3, 0, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (&b, x, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb2, x, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb4, x, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb1, x, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb2, x, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb3, x, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (x, &b, sizeof (&b));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb2, sizeof pb2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb4, sizeof pb4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb1, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb2, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb3, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (&b, x, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb2, x, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb4, x, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb1, x, sizeof (struct B *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb2, x, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb3, x, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (x, &b, sizeof (&b));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb2, sizeof pb2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb4, sizeof pb4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb1, sizeof (struct B *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb2, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb3, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (&b, x, sizeof (&b));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb2, x, sizeof pb2);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb4, x, sizeof pb4);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pb2, x, sizeof (PTB));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pb3, x, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (x, &b, sizeof (&b));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb2, sizeof pb2);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb4, sizeof pb4);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pb2, sizeof (PTB));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pb3, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  // These are correct, no warning. 
+  memset (&b, 0, sizeof b);
+  memset (&b, 0, sizeof (b));
+  memset (&b, 0, sizeof (struct B));
+  memset (&b, 0, sizeof (const struct B));
+  memset (&b, 0, sizeof (volatile struct B));
+  memset (&b, 0, sizeof (volatile const struct B));
+  memset (&b, 0, sizeof (TB));
+  memset (&b, 0, sizeof (__typeof (*&b)));
+  memset (pb1, 0, sizeof (*pb1));
+  memset (pb2, 0, sizeof (*pb3));
+  memset (pb3, 0, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) &b, 0, sizeof (&b));
+  memset ((char *) &b, 0, sizeof (&b));
+  memset (&b, 0, sizeof (&b) + 0);
+  memset (&b, 0, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memcpy (&b, x, sizeof b);
+  memcpy (&b, x, sizeof (b));
+  memcpy (&b, x, sizeof (struct B));
+  memcpy (&b, x, sizeof (const struct B));
+  memcpy (&b, x, sizeof (volatile struct B));
+  memcpy (&b, x, sizeof (volatile const struct B));
+  memcpy (&b, x, sizeof (TB));
+  memcpy (&b, x, sizeof (__typeof (*&b)));
+  memcpy (pb1, x, sizeof (*pb1));
+  memcpy (pb2, x, sizeof (*pb3));
+  memcpy (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) &b, x, sizeof (&b));
+  memcpy ((char *) &b, x, sizeof (&b));
+  memcpy (&b, x, sizeof (&b) + 0);
+  memcpy (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memcpy (x, &b, sizeof b);
+  memcpy (x, &b, sizeof (b));
+  memcpy (x, &b, sizeof (struct B));
+  memcpy (x, &b, sizeof (const struct B));
+  memcpy (x, &b, sizeof (volatile struct B));
+  memcpy (x, &b, sizeof (volatile const struct B));
+  memcpy (x, &b, sizeof (TB));
+  memcpy (x, &b, sizeof (__typeof (*&b)));
+  memcpy (x, pb1, sizeof (*pb1));
+  memcpy (x, pb2, sizeof (*pb3));
+  memcpy (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) &b, sizeof (&b));
+  memcpy (x, (char *) &b, sizeof (&b));
+  memcpy (x, &b, sizeof (&b) + 0);
+  memcpy (x, &b, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memmove (&b, x, sizeof b);
+  memmove (&b, x, sizeof (b));
+  memmove (&b, x, sizeof (struct B));
+  memmove (&b, x, sizeof (const struct B));
+  memmove (&b, x, sizeof (volatile struct B));
+  memmove (&b, x, sizeof (volatile const struct B));
+  memmove (&b, x, sizeof (TB));
+  memmove (&b, x, sizeof (__typeof (*&b)));
+  memmove (pb1, x, sizeof (*pb1));
+  memmove (pb2, x, sizeof (*pb3));
+  memmove (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) &b, x, sizeof (&b));
+  memmove ((char *) &b, x, sizeof (&b));
+  memmove (&b, x, sizeof (&b) + 0);
+  memmove (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memmove (x, &b, sizeof b);
+  memmove (x, &b, sizeof (b));
+  memmove (x, &b, sizeof (struct B));
+  memmove (x, &b, sizeof (const struct B));
+  memmove (x, &b, sizeof (volatile struct B));
+  memmove (x, &b, sizeof (volatile const struct B));
+  memmove (x, &b, sizeof (TB));
+  memmove (x, &b, sizeof (__typeof (*&b)));
+  memmove (x, pb1, sizeof (*pb1));
+  memmove (x, pb2, sizeof (*pb3));
+  memmove (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) &b, sizeof (&b));
+  memmove (x, (char *) &b, sizeof (&b));
+  memmove (x, &b, sizeof (&b) + 0);
+  memmove (x, &b, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  z += memcmp (&b, x, sizeof b);
+  z += memcmp (&b, x, sizeof (b));
+  z += memcmp (&b, x, sizeof (struct B));
+  z += memcmp (&b, x, sizeof (const struct B));
+  z += memcmp (&b, x, sizeof (volatile struct B));
+  z += memcmp (&b, x, sizeof (volatile const struct B));
+  z += memcmp (&b, x, sizeof (TB));
+  z += memcmp (&b, x, sizeof (__typeof (*&b)));
+  z += memcmp (pb1, x, sizeof (*pb1));
+  z += memcmp (pb2, x, sizeof (*pb3));
+  z += memcmp (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) &b, x, sizeof (&b));
+  z += memcmp ((char *) &b, x, sizeof (&b));
+  z += memcmp (&b, x, sizeof (&b) + 0);
+  z += memcmp (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  z += memcmp (x, &b, sizeof b);
+  z += memcmp (x, &b, sizeof (b));
+  z += memcmp (x, &b, sizeof (struct B));
+  z += memcmp (x, &b, sizeof (const struct B));
+  z += memcmp (x, &b, sizeof (volatile struct B));
+  z += memcmp (x, &b, sizeof (volatile const struct B));
+  z += memcmp (x, &b, sizeof (TB));
+  z += memcmp (x, &b, sizeof (__typeof (*&b)));
+  z += memcmp (x, pb1, sizeof (*pb1));
+  z += memcmp (x, pb2, sizeof (*pb3));
+  z += memcmp (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) &b, sizeof (&b));
+  z += memcmp (x, (char *) &b, sizeof (&b));
+  z += memcmp (x, &b, sizeof (&b) + 0);
+  z += memcmp (x, &b, 0 + sizeof (&b));
+
+  return z;
+}
+
+template <int N>
+int
+f3 (void *x, char *y, int z, X w)
+{
+  unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16);
+  char buf1[7];
+  signed char buf2[z + 32];
+  long buf3[17];
+  int *buf4[9];
+  signed char *y2 = buf2;
+  char c;
+  char *y3;
+  memset (y, 0, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (y1, 0, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (y2, 0, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (&c, 0, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (w, 0, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memcpy (y, x, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (y1, x, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (y2, x, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (&c, x, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memcpy (x, y, sizeof (y));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, y1, sizeof (y1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, y2, sizeof (y2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, &c, sizeof (&c));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  memmove (y, x, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (y1, x, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (y2, x, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (&c, x, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memmove (x, y, sizeof (y));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, y1, sizeof (y1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, y2, sizeof (y2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, &c, sizeof (&c));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  z += memcmp (y, x, sizeof (y));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (y1, x, sizeof (y1));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (y2, x, sizeof (y2));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (&c, x, sizeof (&c));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  z += memcmp (x, y, sizeof (y));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, y1, sizeof (y1));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, y2, sizeof (y2));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, &c, sizeof (&c));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  // These are correct, no warning. 
+  memset (y, 0, sizeof (*y));
+  memset (y1, 0, sizeof (*y2));
+  memset (buf1, 0, sizeof buf1);
+  memset (buf3, 0, sizeof (buf3));
+  memset (&buf3[0], 0, sizeof (buf3));
+  memset (&buf4[0], 0, sizeof (buf4));
+  memset (w, 0, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) y, 0, sizeof (y));
+  memset ((char *) y1, 0, sizeof (y2));
+  memset (y, 0, sizeof (y) + 0);
+  memset (y1, 0, 0 + sizeof (y2));
+  memset ((void *) &c, 0, sizeof (&c));
+  memset ((signed char *) &c, 0, sizeof (&c));
+  memset (&c, 0, sizeof (&c) + 0);
+  memset (&c, 0, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memcpy (y, x, sizeof (*y));
+  memcpy (y1, x, sizeof (*y2));
+  memcpy (buf1, x, sizeof buf1);
+  memcpy (buf3, x, sizeof (buf3));
+  memcpy (&buf3[0], x, sizeof (buf3));
+  memcpy (&buf4[0], x, sizeof (buf4));
+  memcpy (&y3, y, sizeof (y3));
+  memcpy ((char *) &y3, y, sizeof (y3));
+  memcpy (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) y, x, sizeof (y));
+  memcpy ((char *) y1, x, sizeof (y2));
+  memcpy (y, x, sizeof (y) + 0);
+  memcpy (y1, x, 0 + sizeof (y2));
+  memcpy ((void *) &c, x, sizeof (&c));
+  memcpy ((signed char *) &c, x, sizeof (&c));
+  memcpy (&c, x, sizeof (&c) + 0);
+  memcpy (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memcpy (x, y, sizeof (*y));
+  memcpy (x, y1, sizeof (*y2));
+  memcpy (x, buf1, sizeof buf1);
+  memcpy (x, buf3, sizeof (buf3));
+  memcpy (x, &buf3[0], sizeof (buf3));
+  memcpy (x, &buf4[0], sizeof (buf4));
+  memcpy (y, &y3, sizeof (y3));
+  memcpy (y, (char *) &y3, sizeof (y3));
+  memcpy (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) y, sizeof (y));
+  memcpy (x, (char *) y1, sizeof (y2));
+  memcpy (x, y, sizeof (y) + 0);
+  memcpy (x, y1, 0 + sizeof (y2));
+  memcpy (x, (void *) &c, sizeof (&c));
+  memcpy (x, (signed char *) &c, sizeof (&c));
+  memcpy (x, &c, sizeof (&c) + 0);
+  memcpy (x, &c, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memmove (y, x, sizeof (*y));
+  memmove (y1, x, sizeof (*y2));
+  memmove (buf1, x, sizeof buf1);
+  memmove (buf3, x, sizeof (buf3));
+  memmove (&buf3[0], x, sizeof (buf3));
+  memmove (&buf4[0], x, sizeof (buf4));
+  memmove (&y3, y, sizeof (y3));
+  memmove ((char *) &y3, y, sizeof (y3));
+  memmove (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) y, x, sizeof (y));
+  memmove ((char *) y1, x, sizeof (y2));
+  memmove (y, x, sizeof (y) + 0);
+  memmove (y1, x, 0 + sizeof (y2));
+  memmove ((void *) &c, x, sizeof (&c));
+  memmove ((signed char *) &c, x, sizeof (&c));
+  memmove (&c, x, sizeof (&c) + 0);
+  memmove (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memmove (x, y, sizeof (*y));
+  memmove (x, y1, sizeof (*y2));
+  memmove (x, buf1, sizeof buf1);
+  memmove (x, buf3, sizeof (buf3));
+  memmove (x, &buf3[0], sizeof (buf3));
+  memmove (x, &buf4[0], sizeof (buf4));
+  memmove (y, &y3, sizeof (y3));
+  memmove (y, (char *) &y3, sizeof (y3));
+  memmove (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) y, sizeof (y));
+  memmove (x, (char *) y1, sizeof (y2));
+  memmove (x, y, sizeof (y) + 0);
+  memmove (x, y1, 0 + sizeof (y2));
+  memmove (x, (void *) &c, sizeof (&c));
+  memmove (x, (signed char *) &c, sizeof (&c));
+  memmove (x, &c, sizeof (&c) + 0);
+  memmove (x, &c, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  z += memcmp (y, x, sizeof (*y));
+  z += memcmp (y1, x, sizeof (*y2));
+  z += memcmp (buf1, x, sizeof buf1);
+  z += memcmp (buf3, x, sizeof (buf3));
+  z += memcmp (&buf3[0], x, sizeof (buf3));
+  z += memcmp (&buf4[0], x, sizeof (buf4));
+  z += memcmp (&y3, y, sizeof (y3));
+  z += memcmp ((char *) &y3, y, sizeof (y3));
+  z += memcmp (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) y, x, sizeof (y));
+  z += memcmp ((char *) y1, x, sizeof (y2));
+  z += memcmp (y, x, sizeof (y) + 0);
+  z += memcmp (y1, x, 0 + sizeof (y2));
+  z += memcmp ((void *) &c, x, sizeof (&c));
+  z += memcmp ((signed char *) &c, x, sizeof (&c));
+  z += memcmp (&c, x, sizeof (&c) + 0);
+  z += memcmp (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  z += memcmp (x, y, sizeof (*y));
+  z += memcmp (x, y1, sizeof (*y2));
+  z += memcmp (x, buf1, sizeof buf1);
+  z += memcmp (x, buf3, sizeof (buf3));
+  z += memcmp (x, &buf3[0], sizeof (buf3));
+  z += memcmp (x, &buf4[0], sizeof (buf4));
+  z += memcmp (y, &y3, sizeof (y3));
+  z += memcmp (y, (char *) &y3, sizeof (y3));
+  z += memcmp (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) y, sizeof (y));
+  z += memcmp (x, (char *) y1, sizeof (y2));
+  z += memcmp (x, y, sizeof (y) + 0);
+  z += memcmp (x, y1, 0 + sizeof (y2));
+  z += memcmp (x, (void *) &c, sizeof (&c));
+  z += memcmp (x, (signed char *) &c, sizeof (&c));
+  z += memcmp (x, &c, sizeof (&c) + 0);
+  z += memcmp (x, &c, 0 + sizeof (&c));
+
+  return z;
+}
+
+template <int N>
+int
+f4 (char *x, char **y, int z)
+{
+  const char *s1 = "foobarbaz";
+  const char *s2 = "abcde12345678";
+  strncpy (x, s1, sizeof (s1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  strncat (x, s2, sizeof (s2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  y[0] = strndup (s1, sizeof (s1));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += strncmp (s1, s2, sizeof (s1));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += strncmp (s1, s2, sizeof (s2));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += strncasecmp (s1, s2, sizeof (s1));   // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += strncasecmp (s1, s2, sizeof (s2));   // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+
+  // These are correct, no warning. 
+  const char s3[] = "foobarbaz";
+  const char s4[] = "abcde12345678";
+  strncpy (x, s3, sizeof (s3));
+  strncat (x, s4, sizeof (s4));
+  y[1] = strndup (s3, sizeof (s3));
+  z += strncmp (s3, s4, sizeof (s3));
+  z += strncmp (s3, s4, sizeof (s4));
+  z += strncasecmp (s3, s4, sizeof (s3));
+  z += strncasecmp (s3, s4, sizeof (s4));
+
+  return z;
+}
+
+int
+f (void *x, char *y, int z, X w, char **u)
+{
+  z += f1<0> (x, z);
+  z += f2<0> (x, z);
+  z += f3<0> (x, y, z, w);
+  z += f4<0> (y, u, z);
+  return z;
+}
+
+// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" }
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C.jj	2012-10-01 17:38:18.549576540 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C	2012-10-01 17:38:18.549576540 +0200
@@ -0,0 +1,702 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
+// { dg-skip-if "" { *-*-* }  { "*" } { "-O0" "-O2" } }
+// { dg-skip-if "" { *-*-* }  { "-flto" } { "" } }
+
+extern "C" {
+
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *, int, size_t);
+extern void *memcpy (void *__restrict, const void *__restrict, size_t);
+extern void *memmove (void *__restrict, const void *__restrict, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strncpy (char *__restrict, const char *__restrict, size_t);
+extern char *strncat (char *__restrict, const char *__restrict, size_t);
+extern char *strndup (const char *, size_t);
+extern int strncmp (const char *, const char *, size_t);
+extern int strncasecmp (const char *, const char *, size_t);
+
+#ifdef __OPTIMIZE__
+# define bos(ptr) __builtin_object_size (ptr, 1)
+# define bos0(ptr) __builtin_object_size (ptr, 0)
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memset (void *dest, int c, size_t len)
+{
+  return __builtin___memset_chk (dest, c, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memcpy (void *__restrict dest, const void *__restrict src, size_t len)
+{
+  return __builtin___memcpy_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memmove (void *dest, const void *src, size_t len)
+{
+  return __builtin___memmove_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncpy (char *__restrict dest, const char *__restrict src, size_t len)
+{
+  return __builtin___strncpy_chk (dest, src, len, bos (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncat (char *dest, const char *src, size_t len)
+{
+  return __builtin___strncat_chk (dest, src, len, bos (dest));
+}
+#endif
+
+}
+
+struct A { short a, b; int c, d; long e, f; };
+typedef struct A TA;
+typedef struct A *PA;
+typedef TA *PTA;
+struct B {};
+typedef struct B TB;
+typedef struct B *PB;
+typedef TB *PTB;
+typedef int X[3][3][3];
+
+int
+f1 (void *x, int z)
+{
+  struct A a, *pa1 = &a;
+  TA *pa2 = &a;
+  PA pa3 = &a;
+  PTA pa4 = &a;
+  memset (&a, 0, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (pa1, 0, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa2, 0, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa3, 0, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa4, 0, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pa1, 0, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa2, 0, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa3, 0, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (&a, x, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa2, x, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa4, x, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pa1, x, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa2, x, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa3, x, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (x, &a, sizeof (&a));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa2, sizeof pa2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa4, sizeof pa4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pa1, sizeof (struct A *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa2, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa3, sizeof (PA));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (&a, x, sizeof (&a));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa2, x, sizeof pa2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa4, x, sizeof pa4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pa1, x, sizeof (struct A *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa2, x, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa3, x, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (x, &a, sizeof (&a));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa2, sizeof pa2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa4, sizeof pa4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pa1, sizeof (struct A *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa2, sizeof (PTA));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa3, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (&a, x, sizeof (&a));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (pa1, x, sizeof (pa1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa2, x, sizeof pa2);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa3, x, sizeof (pa3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa4, x, sizeof pa4);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pa2, x, sizeof (PTA));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pa3, x, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (x, &a, sizeof (&a));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, pa1, sizeof (pa1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa2, sizeof pa2);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa3, sizeof (pa3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa4, sizeof pa4);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pa2, sizeof (PTA));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pa3, sizeof (PA));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  // These are correct, no warning. 
+  memset (&a, 0, sizeof a);
+  memset (&a, 0, sizeof (a));
+  memset (&a, 0, sizeof (struct A));
+  memset (&a, 0, sizeof (const struct A));
+  memset (&a, 0, sizeof (volatile struct A));
+  memset (&a, 0, sizeof (volatile const struct A));
+  memset (&a, 0, sizeof (TA));
+  memset (&a, 0, sizeof (__typeof (*&a)));
+  memset (pa1, 0, sizeof (*pa1));
+  memset (pa2, 0, sizeof (*pa3));
+  memset (pa3, 0, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) &a, 0, sizeof (&a));
+  memset ((char *) &a, 0, sizeof (&a));
+  memset (&a, 0, sizeof (&a) + 0);
+  memset (&a, 0, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memcpy (&a, x, sizeof a);
+  memcpy (&a, x, sizeof (a));
+  memcpy (&a, x, sizeof (struct A));
+  memcpy (&a, x, sizeof (const struct A));
+  memcpy (&a, x, sizeof (volatile struct A));
+  memcpy (&a, x, sizeof (volatile const struct A));
+  memcpy (&a, x, sizeof (TA));
+  memcpy (&a, x, sizeof (__typeof (*&a)));
+  memcpy (pa1, x, sizeof (*pa1));
+  memcpy (pa2, x, sizeof (*pa3));
+  memcpy (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) &a, x, sizeof (&a));
+  memcpy ((char *) &a, x, sizeof (&a));
+  memcpy (&a, x, sizeof (&a) + 0);
+  memcpy (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memcpy (x, &a, sizeof a);
+  memcpy (x, &a, sizeof (a));
+  memcpy (x, &a, sizeof (struct A));
+  memcpy (x, &a, sizeof (const struct A));
+  memcpy (x, &a, sizeof (volatile struct A));
+  memcpy (x, &a, sizeof (volatile const struct A));
+  memcpy (x, &a, sizeof (TA));
+  memcpy (x, &a, sizeof (__typeof (*&a)));
+  memcpy (x, pa1, sizeof (*pa1));
+  memcpy (x, pa2, sizeof (*pa3));
+  memcpy (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) &a, sizeof (&a));
+  memcpy (x, (char *) &a, sizeof (&a));
+  memcpy (x, &a, sizeof (&a) + 0);
+  memcpy (x, &a, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memmove (&a, x, sizeof a);
+  memmove (&a, x, sizeof (a));
+  memmove (&a, x, sizeof (struct A));
+  memmove (&a, x, sizeof (const struct A));
+  memmove (&a, x, sizeof (volatile struct A));
+  memmove (&a, x, sizeof (volatile const struct A));
+  memmove (&a, x, sizeof (TA));
+  memmove (&a, x, sizeof (__typeof (*&a)));
+  memmove (pa1, x, sizeof (*pa1));
+  memmove (pa2, x, sizeof (*pa3));
+  memmove (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) &a, x, sizeof (&a));
+  memmove ((char *) &a, x, sizeof (&a));
+  memmove (&a, x, sizeof (&a) + 0);
+  memmove (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  memmove (x, &a, sizeof a);
+  memmove (x, &a, sizeof (a));
+  memmove (x, &a, sizeof (struct A));
+  memmove (x, &a, sizeof (const struct A));
+  memmove (x, &a, sizeof (volatile struct A));
+  memmove (x, &a, sizeof (volatile const struct A));
+  memmove (x, &a, sizeof (TA));
+  memmove (x, &a, sizeof (__typeof (*&a)));
+  memmove (x, pa1, sizeof (*pa1));
+  memmove (x, pa2, sizeof (*pa3));
+  memmove (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) &a, sizeof (&a));
+  memmove (x, (char *) &a, sizeof (&a));
+  memmove (x, &a, sizeof (&a) + 0);
+  memmove (x, &a, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  z += memcmp (&a, x, sizeof a);
+  z += memcmp (&a, x, sizeof (a));
+  z += memcmp (&a, x, sizeof (struct A));
+  z += memcmp (&a, x, sizeof (const struct A));
+  z += memcmp (&a, x, sizeof (volatile struct A));
+  z += memcmp (&a, x, sizeof (volatile const struct A));
+  z += memcmp (&a, x, sizeof (TA));
+  z += memcmp (&a, x, sizeof (__typeof (*&a)));
+  z += memcmp (pa1, x, sizeof (*pa1));
+  z += memcmp (pa2, x, sizeof (*pa3));
+  z += memcmp (pa3, x, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) &a, x, sizeof (&a));
+  z += memcmp ((char *) &a, x, sizeof (&a));
+  z += memcmp (&a, x, sizeof (&a) + 0);
+  z += memcmp (&a, x, 0 + sizeof (&a));
+
+  // These are correct, no warning. 
+  z += memcmp (x, &a, sizeof a);
+  z += memcmp (x, &a, sizeof (a));
+  z += memcmp (x, &a, sizeof (struct A));
+  z += memcmp (x, &a, sizeof (const struct A));
+  z += memcmp (x, &a, sizeof (volatile struct A));
+  z += memcmp (x, &a, sizeof (volatile const struct A));
+  z += memcmp (x, &a, sizeof (TA));
+  z += memcmp (x, &a, sizeof (__typeof (*&a)));
+  z += memcmp (x, pa1, sizeof (*pa1));
+  z += memcmp (x, pa2, sizeof (*pa3));
+  z += memcmp (x, pa3, sizeof (__typeof (*pa3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) &a, sizeof (&a));
+  z += memcmp (x, (char *) &a, sizeof (&a));
+  z += memcmp (x, &a, sizeof (&a) + 0);
+  z += memcmp (x, &a, 0 + sizeof (&a));
+
+  return z;
+}
+
+int
+f2 (void *x, int z)
+{
+  struct B b, *pb1 = &b;
+  TB *pb2 = &b;
+  PB pb3 = &b;
+  PTB pb4 = &b;
+  memset (&b, 0, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (pb1, 0, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb2, 0, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb3, 0, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb4, 0, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memset (pb1, 0, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb2, 0, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb3, 0, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (&b, x, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb2, x, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb4, x, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memcpy (pb1, x, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb2, x, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb3, x, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memcpy (x, &b, sizeof (&b));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb2, sizeof pb2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb4, sizeof pb4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memcpy (x, pb1, sizeof (struct B *));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb2, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb3, sizeof (PB));		    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (&b, x, sizeof (&b));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb2, x, sizeof pb2);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb4, x, sizeof pb4);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  memmove (pb1, x, sizeof (struct B *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb2, x, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb3, x, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  memmove (x, &b, sizeof (&b));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb2, sizeof pb2);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb4, sizeof pb4);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  memmove (x, pb1, sizeof (struct B *));    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb2, sizeof (PTB));    	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb3, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (&b, x, sizeof (&b));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (pb1, x, sizeof (pb1));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb2, x, sizeof pb2);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb3, x, sizeof (pb3));	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb4, x, sizeof pb4);	    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+  z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pb2, x, sizeof (PTB));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (pb3, x, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+  z += memcmp (x, &b, sizeof (&b));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, pb1, sizeof (pb1));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb2, sizeof pb2);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb3, sizeof (pb3));	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb4, sizeof pb4);	    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+  z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pb2, sizeof (PTB));       // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+  z += memcmp (x, pb3, sizeof (PB));	    // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+  // These are correct, no warning. 
+  memset (&b, 0, sizeof b);
+  memset (&b, 0, sizeof (b));
+  memset (&b, 0, sizeof (struct B));
+  memset (&b, 0, sizeof (const struct B));
+  memset (&b, 0, sizeof (volatile struct B));
+  memset (&b, 0, sizeof (volatile const struct B));
+  memset (&b, 0, sizeof (TB));
+  memset (&b, 0, sizeof (__typeof (*&b)));
+  memset (pb1, 0, sizeof (*pb1));
+  memset (pb2, 0, sizeof (*pb3));
+  memset (pb3, 0, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) &b, 0, sizeof (&b));
+  memset ((char *) &b, 0, sizeof (&b));
+  memset (&b, 0, sizeof (&b) + 0);
+  memset (&b, 0, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memcpy (&b, x, sizeof b);
+  memcpy (&b, x, sizeof (b));
+  memcpy (&b, x, sizeof (struct B));
+  memcpy (&b, x, sizeof (const struct B));
+  memcpy (&b, x, sizeof (volatile struct B));
+  memcpy (&b, x, sizeof (volatile const struct B));
+  memcpy (&b, x, sizeof (TB));
+  memcpy (&b, x, sizeof (__typeof (*&b)));
+  memcpy (pb1, x, sizeof (*pb1));
+  memcpy (pb2, x, sizeof (*pb3));
+  memcpy (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) &b, x, sizeof (&b));
+  memcpy ((char *) &b, x, sizeof (&b));
+  memcpy (&b, x, sizeof (&b) + 0);
+  memcpy (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memcpy (x, &b, sizeof b);
+  memcpy (x, &b, sizeof (b));
+  memcpy (x, &b, sizeof (struct B));
+  memcpy (x, &b, sizeof (const struct B));
+  memcpy (x, &b, sizeof (volatile struct B));
+  memcpy (x, &b, sizeof (volatile const struct B));
+  memcpy (x, &b, sizeof (TB));
+  memcpy (x, &b, sizeof (__typeof (*&b)));
+  memcpy (x, pb1, sizeof (*pb1));
+  memcpy (x, pb2, sizeof (*pb3));
+  memcpy (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) &b, sizeof (&b));
+  memcpy (x, (char *) &b, sizeof (&b));
+  memcpy (x, &b, sizeof (&b) + 0);
+  memcpy (x, &b, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memmove (&b, x, sizeof b);
+  memmove (&b, x, sizeof (b));
+  memmove (&b, x, sizeof (struct B));
+  memmove (&b, x, sizeof (const struct B));
+  memmove (&b, x, sizeof (volatile struct B));
+  memmove (&b, x, sizeof (volatile const struct B));
+  memmove (&b, x, sizeof (TB));
+  memmove (&b, x, sizeof (__typeof (*&b)));
+  memmove (pb1, x, sizeof (*pb1));
+  memmove (pb2, x, sizeof (*pb3));
+  memmove (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) &b, x, sizeof (&b));
+  memmove ((char *) &b, x, sizeof (&b));
+  memmove (&b, x, sizeof (&b) + 0);
+  memmove (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  memmove (x, &b, sizeof b);
+  memmove (x, &b, sizeof (b));
+  memmove (x, &b, sizeof (struct B));
+  memmove (x, &b, sizeof (const struct B));
+  memmove (x, &b, sizeof (volatile struct B));
+  memmove (x, &b, sizeof (volatile const struct B));
+  memmove (x, &b, sizeof (TB));
+  memmove (x, &b, sizeof (__typeof (*&b)));
+  memmove (x, pb1, sizeof (*pb1));
+  memmove (x, pb2, sizeof (*pb3));
+  memmove (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) &b, sizeof (&b));
+  memmove (x, (char *) &b, sizeof (&b));
+  memmove (x, &b, sizeof (&b) + 0);
+  memmove (x, &b, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  z += memcmp (&b, x, sizeof b);
+  z += memcmp (&b, x, sizeof (b));
+  z += memcmp (&b, x, sizeof (struct B));
+  z += memcmp (&b, x, sizeof (const struct B));
+  z += memcmp (&b, x, sizeof (volatile struct B));
+  z += memcmp (&b, x, sizeof (volatile const struct B));
+  z += memcmp (&b, x, sizeof (TB));
+  z += memcmp (&b, x, sizeof (__typeof (*&b)));
+  z += memcmp (pb1, x, sizeof (*pb1));
+  z += memcmp (pb2, x, sizeof (*pb3));
+  z += memcmp (pb3, x, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) &b, x, sizeof (&b));
+  z += memcmp ((char *) &b, x, sizeof (&b));
+  z += memcmp (&b, x, sizeof (&b) + 0);
+  z += memcmp (&b, x, 0 + sizeof (&b));
+
+  // These are correct, no warning. 
+  z += memcmp (x, &b, sizeof b);
+  z += memcmp (x, &b, sizeof (b));
+  z += memcmp (x, &b, sizeof (struct B));
+  z += memcmp (x, &b, sizeof (const struct B));
+  z += memcmp (x, &b, sizeof (volatile struct B));
+  z += memcmp (x, &b, sizeof (volatile const struct B));
+  z += memcmp (x, &b, sizeof (TB));
+  z += memcmp (x, &b, sizeof (__typeof (*&b)));
+  z += memcmp (x, pb1, sizeof (*pb1));
+  z += memcmp (x, pb2, sizeof (*pb3));
+  z += memcmp (x, pb3, sizeof (__typeof (*pb3)));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) &b, sizeof (&b));
+  z += memcmp (x, (char *) &b, sizeof (&b));
+  z += memcmp (x, &b, sizeof (&b) + 0);
+  z += memcmp (x, &b, 0 + sizeof (&b));
+
+  return z;
+}
+
+int
+f3 (void *x, char *y, int z, X w)
+{
+  unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16);
+  char buf1[7];
+  signed char buf2[z + 32];
+  long buf3[17];
+  int *buf4[9];
+  signed char *y2 = buf2;
+  char c;
+  char *y3;
+  memset (y, 0, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (y1, 0, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (y2, 0, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memset (&c, 0, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memset (w, 0, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memcpy (y, x, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (y1, x, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (y2, x, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memcpy (&c, x, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memcpy (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memcpy (x, y, sizeof (y));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, y1, sizeof (y1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, y2, sizeof (y2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memcpy (x, &c, sizeof (&c));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memcpy (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  memmove (y, x, sizeof (y));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (y1, x, sizeof (y1));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (y2, x, sizeof (y2));		    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  memmove (&c, x, sizeof (&c));		    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  memmove (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  memmove (x, y, sizeof (y));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, y1, sizeof (y1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, y2, sizeof (y2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  memmove (x, &c, sizeof (&c));		    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  memmove (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  z += memcmp (y, x, sizeof (y));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (y1, x, sizeof (y1));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (y2, x, sizeof (y2));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += memcmp (&c, x, sizeof (&c));	    // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+  z += memcmp (w, x, sizeof w);		    // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+  z += memcmp (x, y, sizeof (y));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, y1, sizeof (y1));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, y2, sizeof (y2));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += memcmp (x, &c, sizeof (&c));	    // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+  z += memcmp (x, w, sizeof w);		    // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+  // These are correct, no warning. 
+  memset (y, 0, sizeof (*y));
+  memset (y1, 0, sizeof (*y2));
+  memset (buf1, 0, sizeof buf1);
+  memset (buf3, 0, sizeof (buf3));
+  memset (&buf3[0], 0, sizeof (buf3));
+  memset (&buf4[0], 0, sizeof (buf4));
+  memset (w, 0, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memset ((void *) y, 0, sizeof (y));
+  memset ((char *) y1, 0, sizeof (y2));
+  memset (y, 0, sizeof (y) + 0);
+  memset (y1, 0, 0 + sizeof (y2));
+  memset ((void *) &c, 0, sizeof (&c));
+  memset ((signed char *) &c, 0, sizeof (&c));
+  memset (&c, 0, sizeof (&c) + 0);
+  memset (&c, 0, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memcpy (y, x, sizeof (*y));
+  memcpy (y1, x, sizeof (*y2));
+  memcpy (buf1, x, sizeof buf1);
+  memcpy (buf3, x, sizeof (buf3));
+  memcpy (&buf3[0], x, sizeof (buf3));
+  memcpy (&buf4[0], x, sizeof (buf4));
+  memcpy (&y3, y, sizeof (y3));
+  memcpy ((char *) &y3, y, sizeof (y3));
+  memcpy (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy ((void *) y, x, sizeof (y));
+  memcpy ((char *) y1, x, sizeof (y2));
+  memcpy (y, x, sizeof (y) + 0);
+  memcpy (y1, x, 0 + sizeof (y2));
+  memcpy ((void *) &c, x, sizeof (&c));
+  memcpy ((signed char *) &c, x, sizeof (&c));
+  memcpy (&c, x, sizeof (&c) + 0);
+  memcpy (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memcpy (x, y, sizeof (*y));
+  memcpy (x, y1, sizeof (*y2));
+  memcpy (x, buf1, sizeof buf1);
+  memcpy (x, buf3, sizeof (buf3));
+  memcpy (x, &buf3[0], sizeof (buf3));
+  memcpy (x, &buf4[0], sizeof (buf4));
+  memcpy (y, &y3, sizeof (y3));
+  memcpy (y, (char *) &y3, sizeof (y3));
+  memcpy (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memcpy (x, (void *) y, sizeof (y));
+  memcpy (x, (char *) y1, sizeof (y2));
+  memcpy (x, y, sizeof (y) + 0);
+  memcpy (x, y1, 0 + sizeof (y2));
+  memcpy (x, (void *) &c, sizeof (&c));
+  memcpy (x, (signed char *) &c, sizeof (&c));
+  memcpy (x, &c, sizeof (&c) + 0);
+  memcpy (x, &c, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memmove (y, x, sizeof (*y));
+  memmove (y1, x, sizeof (*y2));
+  memmove (buf1, x, sizeof buf1);
+  memmove (buf3, x, sizeof (buf3));
+  memmove (&buf3[0], x, sizeof (buf3));
+  memmove (&buf4[0], x, sizeof (buf4));
+  memmove (&y3, y, sizeof (y3));
+  memmove ((char *) &y3, y, sizeof (y3));
+  memmove (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove ((void *) y, x, sizeof (y));
+  memmove ((char *) y1, x, sizeof (y2));
+  memmove (y, x, sizeof (y) + 0);
+  memmove (y1, x, 0 + sizeof (y2));
+  memmove ((void *) &c, x, sizeof (&c));
+  memmove ((signed char *) &c, x, sizeof (&c));
+  memmove (&c, x, sizeof (&c) + 0);
+  memmove (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  memmove (x, y, sizeof (*y));
+  memmove (x, y1, sizeof (*y2));
+  memmove (x, buf1, sizeof buf1);
+  memmove (x, buf3, sizeof (buf3));
+  memmove (x, &buf3[0], sizeof (buf3));
+  memmove (x, &buf4[0], sizeof (buf4));
+  memmove (y, &y3, sizeof (y3));
+  memmove (y, (char *) &y3, sizeof (y3));
+  memmove (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  memmove (x, (void *) y, sizeof (y));
+  memmove (x, (char *) y1, sizeof (y2));
+  memmove (x, y, sizeof (y) + 0);
+  memmove (x, y1, 0 + sizeof (y2));
+  memmove (x, (void *) &c, sizeof (&c));
+  memmove (x, (signed char *) &c, sizeof (&c));
+  memmove (x, &c, sizeof (&c) + 0);
+  memmove (x, &c, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  z += memcmp (y, x, sizeof (*y));
+  z += memcmp (y1, x, sizeof (*y2));
+  z += memcmp (buf1, x, sizeof buf1);
+  z += memcmp (buf3, x, sizeof (buf3));
+  z += memcmp (&buf3[0], x, sizeof (buf3));
+  z += memcmp (&buf4[0], x, sizeof (buf4));
+  z += memcmp (&y3, y, sizeof (y3));
+  z += memcmp ((char *) &y3, y, sizeof (y3));
+  z += memcmp (w, x, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp ((void *) y, x, sizeof (y));
+  z += memcmp ((char *) y1, x, sizeof (y2));
+  z += memcmp (y, x, sizeof (y) + 0);
+  z += memcmp (y1, x, 0 + sizeof (y2));
+  z += memcmp ((void *) &c, x, sizeof (&c));
+  z += memcmp ((signed char *) &c, x, sizeof (&c));
+  z += memcmp (&c, x, sizeof (&c) + 0);
+  z += memcmp (&c, x, 0 + sizeof (&c));
+
+  // These are correct, no warning. 
+  z += memcmp (x, y, sizeof (*y));
+  z += memcmp (x, y1, sizeof (*y2));
+  z += memcmp (x, buf1, sizeof buf1);
+  z += memcmp (x, buf3, sizeof (buf3));
+  z += memcmp (x, &buf3[0], sizeof (buf3));
+  z += memcmp (x, &buf4[0], sizeof (buf4));
+  z += memcmp (y, &y3, sizeof (y3));
+  z += memcmp (y, (char *) &y3, sizeof (y3));
+  z += memcmp (x, w, sizeof (X));
+  // These are probably broken, but obfuscated, no warning. 
+  z += memcmp (x, (void *) y, sizeof (y));
+  z += memcmp (x, (char *) y1, sizeof (y2));
+  z += memcmp (x, y, sizeof (y) + 0);
+  z += memcmp (x, y1, 0 + sizeof (y2));
+  z += memcmp (x, (void *) &c, sizeof (&c));
+  z += memcmp (x, (signed char *) &c, sizeof (&c));
+  z += memcmp (x, &c, sizeof (&c) + 0);
+  z += memcmp (x, &c, 0 + sizeof (&c));
+
+  return z;
+}
+
+int
+f4 (char *x, char **y, int z)
+{
+  const char *s1 = "foobarbaz";
+  const char *s2 = "abcde12345678";
+  strncpy (x, s1, sizeof (s1));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  strncat (x, s2, sizeof (s2));		    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  y[0] = strndup (s1, sizeof (s1));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += strncmp (s1, s2, sizeof (s1));	    // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += strncmp (s1, s2, sizeof (s2));	    // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+  z += strncasecmp (s1, s2, sizeof (s1));   // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+  z += strncasecmp (s1, s2, sizeof (s2));   // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+
+  // These are correct, no warning. 
+  const char s3[] = "foobarbaz";
+  const char s4[] = "abcde12345678";
+  strncpy (x, s3, sizeof (s3));
+  strncat (x, s4, sizeof (s4));
+  y[1] = strndup (s3, sizeof (s3));
+  z += strncmp (s3, s4, sizeof (s3));
+  z += strncmp (s3, s4, sizeof (s4));
+  z += strncasecmp (s3, s4, sizeof (s3));
+  z += strncasecmp (s3, s4, sizeof (s4));
+
+  return z;
+}
+
+// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" }
--- gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C.jj	2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C	2012-10-01 17:38:18.556576500 +0200
@@ -0,0 +1,13 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" void *memset (void *, int, size_t);
+
+int
+foo (int x, char b[10])
+{
+  long a[memset (b, 0, sizeof (b)) ? x + 10 : x];	// { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length?" }
+  return a[0];
+}
--- gcc/testsuite/g++.dg/warn/Wsign-compare-5.C.jj	2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/warn/Wsign-compare-5.C	2012-10-01 17:38:18.556576500 +0200
@@ -0,0 +1,20 @@
+// Test that -Wsign-compare doesn't warn about
+// equality/non-equality comparisons with sizeof.
+// { dg-do compile }
+// { dg-options "-Wsign-compare" }
+
+int
+foo (int x)
+{
+  if (x != sizeof (sizeof (x)))		// { dg-bogus "comparison between signed and unsigned integer expressions" }
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x == sizeof (sizeof (x)) + 1)	// { dg-bogus "comparison between signed and unsigned integer expressions" }
+    return 1;
+  return 0;
+}
--- gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C.jj	2011-05-02 18:39:10.000000000 +0200
+++ gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C	2012-10-02 10:32:08.764195850 +0200
@@ -9,7 +9,7 @@ void func2() {
   int* t = false;             // { dg-warning "converting 'false' to pointer" }
   int* p;
   p = false;                  // { dg-warning "converting 'false' to pointer" }
-  int* r = sizeof(char) / 2;
+  int* r = sizeof(char) / 2;  // { dg-error "invalid conversion from" "" { target c++11 } }
   func1(false);               // { dg-warning "converting 'false' to pointer" }
   int i = NULL;               // { dg-warning "converting to non-pointer" }
 }
--- gcc/testsuite/g++.dg/ext/vla12.C.jj	2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/ext/vla12.C	2012-10-01 17:38:18.557576495 +0200
@@ -0,0 +1,28 @@
+// VLA sizeof test
+// { dg-do compile }
+// { dg-options "" }
+
+int
+f1 (int i)
+{
+  char a[sizeof (i) + 6 + i];
+  char b[sizeof (a) + 1];
+  return sizeof (b);
+}
+
+int
+f2 (int i)
+{
+  char a[sizeof (i) + 6 + i];
+  char b[sizeof (a)];
+  return sizeof (b);
+}
+
+int
+f3 (int i)
+{
+  char a[sizeof (i) + 6 + i];
+  char b[sizeof (i) + i];
+  char c[sizeof (a) + sizeof (b) + 7];
+  return sizeof (c);
+}
--- gcc/testsuite/g++.dg/ext/builtin30.C.jj	2012-10-01 17:38:18.557576495 +0200
+++ gcc/testsuite/g++.dg/ext/builtin30.C	2012-10-01 17:38:18.557576495 +0200
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" {
+extern void __chk_fail (void);
+extern int snprintf (char *, size_t, const char *, ...);
+extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...)
+{
+  if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b)
+    __chk_fail ();
+  return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ());
+}
+extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf");
+}
+
+char buf[10];
+
+int
+main (void)
+{
+  snprintf (buf, 10, "%d%d\n", 10, 10);
+  return 0;
+}
+
+// { dg-final { scan-assembler "mysnprintf" } }
+// { dg-final { scan-assembler-not "__chk_fail" } }
--- gcc/testsuite/gcc.dg/builtins-85.c.jj	2012-10-01 17:38:18.557576495 +0200
+++ gcc/testsuite/gcc.dg/builtins-85.c	2012-10-01 17:38:18.557576495 +0200
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void __chk_fail (void);
+extern int snprintf (char *, size_t, const char *, ...);
+extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...)
+{
+  if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b)
+    __chk_fail ();
+  return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ());
+}
+extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf");
+
+char buf[10];
+
+int
+main (void)
+{
+  snprintf (buf, 10, "%d%d\n", 10, 10);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mysnprintf" } } */
+/* { dg-final { scan-assembler-not "__chk_fail" } } */
--- libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc.jj	2012-08-10 12:57:16.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc	2012-09-25 15:28:16.902924472 +0200
@@ -32,9 +32,9 @@ void test01()
 {
   X* px = 0;
   std::shared_ptr<X> p1(px);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 776 }
+  // { dg-error "incomplete" "" { target *-*-* } 775 }
 
   std::shared_ptr<X> p9(ap());  // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 310 }
+  // { dg-error "incomplete" "" { target *-*-* } 307 }
 
 }

	Jakub



More information about the Gcc-patches mailing list