diff options
Diffstat (limited to 'gcc/d/d-codegen.cc')
-rw-r--r-- | gcc/d/d-codegen.cc | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 403e3c7..c082ac5 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -2140,6 +2140,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object, /* Build the argument list for the call. */ vec <tree, va_gc> *args = NULL; tree saved_args = NULL_TREE; + bool noreturn_call = false; /* If this is a delegate call or a nested function being called as a delegate, the object should not be NULL. */ @@ -2165,9 +2166,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object, } } - size_t nparams = tf->parameterList.length (); + const size_t nparams = tf->parameterList.length (); /* if _arguments[] is the first argument. */ - size_t varargs = tf->isDstyleVariadic (); + const size_t varargs = tf->isDstyleVariadic (); /* Assumes arguments->length <= formal_args->length if (!tf->varargs). */ for (size_t i = 0; i < arguments->length; ++i) @@ -2206,6 +2207,11 @@ d_build_call (TypeFunction *tf, tree callable, tree object, build_address (targ)); } + /* Type `noreturn` is a terminator, as no other arguments can possibly + be evaluated after it. */ + if (TREE_TYPE (targ) == noreturn_type_node) + noreturn_call = true; + vec_safe_push (args, targ); } } @@ -2217,13 +2223,27 @@ d_build_call (TypeFunction *tf, tree callable, tree object, saved_args = compound_expr (callee, saved_args); } + /* If we saw a `noreturn` parameter, any unreachable argument evaluations + after it are discarded, as well as the function call itself. */ + if (noreturn_call) + { + if (TREE_SIDE_EFFECTS (callee)) + saved_args = compound_expr (callee, saved_args); + + tree arg; + unsigned int ix; + + FOR_EACH_VEC_SAFE_ELT (args, ix, arg) + saved_args = compound_expr (saved_args, arg); + + /* Add a stub result type for the expression. */ + tree result = build_zero_cst (TREE_TYPE (ctype)); + return compound_expr (saved_args, result); + } + tree result = build_call_vec (TREE_TYPE (ctype), callee, args); SET_EXPR_LOCATION (result, input_location); - /* Enforce left to right evaluation. */ - if (tf->linkage == LINK::d) - CALL_EXPR_ARGS_ORDERED (result) = 1; - result = maybe_expand_intrinsic (result); /* Return the value in a temporary slot so that it can be evaluated @@ -2296,6 +2316,10 @@ build_vthis_function (tree basetype, tree type) TYPE_ARG_TYPES (type)); tree fntype = build_function_type (TREE_TYPE (type), argtypes); + /* Copy volatile qualifiers from the original function type. */ + if (TYPE_QUALS (type) & TYPE_QUAL_VOLATILE) + fntype = build_qualified_type (fntype, TYPE_QUAL_VOLATILE); + if (RECORD_OR_UNION_TYPE_P (basetype)) TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype); else |