On Fri, 2018-01-05 at 15:29 -0500, Jason Merrill wrote:
> On 12/29/2017 12:06 PM, David Malcolm wrote:
> > One issue I ran into was that fold_for_warn doesn't eliminate
> > location wrappers when processing_template_decl, leading to
> > failures of the template-based cases in
> > g++.dg/warn/Wmemset-transposed-args-1.C.
> > 
> > This is due to the early bailout when processing_template_decl
> > within cp_fold:
> > 
> > 2078          if (processing_template_decl
> > 2079              || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE
> > (x) == error_mark_node)))
> > 2080            return x;
> > 
> > which dates back to the merger of the C++ delayed folding branch.
> > 
> > I've fixed that in this version of the patch by removing that
> > "processing_template_decl ||" condition from that cp_fold early
> > bailout.
> 
> Hmm, that makes me nervous.  We might want to fold in templates when 
> called from fold_for_warn, but not for other occurrences.  But I see 
> that we check processing_template_decl in cp_fully_fold and in the
> call 
> to cp_fold_function, so I guess this is fine.

(I wondered if it would be possible to add a new flag to the various
fold* calls to request folding in templates, but given that the API is
partially shared with C doing so doesn't seem to make sense)

> > +    case VIEW_CONVERT_EXPR:
> > +    case NON_LVALUE_EXPR:
> >      case CAST_EXPR:
> >      case REINTERPRET_CAST_EXPR:
> >      case CONST_CAST_EXPR:
> > @@ -14937,6 +14940,15 @@ tsubst_copy (tree t, tree args,
> > tsubst_flags_t complain, tree in_decl)
> >      case CONVERT_EXPR:
> >      case NOP_EXPR:
> >        {
> > +   if (location_wrapper_p (t))
> > +     {
> > +       /* Handle location wrappers by substituting the
> > wrapped node
> > +          first, *then* reusing the resulting type.  Doing
> > the type
> > +          first ensures that we handle template parameters
> > and
> > +          parameter pack expansions.  */
> > +       tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args,
> > complain, in_decl);
> > +       return build1 (code, TREE_TYPE (op0), op0);
> > +     }
> 
> I'd rather handle location wrappers separately, and abort if 
> VIEW_CONVERT_EXPR or NON_LVALUE_EXPR appear other than as wrappers.

OK.  I'm testing an updated version which does so.

> > @@ -24998,6 +25018,8 @@ build_non_dependent_expr (tree expr)
> >        && !expanding_concept ())
> >      fold_non_dependent_expr (expr);
> >  
> > +  STRIP_ANY_LOCATION_WRAPPER (expr);
> 
> Why is this needed?

I added this to fix a failure:

template argument deduction/substitution failed:
note:   cannot convert ‘0’ (type ‘int’) to type ‘char**’

seen building the precompiled header, where build_non_dependent_expr
adds a NON_DEPENDENT_EXPR around a location wrapper around an
INTEGER_CST, whereas without location wrappers we'd just have an
INTEGER_CST.

build_non_dependent_expr performs various tests for exact TREE_CODEs,
special-casing constants; without the stripping these TREE_CODE tests
don't match when the constants have location wrappers, leading to the
failure.

Here are the gory details:

In file included from ./src/libstdc++-
v3/include/precompiled/extc++.h:82:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h: In member function ‘virtual
std::codecvt_base::result std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::do_unshift(std::codecvt<_InternT,
_ExternT, __gnu_cxx::__cxx11::encoding_state>::state_type&,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*,
std::codecvt<_InternT, _ExternT,
__gnu_cxx::__cxx11::encoding_state>::extern_type*&) const’:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:392:58: error: no matching
function for call to ‘__iconv_adaptor(size_t (&)(iconv_t, char**,
size_t*, char**, size_t*), void* const&, int, int, char**,
std::size_t*)’
                                           &__cto, &__tlen);
                                                          ^
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:301:5: note: candidate:
‘template<class _Tp> std::size_t std::__iconv_adaptor(std::size_t
(*)(iconv_t, _Tp, std::size_t*, char**, std::size_t*), iconv_t, char**,
std::size_t*, char**, std::size_t*)’
     __iconv_adaptor(size_t(*__func)(iconv_t, _Tp, size_t*, char**,
size_t*),
     ^~~~~~~~~~~~~~~
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:301:5: note:   template
argument deduction/substitution failed:
./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:392:58: note:   cannot convert
‘0’ (type ‘int’) to type ‘char**’
                                           &__cto, &__tlen);
                                                          ^



(gdb) call debug_tree (arg)
 <non_dependent_expr 0x7fffe7402820
    type <integer_type 0x7ffff0e4f5e8 int asm_written public type_6 SI
        size <integer_cst 0x7ffff0e520c0 constant 32>
        unit-size <integer_cst 0x7ffff0e520d8 constant 4>
        align:32 warn_if_not_align:0 symtab:-291372496 alias-set -1
canonical-type 0x7ffff0e4f5e8 precision:32 min <integer_cst
0x7ffff0e52078 -2147483648> max <integer_cst 0x7ffff0e52090 2147483647>
        pointer_to_this <pointer_type 0x7ffff0e57a80> reference_to_this
<reference_type 0x7fffee916e70>>
   
    arg:0 <non_lvalue_expr 0x7fffe7402720 type <integer_type
0x7ffff0e4f5e8 int>
        constant
        arg:0 <integer_cst 0x7ffff0e52210 constant 0>
        ./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:391:50 start: ./build/x86_64-
pc-linux-gnu/libstdc++-v3/include/ext/codecvt_specializations.h:391:50
finish: ./build/x86_64-pc-linux-gnu/libstdc++-
v3/include/ext/codecvt_specializations.h:391:50>>


...when for a unpatched build we'd just have an INTEGER_CST.

Given the various TREE_CODE comparisons, using the
STRIP_ANY_LOCATION_WRAPPER macro seemed most appropriate; I put it
before the first TREE_CODE test.

I also added selftest::test_build_non_dependent_expr for this, to
verify that location wrappers don't affect the result of
build_non_dependent_expr (for integer constants and on string
literals).

Thanks
Dave

Reply via email to