C++: Fix crash in warn_for_memset within templates (PR c++/83814)

gcc/c-family/ChangeLog:
	PR c++/83814
	* c-common.c (fold_for_warn): Move to c/c-fold.c and cp/expr.c.

gcc/c/ChangeLog:
	PR c++/83814
	* c-fold.c (fold_for_warn): Move from c-common.c, reducing to just
	the C part.

gcc/cp/ChangeLog:
	PR c++/83814
	* expr.c (fold_for_warn): Move from c-common.c, reducing to just
	the C++ part.  If processing a template, call
	fold_non_dependent_expr rather than fully folding.

gcc/testsuite/ChangeLog:
	PR c++/83814
	PR c++/83902
	* g++.dg/wrappers/pr83814.C: New test case.
	* g++.dg/wrappers/pr83902.C: New test case.

From-SVN: r256804
This commit is contained in:
David Malcolm 2018-01-17 17:51:25 +00:00 committed by David Malcolm
parent d2edcd7083
commit bb9869d5a3
9 changed files with 129 additions and 13 deletions

View file

@ -1,3 +1,8 @@
2018-01-17 David Malcolm <dmalcolm@redhat.com>
PR c++/83814
* c-common.c (fold_for_warn): Move to c/c-fold.c and cp/expr.c.
2018-01-10 Eric Botcazou <ebotcazou@adacore.com>
* c-ada-spec.c (dump_number): Add FLOAT_P parameter.

View file

@ -868,19 +868,6 @@ c_get_substring_location (const substring_loc &substr_loc,
}
/* Fold X for consideration by one of the warning functions when checking
whether an expression has a constant value. */
tree
fold_for_warn (tree x)
{
if (c_dialect_cxx ())
return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
else
/* The C front-end has already folded X appropriately. */
return x;
}
/* Return true iff T is a boolean promoted to int. */
bool

View file

@ -1,3 +1,9 @@
2018-01-17 David Malcolm <dmalcolm@redhat.com>
PR c++/83814
* c-fold.c (fold_for_warn): Move from c-common.c, reducing to just
the C part.
2018-01-13 Jakub Jelinek <jakub@redhat.com>
PR c/83801

View file

@ -676,3 +676,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
}
return ret;
}
/* Fold X for consideration by one of the warning functions when checking
whether an expression has a constant value. */
tree
fold_for_warn (tree x)
{
/* The C front-end has already folded X appropriately. */
return x;
}

View file

@ -1,3 +1,10 @@
2018-01-17 David Malcolm <dmalcolm@redhat.com>
PR c++/83814
* expr.c (fold_for_warn): Move from c-common.c, reducing to just
the C++ part. If processing a template, call
fold_non_dependent_expr rather than fully folding.
2018-01-17 Jason Merrill <jason@redhat.com>
PR c++/81067 - redundant NULL warning.

View file

@ -315,3 +315,18 @@ mark_exp_read (tree exp)
}
}
/* Fold X for consideration by one of the warning functions when checking
whether an expression has a constant value. */
tree
fold_for_warn (tree x)
{
/* C++ implementation. */
/* It's not generally safe to fully fold inside of a template, so
call fold_non_dependent_expr instead. */
if (processing_template_decl)
return fold_non_dependent_expr (x);
return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
}

View file

@ -1,3 +1,10 @@
2018-01-17 David Malcolm <dmalcolm@redhat.com>
PR c++/83814
PR c++/83902
* g++.dg/wrappers/pr83814.C: New test case.
* g++.dg/wrappers/pr83902.C: New test case.
2018-01-17 David Malcolm <dmalcolm@redhat.com>
PR lto/83121

View file

@ -0,0 +1,70 @@
/* Verify that our memset warnings don't crash when folding
arguments within a template (PR c++/83814). */
// { dg-options "-Wno-int-to-pointer-cast -Wmemset-transposed-args -Wmemset-elt-size" }
template <class>
void test_1()
{
__builtin_memset (int() - char(), 0, 0);
}
template <class>
void test_2()
{
__builtin_memset (0, 0, int() - char());
}
template <class>
void test_3 (unsigned a, int c)
{
__builtin_memset((char *)c + a, 0, a);
}
template <class>
void test_4 (unsigned a, int c)
{
__builtin_memset(0, 0, (char *)c + a);
}
/* Verify that we warn for -Wmemset-transposed-args inside
a template. */
char buf[1024];
template <class>
void test_5 ()
{
__builtin_memset (buf, sizeof buf, 0); // { dg-warning "transposed parameters" }
}
/* Adapted from c-c++-common/memset-array.c; verify that
-Wmemset-elt-size works within a template. */
enum a {
a_1,
a_2,
a_n
};
int t1[20];
int t2[a_n];
struct s
{
int t[20];
};
template<class>
void foo (struct s *s)
{
__builtin_memset (t1, 0, 20); // { dg-warning "element size" }
// This case requires reading through an enum value:
__builtin_memset (t2, 0, a_n); // { dg-warning "element size" }
__builtin_memset (s->t, 0, 20); // { dg-warning "element size" }
// These cases require folding of arg2 within a template:
__builtin_memset (t2, 0, a_n + 0); // { dg-warning "element size" }
__builtin_memset (t2, 0, a_n * 1); // { dg-warning "element size" }
}

View file

@ -0,0 +1,9 @@
extern "C" void *memset (void *, int, __SIZE_TYPE__);
void *p;
template <int T>
struct B
{
void foo () { memset (p, 0, 4 * T * sizeof(float)); }
};