2014-09-08 Jason Merrill <jason@redhat.com>
+ * typeck.c (build_class_member_access_expr): Move
+ -Winvalid-offsetof code...
+ * semantics.c (finish_offsetof): ...here.
+ * parser.c (cp_parser_builtin_offsetof): Remember the location of
+ the type argument.
+ * pt.c (tsubst_copy_and_build) [OFFSETOF_EXPR]: Preserve it.
+
PR c++/62255
* pt.c (instantiate_decl): Handle recursive instantiation of
static data member.
extern tree calculate_bases (tree);
extern tree finish_bases (tree, bool);
extern tree calculate_direct_bases (tree);
-extern tree finish_offsetof (tree);
+extern tree finish_offsetof (tree, location_t);
extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
extern void emit_associated_thunks (tree);
/* Consume the opening `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
/* Parse the type-id. */
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
type = cp_parser_type_id (parser);
/* Look for the `,'. */
cp_parser_require (parser, CPP_COMMA, RT_COMMA);
/* 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 = build1 (OFFSETOF_EXPR, size_type_node, expr);
+ SET_EXPR_LOCATION (expr, loc);
+ }
else
- expr = finish_offsetof (expr);
+ expr = finish_offsetof (expr, loc);
failure:
parser->integral_constant_expression_p = save_ice_p;
}
case OFFSETOF_EXPR:
- RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0))));
+ RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
+ EXPR_LOCATION (t)));
case TRAIT_EXPR:
{
fold_offsetof. */
tree
-finish_offsetof (tree expr)
+finish_offsetof (tree expr, location_t loc)
{
if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
{
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));
}
return fold_offsetof (expr);
}
{
if (complain & tf_error)
{
- error ("invalid access to non-static data member %qD of "
- "NULL object",
- member);
- error ("(perhaps the %<offsetof%> macro was used incorrectly)");
+ error ("invalid access to non-static data member %qD in "
+ "virtual base of NULL object", member);
}
return error_mark_node;
}
gcc_assert (object != error_mark_node);
}
- /* Complain about other invalid uses of offsetof, even though they will
- give the right answer. Note that we complain whether or not they
- actually used the offsetof macro, since there's no way to know at this
- point. So we just give a warning, instead of a pedwarn. */
- /* Do not produce this warning for base class field references, because
- we know for a fact that didn't come from offsetof. This does occur
- in various testsuite cases where a null object is passed where a
- vtable access is required. */
- if (null_object_p && warn_invalid_offsetof
- && CLASSTYPE_NON_STD_LAYOUT (object_type)
- && !DECL_FIELD_IS_BASE (member)
- && cp_unevaluated_operand == 0
- && (complain & tf_warning))
- {
- warning (OPT_Winvalid_offsetof,
- "invalid access to non-static data member %qD "
- " of NULL object", member);
- warning (OPT_Winvalid_offsetof,
- "(perhaps the %<offsetof%> macro was used incorrectly)");
- }
-
/* If MEMBER is from an anonymous aggregate, we have converted
OBJECT so that it refers to the class containing the
anonymous union. Generate a reference to the anonymous union
@opindex Wno-invalid-offsetof
@opindex Winvalid-offsetof
Suppress warnings from applying the @samp{offsetof} macro to a non-POD
-type. According to the 1998 ISO C++ standard, applying @samp{offsetof}
-to a non-POD type is undefined. In existing C++ implementations,
-however, @samp{offsetof} typically gives meaningful results even when
-applied to certain kinds of non-POD types (such as a simple
-@samp{struct} that fails to be a POD type only by virtue of having a
-constructor). This flag is for users who are aware that they are
+type. According to the 2014 ISO C++ standard, applying @samp{offsetof}
+to a non-standard-layout type is undefined. In existing C++ implementations,
+however, @samp{offsetof} typically gives meaningful results.
+This flag is for users who are aware that they are
writing nonportable code and who have deliberately chosen to ignore the
warning about it.
// implementation thereof.
// Yes, this is bad, naughty, evil code. But it seems to be well-formed.
-// So we'll just warn.
// { dg-do run }
int main ()
{
- return ((__SIZE_TYPE__) &((C*)0)->i) != sizeof(void*); // { dg-warning "offsetof|invalid" "" }
+ return ((__SIZE_TYPE__) &((C*)0)->i) != sizeof(void*);
}
-/* Verify that offsetof warns if given a non-standard-layout class */
+/* Verify that offsetof complains if given a non-standard-layout class. */
/* Copyright (C) 2003 Free Software Foundation, Inc. */
/* Contributed by Matt Austern <austern@apple.com> 15 May 2003 */
-/* { dg-do compile } */
struct X
{
typedef X* pX;
typedef __SIZE_TYPE__ size_t;
-size_t yoff = size_t(&(pX(0)->y)); /* { dg-warning "invalid access" "" } */
-/* { dg-warning "macro was used incorrectly" "macro" { target *-*-* } 16 } */
+size_t yoff = __builtin_offsetof (X, y); /* { dg-error "35:non-standard-layout" } */
int &i;
};
-int j = offsetof (A, i); // { dg-warning "invalid access|offsetof" }
+int j = offsetof (A, i); // { dg-error "offsetof" }
template <typename T>
struct S
{
T h;
T &i;
- static const int j = offsetof (S, i); // { dg-warning "invalid access|offsetof" }
+ static const int j = offsetof (S, i); // { dg-error "offsetof" }
};
int k = S<int>::j; // { dg-message "required from here" }