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:
Jakub Jelinek 2017-01-26 20:39:40 +01:00 committed by Jakub Jelinek
parent c1cadde1cb
commit 905d2812e7
9 changed files with 66 additions and 24 deletions

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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),

View file

@ -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);
}

View file

@ -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.

View file

@ -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 }

View 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> ();