Bug 10200 - [6 Regression] Weird clash with same names in different scopes
Summary: [6 Regression] Weird clash with same names in different scopes
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: 6.0
Assignee: Jason Merrill
URL:
Keywords: monitored, rejects-valid
: 20308 32408 39407 51664 56516 63414 65878 (view as bug list)
Depends on:
Blocks: c++-lookup, c++-name-lookup 20679
  Show dependency treegraph
 
Reported: 2003-03-24 16:56 UTC by sturgill
Modified: 2021-07-27 00:28 UTC (History)
13 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-02-08 00:00:00


Attachments
driver.ii.bz2 (77.50 KB, application/octet-stream)
2003-05-21 15:17 UTC, sturgill
Details

Note You need to log in before you can comment on or make changes to this bug.
Description sturgill 2003-03-24 16:56:00 UTC
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
Comment 1 Wolfgang Bangerth 2003-03-24 17:26:13 UTC
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.
Comment 2 Andrew Pinski 2003-06-07 16:43:06 UTC
Still happens on the mainline (20030607).
Comment 3 Andrew Pinski 2003-07-17 00:10:58 UTC
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.
Comment 4 Volker Reichelt 2003-08-08 00:07:56 UTC
Maybe related to PR 11814.
Comment 5 Andrew Pinski 2003-08-23 17:05:22 UTC
The ICE is a regression.
Comment 6 Kriang Lerdsuwanakij 2003-11-23 11:02:40 UTC
With my patch to PR12924, the ICE is gone.  We still
get an incorrect error message however.
Comment 7 Kriang Lerdsuwanakij 2003-11-23 11:38:10 UTC
Keywords updated to remove the ICE.  Will look at this issue.
Comment 8 Kriang Lerdsuwanakij 2003-11-23 11:54:18 UTC
It's no longer a regression.
Comment 9 Mark Mitchell 2003-12-17 17:05:27 UTC
Since this is no longer a regression, I've removed the 3.4 target milestone.
Comment 10 Andrew Pinski 2004-08-04 06:12:27 UTC
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
Comment 11 Kriang Lerdsuwanakij 2004-10-13 14:50:47 UTC
It's parser bug.  Not working on it anymore.
Comment 12 Mark Mitchell 2005-04-05 06:03:01 UTC
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.
Comment 13 Andrew Pinski 2007-06-19 23:10:48 UTC
*** Bug 32408 has been marked as a duplicate of this bug. ***
Comment 14 Andrew Pinski 2008-09-20 02:56:40 UTC
*** Bug 20308 has been marked as a duplicate of this bug. ***
Comment 15 Andrew Pinski 2009-03-09 18:16:09 UTC
*** Bug 39407 has been marked as a duplicate of this bug. ***
Comment 16 Jay Foad 2011-05-24 09:17:21 UTC
> 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.
Comment 17 Wolfgang Bangerth 2011-10-09 13:34:27 UTC
Still happens with gcc 4.5.1.
Comment 18 Manuel López-Ibáñez 2011-10-19 22:29:28 UTC
This still happens in trunk (GCC 4.7 rev 180166).
Comment 19 Andrew Pinski 2011-12-23 18:56:42 UTC
*** Bug 51664 has been marked as a duplicate of this bug. ***
Comment 20 Matt Giuca 2012-05-30 00:05:47 UTC
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
Comment 21 Paolo Carlini 2012-08-23 10:14:16 UTC
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...
Comment 22 Paolo Carlini 2013-03-04 10:09:01 UTC
*** Bug 56516 has been marked as a duplicate of this bug. ***
Comment 23 Paolo Carlini 2013-10-10 20:42:02 UTC
Mine.
Comment 24 Andrew Pinski 2014-09-30 12:22:17 UTC
*** Bug 63414 has been marked as a duplicate of this bug. ***
Comment 25 Paolo Carlini 2015-06-23 15:03:03 UTC
*** Bug 65878 has been marked as a duplicate of this bug. ***
Comment 26 Colin MacKenzie 2015-06-23 22:19:29 UTC
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);
Comment 27 Paolo Carlini 2015-06-23 22:21:28 UTC
This should be fixed ASAP, but I'm not actively working on it at the moment.
Comment 28 Jonathan Wakely 2016-01-22 18:21:14 UTC
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; }
                                                             ^~~~~~~
Comment 29 Jonathan Wakely 2016-01-22 18:28:51 UTC
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<" :-)
Comment 30 Manuel López-Ibáñez 2016-01-22 18:54:44 UTC
(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.
Comment 31 Marek Polacek 2016-02-08 19:23:10 UTC
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);
}
Comment 32 Jonathan Wakely 2016-02-08 20:03:56 UTC
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);
       ^
Comment 33 Jakub Jelinek 2016-02-09 10:46:43 UTC
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?
Comment 34 Jonathan Wakely 2016-02-09 10:54:21 UTC
(In reply to Jakub Jelinek from comment #33)
> we now have a regression from 5 to 6, right?

Right.
Comment 35 Jason Merrill 2016-02-10 15:35:20 UTC
Fixed for GCC 6.
Comment 36 Jason Merrill 2016-02-10 15:35:24 UTC
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
Comment 37 Jason Merrill 2016-02-17 00:50:55 UTC
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
Comment 38 Jason Merrill 2016-05-13 19:19:07 UTC
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
Comment 39 Jason Merrill 2016-05-19 19:21:13 UTC
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