https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86302

            Bug ID: 86302
           Summary: Ill-formed code becomes legal?
           Product: gcc
           Version: 8.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zhonghao at pku dot org.cn
  Target Milestone: ---

The code is as follow:

template<typename T>
void f();

int main() {
 f<int> != 0;
}

clang++ produces warnings, but g++ rejects it with a message:
error: invalid operands of types '<unresolved overloaded function type>' and
'int' to binary 'operator!='
  f<int> != 0;
  ~~~~~~~^~~~

The code comes from a clang report: https://bugs.llvm.org/show_bug.cgi?id=9208

Seth reported the difference. Johannes Schaub explained "It should be noted
that the recent resolution of PR7505 makes this code and similar code
well-formed (I didn't test this specific case though). It interprets 14.1p1
which says "An overloaded function name shall not be used without arguments in
contexts other than those listed." to not apply when the overloaded function
name is "foo<int>", as it resolves the template-id to an lvalue later and then
makes it so this rule does not apply anymore to the then resolved lvalue,
ignoring that the name once was the name of an overloaded function according to
14.1p1. As a result, it also allows statement-expressions whose mere constitute
is a "foo<int>;". "

So, the code becomes legal, and shall g++ accept it. 

The clang report lists related expressions:

  Clang     Comeau/EDG  GCC (4.5.2)
 -----------------+------------------------------------
  typeid(f<int>);   OK (?)    OK          OK
  +f<int>;          OK        OK          ERROR
  !f<int>;          OK        OK          ERROR
  &f<int>;          OK        OK          OK
  f<int> == 0;      ERROR     OK          ERROR
  f<int> != 0;      ERROR     OK          ERROR
  f<int> && 0;      OK        OK          ERROR
  f<int> || 0;      OK        OK          ERROR 
  f<int> ? f<int>   OK        OK          ERROR (only 1st op?)
         : f<int>   
  (f<int>, f<int>)  OK        OK          ERROR
  f<int>;           OK (?)    OK          OK

Reply via email to