From cf8aa843a7bb5f173eb8107b1c721e964b9e0677 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 7 Dec 2015 13:47:03 -0500
Subject: [PATCH] WIP: add INVALID_LOCATION and use it to poison src_range
---
gcc/c/c-parser.c | 8 +++++++-
gcc/c/c-tree.h | 26 ++++++++++++++++++++++++++
gcc/c/c-typeck.c | 2 ++
gcc/tree.c | 6 ++++++
libcpp/include/line-map.h | 10 +++++++++-
libcpp/line-map.c | 7 +++++++
6 files changed, 57 insertions(+), 2 deletions(-)
@@ -63,6 +63,8 @@ void
set_c_expr_source_range (c_expr *expr,
location_t start, location_t finish)
{
+ gcc_assert (start != INVALID_LOCATION);
+ gcc_assert (finish != INVALID_LOCATION);
expr->src_range.m_start = start;
expr->src_range.m_finish = finish;
if (expr->value)
@@ -73,6 +75,8 @@ void
set_c_expr_source_range (c_expr *expr,
source_range src_range)
{
+ gcc_assert (src_range.m_start != INVALID_LOCATION);
+ gcc_assert (src_range.m_finish != INVALID_LOCATION);
expr->src_range = src_range;
if (expr->value)
set_source_range (expr->value, src_range);
@@ -6145,6 +6149,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
c_parser_consume_token (parser);
exp_location = c_parser_peek_token (parser)->location;
rhs = c_parser_expr_no_commas (parser, NULL);
+ gcc_assert (rhs.src_range.m_start != INVALID_LOCATION);
+ gcc_assert (rhs.src_range.m_finish != INVALID_LOCATION);
rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
@@ -6917,7 +6923,6 @@ c_parser_alignof_expression (c_parser *parser)
}
else
{
- struct c_expr ret;
expr = c_parser_unary_expression (parser);
end_loc = expr.src_range.m_finish;
alignof_expr:
@@ -6927,6 +6932,7 @@ c_parser_alignof_expression (c_parser *parser)
pedwarn (start_loc,
OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
alignof_spelling);
+ struct c_expr ret;
ret.value = c_alignof_expr (start_loc, expr.value);
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
@@ -118,6 +118,32 @@ along with GCC; see the file COPYING3. If not see
for code generation alongside a tree representing its value. */
struct c_expr
{
+ c_expr ()
+ {
+ /* In a checkeed build, poison the initial value of src_range so
+ that attempts to use uninitialized data fail with an assertion,
+ without needing to run under Valgrind. */
+#if CHECKING_P
+ src_range.m_start = INVALID_LOCATION;
+ src_range.m_finish = INVALID_LOCATION;
+#endif
+ }
+
+ c_expr (const c_expr &other)
+ {
+ value = other.value;
+ original_code = other.original_code;
+ original_type = other.original_type;
+#if CHECKING_P
+ if (value != error_mark_node)
+ {
+ gcc_assert (other.src_range.m_start != INVALID_LOCATION);
+ gcc_assert (other.src_range.m_finish != INVALID_LOCATION);
+ }
+#endif
+ src_range = other.src_range;
+ }
+
/* The value of the expression. */
tree value;
/* Record the original unary/binary operator of an expression, which may
@@ -6821,6 +6821,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
expr.original_type = NULL;
+ expr.src_range.m_start = init_loc;
+ expr.src_range.m_finish = init_loc;
maybe_warn_string_init (init_loc, type, expr);
if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
@@ -13938,6 +13938,9 @@ set_block (location_t loc, tree block)
location_t
set_source_range (tree expr, location_t start, location_t finish)
{
+ gcc_assert (start != INVALID_LOCATION);
+ gcc_assert (finish != INVALID_LOCATION);
+
source_range src_range;
src_range.m_start = start;
src_range.m_finish = finish;
@@ -13950,6 +13953,9 @@ set_source_range (tree expr, source_range src_range)
if (!EXPR_P (expr))
return UNKNOWN_LOCATION;
+ gcc_assert (src_range.m_start != INVALID_LOCATION);
+ gcc_assert (src_range.m_finish != INVALID_LOCATION);
+
location_t pure_loc = get_pure_location (EXPR_LOCATION (expr));
location_t adhoc = COMBINE_LOCATION_DATA (line_table,
pure_loc,
@@ -160,7 +160,7 @@ typedef unsigned int linenum_type;
-----------+-------------------------------+-------------------------------
0x80000000 | Start of ad-hoc values; the lower 31 bits are used as an index
... | into the line_table->location_adhoc_data_map.data array.
- 0xffffffff | UINT_MAX |
+ 0xffffffff | UINT_MAX == INVALID_LOCATION |
-----------+-------------------------------+-------------------------------
Examples of location encoding.
@@ -260,6 +260,10 @@ typedef unsigned int linenum_type;
worked example in libcpp/location-example.txt. */
typedef unsigned int source_location;
+/* A bogus value, used for detecting uninitialized data in checked
+ builds. */
+#define INVALID_LOCATION ((source_location) UINT_MAX)
+
/* A range of source locations.
Ranges are closed:
@@ -1004,6 +1008,10 @@ COMBINE_LOCATION_DATA (struct line_maps *set,
source_range src_range,
void *block)
{
+ linemap_assert (loc != INVALID_LOCATION);
+ linemap_assert (src_range.m_start != INVALID_LOCATION);
+ linemap_assert (src_range.m_finish != INVALID_LOCATION);
+
return get_combined_adhoc_loc (set, loc, src_range, block);
}
@@ -84,6 +84,10 @@ location_adhoc_data_eq (const void *l1, const void *l2)
(const struct location_adhoc_data *) l1;
const struct location_adhoc_data *lb2 =
(const struct location_adhoc_data *) l2;
+ linemap_assert (lb1->src_range.m_start != INVALID_LOCATION);
+ linemap_assert (lb1->src_range.m_finish != INVALID_LOCATION);
+ linemap_assert (lb2->src_range.m_start != INVALID_LOCATION);
+ linemap_assert (lb2->src_range.m_finish != INVALID_LOCATION);
return (lb1->locus == lb2->locus
&& lb1->src_range.m_start == lb2->src_range.m_start
&& lb1->src_range.m_finish == lb2->src_range.m_finish
@@ -166,6 +170,9 @@ get_combined_adhoc_loc (struct line_maps *set,
struct location_adhoc_data lb;
struct location_adhoc_data **slot;
+ linemap_assert (src_range.m_start != INVALID_LOCATION);
+ linemap_assert (src_range.m_finish != INVALID_LOCATION);
+
if (IS_ADHOC_LOC (locus))
locus
= set->location_adhoc_data_map.data[locus & MAX_SOURCE_LOCATION].locus;
--
1.8.5.3