File: n809.c

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (122 lines) | stat: -rw-r--r-- 6,142 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// RUN: %clang_cc1 -verify -std=c99 %s

/* WG14 N620, N638, N657, N694, N809: Partial
 * Complex and imaginary support in <complex.h>
 *
 * NB: Clang supports _Complex but not _Imaginary. In C99, _Complex support is
 * required outside of freestanding, but _Imaginary support is fully optional.
 * In C11, both are made fully optional.
 *
 * NB: _Complex support requires an underlying support library such as
 * compiler-rt to provide functions like __divsc3. Compiler-rt is not supported
 * on Windows.
 *
 * Because the functionality is so intertwined between the various papers,
 * we're testing all of the functionality in one file.
 */

// Demonstrate that we support spelling complex floating-point objects.
float _Complex f1;
_Complex float f2;

double _Complex d1;
_Complex double d2;

long double _Complex ld1;
_Complex long double ld2;

// Show that we don't support spelling imaginary types.
float _Imaginary fi1; // expected-error {{imaginary types are not supported}}
_Imaginary float fi2; // expected-error {{imaginary types are not supported}}

double _Imaginary di1; // expected-error {{imaginary types are not supported}}
_Imaginary double di2; // expected-error {{imaginary types are not supported}}

long double _Imaginary ldi1; // expected-error {{imaginary types are not supported}}
_Imaginary long double ldi2; // expected-error {{imaginary types are not supported}}

// Each complex type has the same representation and alignment as an array
// containing two elements of the corresponding real type. Note, it is not
// mandatory that the alignment of a structure containing an array of two
// elements has the same alignment as an array of two elements outside of a
// structure, but this is a property Clang supports.
_Static_assert(sizeof(float _Complex) == sizeof(struct { float mem[2]; }), "");
_Static_assert(_Alignof(float _Complex) == _Alignof(struct { float mem[2]; }), "");

_Static_assert(sizeof(double _Complex) == sizeof(struct { double mem[2]; }), "");
_Static_assert(_Alignof(double _Complex) == _Alignof(struct { double mem[2]; }), "");

_Static_assert(sizeof(long double _Complex) == sizeof(struct { long double mem[2]; }), "");
_Static_assert(_Alignof(long double _Complex) == _Alignof(struct { long double mem[2]; }), "");

// The first element corresponds to the real part and the second element
// corresponds to the imaginary part.
_Static_assert(__real((float _Complex){ 1.0f, 2.0f }) == 1.0f, "");
_Static_assert(__imag((float _Complex){ 1.0f, 2.0f }) == 2.0f, "");

_Static_assert(__real((double _Complex){ 1.0, 2.0 }) == 1.0, "");
_Static_assert(__imag((double _Complex){ 1.0, 2.0 }) == 2.0, "");

_Static_assert(__real((long double _Complex){ 1.0L, 2.0L }) == 1.0L, "");
_Static_assert(__imag((long double _Complex){ 1.0L, 2.0L }) == 2.0L, "");

// When a real value is converted to a complex value, the real part follows the
// usual conversion rules and the imaginary part should be zero.
_Static_assert(__real((float _Complex)1.0f) == 1.0f, "");
_Static_assert(__imag((float _Complex)1.0f) == 0.0f, "");

_Static_assert(__real((double _Complex)1.0f) == 1.0, "");
_Static_assert(__imag((double _Complex)1.0f) == 0.0, "");

_Static_assert(__real((long double _Complex)1.0f) == 1.0L, "");
_Static_assert(__imag((long double _Complex)1.0f) == 0.0L, "");

// When a complex value is converted to a real value, the real part follows the
// usual conversion rules and the imaginary part is discarded.
_Static_assert((float)(float _Complex){ 1.0f, 2.0f } == 1.0f, "");
_Static_assert((double)(float _Complex){ 1.0f, 2.0f } == 1.0, "");
_Static_assert((long double)(float _Complex){ 1.0f, 2.0f } == 1.0L, "");

// Complex values are only equal if both the real and imaginary parts are equal.
_Static_assert((float _Complex){ 1.0f, 2.0f } == (float _Complex){ 1.0f, 2.0f }, "");
_Static_assert((double _Complex){ 1.0, 2.0 } == (double _Complex){ 1.0, 2.0 }, "");
_Static_assert((long double _Complex){ 1.0L, 2.0L } == (long double _Complex){ 1.0L, 2.0L }, "");

_Static_assert((float _Complex){ 1.0f, 2.0f } != (float _Complex){ 2.0f, 0.0f }, "");
_Static_assert((double _Complex){ 1.0, 2.0 } != (double _Complex){ 2.0, 0.0 }, "");
_Static_assert((long double _Complex){ 1.0L, 2.0L } != (long double _Complex){ 2.0L, 0.0L }, "");

// You cannot use relational operator on complex values.
int i1 = (float _Complex){ 1.0f, 2.0f } < 10;        // expected-error {{invalid operands to binary expression}}
int i2 = (double _Complex){ 1.0f, 2.0f } > 10;       // expected-error {{invalid operands to binary expression}}
int i3 = (long double _Complex){ 1.0f, 2.0f } <= 10; // expected-error {{invalid operands to binary expression}}
int i4 = (float _Complex){ 1.0f, 2.0f } >= 10;       // expected-error {{invalid operands to binary expression}}

// As a type specifier, _Complex cannot appear alone; however, we support it as
// an extension by assuming _Complex double.
_Complex c = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}}
// Because we don't support imaginary types, we don't extend the extension to
// that type specifier.
// FIXME: the warning diagnostic here is incorrect and should not be emitted.
_Imaginary i = 1.0f; // expected-warning {{plain '_Complex' requires a type specifier; assuming '_Complex double'}} \
                        expected-error {{imaginary types are not supported}}

void func(void) {
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wpedantic"
  // Increment and decrement operators have a constraint that their operand be
  // a real type; Clang supports this as an extension on complex types as well.
  _Complex float cf = 0.0f;

  cf++; // expected-warning {{'++' on an object of complex type is a C2y extension}}
  ++cf; // expected-warning {{'++' on an object of complex type is a C2y extension}}

  cf--; // expected-warning {{'--' on an object of complex type is a C2y extension}}
  --cf; // expected-warning {{'--' on an object of complex type is a C2y extension}}

  // However, unary + and - are fine, as is += 1.
  (void)-cf;
  (void)+cf;
  cf += 1;
#pragma clang diagnostic pop
}