Problem parsing the < operator inside a template class with an inner struct containing some anonymous fields. If I reorder the expression to use > instead, seems to compile just fine. Older version of the compiler complains about the closing ) on the offending line, but the 3.2 version complains about a ;. Command Line: g++ -v -save-temps driver.cpp Compiler Output: Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --host=i386-redhat-linux --with-system-zlib --enable-__cxa_atexit Thread model: posix gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) /usr/lib/gcc-lib/i386-redhat-linux/3.2/cpp0 -lang-c++ -D__GNUG__=3 -D__DEPRECATED -D__EXCEPTIONS -v -D__GNUC__=3 -D__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=0 -D__GXX_ABI_VERSION=102 -D__ELF__ -Dunix -D__gnu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__ -D__unix -D__linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -D_GNU_SOURCE -Acpu=i386 -Amachine=i386 -Di386 -D__i386 -D__i386__ -D__tune_i386__ driver.cpp driver.ii GNU CPP version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) (cpplib) (i386 Linux/ELF)ignoring nonexistent directory "/usr/i386-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/3.2 /usr/include/c++/3.2/i386-redhat-linux /usr/include/c++/3.2/backward /usr/local/include /usr/lib/gcc-lib/i386-redhat-linux/3.2/include /usr/include End of search list. /usr/lib/gcc-lib/i386-redhat-linux/3.2/cc1plus -fpreprocessed driver.ii -quiet -dumpbase driver.cpp -version -o driver.s GNU CPP version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) (cpplib) (i386 Linux/ELF)GNU C++ version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) (i386-redhat-linux) compiled by GNU C version 3.2 20020903 (Red Hat Linux 8.0 3.2-7). In file included from driver.cpp:4: RangeMap.h: In member function `void RangeMap<T>::insert(const T&, RangeMap<T>::Node*&, double*, double*)': RangeMap.h:72: parse error before `;' token Release: gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) Environment: Red Hat 8.0
State-Changed-From-To: open->analyzed State-Changed-Why: Confirmed. A very weird error: ------------------ template<typename> void foo() {} template <typename T> struct X { struct { int foo; } node; bool bar() { return (node.foo < 5); } }; template struct X<int>; -------------------------- Note that template function and member variable have to have the same name, to get this from 3.2.3pre and 3.3pre: g/x> /home/bangerth/bin/gcc-3.2.3-pre/bin/c++ -c x.cc x.cc: In member function `bool X<T>::bar()': x.cc:8: parse error before `;' token Present mainline gives g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc x.cc: In member function `bool X<T>::bar() [with T = int]': x.cc:11: instantiated from here x.cc:8: error: invalid use of `foo()' This is just as wrong. W.
Still happens on the mainline (20030607).
With the small testcase, we now ICE on the mainline (20030716): pr10200.cc: In member function `bool X<T>::bar() [with T = int]': pr10200.cc:12: instantiated from here pr10200.cc:9: internal compiler error: in lookup_member, at cp/search.c:1219 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions.
Maybe related to PR 11814.
The ICE is a regression.
With my patch to PR12924, the ICE is gone. We still get an incorrect error message however.
Keywords updated to remove the ICE. Will look at this issue.
It's no longer a regression.
Since this is no longer a regression, I've removed the 3.4 target milestone.
It is even worse now on the mainline: pr10200.cc: In member function `bool X<T>::bar()': pr10200.cc:8: error: missing `>' to terminate the template argument list pr10200.cc: In member function `bool X<T>::bar() [with T = int]': pr10200.cc:11: instantiated from here pr10200.cc:8: error: `foo' is not a member template function
It's parser bug. Not working on it anymore.
This is almost the same as the case discussed in DR 141. In particular, we must determine whether "node.foo <" is the start of a template, or not. [basic.lookup.classref] says that we look in the class of the object expression, i.e., X<T>::node. However, that's a dependent type. So, we don't actually try to lookup there. Thus, we then go on to do lookup in the scope of the containing postfix-expression, which finds the global template function. DR 141 suggests that we should not do the second lookup. However, this DR is still in the "open" state; the committee has taken no action as of yet. However, independently of that, [temp.names] says that when the object has a dependent type (as it does in this case), then the name is a template only if the template keyword is explicitly used. So, the compiler is definitely wrong in this case.
*** Bug 32408 has been marked as a duplicate of this bug. ***
*** Bug 20308 has been marked as a duplicate of this bug. ***
*** Bug 39407 has been marked as a duplicate of this bug. ***
> This is almost the same as the case discussed in DR 141. > > In particular, we must determine whether "node.foo <" is the start of a > template, or not. [basic.lookup.classref] says that we look in the class of the > object expression, i.e., X<T>::node. However, that's a dependent type. So, we > don't actually try to lookup there. Thus, we then go on to do lookup in the > scope of the containing postfix-expression, which finds the global template > function. DR 141 suggests that we should not do the second lookup. However, > this DR is still in the "open" state; the committee has taken no action as of yet. DR 141 was resolved in CD1: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#141 It seems like we should still do the second lookup.
Still happens with gcc 4.5.1.
This still happens in trunk (GCC 4.7 rev 180166).
*** Bug 51664 has been marked as a duplicate of this bug. ***
I think this is the same bug in Clang: http://llvm.org/bugs/show_bug.cgi?id=11856 It was fixed in March: http://llvm.org/viewvc/llvm-project?view=rev&revision=152520
Jason, noticed this very, very old issue which however clang too fixed only this March. Wondered if you have tips, believe it would be easy to fix in our front-end too, what else...
*** Bug 56516 has been marked as a duplicate of this bug. ***
Mine.
*** Bug 63414 has been marked as a duplicate of this bug. ***
*** Bug 65878 has been marked as a duplicate of this bug. ***
Had this one today. Strange that it compiles fine in 4.4.6 but not in 4.8.2. error: parse error in template argument list Ex: assert(block.begin < block.end); works when I parenthesize the block.begin Ex. assert( (block.begin) < block.end);
This should be fixed ASAP, but I'm not actively working on it at the moment.
Another example: template<class Tp> inline void end(Tp) { } template <typename T> bool tnegative(const T& t) { return t.end < 0; } pe.cc: In function ‘bool tnegative(const T&)’: pe.cc:3:61: error: parse error in template argument list template <typename T> bool tnegative(const T& t) { return t.end < 0; } ^~~~~~~
You can trick G++ into finishing the parse incorrectly: template<bool> inline void end(int) { } struct S { int end; }; template <typename T> bool both_negative(const T& t, int u) { return t.end < 0 && 0 > (u); } int main() { return both_negative( S{-1}, -2 ); } pe.cc: In instantiation of ‘bool both_negative(const T&, int) [with T = S]’: pe.cc:10:35: required from here pe.cc:6:50: error: ‘end’ is not a member template function bool both_negative(const T& t, int u) { return t.end < 0 && 0 > (u); } ~~^~~~~~~~~~~~~~ I know it isn't, that's why I didn't write "t.template end<" :-)
(In reply to Jonathan Wakely from comment #28) > Another example: > > template<class Tp> inline void end(Tp) { } > > template <typename T> bool tnegative(const T& t) { return t.end < 0; } > > > pe.cc: In function ‘bool tnegative(const T&)’: > pe.cc:3:61: error: parse error in template argument list > template <typename T> bool tnegative(const T& t) { return t.end < 0; } > ^~~~~~~ /* ??? Can we actually assume that, if template_id == error_mark_node, we will have issued a diagnostic to the user, as opposed to simply marking the tentative parse as failed? */ if (cp_parser_error_occurred (parser) && template_id != error_mark_node) => error_at (token->location, "parse error in template argument list"); But actually the issue is that template_id != error_mark_node, but it is not a template id, so we are still tentatively parsing and this error is wrong.
Another testcase which we just stumbled upon: double exp(double); #ifndef HIDE_NEW_OVERLOAD template<typename T> T exp(T t) { return ::exp((double)t); } #endif template <typename> class A { struct B { long exp; }; void m_fn1(); }; template <typename Key> void A<Key>::m_fn1() { long insert_exp = 1; B q; (q->exp < insert_exp); }
The new testcase gets two errors (both due to treating "q->exp< N" as the start of a template) and Manu's suggestion in comment 30 only helps with the second one. Slightly further reduced (the macro shows how in gcc-5 this bug was only encountered by using <cmath> and using std::exp, but in gcc 6 it's also encountered with <math.h> because that now has the using declaration): namespace std { template<typename T> T exp(T t) { return t; } } #ifndef NO_USING using std::exp; #endif template <typename> class A { struct B { long exp; }; void m_fn1(); }; template <typename Key> void A<Key>::m_fn1() { long insert_exp = 1; B q; (q->exp < insert_exp); } exp.cc: In member function ‘void A< <template-parameter-1-1> >::m_fn1()’: exp.cc:16:13: error: the value of ‘insert_exp’ is not usable in a constant expression (q->exp < insert_exp); ^ exp.cc:14:8: note: ‘long int insert_exp’ is not const long insert_exp = 1; ^ exp.cc:16:7: error: parse error in template argument list (q->exp < insert_exp); ^
So, with #include <math.h> template <typename> class A { struct B { long exp; }; void m_fn1(); }; template <typename Key> void A<Key>::m_fn1() { long insert_exp = 1; B q; (q->exp < insert_exp); } we now have a regression from 5 to 6, right?
(In reply to Jakub Jelinek from comment #33) > we now have a regression from 5 to 6, right? Right.
Fixed for GCC 6.
Author: jason Date: Wed Feb 10 15:34:52 2016 New Revision: 233277 URL: https://gcc.gnu.org/viewcvs?rev=233277&root=gcc&view=rev Log: PR c++/10200 * parser.c (cp_parser_lookup_name): When looking for a template after . or ->, only consider class templates. (cp_parser_postfix_dot_deref_expression): Handle the current instantiation. Remember a dependent object expression. * typeck2.c (build_x_arrow): Handle the current instantiation. Added: trunk/gcc/testsuite/g++.dg/lookup/member2.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/parser.c trunk/gcc/cp/typeck2.c
Author: jason Date: Wed Feb 17 00:50:23 2016 New Revision: 233481 URL: https://gcc.gnu.org/viewcvs?rev=233481&root=gcc&view=rev Log: PR c++/10200 PR c++/69753 * call.c, cp-tree.h, name-lookup.c, pt.c, search.c, semantics.c, tree.c, typeck2.c: Revert earlier changes. * parser.c (cp_parser_lookup_name): Ignore namespace-scope non-type templates after -> or . Added: trunk/gcc/testsuite/g++.dg/template/dependent-expr9.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/name-lookup.c trunk/gcc/cp/parser.c trunk/gcc/cp/pt.c trunk/gcc/cp/search.c trunk/gcc/cp/semantics.c trunk/gcc/cp/tree.c trunk/gcc/cp/typeck2.c
Author: jason Date: Fri May 13 19:18:35 2016 New Revision: 236221 URL: https://gcc.gnu.org/viewcvs?rev=236221&root=gcc&view=rev Log: Fix type-dependence and the current instantiation. PR c++/10200 PR c++/69753 * pt.c (tsubst_decl): Use uses_template_parms. (instantiate_template_1): Handle non-dependent calls in templates. (value_dependent_expression_p): Handle BASELINK, FUNCTION_DECL. (type_dependent_expression_p): Only consider innermost template args. (dependent_template_arg_p): Check enclosing class of a template here. (dependent_template_p): Not here. (type_dependent_object_expression_p): New. * typeck.c (finish_class_member_access_expr): Use it. * parser.c (cp_parser_postfix_expression): Use it. (cp_parser_postfix_dot_deref_expression): Use it. Use comptypes to detect the current instantiation. (cp_parser_lookup_name): Really implement DR 141. * search.c (lookup_field_r): Prefer a dependent using-declaration. (any_dependent_bases_p): Split out from... * name-lookup.c (do_class_using_decl): ...here. * call.c (build_new_method_call_1): Use it. * semantics.c (finish_call_expr): 'this' doesn't make a call dependent. * tree.c (non_static_member_function_p): Remove. * typeck2.c (build_x_arrow): Use dependent_scope_p. Added: trunk/gcc/testsuite/g++.dg/lookup/member4.C trunk/gcc/testsuite/g++.dg/lookup/member5.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/name-lookup.c trunk/gcc/cp/parser.c trunk/gcc/cp/pt.c trunk/gcc/cp/search.c trunk/gcc/cp/semantics.c trunk/gcc/cp/tree.c trunk/gcc/cp/typeck.c trunk/gcc/cp/typeck2.c trunk/gcc/testsuite/g++.dg/template/using14.C
Author: jason Date: Thu May 19 19:20:40 2016 New Revision: 236486 URL: https://gcc.gnu.org/viewcvs?rev=236486&root=gcc&view=rev Log: Fix handling of non-dependent calls with default template args. PR c++/10200 * pt.c (fn_type_unification): Add outer template args if needed. (type_unification_real): Handle getting full args. Added: trunk/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg6.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c