Skip to content

Commit d89c8cc

Browse files
bors[bot]philberty
andauthored
Merge #990
990: Add must use attribute support r=philberty a=philberty This is a port of the CPP front-end nodiscard attribute to be used for must_use. It contains a patch to clean up how we handle expressions vs statements and removes more of the GCC abstraction. Its my hope that we can leverage more and more existing code to get the static analysis where we want it. Fixes #856 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
2 parents b4bd389 + d6e1771 commit d89c8cc

20 files changed

+1004
-125
lines changed

gcc/rust/Make-lang.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ GRS_OBJS = \
111111
rust/rust-compile-type.o \
112112
rust/rust-constexpr.o \
113113
rust/rust-compile-base.o \
114+
rust/rust-tree.o \
114115
$(END)
115116
# removed object files from here
116117

gcc/rust/backend/rust-compile-base.cc

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "rust-compile-fnparam.h"
2323
#include "rust-compile-var-decl.h"
2424

25+
#include "rust-expr.h" // for AST::AttrInputLiteral
26+
2527
#include "fold-const.h"
2628
#include "stringpool.h"
2729

@@ -52,10 +54,16 @@ HIRCompileBase::setup_attributes_on_fndecl (
5254
for (const auto &attr : attrs)
5355
{
5456
bool is_inline = attr.get_path ().as_string ().compare ("inline") == 0;
57+
bool is_must_use
58+
= attr.get_path ().as_string ().compare ("must_use") == 0;
5559
if (is_inline)
5660
{
5761
handle_inline_attribute_on_fndecl (fndecl, attr);
5862
}
63+
else if (is_must_use)
64+
{
65+
handle_must_use_attribute_on_fndecl (fndecl, attr);
66+
}
5967
}
6068
}
6169

@@ -107,6 +115,30 @@ HIRCompileBase::handle_inline_attribute_on_fndecl (tree fndecl,
107115
}
108116
}
109117

118+
void
119+
HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl,
120+
const AST::Attribute &attr)
121+
{
122+
tree nodiscard = get_identifier ("nodiscard");
123+
tree value = NULL_TREE;
124+
125+
if (attr.has_attr_input ())
126+
{
127+
rust_assert (attr.get_attr_input ().get_attr_input_type ()
128+
== AST::AttrInput::AttrInputType::LITERAL);
129+
130+
auto &literal
131+
= static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
132+
const auto &msg_str = literal.get_literal ().as_string ();
133+
tree message = build_string (msg_str.size (), msg_str.c_str ());
134+
135+
value = tree_cons (nodiscard, message, NULL_TREE);
136+
}
137+
138+
DECL_ATTRIBUTES (fndecl)
139+
= tree_cons (nodiscard, value, DECL_ATTRIBUTES (fndecl));
140+
}
141+
110142
void
111143
HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
112144
{
@@ -262,9 +294,8 @@ HIRCompileBase::compile_function_body (Context *ctx, tree fndecl,
262294
auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
263295
if (compiled_expr != nullptr)
264296
{
265-
tree compiled_stmt
266-
= ctx->get_backend ()->expression_statement (fndecl, compiled_expr);
267-
ctx->add_statement (compiled_stmt);
297+
tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
298+
ctx->add_statement (s);
268299
}
269300
}
270301

@@ -289,10 +320,8 @@ HIRCompileBase::compile_function_body (Context *ctx, tree fndecl,
289320
}
290321
else
291322
{
292-
tree final_stmt
293-
= ctx->get_backend ()->expression_statement (fndecl,
294-
compiled_expr);
295-
ctx->add_statement (final_stmt);
323+
// FIXME can this actually happen?
324+
ctx->add_statement (compiled_expr);
296325
}
297326
}
298327
}

gcc/rust/backend/rust-compile-base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class HIRCompileBase
7979
static void handle_inline_attribute_on_fndecl (tree fndecl,
8080
const AST::Attribute &attr);
8181

82+
static void handle_must_use_attribute_on_fndecl (tree fndecl,
83+
const AST::Attribute &attr);
84+
8285
static void setup_abi_options (tree fndecl, ABI abi);
8386

8487
static tree address_expression (tree, Location);

gcc/rust/backend/rust-compile-context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
#include "rust-hir-type-check.h"
2626
#include "rust-backend.h"
2727
#include "rust-compile-tyty.h"
28-
#include "rust-ast-full.h"
2928
#include "rust-hir-full.h"
3029
#include "rust-mangle.h"
30+
#include "rust-tree.h"
3131

