re PR c++/68727 (invalid offsetof expressions accepted)
PR c++/68727 * cp-tree.def (OFFSETOF_EXPR): Bump number of operands to 2. * cp-tree.h (finish_offsetof): Add OBJECT_PTR argument. * parser.c (cp_parser_builtin_offsetof): Pass result of build_static_cast of null_pointer_node to finish_offsetof. * semantics.c (finish_offsetof): Add OBJECT_PTR argument, use it for -Winvalid-offsetof pedwarn instead of trying to guess original offsetof type from EXPR. Save OBJECT_PTR as a new second operand to OFFSETOF_EXPR. * pt.c (tsubst_copy_and_build) <case OFFSETOF_EXPR>: Adjust finish_offsetof caller, pass the second operand of OFFSETOF_EXPR as OBJECT_PTR. * g++.dg/other/offsetof8.C: Add expected error. * g++.dg/other/offsetof9.C: New test. From-SVN: r244949
This commit is contained in:
parent
c1cadde1cb
commit
905d2812e7
9 changed files with 66 additions and 24 deletions
|
@ -1,3 +1,18 @@
|
|||
2017-01-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/68727
|
||||
* cp-tree.def (OFFSETOF_EXPR): Bump number of operands to 2.
|
||||
* cp-tree.h (finish_offsetof): Add OBJECT_PTR argument.
|
||||
* parser.c (cp_parser_builtin_offsetof): Pass result of
|
||||
build_static_cast of null_pointer_node to finish_offsetof.
|
||||
* semantics.c (finish_offsetof): Add OBJECT_PTR argument, use
|
||||
it for -Winvalid-offsetof pedwarn instead of trying to guess
|
||||
original offsetof type from EXPR. Save OBJECT_PTR as a new
|
||||
second operand to OFFSETOF_EXPR.
|
||||
* pt.c (tsubst_copy_and_build) <case OFFSETOF_EXPR>: Adjust
|
||||
finish_offsetof caller, pass the second operand of OFFSETOF_EXPR
|
||||
as OBJECT_PTR.
|
||||
|
||||
2017-01-26 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* name-lookup.c (parse_using_directive): Deprecate strong using.
|
||||
|
|
|
@ -333,7 +333,7 @@ DEFTREECODE (EXPR_STMT, "expr_stmt", tcc_expression, 1)
|
|||
DEFTREECODE (TAG_DEFN, "tag_defn", tcc_expression, 0)
|
||||
|
||||
/* Represents an 'offsetof' expression during template expansion. */
|
||||
DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1)
|
||||
DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 2)
|
||||
|
||||
/* Represents an '__builtin_addressof' expression during template
|
||||
expansion. This is similar to ADDR_EXPR, but it doesn't invoke
|
||||
|
|
|
@ -6487,7 +6487,7 @@ extern tree finish_underlying_type (tree);
|
|||
extern tree calculate_bases (tree);
|
||||
extern tree finish_bases (tree, bool);
|
||||
extern tree calculate_direct_bases (tree);
|
||||
extern tree finish_offsetof (tree, location_t);
|
||||
extern tree finish_offsetof (tree, tree, location_t);
|
||||
extern void finish_decl_cleanup (tree, tree);
|
||||
extern void finish_eh_cleanup (tree);
|
||||
extern void emit_associated_thunks (tree);
|
||||
|
|
|
@ -9498,11 +9498,12 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
|||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* Build the (type *)null that begins the traditional offsetof macro. */
|
||||
expr = build_static_cast (build_pointer_type (type), null_pointer_node,
|
||||
tf_warning_or_error);
|
||||
tree object_ptr
|
||||
= build_static_cast (build_pointer_type (type), null_pointer_node,
|
||||
tf_warning_or_error);
|
||||
|
||||
/* Parse the offsetof-member-designator. We begin as if we saw "expr->". */
|
||||
expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
|
||||
expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, object_ptr,
|
||||
true, &dummy, token->location);
|
||||
while (true)
|
||||
{
|
||||
|
@ -9554,7 +9555,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
|||
loc = make_location (loc, start_loc, finish_loc);
|
||||
/* The result will be an INTEGER_CST, so we need to explicitly
|
||||
preserve the location. */
|
||||
expr = cp_expr (finish_offsetof (expr, loc), loc);
|
||||
expr = cp_expr (finish_offsetof (object_ptr, expr, loc), loc);
|
||||
|
||||
failure:
|
||||
parser->integral_constant_expression_p = save_ice_p;
|
||||
|
|
11
gcc/cp/pt.c
11
gcc/cp/pt.c
|
@ -17707,8 +17707,15 @@ tsubst_copy_and_build (tree t,
|
|||
}
|
||||
|
||||
case OFFSETOF_EXPR:
|
||||
RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
|
||||
EXPR_LOCATION (t)));
|
||||
{
|
||||
tree object_ptr
|
||||
= tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
|
||||
in_decl, /*function_p=*/false,
|
||||
/*integral_constant_expression_p=*/false);
|
||||
RETURN (finish_offsetof (object_ptr,
|
||||
RECUR (TREE_OPERAND (t, 0)),
|
||||
EXPR_LOCATION (t)));
|
||||
}
|
||||
|
||||
case ADDRESSOF_EXPR:
|
||||
RETURN (cp_build_addressof (EXPR_LOCATION (t),
|
||||
|
|
|
@ -3995,13 +3995,13 @@ finish_bases (tree type, bool direct)
|
|||
fold_offsetof. */
|
||||
|
||||
tree
|
||||
finish_offsetof (tree expr, location_t loc)
|
||||
finish_offsetof (tree object_ptr, tree expr, location_t loc)
|
||||
{
|
||||
/* If we're processing a template, we can't finish the semantics yet.
|
||||
Otherwise we can fold the entire expression now. */
|
||||
if (processing_template_decl)
|
||||
{
|
||||
expr = build1 (OFFSETOF_EXPR, size_type_node, expr);
|
||||
expr = build2 (OFFSETOF_EXPR, size_type_node, expr, object_ptr);
|
||||
SET_EXPR_LOCATION (expr, loc);
|
||||
return expr;
|
||||
}
|
||||
|
@ -4031,19 +4031,15 @@ finish_offsetof (tree expr, location_t loc)
|
|||
}
|
||||
if (REFERENCE_REF_P (expr))
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
if (TREE_CODE (expr) == COMPONENT_REF)
|
||||
{
|
||||
tree object = TREE_OPERAND (expr, 0);
|
||||
if (!complete_type_or_else (TREE_TYPE (object), object))
|
||||
return error_mark_node;
|
||||
if (warn_invalid_offsetof
|
||||
&& CLASS_TYPE_P (TREE_TYPE (object))
|
||||
&& CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (object))
|
||||
&& cp_unevaluated_operand == 0)
|
||||
pedwarn (loc, OPT_Winvalid_offsetof,
|
||||
"offsetof within non-standard-layout type %qT is undefined",
|
||||
TREE_TYPE (object));
|
||||
}
|
||||
if (!complete_type_or_else (TREE_TYPE (TREE_TYPE (object_ptr)), object_ptr))
|
||||
return error_mark_node;
|
||||
if (warn_invalid_offsetof
|
||||
&& CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr)))
|
||||
&& CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr)))
|
||||
&& cp_unevaluated_operand == 0)
|
||||
pedwarn (loc, OPT_Winvalid_offsetof,
|
||||
"offsetof within non-standard-layout type %qT is undefined",
|
||||
TREE_TYPE (TREE_TYPE (object_ptr)));
|
||||
return fold_offsetof (expr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2017-01-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/68727
|
||||
* g++.dg/other/offsetof8.C: Add expected error.
|
||||
* g++.dg/other/offsetof9.C: New test.
|
||||
|
||||
2017-01-26 David Edelsohn <dje.gcc@gmail.com>
|
||||
|
||||
* g++.dg/opt/declone3.C: Require LTO.
|
||||
|
|
|
@ -9,4 +9,4 @@ struct B: virtual A { };
|
|||
int a[] = {
|
||||
!&((B*)0)->i, // { dg-error "invalid access to non-static data member" }
|
||||
__builtin_offsetof (B, i) // { dg-error "invalid access to non-static" }
|
||||
};
|
||||
}; // { dg-error "offsetof within non-standard-layout type" "" { target *-*-* } .-1 }
|
||||
|
|
17
gcc/testsuite/g++.dg/other/offsetof9.C
Normal file
17
gcc/testsuite/g++.dg/other/offsetof9.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// PR c++/68727
|
||||
// { dg-do compile }
|
||||
// { dg-options "-Winvalid-offsetof" }
|
||||
|
||||
struct A { int i; };
|
||||
struct B : virtual A { };
|
||||
__SIZE_TYPE__ s = __builtin_offsetof (B, A::i); // { dg-warning "offsetof within non-standard-layout type" }
|
||||
|
||||
template <typename T>
|
||||
__SIZE_TYPE__
|
||||
foo ()
|
||||
{
|
||||
return __builtin_offsetof (T, A::i) // { dg-warning "offsetof within non-standard-layout type" }
|
||||
+ __builtin_offsetof (B, A::i); // { dg-warning "offsetof within non-standard-layout type" }
|
||||
}
|
||||
|
||||
__SIZE_TYPE__ t = foo<B> ();
|
Loading…
Add table
Reference in a new issue