This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix ICE with label difference as template non-type argument (PR c++/79650)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Nathan Sidwell <nathan at acm dot org>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 13 Dec 2017 23:21:54 +0100
- Subject: [C++ PATCH] Fix ICE with label difference as template non-type argument (PR c++/79650)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
reduced_constant_expression_p uses initializer_constant_valid_p
to determine what is a valid constant expression. That accepts several
cases which aren't compile time INTEGER_CST, just something that the assembler
can finalize into a constant, e.g. difference of labels, difference of
STRING_CSTs, something plus ADDR_EXPR of a static var etc.
But for template non-type arguments my understanding is we really need
an INTEGER_CST, we cam hardly instantiate on something that only during
assembly will become a constant.
The following patch attempts to diagnose it.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Or do you have better suggestions for the diagnostics wording?
2017-12-13 Jakub Jelinek <jakub@redhat.com>
PR c++/79650
* pt.c (convert_nontype_argument): Diagnose
reduced_constant_expression_p expressions that aren't INTEGER_CST.
* g++.dg/template/pr79650.C: New test.
--- gcc/cp/pt.c.jj 2017-12-13 15:52:51.000000000 +0100
+++ gcc/cp/pt.c 2017-12-13 19:21:35.861825357 +0100
@@ -6577,7 +6577,19 @@ convert_nontype_argument (tree type, tre
return NULL_TREE;
/* else cxx_constant_value complained but gave us
a real constant, so go ahead. */
- gcc_assert (TREE_CODE (expr) == INTEGER_CST);
+ if (TREE_CODE (expr) != INTEGER_CST)
+ {
+ /* Some assemble time constant expressions like
+ (intptr_t)&&lab1 - (intptr_t)&&lab2 or
+ 4 + (intptr_t)&&var satisfy reduced_constant_expression_p
+ as we can emit them into .rodata initializers of
+ variables, yet they can't fold into an INTEGER_CST at
+ compile time. Refuse them here. */
+ gcc_checking_assert (reduced_constant_expression_p (expr));
+ error_at (loc, "template argument %qE for type %qT not "
+ "a constant integer", expr, type);
+ return NULL_TREE;
+ }
}
else
return NULL_TREE;
--- gcc/testsuite/g++.dg/template/pr79650.C.jj 2017-12-13 19:29:04.549196268 +0100
+++ gcc/testsuite/g++.dg/template/pr79650.C 2017-12-13 19:34:15.202298913 +0100
@@ -0,0 +1,20 @@
+// PR c++/79650
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+typedef __INTPTR_TYPE__ intptr_t;
+template<intptr_t> struct A {};
+
+void
+foo ()
+{
+ static int a, b;
+lab1:
+lab2:
+ A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c; // { dg-error "not a constant integer" }
+ A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d;
+ A<(intptr_t)&a - (intptr_t)&b> e; // { dg-error "is not a constant expression" }
+ A<(intptr_t)&a - (intptr_t)&a> f;
+ A<(intptr_t)sizeof(a) + (intptr_t)&a> g; // { dg-error "not a constant integer" }
+ A<(intptr_t)&a> h; // { dg-error "conversion from pointer type" }
+}
Jakub