Hi! We instantiate FIX_TRUNC_EXPR using cp_build_unary_op, but that function doesn't look like a good match for this tree, what it really does for it is: 1) handle error_operand_p 2) on ia64 only diagnose __fpreg uses (I believe a cast of __fpreg to int is fine, so we shouldn't warn) 3) and then it does: argtype = TREE_TYPE (arg); return build1 (code, argtype, arg); which creates FIX_TRUNC_EXPR with the type of the argument rather than the integral type it should have. The following patch thus bypasses that function and just builds the FIX_TRUNC_EXPR with the right type. I think we don't need to tsubst the type, because if it is type dependent, we wouldn't be creating FIX_TRUNC_EXPR, but record it just as a some kind of conversion.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-03-19 Jakub Jelinek <ja...@redhat.com> PR c++/84942 * pt.c (tsubst_copy_and_build) <case FIX_TRUNC_EXPR>: Don't call cp_build_unary_op, just use build1. * g++.dg/cpp1y/pr84942.C: New test. --- gcc/cp/pt.c.jj 2018-03-16 21:11:04.440773108 +0100 +++ gcc/cp/pt.c 2018-03-19 10:58:39.803657613 +0100 @@ -17495,8 +17495,10 @@ tsubst_copy_and_build (tree t, complain|decltype_flag)); case FIX_TRUNC_EXPR: - RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)), - false, complain)); + op1 = RECUR (TREE_OPERAND (t, 0)); + if (error_operand_p (op1)) + RETURN (error_mark_node); + RETURN (build1 (FIX_TRUNC_EXPR, TREE_TYPE (t), op1)); case ADDR_EXPR: op1 = TREE_OPERAND (t, 0); --- gcc/testsuite/g++.dg/cpp1y/pr84942.C.jj 2018-03-19 11:04:16.201588211 +0100 +++ gcc/testsuite/g++.dg/cpp1y/pr84942.C 2018-03-19 11:02:37.950609950 +0100 @@ -0,0 +1,7 @@ +// PR c++/84942 +// { dg-do compile { target c++14 } } +// { dg-options "-w" } + +int a(__attribute__((b((int)__builtin_inf() * 1ULL / auto)))); +// { dg-error "expected primary-expression before" "" { target *-*-* } .-1 } +// { dg-error "declared as implicit template" "" { target *-*-* } .-2 } Jakub