3232
namespace Rust {
3333
namespace Compile {

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
6363
void
6464
CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
6565
{
66-
fncontext fn = ctx->peek_fn ();
67-
6866
auto op = expr.get_expr_type ();
6967
auto lhs = CompileExpr::Compile (expr.get_left_expr ().get (), ctx);
7068
auto rhs = CompileExpr::Compile (expr.get_right_expr ().get (), ctx);
@@ -82,10 +80,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
8280
= resolve_operator_overload (lang_item_type, expr, lhs, rhs,
8381
expr.get_left_expr ().get (),
8482
expr.get_right_expr ().get ());
85-
auto assignment
86-
= ctx->get_backend ()->expression_statement (fn.fndecl,
87-
compound_assignment);
88-
ctx->add_statement (assignment);
83+
ctx->add_statement (compound_assignment);
8984

9085
return;
9186
}
@@ -94,7 +89,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr)
9489
= ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs,
9590
expr.get_locus ());
9691
tree assignment
97-
= ctx->get_backend ()->assignment_statement (fn.fndecl, lhs, operator_expr,
92+
= ctx->get_backend ()->assignment_statement (lhs, operator_expr,
9893
expr.get_locus ());
9994
ctx->add_statement (assignment);
10095
}
@@ -304,8 +299,10 @@ CompileExpr::visit (HIR::MatchExpr &expr)
304299
{
305300
tree result_reference
306301
= ctx->get_backend ()->var_expression (tmp, arm_locus);
307-
tree assignment = ctx->get_backend ()->assignment_statement (
308-
fnctx.fndecl, result_reference, kase_expr_tree, arm_locus);
302+
tree assignment
303+
= ctx->get_backend ()->assignment_statement (result_reference,
304+
kase_expr_tree,
305+
arm_locus);
309306
ctx->add_statement (assignment);
310307
}
311308

gcc/rust/backend/rust-compile-expr.h

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
169169

170170
void visit (HIR::AssignmentExpr &expr) override
171171
{
172-
fncontext fn = ctx->peek_fn ();
173172
auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx);
174173
auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx);
175174

@@ -191,7 +190,7 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
191190
expr.get_rhs ()->get_locus ());
192191

193192
tree assignment
194-
= ctx->get_backend ()->assignment_statement (fn.fndecl, lvalue, rvalue,
193+
= ctx->get_backend ()->assignment_statement (lvalue, rvalue,
195194
expr.get_locus ());
196195

197196
ctx->add_statement (assignment);
@@ -594,9 +593,7 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
594593
= CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr);
595594
tree loop_expr
596595
= ctx->get_backend ()->loop_expression (code_block, expr.get_locus ());
597-
tree loop_stmt
598-
= ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
599-
ctx->add_statement (loop_stmt);
596+
ctx->add_statement (loop_expr);
600597

601598
if (tmp != NULL)
602599
{
@@ -645,9 +642,7 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
645642
= CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx);
646643
tree exit_expr
647644
= ctx->get_backend ()->exit_expression (condition, expr.get_locus ());
648-
tree break_stmt
649-
= ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
650-
ctx->add_statement (break_stmt);
645+
ctx->add_statement (exit_expr);
651646

652647
tree code_block_stmt
653648
= CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr);
@@ -659,14 +654,11 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
659654

660655
tree loop_expr
661656
= ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ());
662-
tree loop_stmt
663-
= ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
664-
ctx->add_statement (loop_stmt);
657+
ctx->add_statement (loop_expr);
665658
}
666659

667660
void visit (HIR::BreakExpr &expr) override
668661
{
669-
fncontext fnctx = ctx->peek_fn ();
670662
if (expr.has_break_expr ())
671663
{
672664
tree compiled_expr
@@ -676,8 +668,10 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
676668
tree result_reference = ctx->get_backend ()->var_expression (
677669
loop_result_holder, expr.get_expr ()->get_locus ());
678670

679-
tree assignment = ctx->get_backend ()->assignment_statement (
680-
fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ());
671+
tree assignment
672+
= ctx->get_backend ()->assignment_statement (result_reference,
673+
compiled_expr,
674+
expr.get_locus ());
681675
ctx->add_statement (assignment);
682676
}
683677

@@ -721,9 +715,7 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
721715
tree exit_expr = ctx->get_backend ()->exit_expression (
722716
ctx->get_backend ()->boolean_constant_expression (true),
723717
expr.get_locus ());
724-
tree break_stmt
725-
= ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
726-
ctx->add_statement (break_stmt);
718+
ctx->add_statement (exit_expr);
727719
}
728720
}
729721

@@ -761,9 +753,7 @@ class CompileExpr : public HIRCompileBase, public HIR::HIRExpressionVisitor
761753
}
762754
}
763755

