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

Reply via email to