* C++ PATCH: PR 24389
@ 2005-10-16 23:30 Mark Mitchell
2005-10-17 16:21 ` Gabriel Dos Reis
0 siblings, 1 reply; 2+ messages in thread
From: Mark Mitchell @ 2005-10-16 23:30 UTC (permalink / raw)
To: gcc-patches
This patch fixes PR c++/24389, which was (yet more) fallout from the
static data member patch. The problem here was not, as stated in the
PR, that we were giving X<0>::n_primes non-weak linkage, but rather
that we are emitting a definition for X<I>::n_primes, where I was a
non-type template parameter!
The cause was that the C++ standard, in its infinite wisdom, makes a
non-static data member in a class template non-dependent within the
scope of that template, so that, for example:
template <typename T>
struct S {
static const int I = 7; // I is not value-dependent within S<T>
void f() {
A<I>::type t; // No "typename" keyword required; this is A<7>.
}
};
As a result, we must play funny games with non-static data members,
even though we generally never evaluate expressions within
uninstantiated templates. In particular, within integral constant
expressions, we must fold non-dependent expressions.
Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0 branch.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/24389
* decl2.c (mark_used): Use uses_template_parms instead of
dependent_type_p.
* init.c (constant_value_1): Handle uninstantiated templates
specially.
* pt.c (instantiate_decl): Add sanity check.
2005-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/24389
* g++.dg/template/static21.C: New test.
* g++.dg/template/static21-a.cc: Likewise.
Index: gcc/testsuite/g++.dg/template/static21.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/static21.C
diff -N gcc/testsuite/g++.dg/template/static21.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/static21.C 16 Oct 2005 21:36:44 -0000
***************
*** 0 ****
--- 1,20 ----
+ // PR c++/24389
+ // { dg-additional-sources "static21-a.cc" }
+ // { dg-do link }
+
+ template<int dummy>
+ struct X
+ {
+ static const int n_primes = 256;
+ static const unsigned long primes[n_primes + 1];
+ };
+
+ template<int dummy>
+ const int X<dummy>::n_primes;
+
+ template<int dummy>
+ const unsigned long X<dummy>::primes[n_primes + 1] =
+ { 0 };
+
+ const unsigned long *f(void){return &X<0>::primes[0];}
+
Index: gcc/testsuite/g++.dg/template/static21-a.cc
===================================================================
RCS file: gcc/testsuite/g++.dg/template/static21-a.cc
diff -N gcc/testsuite/g++.dg/template/static21-a.cc
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/static21-a.cc 16 Oct 2005 21:36:44 -0000
***************
*** 0 ****
--- 1,17 ----
+ template<int dummy>
+ struct X
+ {
+ static const int n_primes = 256;
+ static const unsigned long primes[n_primes + 1];
+ };
+
+ template<int dummy>
+ const int X<dummy>::n_primes;
+
+ template<int dummy>
+ const unsigned long X<dummy>::primes[n_primes + 1] =
+ { 0 };
+
+
+ const unsigned long *f1(void){return &X<0>::primes[0];}
+ int main(){}
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.770.2.10
diff -c -5 -p -r1.770.2.10 decl2.c
*** gcc/cp/decl2.c 7 Oct 2005 10:54:09 -0000 1.770.2.10
--- gcc/cp/decl2.c 16 Oct 2005 21:36:44 -0000
*************** mark_used (tree decl)
*** 3208,3233 ****
return;
/* Normally, we can wait until instantiation-time to synthesize
DECL. However, if DECL is a static data member initialized with
a constant, we need the value right now because a reference to
such a data member is not value-dependent. */
! if (processing_template_decl)
{
! if (TREE_CODE (decl) == VAR_DECL
! && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
! && DECL_CLASS_SCOPE_P (decl)
! && !dependent_type_p (DECL_CONTEXT (decl)))
! {
! /* Pretend that we are not in a template so that the
! initializer for the static data member will be full
! simplified. */
! saved_processing_template_decl = processing_template_decl;
! processing_template_decl = 0;
! }
! else
! return;
}
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
{
--- 3208,3237 ----
return;
/* Normally, we can wait until instantiation-time to synthesize
DECL. However, if DECL is a static data member initialized with
a constant, we need the value right now because a reference to
such a data member is not value-dependent. */
! if (TREE_CODE (decl) == VAR_DECL
! && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
! && DECL_CLASS_SCOPE_P (decl))
{
! /* Don't try to instantiate members of dependent types. We
! cannot just use dependent_type_p here because this function
! may be called from fold_non_dependent_expr, and then we may
! see dependent types, even though processing_template_decl
! will not be set. */
! if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
! && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
! return;
! /* Pretend that we are not in a template, even if we are, so
! that the static data member initializer will be processed. */
! saved_processing_template_decl = processing_template_decl;
! processing_template_decl = 0;
}
+
+ if (processing_template_decl)
+ return;
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
{
Index: gcc/cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.412.2.11
diff -c -5 -p -r1.412.2.11 init.c
*** gcc/cp/init.c 11 Oct 2005 20:59:50 -0000 1.412.2.11
--- gcc/cp/init.c 16 Oct 2005 21:36:45 -0000
*************** constant_value_1 (tree decl, bool integr
*** 1572,1591 ****
? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
: (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
{
tree init;
! /* If DECL is a static data member in a template class, we must
! instantiate it here. The initializer for the static data
! member is not processed until needed; we need it now. */
! mark_used (decl);
! init = DECL_INITIAL (decl);
! /* If we are currently processing a template, the
! initializer for a static data member may not be dependent,
! but it is not folded until instantiation time. */
! if (init)
! init = fold_non_dependent_expr (init);
if (!(init || init == error_mark_node)
|| !TREE_TYPE (init)
|| (integral_p
? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
: (!TREE_CONSTANT (init)
--- 1572,1602 ----
? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
: (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
{
tree init;
! /* Static data members in template classes may have
! non-dependent initializers. References to such non-static
! data members are no value-dependent, so we must retrieve the
! initializer here. The DECL_INITIAL will have the right type,
! but will not have been folded because that would prevent us
! from performing all appropriate semantic checks at
! instantiation time. */
! if (DECL_CLASS_SCOPE_P (decl)
! && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
! && uses_template_parms (CLASSTYPE_TI_ARGS
! (DECL_CONTEXT (decl))))
! init = fold_non_dependent_expr (DECL_INITIAL (decl));
! else
! {
! /* If DECL is a static data member in a template
! specialization, we must instantiate it here. The
! initializer for the static data member is not processed
! until needed; we need it now. */
! mark_used (decl);
! init = DECL_INITIAL (decl);
! }
if (!(init || init == error_mark_node)
|| !TREE_TYPE (init)
|| (integral_p
? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
: (!TREE_CONSTANT (init)
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.978.2.32
diff -c -5 -p -r1.978.2.32 pt.c
*** gcc/cp/pt.c 13 Oct 2005 08:36:37 -0000 1.978.2.32
--- gcc/cp/pt.c 16 Oct 2005 21:36:47 -0000
*************** instantiate_decl (tree d, int defer_ok,
*** 11449,11458 ****
--- 11449,11462 ----
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. */
td = template_for_substitution (d);
code_pattern = DECL_TEMPLATE_RESULT (td);
+ /* We should never be trying to instantiate a member of a class
+ template or partial specialization. */
+ gcc_assert (d != code_pattern);
+
if ((DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
|| DECL_TEMPLATE_SPECIALIZATION (td))
/* In the case of a friend template whose definition is provided
outside the class, we may have too many arguments. Drop the
ones we don't need. The same is true for specializations. */
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: C++ PATCH: PR 24389
2005-10-16 23:30 C++ PATCH: PR 24389 Mark Mitchell
@ 2005-10-17 16:21 ` Gabriel Dos Reis
0 siblings, 0 replies; 2+ messages in thread
From: Gabriel Dos Reis @ 2005-10-17 16:21 UTC (permalink / raw)
To: mark; +Cc: gcc-patches
Mark Mitchell <mark@codesourcery.com> writes:
| This patch fixes PR c++/24389, which was (yet more) fallout from the
| static data member patch. The problem here was not, as stated in the
| PR, that we were giving X<0>::n_primes non-weak linkage, but rather
| that we are emitting a definition for X<I>::n_primes, where I was a
| non-type template parameter!
|
| The cause was that the C++ standard, in its infinite wisdom, makes a
| non-static data member in a class template non-dependent within the
| scope of that template, so that, for example:
|
| template <typename T>
| struct S {
| static const int I = 7; // I is not value-dependent within S<T>
| void f() {
| A<I>::type t; // No "typename" keyword required; this is A<7>.
| }
| };
|
| As a result, we must play funny games with non-static data members,
| even though we generally never evaluate expressions within
| uninstantiated templates. In particular, within integral constant
| expressions, we must fold non-dependent expressions.
That was new in C++03, compared to C++98, in search of rule optimizations
in small. I'm glad we share similar appreciationsof list of special rules
and optimization in small ;-)
-- Gaby
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2005-10-17 16:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-16 23:30 C++ PATCH: PR 24389 Mark Mitchell
2005-10-17 16:21 ` Gabriel Dos Reis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).