robertoraggi / cplusplus

A compiler front end for the C++ language
https://robertoraggi.github.io/cplusplus/
MIT License
121 stars 12 forks source link

return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f }; #318

Open mingodad opened 8 months ago

mingodad commented 8 months ago

While testing cxx with https://github.com/PX4/eigen/tree/3.4 :

/* The Intel API is flexible enough that we must allow aliasing with other
   vector types, and their scalar components.  */
typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));

/* Create a vector of zeros.  */
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_setzero_ps (void)
{
  return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
}

Output:

g++ -fsyntax-only test-m128.cpp
#no error

clang++ -fsyntax-only test-m128.cpp
test-m128.cpp:6:74: warning: unknown attribute '__artificial__' ignored [-Wunknown-attributes]
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
                                                                         ^
1 warning generated.

cxx -fsyntax-only -toolchain linux test-m128.cpp
test-m128.cpp:9:32: expected ';'
  return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
                               ^
test-m128.cpp:9:57: expected ';'
  return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
                                                        ^
mingodad commented 8 months ago

Also I noticed that the error messages when inside macros only point to the macro without referencing the actual place where the macro is expanded, see bellow that the Memory.h:937:17: expected '(' is repeated several times because the macro is found in several places, clang and gcc would also indicate where the macros have been expanded.

/usr/bin/time ../build-release/src/frontend/cxx -fsyntax-only -toolchain linux -DEIGEN_NO_CPUIDx eigen/test/array_reverse.cpp -Ieigen/test/..
/usr/lib/gcc/x86_64-linux-gnu/11/include/xmmintrin.h:120:32: expected ';'
  return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
                               ^
...
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:17: expected '('
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                ^
eigen/test/../Eigen/src/Core/util/Memory.h:937:84: expected ')'
        __asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
                                                                                   ^
Command exited with non-zero status 1
0.75user 0.05system 0:00.81elapsed 99%CPU (0avgtext+0avgdata 137660maxresident)k
0inputs+0outputs (0major+37458minor)pagefaults 0swaps
==rc:FAILED==

Look at this small example:

#define BADMACRO(x)  if(x) true

int  test()
{
    return BADMACRO(3);
}

g++:

g++  test-macro-error-message.cpp
test-macro-error-message.cpp: In function ‘int test()’:
test-macro-error-message.cpp:1:22: error: expected primary-expression before ‘if’
    1 | #define BADMACRO(x)  if(x) true
      |                      ^~
test-macro-error-message.cpp:5:9: note: in expansion of macro ‘BADMACRO’
    5 |  return BADMACRO(3);
      |         ^~~~~~~~
test-macro-error-message.cpp:5:8: error: expected ‘;’ before ‘if’
    5 |  return BADMACRO(3);
      |        ^
      |        ;

cxx:

cxx  test-macro-error-message.cpp
test-macro-error-message.cpp:1:22: expected an expression
#define BADMACRO(x)  if(x) true
                     ^
mingodad commented 8 months ago

This somehow g++ manage to give a better error message:

g++  -E test-macro-error-message.cpp
# 1 "test-macro-error-message.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test-macro-error-message.cpp"

int test()
{
 return if(3) true;
}
>g++   test-macro-error-message.i
test-macro-error-message.cpp: In function ‘int test()’:
test-macro-error-message.cpp:5:9: error: expected primary-expression before ‘if’
    5 |  return BADMACRO(3);
      |         ^~
test-macro-error-message.cpp:5:8: error: expected ‘;’ before ‘if’
    5 |  return BADMACRO(3);
      |        ^~~
      |        ;
robertoraggi commented 8 months ago

Yes, these are the compound literals. It’s gcc extension for c++, i believe you already reported it here https://github.com/robertoraggi/cplusplus/issues/306

mingodad commented 8 months ago

Doing more tests I came with this one:

int test()
{
return 3 = 1;
}

That cxx parses without showing any error:

cxx test-int-eq-int.cpp
# no error at all

g++ test-int-eq-int.cpp
test-int-eq-int.cpp: In function ‘int test()’:
test-int-eq-int.cpp:3:12: error: lvalue required as left operand of assignment
    3 | return 3 = 1;
      |            ^
mingodad commented 8 months ago

Ok g++ and clang does semantic analyzes even with -fsyntax-only and cxx only does syntaic analyzes always, my bad.

robertoraggi commented 8 months ago

Doing more tests I came with this one: That cxx parses without showing any error:

semantic errors are protected by the cli option -fcheck. But i just started working on the semantics, it’s going to take awhile before i can enable the checks. After I’m done binding the symbols and with the name lookup i will report the errors

robertoraggi commented 8 months ago

Ok g++ and clang does semantic analyzes even with -fsyntax-only and cxx only does syntaic analyzes always, my bad.

-fsyntax-only is a nop at the moment

mingodad commented 8 months ago

Thank you for reply ! I can understand the complexity that you are fighting with this project.