aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2023-12-05 15:23:52 -0500
committerMarek Polacek <polacek@redhat.com>2023-12-14 16:05:37 -0500
commit8cccdc2176740f3e034ee6caa49552cf2f142744 (patch)
tree090045eb688fa26f2ffc7683c7be88b6982dd4ef /gcc
parent7b15959f8e35b821ebfe832a36e5e712b708dae1 (diff)
downloadgcc-8cccdc2176740f3e034ee6caa49552cf2f142744.zip
gcc-8cccdc2176740f3e034ee6caa49552cf2f142744.tar.gz
gcc-8cccdc2176740f3e034ee6caa49552cf2f142744.tar.bz2
c++: fix ICE with sizeof in a template [PR112869]
This test shows that we cannot clear *walk_subtrees in cp_fold_immediate_r when we're in_immediate_context, because that checks even e.g. sk_template_parms, and, as the comment says, affects cp_fold_r as well. Here we had an expression with min ((long int) VIEW_CONVERT_EXPR<long unsigned int>(bytecount), (long int) <<< Unknown tree: sizeof_expr (int) <<< error >>> >>>) as its sub-expression, and we never evaluated that into min ((long int) bytecount, 4) so the SIZEOF_EXPR leaked into the middle end. We need to make sure we are calling cp_fold on the SIZEOF_EXPR. PR c++/112869 gcc/cp/ChangeLog: * cp-gimplify.cc (cp_fold_immediate_r): Check cp_unevaluated_operand and DECL_IMMEDIATE_FUNCTION_P rather than in_immediate_context. gcc/testsuite/ChangeLog: * g++.dg/template/sizeof18.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-gimplify.cc8
-rw-r--r--gcc/testsuite/g++.dg/template/sizeof18.C8
2 files changed, 15 insertions, 1 deletions
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index c307e1b..64049f4 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1179,7 +1179,13 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)
/* No need to look into types or unevaluated operands.
NB: This affects cp_fold_r as well. */
- if (TYPE_P (stmt) || unevaluated_p (code) || in_immediate_context ())
+ if (TYPE_P (stmt)
+ || unevaluated_p (code)
+ /* We do not use in_immediate_context here because it checks
+ more than is desirable, e.g., sk_template_parms. */
+ || cp_unevaluated_operand
+ || (current_function_decl
+ && DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
{
*walk_subtrees = 0;
return NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/template/sizeof18.C b/gcc/testsuite/g++.dg/template/sizeof18.C
new file mode 100644
index 0000000..afba994
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sizeof18.C
@@ -0,0 +1,8 @@
+// PR c++/112869
+// { dg-do compile }
+
+void min(long, long);
+template <class T> void Binaryread(int &, T, unsigned long);
+template <> void Binaryread(int &, float, unsigned long bytecount) {
+ min(bytecount, sizeof(int));
+}