This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR 61210: recursive template substitution depending on system compiler


PR 61210 is about a case where a templated wi:: function had "x | y"
and where both "x" and "y" needed temporary variables.  The recursive
instantation of x and y were done as two arguments to the same function
call, which meant that the order of instantiation depended on the host
compiler.  The uids of the temporary variables could therefore be in a
different (but still valid) order than when compiled with the stage1
compiler, which caused code differences later when the uids were used
as tie-breakers to get a stable sort.

I've gone through pt.c a couple of times trying to find all cases
of this, but I might have missed some.

Tested on x86_64-linux-gnu.  Also tested by using clang as the stage1
compiler in an i486-pc-linux-gnu bootstrap.  OK to install?

Thanks,
Richard


gcc/cp/
	PR bootstrap/61210
	* pt.c (tsubst_copy, tsubst_omp_for_iterator, tsubst_expr)
	(tsubst_copy_and_build): Perform recursive substitutions in a
	deterministic order.

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	2014-05-19 18:27:03.510024737 +0100
+++ gcc/cp/pt.c	2014-05-19 22:17:17.854250621 +0100
@@ -12731,9 +12731,11 @@ tsubst_copy (tree t, tree args, tsubst_f
     case IMPLICIT_CONV_EXPR:
     case CONVERT_EXPR:
     case NOP_EXPR:
-      return build1
-	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	return build1 (code, type, op0);
+      }
 
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
@@ -12801,9 +12803,11 @@ tsubst_copy (tree t, tree args, tsubst_f
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case PAREN_EXPR:
-      return build1
-	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	return build1 (code, type, op0);
+      }
 
     case COMPONENT_REF:
       {
@@ -12877,24 +12881,26 @@ tsubst_copy (tree t, tree args, tsubst_f
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
-      return build_nt
-	(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+      {
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	return build_nt (code, op0, op1);
+      }
 
     case SCOPE_REF:
-      return build_qualified_name (/*type=*/NULL_TREE,
-				   tsubst_copy (TREE_OPERAND (t, 0),
-						args, complain, in_decl),
-				   tsubst_copy (TREE_OPERAND (t, 1),
-						args, complain, in_decl),
-				   QUALIFIED_NAME_IS_TEMPLATE (t));
+      {
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	return build_qualified_name (/*type=*/NULL_TREE, op0, op1,
+				     QUALIFIED_NAME_IS_TEMPLATE (t));
+      }
 
     case ARRAY_REF:
-      return build_nt
-	(ARRAY_REF,
-	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
-	 NULL_TREE, NULL_TREE);
+      {
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	return build_nt (ARRAY_REF, op0, op1, NULL_TREE, NULL_TREE);
+      }
 
     case CALL_EXPR:
       {
@@ -12912,29 +12918,29 @@ tsubst_copy (tree t, tree args, tsubst_f
     case PSEUDO_DTOR_EXPR:
     case VEC_PERM_EXPR:
       {
-	r = build_nt
-	  (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	   tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
-	   tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+	r = build_nt (code, op0, op1, op2);
 	TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
 	return r;
       }
 
     case NEW_EXPR:
       {
-	r = build_nt
-	(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+	r = build_nt (code, op0, op1, op2);
 	NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
 	return r;
       }
 
     case DELETE_EXPR:
       {
-	r = build_nt
-	(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	r = build_nt (code, op0, op1);
 	DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
 	DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
 	return r;
@@ -13014,10 +13020,11 @@ tsubst_copy (tree t, tree args, tsubst_f
       gcc_unreachable ();
 
     case VA_ARG_EXPR:
-      return build_x_va_arg (EXPR_LOCATION (t),
-			     tsubst_copy (TREE_OPERAND (t, 0), args, complain,
-					  in_decl),
-			     tsubst (TREE_TYPE (t), args, complain, in_decl));
+      {
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	return build_x_va_arg (EXPR_LOCATION (t), op0, type);
+      }
 
     case CLEANUP_POINT_EXPR:
       /* We shouldn't have built any of these during initial template
@@ -13026,13 +13033,15 @@ tsubst_copy (tree t, tree args, tsubst_f
       gcc_unreachable ();
 
     case OFFSET_REF:
-      r = build2
-	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
-	 tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
-      PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
-      mark_used (TREE_OPERAND (r, 1));
-      return r;
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+	r = build2 (code, type, op0, op1);
+	PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
+	mark_used (TREE_OPERAND (r, 1));
+	return r;
+      }
 
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
@@ -13267,10 +13276,12 @@ #define RECUR(NODE)				\
       cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
       incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
       if (TREE_CODE (incr) == MODIFY_EXPR)
-	incr = build_x_modify_expr (EXPR_LOCATION (incr),
-				    RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
-				    RECUR (TREE_OPERAND (incr, 1)),
-				    complain);
+	{
+	  tree lhs = RECUR (TREE_OPERAND (incr, 0));
+	  tree rhs = RECUR (TREE_OPERAND (incr, 1));
+	  incr = build_x_modify_expr (EXPR_LOCATION (incr), lhs,
+				      NOP_EXPR, rhs, complain);
+	}
       else
 	incr = RECUR (incr);
       TREE_VEC_ELT (declv, i) = decl;
@@ -13316,9 +13327,11 @@ #define RECUR(NODE)				\
     }
   cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
   if (COMPARISON_CLASS_P (cond))
-    cond = build2 (TREE_CODE (cond), boolean_type_node,
-		   RECUR (TREE_OPERAND (cond, 0)),
-		   RECUR (TREE_OPERAND (cond, 1)));
+    {
+      tree op0 = RECUR (TREE_OPERAND (cond, 0));
+      tree op1 = RECUR (TREE_OPERAND (cond, 1));
+      cond = build2 (TREE_CODE (cond), boolean_type_node, op0, op1);
+    }
   else
     cond = RECUR (cond);
   incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
@@ -13336,11 +13349,12 @@ #define RECUR(NODE)				\
 	  || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
 	{
 	  tree rhs = TREE_OPERAND (incr, 1);
-	  incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
-			 RECUR (TREE_OPERAND (incr, 0)),
+	  tree lhs = RECUR (TREE_OPERAND (incr, 0));
+	  tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+	  tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+	  incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
 			 build2 (TREE_CODE (rhs), TREE_TYPE (decl),
-				 RECUR (TREE_OPERAND (rhs, 0)),
-				 RECUR (TREE_OPERAND (rhs, 1))));
+				 rhs0, rhs1));
 	}
       else
 	incr = RECUR (incr);
@@ -13360,11 +13374,12 @@ #define RECUR(NODE)				\
 		   || (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
 	{
 	  tree rhs = TREE_OPERAND (incr, 2);
-	  incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
-			 RECUR (TREE_OPERAND (incr, 0)),
+	  tree lhs = RECUR (TREE_OPERAND (incr, 0));
+	  tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+	  tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+	  incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
 			 build2 (TREE_CODE (rhs), TREE_TYPE (decl),
-				 RECUR (TREE_OPERAND (rhs, 0)),
-				 RECUR (TREE_OPERAND (rhs, 1))));
+				 rhs0, rhs1));
 	}
       else
 	incr = RECUR (incr);
@@ -13642,9 +13657,11 @@ #define RECUR(NODE)				\
       break;
 
     case CASE_LABEL_EXPR:
-      finish_case_label (EXPR_LOCATION (t),
-			 RECUR (CASE_LOW (t)),
-			 RECUR (CASE_HIGH (t)));
+      {
+	tree low = RECUR (CASE_LOW (t));
+	tree high = RECUR (CASE_HIGH (t));
+	finish_case_label (EXPR_LOCATION (t), low, high);
+      }
       break;
 
     case LABEL_EXPR:
@@ -13671,14 +13688,18 @@ #define RECUR(NODE)				\
       break;
 
     case ASM_EXPR:
-      tmp = finish_asm_stmt
-	(ASM_VOLATILE_P (t),
-	 RECUR (ASM_STRING (t)),
-	 tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
-	 tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
-	 tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
-	 tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
       {
+	tree string = RECUR (ASM_STRING (t));
+	tree outputs = tsubst_copy_asm_operands (ASM_OUTPUTS (t), args,
+						 complain, in_decl);
+	tree inputs = tsubst_copy_asm_operands (ASM_INPUTS (t), args,
+						complain, in_decl);
+	tree clobbers = tsubst_copy_asm_operands (ASM_CLOBBERS (t), args,
+	 					  complain, in_decl);
+	tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
+						complain, in_decl);
+	tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
+			       clobbers, labels);
 	tree asm_expr = tmp;
 	if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
 	  asm_expr = TREE_OPERAND (asm_expr, 0);
@@ -13975,8 +13996,11 @@ #define RECUR(NODE)				\
       break;
 
     case MUST_NOT_THROW_EXPR:
-      RETURN (build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
-					RECUR (MUST_NOT_THROW_COND (t))));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree cond = RECUR (MUST_NOT_THROW_COND (t));
+	RETURN (build_must_not_throw_expr (op0, cond));
+      }
 
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
@@ -14243,9 +14267,11 @@ #define RECUR(NODE)						\
       }
 
     case NOP_EXPR:
-      RETURN (build_nop
-	(tsubst (TREE_TYPE (t), args, complain, in_decl),
-	 RECUR (TREE_OPERAND (t, 0))));
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	RETURN (build_nop (type, op0));
+      }
 
     case IMPLICIT_CONV_EXPR:
       {
@@ -14259,10 +14285,11 @@ #define RECUR(NODE)						\
       }
 
     case CONVERT_EXPR:
-      RETURN (build1
-	(CONVERT_EXPR,
-	 tsubst (TREE_TYPE (t), args, complain, in_decl),
-	 RECUR (TREE_OPERAND (t, 0))));
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	RETURN (build1 (CONVERT_EXPR, type, op0));
+      }
 
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
@@ -14327,12 +14354,12 @@ #define RECUR(NODE)						\
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       RETURN (build_x_unary_op (input_location, TREE_CODE (t),
-			       RECUR (TREE_OPERAND (t, 0)),
+				RECUR (TREE_OPERAND (t, 0)),
 				complain|decltype_flag));
 
     case FIX_TRUNC_EXPR:
       RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
-				0, complain));
+				 0, complain));
 
     case ADDR_EXPR:
       op1 = TREE_OPERAND (t, 0);
@@ -14382,13 +14409,15 @@ #define RECUR(NODE)						\
       {
 	warning_sentinel s1(warn_type_limits);
 	warning_sentinel s2(warn_div_by_zero);
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree op1 = RECUR (TREE_OPERAND (t, 1));
 	tree r = build_x_binary_op
 	  (input_location, TREE_CODE (t),
-	   RECUR (TREE_OPERAND (t, 0)),
+	   op0,
 	   (TREE_NO_WARNING (TREE_OPERAND (t, 0))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 0))),
-	   RECUR (TREE_OPERAND (t, 1)),
+	   op1,
 	   (TREE_NO_WARNING (TREE_OPERAND (t, 1))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 1))),
@@ -14401,8 +14430,11 @@ #define RECUR(NODE)						\
       }
 
     case POINTER_PLUS_EXPR:
-      return fold_build_pointer_plus (RECUR (TREE_OPERAND (t, 0)),
-				      RECUR (TREE_OPERAND (t, 1)));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	return fold_build_pointer_plus (op0, op1);
+      }
 
     case SCOPE_REF:
       RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
@@ -14512,11 +14544,10 @@ #define RECUR(NODE)						\
     case MODOP_EXPR:
       {
 	warning_sentinel s(warn_div_by_zero);
+	tree lhs = RECUR (TREE_OPERAND (t, 0));
+	tree rhs = RECUR (TREE_OPERAND (t, 2));
 	tree r = build_x_modify_expr
-	  (EXPR_LOCATION (t),
-	   RECUR (TREE_OPERAND (t, 0)),
-	   TREE_CODE (TREE_OPERAND (t, 1)),
-	   RECUR (TREE_OPERAND (t, 2)),
+	  (EXPR_LOCATION (t), lhs, TREE_CODE (TREE_OPERAND (t, 1)), rhs,
 	   complain|decltype_flag);
 	/* TREE_NO_WARNING must be set if either the expression was
 	   parenthesized or it uses an operator such as >>= rather
@@ -14575,10 +14606,9 @@ #define RECUR(NODE)						\
 	      }
 	  }
 
-	ret = build_new (&placement_vec,
-			 tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
-			 RECUR (TREE_OPERAND (t, 2)),
-			 &init_vec,
+	tree op1 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
+	tree op2 = RECUR (TREE_OPERAND (t, 2));
+	ret = build_new (&placement_vec, op1, op2, &init_vec,
 			 NEW_EXPR_USE_GLOBAL (t),
 			 complain);
 
@@ -14591,12 +14621,14 @@ #define RECUR(NODE)						\
       }
 
     case DELETE_EXPR:
-     RETURN (delete_sanity
-       (RECUR (TREE_OPERAND (t, 0)),
-	RECUR (TREE_OPERAND (t, 1)),
-	DELETE_EXPR_USE_VEC (t),
-	DELETE_EXPR_USE_GLOBAL (t),
-	complain));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	RETURN (delete_sanity (op0, op1,
+			       DELETE_EXPR_USE_VEC (t),
+			       DELETE_EXPR_USE_GLOBAL (t),
+			       complain));
+      }
 
     case COMPOUND_EXPR:
       {
@@ -14863,11 +14895,13 @@ #define RECUR(NODE)						\
       }
 
     case PSEUDO_DTOR_EXPR:
-      RETURN (finish_pseudo_destructor_expr
-	      (RECUR (TREE_OPERAND (t, 0)),
-	       RECUR (TREE_OPERAND (t, 1)),
-	       tsubst (TREE_OPERAND (t, 2), args, complain, in_decl),
-	       input_location));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
+	RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
+					       input_location));
+      }
 
     case TREE_LIST:
       {
@@ -15191,9 +15225,11 @@ #define RECUR(NODE)						\
       }
 
     case VA_ARG_EXPR:
-      RETURN (build_x_va_arg (EXPR_LOCATION (t),
-			     RECUR (TREE_OPERAND (t, 0)),
-			     tsubst (TREE_TYPE (t), args, complain, in_decl)));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	RETURN (build_x_va_arg (EXPR_LOCATION (t), op0, type));
+      }
 
     case OFFSETOF_EXPR:
       RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0))));
@@ -15302,11 +15338,13 @@ #define RECUR(NODE)						\
       RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
 
     case VEC_PERM_EXPR:
-      RETURN (build_x_vec_perm_expr (input_location,
-		RECUR (TREE_OPERAND (t, 0)),
-		RECUR (TREE_OPERAND (t, 1)),
-		RECUR (TREE_OPERAND (t, 2)),
-		complain));
+      {
+	tree op0 = RECUR (TREE_OPERAND (t, 0));
+	tree op1 = RECUR (TREE_OPERAND (t, 1));
+	tree op2 = RECUR (TREE_OPERAND (t, 2));
+	RETURN (build_x_vec_perm_expr (input_location, op0, op1, op2,
+				       complain));
+      }
 
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]