On 12/13/18 3:12 PM, David Malcolm wrote:
On Wed, 2018-12-12 at 15:37 -0500, Jason Merrill wrote:
On 12/7/18 3:13 PM, David Malcolm wrote:
On Tue, 2018-12-04 at 18:31 -0500, Jason Merrill wrote:
On 12/3/18 5:10 PM, Jeff Law wrote:
On 11/19/18 9:51 AM, David Malcolm wrote:

[...]
@@ -1058,6 +1058,9 @@ grokbitfield (const cp_declarator
*declarator,
         return NULL_TREE;
       }
+ if (width)
+    STRIP_ANY_LOCATION_WRAPPER (width);

Why is this needed?  We should already be reducing width to an
unwrapped
constant value somewhere along the line.

"width" is coming from cp_parser_member_declaration, from:

              /* Get the width of the bitfield.  */
              width = cp_parser_constant_expression (parser, false,
NULL,
                                                     cxx_dialect >=
cxx11);

and currently nothing is unwrapping the value.  We presumably need
to
unwrap (or fold?) it before it is stashed in
    DECL_BIT_FIELD_REPRESENTATIVE (value).

Without stripping (or folding) here, we e.g. lose a warning and get
this:
    FAIL: g++.dg/abi/empty22.C  -std=gnu++98  (test for warnings,
line 15)

Why does that happen?  check_bitfield_decl ought to handle the
location
wrapper fine.  That's where it gets folded.

The unstripped location wrapper defeats this check for zero in
check_field_decls within cp/class.c:

3555          if (DECL_C_BIT_FIELD (x)
3556              && integer_zerop (DECL_BIT_FIELD_REPRESENTATIVE (x)))
3556            /* We don't treat zero-width bitfields as making a class
3557               non-empty.  */

Aha. I wonder if integer_zerop should look through location wrappers? Or alternately, abort if it gets one?

On a tangent, perhaps we also want a macro like TREE_CODE that looks through wrappers. TREE_CODE_WRAPPED? _NO_WRAP? Other name ideas?

3558            ;
3559          else

leading it to erroneously use the "else" clause, which thus erroneously
clears CLASSTYPE_EMPTY_P, leading to the loss of:

g++.dg/abi/empty22.C:15:6: warning: empty class 'dummy' parameter passing
   ABI changes in -fabi-version=12 (GCC 8) [-Wabi]
    15 |   fun(d, f); // { dg-warning "empty" }
       |   ~~~^~~~~~

check_bitfield_decl is called *after* that check, so the folding there
doesn't help.

@@ -656,6 +656,9 @@ add_capture (tree lambda, tree id, tree
orig_init, bool by_reference_p,
         listmem = make_pack_expansion (member);
         initializer = orig_init;
       }
+
+  STRIP_ANY_LOCATION_WRAPPER (initializer);

Why is this needed?  What cares about the tree codes of the
capture
initializer?

This is used to populate LAMBDA_EXPR_CAPTURE_LIST.  Without
stripping,
we end up with wrapped VAR_DECLs, rather than the VAR_DECLs
themselves,

Sure, that sounds fine.

and this confuses things later on, for example leading to:

   PASS -> FAIL : g++.dg/cpp0x/lambda/lambda-type.C  -std=c++14
(test for excess errors)
   PASS -> FAIL : g++.dg/cpp0x/lambda/lambda-type.C  -std=c++17
(test for excess errors)

Confuses how?

Without stripping, we get extra errors for decltype() on identifiers in
the capture-list, e.g.:

   [i] {
     same_type<decltype(i),int>();
     same_type<decltype((i)),int const&>();
   };

cpp0x/lambda/lambda-type.C: In lambda function:
cpp0x/lambda/lambda-type.C:48:27: error: 'i' is not captured
    48 |     same_type<decltype((i)),int const&>();
       |                           ^
cpp0x/lambda/lambda-type.C:48:39: error: template argument 1 is invalid
    48 |     same_type<decltype((i)),int const&>();
       |                                       ^

These occur because, in capture_decltype, when searching for the decl for
"i" here:

   tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam));

the LAMBDA_EXPR_CAPTURE_LIST contains a wrapper around "i" rather than "i"
itself, and so "i" isn't found by value_member; "cap" thus becomes NULL_TREE,
and thus the error.

Ah.  Just above that I notice,

  /* FIXME do lookup instead of list walk? */

We could make that change, i.e.

tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
                             /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
...
if (cap && is_capture_proxy (cap))

Jason

Reply via email to