aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-01-26 20:39:40 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-01-26 20:39:40 +0100
commit905d2812e7bd7e41e833ef9bf4c953381b31c83b (patch)
tree156a3b12a0ead50dbb85377ac732b5a2b10a9341 /gcc
parentc1cadde1cbd95e051885c3c9c5794a8d8c64e27a (diff)
downloadgcc-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/ChangeLog15
-rw-r--r--gcc/cp/cp-tree.def2
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/parser.c9
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/cp/semantics.c26
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/other/offsetof8.C2
-rw-r--r--gcc/testsuite/g++.dg/other/offsetof9.C17
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> ();