764-
tree goto_label
765-
= ctx->get_backend ()->goto_statement (label, expr.get_locus ());
766-
ctx->add_statement (goto_label);
756+
translated = ctx->get_backend ()->goto_statement (label, expr.get_locus ());
767757
}
768758

769759
void visit (HIR::BorrowExpr &expr) override;

gcc/rust/backend/rust-compile-stmt.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ class CompileStmt : public HIRCompileBase, public HIR::HIRStmtVisitor
9090
auto fnctx = ctx->peek_fn ();
9191
if (ty->is_unit ())
9292
{
93-
tree expr_stmt
94-
= ctx->get_backend ()->expression_statement (fnctx.fndecl, init);
95-
ctx->add_statement (expr_stmt);
93+
// FIXME this feels wrong
94+
ctx->add_statement (init);
9695
}
9796
else
9897
{

gcc/rust/backend/rust-compile.cc

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,8 @@ CompileBlock::visit (HIR::BlockExpr &expr)
8282
auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
8383
if (compiled_expr != nullptr)
8484
{
85-
tree compiled_stmt
86-
= ctx->get_backend ()->expression_statement (fnctx.fndecl,
87-
compiled_expr);
88-
ctx->add_statement (compiled_stmt);
85+
tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
86+
ctx->add_statement (s);
8987
}
9088
}
9189

@@ -98,19 +96,15 @@ CompileBlock::visit (HIR::BlockExpr &expr)
9896
{
9997
if (result == nullptr)
10098
{
101-
tree final_stmt
102-
= ctx->get_backend ()->expression_statement (fnctx.fndecl,
103-
compiled_expr);
104-
ctx->add_statement (final_stmt);
99+
ctx->add_statement (compiled_expr);
105100
}
106101
else
107102
{
108103
tree result_reference = ctx->get_backend ()->var_expression (
109104
result, expr.get_final_expr ()->get_locus ());
110105

111106
tree assignment
112-
= ctx->get_backend ()->assignment_statement (fnctx.fndecl,
113-
result_reference,
107+
= ctx->get_backend ()->assignment_statement (result_reference,
114108
compiled_expr,
115109
expr.get_locus ());
116110
ctx->add_statement (assignment);

gcc/rust/backend/rust-constexpr.cc

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "rust-constexpr.h"
1818
#include "rust-location.h"
1919
#include "rust-diagnostics.h"
20+
#include "rust-tree.h"
2021

2122
#include "fold-const.h"
2223
#include "realmpfr.h"
@@ -25,52 +26,6 @@
2526
#include "gimplify.h"
2627
#include "tree-iterator.h"
2728

28-
/* Returns true if NODE is a pointer. */
29-
#define TYPE_PTR_P(NODE) (TREE_CODE (NODE) == POINTER_TYPE)
30-
31-
/* Returns true if NODE is a reference. */
32-
#define TYPE_REF_P(NODE) (TREE_CODE (NODE) == REFERENCE_TYPE)
33-
34-
/* Returns true if NODE is a pointer or a reference. */
35-
#define INDIRECT_TYPE_P(NODE) (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
36-
37-
/* [basic.fundamental]
38-
39-
Types bool, char, wchar_t, and the signed and unsigned integer types
40-
are collectively called integral types.
41-
42-
Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration
43-
types as well, which is incorrect in C++. Keep these checks in
44-
ascending code order. */
45-
#define RS_INTEGRAL_TYPE_P(TYPE) \
46-
(TREE_CODE (TYPE) == BOOLEAN_TYPE || TREE_CODE (TYPE) == INTEGER_TYPE)
47-
48-
/* [basic.fundamental]
49-
50-
Integral and floating types are collectively called arithmetic
51-
types.
52-
53-
As a GNU extension, we also accept complex types.
54-
55-
Keep these checks in ascending code order. */
56-
#define ARITHMETIC_TYPE_P(TYPE) \
57-
(RS_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE \
58-
|| TREE_CODE (TYPE) == COMPLEX_TYPE)
59-
60-
/* True iff TYPE is cv decltype(nullptr). */
61-
#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE)
62-
63-
/* [basic.types]
64-
65-
Arithmetic types, enumeration types, pointer types,
66-
pointer-to-member types, and std::nullptr_t are collectively called
67-
scalar types.
68-
69-
Keep these checks in ascending code order. */
70-
#define SCALAR_TYPE_P(TYPE) \
71-
(TREE_CODE (TYPE) == ENUMERAL_TYPE || ARITHMETIC_TYPE_P (TYPE) \
72-
|| TYPE_PTR_P (TYPE) || NULLPTR_TYPE_P (TYPE))
73-
7429
namespace Rust {
7530
namespace Compile {
7631

0 commit comments

Comments
 (0)