c++: hard error w/ ptr+CST and incomplete type [PR103700]
Commit Message
In pointer_int_sum when called from a SFINAE context, we need to avoid
calling size_in_bytes_loc on an incomplete pointed-to type since this
latter function isn't SFINAE-friendly and always emits an error in this
case.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk and perhaps 11? pointer_int_sum is also used in the C FE, but
always with the complain parameter defaulted to true so this change
should have no effect there AFAICT.
PR c++/103700
gcc/c-family/ChangeLog:
* c-common.c (pointer_int_sum): When quiet, return
error_mark_node for an incomplete type and avoid calling
size_in_bytes_loc.
gcc/testsuite/ChangeLog:
* g++.dg/template/sfinae32.C: New test.
---
gcc/c-family/c-common.c | 2 ++
gcc/testsuite/g++.dg/template/sfinae32.C | 17 +++++++++++++++++
2 files changed, 19 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/template/sfinae32.C
Comments
On 12/22/21 12:39, Patrick Palka wrote:
> In pointer_int_sum when called from a SFINAE context, we need to avoid
> calling size_in_bytes_loc on an incomplete pointed-to type since this
> latter function isn't SFINAE-friendly and always emits an error in this
> case.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk and perhaps 11? pointer_int_sum is also used in the C FE, but
> always with the complain parameter defaulted to true so this change
> should have no effect there AFAICT.
LGTM, but let's give the C maintainers time to comment; OK on Friday if
no comment.
> PR c++/103700
>
> gcc/c-family/ChangeLog:
>
> * c-common.c (pointer_int_sum): When quiet, return
> error_mark_node for an incomplete type and avoid calling
> size_in_bytes_loc.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/template/sfinae32.C: New test.
> ---
> gcc/c-family/c-common.c | 2 ++
> gcc/testsuite/g++.dg/template/sfinae32.C | 17 +++++++++++++++++
> 2 files changed, 19 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/template/sfinae32.C
>
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index a25d59fa77b..f3e3e9ba0a5 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -3308,6 +3308,8 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
> size_exp = integer_one_node;
> else
> {
> + if (!complain && !COMPLETE_TYPE_P (TREE_TYPE (result_type)))
> + return error_mark_node;
> size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
> /* Wrap the pointer expression in a SAVE_EXPR to make sure it
> is evaluated first when the size expression may depend
> diff --git a/gcc/testsuite/g++.dg/template/sfinae32.C b/gcc/testsuite/g++.dg/template/sfinae32.C
> new file mode 100644
> index 00000000000..488bf145e21
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/sfinae32.C
> @@ -0,0 +1,17 @@
> +// PR c++/103700
> +// { dg-do compile { target c++11 } }
> +
> +template<class T, T **p, int N> auto f() -> decltype(*p + N) = delete;
> +template<class T, T **p, int N> auto f() -> decltype(*p - N) = delete;
> +template<class T, T **p, int N> auto f() -> decltype(N + *p) = delete;
> +template<class T, T **p, int N> void f();
> +
> +struct Incomplete *p;
> +
> +int main() {
> + f<Incomplete, &p, 0>();
> + f<Incomplete, &p, 1>();
> + f<Incomplete, &p, -1>();
> + f<Incomplete, &p, 42>();
> + f<Incomplete, &p, -42>();
> +}
@@ -3308,6 +3308,8 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
size_exp = integer_one_node;
else
{
+ if (!complain && !COMPLETE_TYPE_P (TREE_TYPE (result_type)))
+ return error_mark_node;
size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
/* Wrap the pointer expression in a SAVE_EXPR to make sure it
is evaluated first when the size expression may depend
new file mode 100644
@@ -0,0 +1,17 @@
+// PR c++/103700
+// { dg-do compile { target c++11 } }
+
+template<class T, T **p, int N> auto f() -> decltype(*p + N) = delete;
+template<class T, T **p, int N> auto f() -> decltype(*p - N) = delete;
+template<class T, T **p, int N> auto f() -> decltype(N + *p) = delete;
+template<class T, T **p, int N> void f();
+
+struct Incomplete *p;
+
+int main() {
+ f<Incomplete, &p, 0>();
+ f<Incomplete, &p, 1>();
+ f<Incomplete, &p, -1>();
+ f<Incomplete, &p, 42>();
+ f<Incomplete, &p, -42>();
+}