diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-09-13 19:49:49 +0200 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-09-13 19:49:49 +0200 |
commit | b18a97e5dd0935e1c4a626c230f21457d0aad3d5 (patch) | |
tree | c1818f41af6fe780deafb6cd6a183f32085fe654 /gcc/d/expr.cc | |
parent | e76a53644c9d70e998c0d050e9a456af388c6b61 (diff) | |
download | gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.zip gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.gz gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.bz2 |
Merged current trunk to branch.
Diffstat (limited to 'gcc/d/expr.cc')
-rw-r--r-- | gcc/d/expr.cc | 121 |
1 files changed, 38 insertions, 83 deletions
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 2a1818a..ea21bd5 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1,5 +1,5 @@ /* expr.cc -- Lower D frontend expressions to GCC trees. - Copyright (C) 2015-2020 Free Software Foundation, Inc. + Copyright (C) 2015-2021 Free Software Foundation, Inc. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -101,8 +101,6 @@ binary_op (tree_code code, tree type, tree arg0, tree arg1) tree t1 = TREE_TYPE (arg1); tree ret = NULL_TREE; - bool unsignedp = TYPE_UNSIGNED (t0) || TYPE_UNSIGNED (t1); - /* Deal with float mod expressions immediately. */ if (code == FLOAT_MOD_EXPR) return build_float_modulus (type, arg0, arg1); @@ -130,12 +128,6 @@ binary_op (tree_code code, tree type, tree arg0, tree arg1) else ret = fold_build2 (POINTER_DIFF_EXPR, ptrtype, arg0, arg1); } - else if (INTEGRAL_TYPE_P (type) && (TYPE_UNSIGNED (type) != unsignedp)) - { - tree inttype = (unsignedp) - ? d_unsigned_type (type) : d_signed_type (type); - ret = fold_build2 (code, inttype, arg0, arg1); - } else { /* If the operation needs excess precision. */ @@ -157,7 +149,7 @@ binary_op (tree_code code, tree type, tree arg0, tree arg1) eptype = type; } - ret = fold_build2 (code, eptype, arg0, arg1); + ret = build2 (code, eptype, arg0, arg1); } return d_convert (type, ret); @@ -1163,9 +1155,9 @@ public: bool destructor = needs_dtor (etype); bool lvalue = lvalue_p (e->e2); - /* Even if the elements in rhs are all rvalues and don't have - to call postblits, this assignment should call dtors on old - assigned elements. */ + /* Optimize static array assignment with array literal. Even if the + elements in rhs are all rvalues and don't have to call postblits, + this assignment should call dtors on old assigned elements. */ if ((!postblit && !destructor) || (e->op == TOKconstruct && e->e2->op == TOKarrayliteral) || (e->op == TOKconstruct && !lvalue && postblit) @@ -1312,8 +1304,8 @@ public: /* If it's a static array and the index is constant, the front end has already checked the bounds. */ - if (tb1->ty != Tpointer && !e->indexIsInBounds) - index = build_bounds_condition (e->e2->loc, index, length, false); + if (tb1->ty != Tpointer) + index = build_bounds_index_condition (e, index, length); /* Index the .ptr. */ ptr = void_okay_p (ptr); @@ -1420,8 +1412,6 @@ public: ptr = build_array_index (void_okay_p (ptr), lwr_tree); ptr = build_nop (ptrtype, ptr); } - else - lwr_tree = NULL_TREE; /* Nothing more to do for static arrays, their bounds checking has been done at compile-time. */ @@ -1434,46 +1424,8 @@ public: gcc_assert (tb->ty == Tarray); /* Generate bounds checking code. */ - tree newlength; - - if (!e->upperIsInBounds) - { - if (length) - { - newlength = build_bounds_condition (e->upr->loc, upr_tree, - length, true); - } - else - { - /* Still need to check bounds lwr <= upr for pointers. */ - gcc_assert (tb1->ty == Tpointer); - newlength = upr_tree; - } - } - else - newlength = upr_tree; - - if (lwr_tree) - { - /* Enforces lwr <= upr. No need to check lwr <= length as - we've already ensured that upr <= length. */ - if (!e->lowerIsLessThanUpper) - { - tree cond = build_bounds_condition (e->lwr->loc, lwr_tree, - upr_tree, true); - - /* When bounds checking is off, the index value is - returned directly. */ - if (cond != lwr_tree) - newlength = compound_expr (cond, newlength); - } - - /* Need to ensure lwr always gets evaluated first, as it may be a - function call. Generates (lwr, upr) - lwr. */ - newlength = fold_build2 (MINUS_EXPR, TREE_TYPE (newlength), - compound_expr (lwr_tree, newlength), lwr_tree); - } - + tree newlength = build_bounds_slice_condition (e, lwr_tree, upr_tree, + length); tree result = d_array_value (build_ctype (e->type), newlength, ptr); this->result_ = compound_expr (array, result); } @@ -1491,7 +1443,7 @@ public: if (tbtype->ty == Tvoid) this->result_ = build_nop (build_ctype (tbtype), result); else - this->result_ = convert_expr (result, ebtype, tbtype); + this->result_ = convert_for_rvalue (result, ebtype, tbtype); } /* Build a delete expression. */ @@ -1751,6 +1703,7 @@ public: tree callee = NULL_TREE; tree object = NULL_TREE; tree cleanup = NULL_TREE; + tree returnvalue = NULL_TREE; TypeFunction *tf = NULL; /* Calls to delegates can sometimes look like this. */ @@ -1819,6 +1772,15 @@ public: else fndecl = build_address (fndecl); + /* C++ constructors return void, even though front-end semantic + treats them as implicitly returning `this'. Set returnvalue + to override the result of this expression. */ + if (fd->isCtorDeclaration () && fd->linkage == LINKcpp) + { + thisexp = d_save_expr (thisexp); + returnvalue = thisexp; + } + callee = build_method_call (fndecl, thisexp, fd->type); } } @@ -1885,6 +1847,9 @@ public: build the call expression. */ tree exp = d_build_call (tf, callee, object, e->arguments); + if (returnvalue != NULL_TREE) + exp = compound_expr (exp, returnvalue); + if (tf->isref) exp = build_deref (exp); @@ -1894,15 +1859,10 @@ public: exp = d_convert (build_ctype (e->type), exp); /* If this call was found to be a constructor for a temporary with a - cleanup, then move the call inside the TARGET_EXPR. The original - initializer is turned into an assignment, to keep its side effect. */ + cleanup, then move the call inside the TARGET_EXPR. */ if (cleanup != NULL_TREE) { tree init = TARGET_EXPR_INITIAL (cleanup); - tree slot = TARGET_EXPR_SLOT (cleanup); - d_mark_addressable (slot); - init = build_assign (INIT_EXPR, slot, init); - TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp); exp = cleanup; } @@ -2023,8 +1983,7 @@ public: tree assert_pass = void_node; tree assert_fail; - if (global.params.useAssert == CHECKENABLEon - && global.params.checkAction == CHECKACTION_D) + if (global.params.useAssert == CHECKENABLEon && !checkaction_trap_p ()) { /* Generate: ((bool) e1 ? (void)0 : _d_assert (...)) or: (e1 != null ? e1._invariant() : _d_assert (...)) */ @@ -2037,10 +1996,10 @@ public: libcall = unittest_p ? LIBCALL_UNITTEST_MSG : LIBCALL_ASSERT_MSG; } else - libcall = unittest_p ? LIBCALL_UNITTEST : LIBCALL_ASSERT; + libcall = unittest_p ? LIBCALL_UNITTESTP : LIBCALL_ASSERTP; /* Build a call to _d_assert(). */ - assert_fail = d_assert_call (e->loc, libcall, tmsg); + assert_fail = build_assert_call (e->loc, libcall, tmsg); if (global.params.useInvariants == CHECKENABLEon) { @@ -2068,8 +2027,7 @@ public: } } } - else if (global.params.useAssert == CHECKENABLEon - && global.params.checkAction == CHECKACTION_C) + else if (global.params.useAssert == CHECKENABLEon && checkaction_trap_p ()) { /* Generate: __builtin_trap() */ tree fn = builtin_decl_explicit (BUILT_IN_TRAP); @@ -2077,15 +2035,9 @@ public: } else { - /* Assert contracts are turned off, if the contract condition has no - side effects can still use it as a predicate for the optimizer. */ - if (TREE_SIDE_EFFECTS (arg)) - { - this->result_ = void_node; - return; - } - - assert_fail = build_predict_expr (PRED_NORETURN, NOT_TAKEN); + /* Assert contracts are turned off. */ + this->result_ = void_node; + return; } /* Build condition that we are asserting in this contract. */ @@ -3174,11 +3126,14 @@ build_return_dtor (Expression *e, Type *type, TypeFunction *tf) tree result = build_expr (e); /* Convert for initializing the DECL_RESULT. */ - result = convert_expr (result, e->type, type); - - /* If we are returning a reference, take the address. */ if (tf->isref) - result = build_address (result); + { + /* If we are returning a reference, take the address. */ + result = convert_expr (result, e->type, type); + result = build_address (result); + } + else + result = convert_for_rvalue (result, e->type, type); /* The decl to store the return expression. */ tree decl = DECL_RESULT (cfun->decl); |