Skip to content

clang reject valid code: <> cmp operator confuse with template <> #178611

@rockeet

Description

@rockeet

The reduced reproduction code:

#define TOPLING_PP_CAT2_1(a,b)    a##b
#define TOPLING_PP_CAT2(a,b)      TOPLING_PP_CAT2_1(a,b)
#define TOPLING_PP_ARG_X(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9, \
           a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z, \
           A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,XX,...) XX
#define TOPLING_PP_ARG_N(...) \
        TOPLING_PP_ARG_X("ignored", ##__VA_ARGS__, \
            Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A, \
            z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a, \
                                            9,8,7,6,5,4,3,2,1,0)
#define TOPLING_PP_VA_NAME(prefix,...) \
        TOPLING_PP_CAT2(prefix,TOPLING_PP_ARG_N(__VA_ARGS__))

#define TOPLING_CMP1(d,f,o) \
    if (__x_ d f o __y_ d f) return true; \
    if (__y_ d f o __x_ d f) return false;

#define TOPLING_CMP_O_2(f,o)     return __x_.f o __y_.f;
#define TOPLING_CMP_O_4(f,o,...) TOPLING_CMP1(. ,f,o)TOPLING_CMP_O_2(__VA_ARGS__)

#define TOPLING_CMP(...) \
 [](const auto& __x_, const auto& __y_) ->bool { \
  TOPLING_PP_VA_NAME(TOPLING_CMP_O_,__VA_ARGS__)(__VA_ARGS__) }

#include <algorithm>
template<class T>
struct x {}; // name same with A::x
struct A { int x, y; };
void f(A* beg, A* end) {
    std::sort(beg, end, TOPLING_CMP(x, <, y, >));
}

gcc is ok, see: https://godbolt.org/z/vzG5ccKEY

clang compile error:

<source>:30:25: error: expected '>'
   30 |     std::sort(beg, end, TOPLING_CMP(x, <, y, >));
      |                         ^
<source>:23:3: note: expanded from macro 'TOPLING_CMP'
   23 |   TOPLING_PP_VA_NAME(TOPLING_CMP_O_,__VA_ARGS__)(__VA_ARGS__) }
      |   ^
<source>:12:9: note: expanded from macro 'TOPLING_PP_VA_NAME'
   12 |         TOPLING_PP_CAT2(prefix,TOPLING_PP_ARG_N(__VA_ARGS__))
      |         ^
<source>:2:35: note: expanded from macro 'TOPLING_PP_CAT2'
    2 | #define TOPLING_PP_CAT2(a,b)      TOPLING_PP_CAT2_1(a,b)
      |                                   ^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
<scratch space>:313:1: note: expanded from here
  313 | TOPLING_CMP_O_4
      | ^
<source>:19:34: note: expanded from macro 'TOPLING_CMP_O_4'
   19 | #define TOPLING_CMP_O_4(f,o,...) TOPLING_CMP1(. ,f,o)TOPLING_CMP_O_2(__VA_ARGS__)
      |                                  ^
<source>:15:28: note: expanded from macro 'TOPLING_CMP1'
   15 |     if (__x_ d f o __y_ d f) return true; \
      |                            ^
<source>:30:40: note: to match this '<'
   30 |     std::sort(beg, end, TOPLING_CMP(x, <, y, >));
      |                                        ^
<source>:30:25: error: expected unqualified-id
   30 |     std::sort(beg, end, TOPLING_CMP(x, <, y, >));
      |                         ^
<source>:23:3: note: expanded from macro 'TOPLING_CMP'
   23 |   TOPLING_PP_VA_NAME(TOPLING_CMP_O_,__VA_ARGS__)(__VA_ARGS__) }
      |   ^
<source>:12:9: note: expanded from macro 'TOPLING_PP_VA_NAME'
   12 |         TOPLING_PP_CAT2(prefix,TOPLING_PP_ARG_N(__VA_ARGS__))
      |         ^
<source>:2:35: note: expanded from macro 'TOPLING_PP_CAT2'
    2 | #define TOPLING_PP_CAT2(a,b)      TOPLING_PP_CAT2_1(a,b)
      |                                   ^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
<scratch space>:313:1: note: expanded from here
  313 | TOPLING_CMP_O_4
      | ^
<source>:19:34: note: expanded from macro 'TOPLING_CMP_O_4'
   19 | #define TOPLING_CMP_O_4(f,o,...) TOPLING_CMP1(. ,f,o)TOPLING_CMP_O_2(__VA_ARGS__)
      |                                  ^
<source>:15:28: note: expanded from macro 'TOPLING_CMP1'
   15 |     if (__x_ d f o __y_ d f) return true; \
      |                            ^
<source>:30:25: error: expected '>'
<source>:23:3: note: expanded from macro 'TOPLING_CMP'
   23 |   TOPLING_PP_VA_NAME(TOPLING_CMP_O_,__VA_ARGS__)(__VA_ARGS__) }
      |   ^
<source>:12:9: note: expanded from macro 'TOPLING_PP_VA_NAME'
   12 |         TOPLING_PP_CAT2(prefix,TOPLING_PP_ARG_N(__VA_ARGS__))
      |         ^
<source>:2:35: note: expanded from macro 'TOPLING_PP_CAT2'
    2 | #define TOPLING_PP_CAT2(a,b)      TOPLING_PP_CAT2_1(a,b)
      |                                   ^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
<scratch space>:313:1: note: expanded from here
  313 | TOPLING_CMP_O_4
      | ^
<source>:19:34: note: expanded from macro 'TOPLING_CMP_O_4'
   19 | #define TOPLING_CMP_O_4(f,o,...) TOPLING_CMP1(. ,f,o)TOPLING_CMP_O_2(__VA_ARGS__)
      |                                  ^
<source>:16:28: note: expanded from macro 'TOPLING_CMP1'
   16 |     if (__y_ d f o __x_ d f) return false;
      |                            ^
<source>:30:40: note: to match this '<'
   30 |     std::sort(beg, end, TOPLING_CMP(x, <, y, >));
      |                                        ^
<source>:30:25: error: expected unqualified-id
   30 |     std::sort(beg, end, TOPLING_CMP(x, <, y, >));
      |                         ^
<source>:23:3: note: expanded from macro 'TOPLING_CMP'
   23 |   TOPLING_PP_VA_NAME(TOPLING_CMP_O_,__VA_ARGS__)(__VA_ARGS__) }
      |   ^
<source>:12:9: note: expanded from macro 'TOPLING_PP_VA_NAME'
   12 |         TOPLING_PP_CAT2(prefix,TOPLING_PP_ARG_N(__VA_ARGS__))
      |         ^
<source>:2:35: note: expanded from macro 'TOPLING_PP_CAT2'
    2 | #define TOPLING_PP_CAT2(a,b)      TOPLING_PP_CAT2_1(a,b)
      |                                   ^
note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
<scratch space>:313:1: note: expanded from here
  313 | TOPLING_CMP_O_4
      | ^
<source>:19:34: note: expanded from macro 'TOPLING_CMP_O_4'
   19 | #define TOPLING_CMP_O_4(f,o,...) TOPLING_CMP1(. ,f,o)TOPLING_CMP_O_2(__VA_ARGS__)
      |                                  ^
<source>:16:28: note: expanded from macro 'TOPLING_CMP1'
   16 |     if (__y_ d f o __x_ d f) return false;
      |                            ^
4 errors generated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"duplicateResolved as duplicaterejects-valid

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions