aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/d-codegen.cc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-10-28 09:42:15 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-10-28 09:53:36 +0200
commit5d2a360f0a541646abb11efdbabc33c6a04de7ee (patch)
tree30f899e4220039d70a9c244498b54dbc0cee7931 /gcc/d/d-codegen.cc
parent7f974c5fd4f59a9d8dd20c49a0e2909cb290f4b4 (diff)
downloadgcc-5d2a360f0a541646abb11efdbabc33c6a04de7ee.zip
gcc-5d2a360f0a541646abb11efdbabc33c6a04de7ee.tar.gz
gcc-5d2a360f0a541646abb11efdbabc33c6a04de7ee.tar.bz2
d: Add warning for call expression without side effects
In the last merge of the dmd front-end with upstream (r14-4830), this warning got removed from the semantic passes. Reimplement the warning for the code generation pass instead, where it cannot have an effect on conditional compilation. gcc/d/ChangeLog: * d-codegen.cc (call_side_effect_free_p): New function. * d-tree.h (CALL_EXPR_WARN_IF_UNUSED): New macro. (call_side_effect_free_p): New prototype. * expr.cc (ExprVisitor::visit (CallExp *)): Set CALL_EXPR_WARN_IF_UNUSED on matched call expressions. (ExprVisitor::visit (NewExp *)): Don't dereference the result of an allocation call here. * toir.cc (add_stmt): Emit warning when call expression added to statement list without being used. gcc/testsuite/ChangeLog: * gdc.dg/Wunused_value.d: New test.
Diffstat (limited to 'gcc/d/d-codegen.cc')
-rw-r--r--gcc/d/d-codegen.cc54
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 155f5d0..91ddb1b 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2102,6 +2102,60 @@ get_function_type (Type *t)
return tf;
}
+/* Returns TRUE if calling the function FUNC, or calling a function or delegate
+ object of type TYPE is be free of side effects. */
+
+bool
+call_side_effect_free_p (FuncDeclaration *func, Type *type)
+{
+ gcc_assert (func != NULL || type != NULL);
+
+ if (func != NULL)
+ {
+ /* Constructor and invariant calls can't be `pure'. */
+ if (func->isCtorDeclaration () || func->isInvariantDeclaration ())
+ return false;
+
+ /* Must be a `nothrow' function. */
+ TypeFunction *tf = func->type->toTypeFunction ();
+ if (!tf->isnothrow ())
+ return false;
+
+ /* Return type can't be `void' or `noreturn', as that implies all work is
+ done via side effects. */
+ if (tf->next->ty == TY::Tvoid || tf->next->ty == TY::Tnoreturn)
+ return false;
+
+ /* Only consider it as `pure' if it can't modify its arguments. */
+ if (func->isPure () == PURE::const_)
+ return true;
+ }
+
+ if (type != NULL)
+ {
+ TypeFunction *tf = get_function_type (type);
+
+ /* Must be a `nothrow` function type. */
+ if (tf == NULL || !tf->isnothrow ())
+ return false;
+
+ /* Return type can't be `void' or `noreturn', as that implies all work is
+ done via side effects. */
+ if (tf->next->ty == TY::Tvoid || tf->next->ty == TY::Tnoreturn)
+ return false;
+
+ /* Delegates that can modify its context can't be `pure'. */
+ if (type->isTypeDelegate () && tf->isMutable ())
+ return false;
+
+ /* Only consider it as `pure' if it can't modify its arguments. */
+ if (tf->purity == PURE::const_)
+ return true;
+ }
+
+ return false;
+}
+
/* Returns TRUE if CALLEE is a plain nested function outside the scope of
CALLER. In which case, CALLEE is being called through an alias that was
passed to CALLER. */