Message ID | 50363851.9070205@oracle.com |
---|---|
State | New |
Headers | show |
On 08/23/2012 10:04 AM, Paolo Carlini wrote: > + if (decl > + && TREE_CODE (decl) == VAR_DECL > + && ! TYPE_P (CP_DECL_CONTEXT (decl))) > + { > + error_at (decl_spec_token_start->location, > + "%qT is not a template type", TREE_TYPE (decl)); > + decl = error_mark_node; > + } Can we just check whether decl has DECL_TEMPLATE_INFO at this point? Jason
On 08/23/2012 05:24 PM, Jason Merrill wrote: > On 08/23/2012 10:04 AM, Paolo Carlini wrote: >> + if (decl >> + && TREE_CODE (decl) == VAR_DECL >> + && ! TYPE_P (CP_DECL_CONTEXT (decl))) >> + { >> + error_at (decl_spec_token_start->location, >> + "%qT is not a template type", TREE_TYPE (decl)); >> + decl = error_mark_node; >> + } > > Can we just check whether decl has DECL_TEMPLATE_INFO at this point? I tried, possibly together with a preliminary DECL_LANG_SPECIFIC check and maybe a check that decl isn't already error_mark_node, but anyway apparently the idea has issues with friends, testcases like template/friend17.C (gave me already headaches earlier today, that's why I'm so quick at replying ;) template <class T> struct X { template <class U> void operator+=(U); template <class V> template <class U> friend void X<V>::operator+=(U); }; int main() { X<int>() += 1.0; } when we parse the friend declaration, DECL_TEMPLATE_INFO is not set. Paolo.
Hi again, On 08/23/2012 05:53 PM, Paolo Carlini wrote: > On 08/23/2012 05:24 PM, Jason Merrill wrote: >> On 08/23/2012 10:04 AM, Paolo Carlini wrote: >>> + if (decl >>> + && TREE_CODE (decl) == VAR_DECL >>> + && ! TYPE_P (CP_DECL_CONTEXT (decl))) >>> + { >>> + error_at (decl_spec_token_start->location, >>> + "%qT is not a template type", TREE_TYPE (decl)); >>> + decl = error_mark_node; >>> + } >> >> Can we just check whether decl has DECL_TEMPLATE_INFO at this point? > I tried, possibly together with a preliminary DECL_LANG_SPECIFIC check > and maybe a check that decl isn't already error_mark_node, but anyway > apparently the idea has issues with friends, testcases like > template/friend17.C (gave me already headaches earlier today, that's > why I'm so quick at replying ;) > > template <class T> > struct X { > template <class U> void operator+=(U); > > template <class V> > template <class U> > friend void X<V>::operator+=(U); > }; > > int main() { > X<int>() += 1.0; > } > > when we parse the friend declaration, DECL_TEMPLATE_INFO is not set. I looked somewhat more into this and I haven't been able to find a simple way to just use DECL_TEMPLATE_INFO. If I arrange to cope with friend17.C by explicitly excluding TEMPLATE_DECLs like in: else if (decl != error_mark_node && TREE_CODE (decl) != TEMPLATE_DECL && (!DECL_LANG_SPECIFIC (decl) || !DECL_TEMPLATE_INFO (decl))) { error_at (decl_spec_token_start->location, "%qT is not a template type", TREE_TYPE (decl)); decl = error_mark_node; } then we regress eg, g++.dg/cpp0x/temp_default4.C, because in that case, again involving friends, we have: lass X { template<typename T = int> friend void f(X) { } template<typename T> friend void g(X); // { dg-error "previously declared here" } template<typename T = int> friend void h(X); // { dg-error "function template friend" } }; template<typename T = int> void g(X) // { dg-error "default template argument" } { } and the out of class g is a FUNCTION_DECL with again DECL_TEMPLATE_INFO not set. Do you have in mind something more specific? Ah, just in case you wondered (like me ;) we do *not* have an issue with things like: template<> int i(int); which obviously aren't VAR_DECLs, because those are handled already by check_explicit_specialization. What about adding a comment about the latter point? Thanks, Paolo.
Index: cp/parser.c =================================================================== --- cp/parser.c (revision 190618) +++ cp/parser.c (working copy) @@ -21429,6 +21429,15 @@ cp_parser_single_declaration (cp_parser* parser, "explicit template specialization cannot have a storage class"); decl = error_mark_node; } + + if (decl + && TREE_CODE (decl) == VAR_DECL + && ! TYPE_P (CP_DECL_CONTEXT (decl))) + { + error_at (decl_spec_token_start->location, + "%qT is not a template type", TREE_TYPE (decl)); + decl = error_mark_node; + } } /* Look for a trailing `;' after the declaration. */ Index: testsuite/g++.dg/parse/error50.C =================================================================== --- testsuite/g++.dg/parse/error50.C (revision 0) +++ testsuite/g++.dg/parse/error50.C (revision 0) @@ -0,0 +1,9 @@ +// PR c++/18747 + +template<> int i; // { dg-error "template" } + +struct A +{ +}; + +template<> A j; // { dg-error "template" }