diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-01-26 20:39:40 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-01-26 20:39:40 +0100 |
commit | 905d2812e7bd7e41e833ef9bf4c953381b31c83b (patch) | |
tree | 156a3b12a0ead50dbb85377ac732b5a2b10a9341 /gcc | |
parent | c1cadde1cbd95e051885c3c9c5794a8d8c64e27a (diff) | |
download | gcc-905d2812e7bd7e41e833ef9bf4c953381b31c83b.zip gcc-905d2812e7bd7e41e833ef9bf4c953381b31c83b.tar.gz gcc-905d2812e7bd7e41e833ef9bf4c953381b31c83b.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 11 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/offsetof8.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/offsetof9.C | 17 |
9 files changed, 66 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 48d6952..443df69 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index ff4f4ef..c51c5c1 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 57833c5..f91b830 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 372a01e..9a61eb1 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 537d107..57334b4 100644 --- a/gcc/cp/pt.c +++ b/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), diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 55710e6..6d5ea95 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 876151b..61551d1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/other/offsetof8.C b/gcc/testsuite/g++.dg/other/offsetof8.C index daca70a..0668199 100644 --- a/gcc/testsuite/g++.dg/other/offsetof8.C +++ b/gcc/testsuite/g++.dg/other/offsetof8.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/other/offsetof9.C b/gcc/testsuite/g++.dg/other/offsetof9.C new file mode 100644 index 0000000..bd80fa5 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/offsetof9.C @@ -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> (); |