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>();
+}