xref: /llvm-project/clang/test/C/C99/n809.c (revision 1e26a251a36b0479c7aca21e2d65d9877c0691ce)
10318ce85SAaron Ballman // RUN: %clang_cc1 -verify -std=c99 %s
20318ce85SAaron Ballman 
30318ce85SAaron Ballman /* WG14 N620, N638, N657, N694, N809: Partial
40318ce85SAaron Ballman  * Complex and imaginary support in <complex.h>
50318ce85SAaron Ballman  *
60318ce85SAaron Ballman  * NB: Clang supports _Complex but not _Imaginary. In C99, _Complex support is
70318ce85SAaron Ballman  * required outside of freestanding, but _Imaginary support is fully optional.
80318ce85SAaron Ballman  * In C11, both are made fully optional.
90318ce85SAaron Ballman  *
100318ce85SAaron Ballman  * NB: _Complex support requires an underlying support library such as
110318ce85SAaron Ballman  * compiler-rt to provide functions like __divsc3. Compiler-rt is not supported
120318ce85SAaron Ballman  * on Windows.
130318ce85SAaron Ballman  *
140318ce85SAaron Ballman  * Because the functionality is so intertwined between the various papers,
150318ce85SAaron Ballman  * we're testing all of the functionality in one file.
160318ce85SAaron Ballman  */
170318ce85SAaron Ballman 
180318ce85SAaron Ballman // Demonstrate that we support spelling complex floating-point objects.
190318ce85SAaron Ballman float _Complex f1;
200318ce85SAaron Ballman _Complex float f2;
210318ce85SAaron Ballman 
220318ce85SAaron Ballman double _Complex d1;
230318ce85SAaron Ballman _Complex double d2;
240318ce85SAaron Ballman 
250318ce85SAaron Ballman long double _Complex ld1;
260318ce85SAaron Ballman _Complex long double ld2;
270318ce85SAaron Ballman 
280318ce85SAaron Ballman // Show that we don't support spelling imaginary types.
290318ce85SAaron Ballman float _Imaginary fi1; // expected-error {{imaginary types are not supported}}
300318ce85SAaron Ballman _Imaginary float fi2; // expected-error {{imaginary types are not supported}}
310318ce85SAaron Ballman 
320318ce85SAaron Ballman double _Imaginary di1; // expected-error {{imaginary types are not supported}}
330318ce85SAaron Ballman _Imaginary double di2; // expected-error {{imaginary types are not supported}}
340318ce85SAaron Ballman 
350318ce85SAaron Ballman long double _Imaginary ldi1; // expected-error {{imaginary types are not supported}}
360318ce85SAaron Ballman _Imaginary long double ldi2; // expected-error {{imaginary types are not supported}}
370318ce85SAaron Ballman 
380318ce85SAaron Ballman // Each complex type has the same representation and alignment as an array
390318ce85SAaron Ballman // containing two elements of the corresponding real type. Note, it is not
400318ce85SAaron Ballman // mandatory that the alignment of a structure containing an array of two
410318ce85SAaron Ballman // elements has the same alignment as an array of two elements outside of a
420318ce85SAaron Ballman // structure, but this is a property Clang supports.
430318ce85SAaron Ballman _Static_assert(sizeof(float _Complex) == sizeof(struct { float mem[2]; }), "");
440318ce85SAaron Ballman _Static_assert(_Alignof(float _Complex) == _Alignof(struct { float mem[2]; }), "");
450318ce85SAaron Ballman 
460318ce85SAaron Ballman _Static_assert(sizeof(double _Complex) == sizeof(struct { double mem[2]; }), "");
470318ce85SAaron Ballman _Static_assert(_Alignof(double _Complex) == _Alignof(struct { double mem[2]; }), "");
480318ce85SAaron Ballman 
490318ce85SAaron Ballman _Static_assert(sizeof(long double _Complex) == sizeof(struct { long double mem[2]; }), "");
500318ce85SAaron Ballman _Static_assert(_Alignof(long double _Complex) == _Alignof(struct { long double mem[2]; }), "");
510318ce85SAaron Ballman 
520318ce85SAaron Ballman // The first element corresponds to the real part and the second element
530318ce85SAaron Ballman // corresponds to the imaginary part.
540318ce85SAaron Ballman _Static_assert(__real((float _Complex){ 1.0f, 2.0f }) == 1.0f, "");
550318ce85SAaron Ballman _Static_assert(__imag((float _Complex){ 1.0f, 2.0f }) == 2.0f, "");
560318ce85SAaron Ballman 
570318ce85SAaron Ballman _Static_assert(__real((double _Complex){ 1.0, 2.0 }) == 1.0, "");
580318ce85SAaron Ballman _Static_assert(__imag((double _Complex){ 1.0, 2.0 }) == 2.0, "");
590318ce85SAaron Ballman 
600318ce85SAaron Ballman _Static_assert(__real((long double _Complex){ 1.0L, 2.0L }) == 1.0L, "");
610318ce85SAaron Ballman _Static_assert(__imag((long double _Complex){ 1.0L, 2.0L }) == 2.0L, "");
620318ce85SAaron Ballman 
630318ce85SAaron Ballman // When a real value is converted to a complex value, the real part follows the
640318ce85SAaron Ballman // usual conversion rules and the imaginary part should be zero.
650318ce85SAaron Ballman _Static_assert(__real((float _Complex)1.0f) == 1.0f, "");
660318ce85SAaron Ballman _Static_assert(__imag((float _Complex)1.0f) == 0.0f, "");
670318ce85SAaron Ballman 
680318ce85SAaron Ballman _Static_assert(__real((double _Complex)1.0f) == 1.0, "");
690318ce85SAaron Ballman _Static_assert(__imag((double _Complex)1.0f) == 0.0, "");
700318ce85SAaron Ballman 
710318ce85SAaron Ballman _Static_assert(__real((long double _Complex)1.0f) == 1.0L, "");
720318ce85SAaron Ballman _Static_assert(__imag((long double _Complex)1.0f) == 0.0L, "");
730318ce85SAaron Ballman 
740318ce85SAaron Ballman // When a complex value is converted to a real value, the real part follows the
750318ce85SAaron Ballman // usual conversion rules and the imaginary part is discarded.
760318ce85SAaron Ballman _Static_assert((float)(float _Complex){ 1.0f, 2.0f } == 1.0f, "");
770318ce85SAaron Ballman _Static_assert((double)(float _Complex){ 1.0f, 2.0f } == 1.0, "");
780318ce85SAaron Ballman _Static_assert((long double)(float _Complex){ 1.0f, 2.0f } == 1.0L, "");
790318ce85SAaron Ballman 
800318ce85SAaron Ballman // Complex values are only equal if both the real and imaginary parts are equal.
810318ce85SAaron Ballman _Static_assert((float _Complex){ 1.0f, 2.0f } == (float _Complex){ 1.0f, 2.0f }, "");
820318ce85SAaron Ballman _Static_assert((double _Complex){ 1.0, 2.0 } == (double _Complex){ 1.0, 2.0 }, "");
830318ce85SAaron Ballman _Static_assert((long double _Complex){ 1.0L, 2.0L } == (long double _Complex){ 1.0L, 2.0L }, "");
840318ce85SAaron Ballman 
850318ce85SAaron Ballman _Static_assert((float _Complex){ 1.0f, 2.0f } != (float _Complex){ 2.0f, 0.0f }, "");
860318ce85SAaron Ballman _Static_assert((double _Complex){ 1.0, 2.0 } != (double _Complex){ 2.0, 0.0 }, "");
870318ce85SAaron Ballman _Static_assert((long double _Complex){ 1.0L, 2.0L } != (long double _Complex){ 2.0L, 0.0L }, "");
880318ce85SAaron Ballman 
890318ce85SAaron Ballman // You cannot use relational operator on complex values.
900318ce85SAaron Ballman int i1 = (float _Complex){ 1.0f, 2.0f } < 10;        // expected-error {{invalid operands to binary expression}}
910318ce85SAaron Ballman int i2 = (double _Complex){ 1.0f, 2.0f } > 10;       // expected-error {{invalid operands to binary expression}}
920318ce85SAaron Ballman int i3 = (long double _Complex){ 1.0f, 2.0f } <= 10; // expected-error {{invalid operands to binary expression}}
930318ce85SAaron Ballman int i4 = (float _Complex){ 1.0f, 2.0f } >= 10;       // expected-error {{invalid operands to binary expression}}
940318ce85SAaron Ballman 
950318ce85SAaron Ballman // As a type specifier, _Complex cannot appear alone; however, we support it as
960318ce85SAaron Ballman // an extension by assuming _Complex double.
970318ce85SAaron Ballman _Complex c = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}}
980318ce85SAaron Ballman // Because we don't support imaginary types, we don't extend the extension to
990318ce85SAaron Ballman // that type specifier.
1000318ce85SAaron Ballman // FIXME: the warning diagnostic here is incorrect and should not be emitted.
1010318ce85SAaron Ballman _Imaginary i = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} \
1020318ce85SAaron Ballman                         expected-error {{imaginary types are not supported}}
1030318ce85SAaron Ballman 
func(void)1040318ce85SAaron Ballman void func(void) {
1050318ce85SAaron Ballman #pragma clang diagnostic push
1060318ce85SAaron Ballman #pragma clang diagnostic warning "-Wpedantic"
1070318ce85SAaron Ballman   // Increment and decrement operators have a constraint that their operand be
1080318ce85SAaron Ballman   // a real type; Clang supports this as an extension on complex types as well.
1090318ce85SAaron Ballman   _Complex float cf = 0.0f;
1100318ce85SAaron Ballman 
111*1e26a251SAaron Ballman   cf++; // expected-warning {{'++' on an object of complex type is a C2y extension}}
112*1e26a251SAaron Ballman   ++cf; // expected-warning {{'++' on an object of complex type is a C2y extension}}
1130318ce85SAaron Ballman 
114*1e26a251SAaron Ballman   cf--; // expected-warning {{'--' on an object of complex type is a C2y extension}}
115*1e26a251SAaron Ballman   --cf; // expected-warning {{'--' on an object of complex type is a C2y extension}}
1160318ce85SAaron Ballman 
1170318ce85SAaron Ballman   // However, unary + and - are fine, as is += 1.
1180318ce85SAaron Ballman   (void)-cf;
1190318ce85SAaron Ballman   (void)+cf;
1200318ce85SAaron Ballman   cf += 1;
1210318ce85SAaron Ballman #pragma clang diagnostic pop
1220318ce85SAaron Ballman }
123