mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
2e7913342e
Fixes https://github.com/llvm/llvm-project/issues/58637. Adds `isAlignas()` method on `AttributeCommonInfo` which accounts for C++ `alignas` as well as C11 `_Alignas`. The method is used to improve diagnostic in C when `_Alignas` is used in C at the wrong location. This corrects the previously suggested move of `_Alignas` past the declaration specifier, now warns attribute `_Alignas` is ignored. Based on https://reviews.llvm.org/D141177.
375 lines
14 KiB
C
375 lines
14 KiB
C
/* RUN: %clang_cc1 -std=c89 -verify=expected,c89only -pedantic -Wno-c11-extensions %s
|
|
RUN: %clang_cc1 -std=c99 -verify=expected -pedantic -Wno-c11-extensions %s
|
|
RUN: %clang_cc1 -std=c11 -verify=expected -pedantic %s
|
|
RUN: %clang_cc1 -std=c17 -verify=expected -pedantic %s
|
|
RUN: %clang_cc1 -std=c2x -verify=expected -pedantic %s
|
|
*/
|
|
|
|
/* The following are DRs which do not require tests to demonstrate
|
|
* conformance or nonconformance.
|
|
*
|
|
* WG14 DR401: yes
|
|
* "happens before" can not be cyclic
|
|
*
|
|
* WG14 DR402: yes
|
|
* Memory model coherence is not aligned with C++11
|
|
*
|
|
* WG14 DR404: yes
|
|
* Joke fragment remains in a footnote
|
|
*
|
|
* WG14 DR406: yes
|
|
* Visible sequences of side effects are redundant
|
|
*
|
|
* WG14 DR415: yes
|
|
* Missing divide by zero entry in Annex J
|
|
*
|
|
* WG14 DR417: yes
|
|
* Annex J not updated with necessary aligned_alloc entries
|
|
*
|
|
* WG14 DR419: yes
|
|
* Generic Functions
|
|
*
|
|
* WG14 DR420: yes
|
|
* Sytax error in specification of for-statement
|
|
*
|
|
* WG14 DR425: yes
|
|
* No specification for the access to variables with temporary lifetime
|
|
*
|
|
* WG14 DR434: yes
|
|
* Possible defect report: Missing constraint w.r.t. Atomic
|
|
*
|
|
* WG14 DR435: yes
|
|
* Possible defect report: Missing constraint w.r.t. Imaginary
|
|
*
|
|
* WG14 DR436: yes
|
|
* Request for interpretation of C11 6.8.5#6
|
|
* Note: This is not really testable because it requires -O1 or higher for LLVM
|
|
* to perform its reachability analysis and -Wunreachable-code only verifies
|
|
* diagnostic behavior, not runtime behavior. Also, both are a matter of QoI as
|
|
* to what they optimize/diagnose. But if someone thinks of a way to test this,
|
|
* we can add a test case for it then.
|
|
*
|
|
* WG14 DR448: yes
|
|
* What are the semantics of a # non-directive?
|
|
*
|
|
* WG14 DR454: yes
|
|
* ATOMIC_VAR_INIT (issues 3 and 4)
|
|
*
|
|
* WG14 DR455: yes
|
|
* ATOMIC_VAR_INIT issue 5
|
|
*
|
|
* WG14 DR459: yes
|
|
* atomic_load missing const qualifier
|
|
*
|
|
* WG14 DR475: yes
|
|
* Misleading Atomic library references to atomic types
|
|
*
|
|
* WG14 DR485: yes
|
|
* Problem with the specification of ATOMIC_VAR_INIT
|
|
*
|
|
* WG14 DR486: yes
|
|
* Inconsistent specification for arithmetic on atomic objects
|
|
*
|
|
* WG14 DR490: yes
|
|
* Unwritten Assumptions About if-then
|
|
*/
|
|
|
|
/* WG14 DR412: yes
|
|
* #elif
|
|
*
|
|
* Note: this is testing that #elif behaves the same as #else followed by #if.
|
|
*/
|
|
#if 1
|
|
#elif this is not a valid expression
|
|
#else
|
|
#if this is not a valid expression
|
|
#endif
|
|
#endif
|
|
|
|
/* WG14 DR413: yes
|
|
* Initialization
|
|
*/
|
|
void dr413(void) {
|
|
typedef struct {
|
|
int k;
|
|
int l;
|
|
int a[2];
|
|
} T;
|
|
|
|
typedef struct {
|
|
int i;
|
|
T t;
|
|
} S;
|
|
|
|
/* Ensure that explicit initialization (.t = { ... }) takes precedence over a
|
|
* later implicit partial initialization (.t.l = 41). The value should be 42,
|
|
* not 0.
|
|
*/
|
|
_Static_assert((S){ /* c89only-warning {{compound literals are a C99-specific feature}}
|
|
expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
|
|
*/
|
|
1,
|
|
.t = { /* c89only-warning {{designated initializers are a C99 feature}} */
|
|
.l = 43, /* c89only-warning {{designated initializers are a C99 feature}}
|
|
expected-note {{previous initialization is here}}
|
|
*/
|
|
.k = 42,
|
|
.a[1] = 19, /* expected-note {{previous initialization is here}} */
|
|
.a[0] = 18
|
|
},
|
|
.t.l = 41, /* expected-warning {{initializer overrides prior initialization of this subobject}} */
|
|
.t.a[1] = 17 /* expected-warning {{initializer overrides prior initialization of this subobject}} */
|
|
}.t.k == 42, "");
|
|
}
|
|
|
|
/* WG14 DR423: partial
|
|
* Defect Report relative to n1570: underspecification for qualified rvalues
|
|
*/
|
|
|
|
/* FIXME: this should pass because the qualifier on the return type should be
|
|
* dropped when forming the function type.
|
|
*/
|
|
const int dr423_const(void);
|
|
int dr423_nonconst(void);
|
|
_Static_assert(__builtin_types_compatible_p(__typeof__(dr423_const), __typeof__(dr423_nonconst)), "fail"); /* expected-error {{fail}} */
|
|
|
|
void dr423_func(void) {
|
|
const int i = 12;
|
|
__typeof__(i) v1 = 12; /* expected-note {{variable 'v1' declared const here}} */
|
|
__typeof__((const int)12) v2 = 12;
|
|
|
|
v1 = 100; /* expected-error {{cannot assign to variable 'v1' with const-qualified type 'typeof (i)' (aka 'const int')}} */
|
|
v2 = 100; /* Not an error; the qualifier was stripped. */
|
|
}
|
|
|
|
/* WG14 DR432: yes
|
|
* Possible defect report: Is 0.0 required to be a representable value?
|
|
*
|
|
* We're going to lean on the fpclassify builtin to tell us whether 0.0
|
|
* represents the value 0, and we'll test that adding and subtracting 0.0 does
|
|
* not change the value, and we'll hope that's enough to validate this DR.
|
|
*/
|
|
_Static_assert(__builtin_fpclassify(0, 1, 2, 3, 4, 0.0f) == 4, "");
|
|
_Static_assert((1.0 / 3.0) + 0.0 == (1.0 / 3.0) - 0.0, ""); /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} */
|
|
|
|
/* WG14 DR444: partial
|
|
* Issues with alignment in C11, part 1
|
|
*/
|
|
void dr444(void) {
|
|
_Alignas(int) int i;
|
|
_Alignas(int) struct S {
|
|
_Alignas(int) int i;
|
|
} s;
|
|
|
|
/* FIXME: This should be accepted as per this DR. */
|
|
int j = (_Alignas(int) int){12}; /* expected-error {{expected expression}} */
|
|
|
|
_Alignas(int) struct T { /* expected-warning {{'_Alignas' attribute ignored}} */
|
|
int i;
|
|
};
|
|
|
|
struct U {
|
|
_Alignas(int) int bit : 1; /* expected-error {{'_Alignas' attribute cannot be applied to a bit-field}} */
|
|
};
|
|
|
|
_Alignas(int) typedef int foo; /* expected-error {{'_Alignas' attribute only applies to variables and fields}} */
|
|
_Alignas(int) register int bar; /* expected-error {{'_Alignas' attribute cannot be applied to a variable with 'register' storage class}} */
|
|
_Alignas(int) void func(void); /* expected-error {{'_Alignas' attribute only applies to variables and fields}} */
|
|
|
|
/* FIXME: it is correct for us to accept this per 6.7.3p5, but it seems like
|
|
* a situation we'd want to diagnose because the alignments are different and
|
|
* the user probably doesn't know which one "wins".
|
|
*/
|
|
_Alignas(int) _Alignas(double) int k;
|
|
}
|
|
|
|
/* WG14 DR447: yes
|
|
* Boolean from complex
|
|
*
|
|
* Ensure that the imaginary part contributes to the conversion to bool, not
|
|
* just the real part.
|
|
*/
|
|
_Static_assert((_Bool)0.0 + 3.0 * (__extension__ 1.0iF), ""); /* c89only-warning {{'_Bool' is a C99 extension}}
|
|
expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
|
|
*/
|
|
_Static_assert(!(_Bool)0.0 + 0.0 * (__extension__ 1.0iF), ""); /* c89only-warning {{'_Bool' is a C99 extension}}
|
|
expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
|
|
*/
|
|
|
|
/* WG14 DR463: yes
|
|
* Left-shifting into the sign bit
|
|
*
|
|
* This DR was NAD and leaves shifting a bit into the high bit of a signed
|
|
* integer type undefined behavior, unlike in C++. Note, the diagnostic is also
|
|
* issued in C++ for shifting into that bit despite being well-defined because
|
|
* the code is questionable and should be validated by the programmer.
|
|
*/
|
|
void dr463(void) {
|
|
(void)(1 << (__CHAR_BIT__ * sizeof(int))); /* expected-warning {{shift count >= width of type}} */
|
|
(void)(1 << ((__CHAR_BIT__ * sizeof(int)) - 1));
|
|
}
|
|
|
|
/* WG14 DR478: yes
|
|
* Valid uses of the main function
|
|
*/
|
|
int main(void) {
|
|
/* This DR clarifies that C explicitly allows you to call main() in a hosted
|
|
* environment; it is not special as it is in C++, so recursive calls are
|
|
* fine as well as nonrecursive direct calls.
|
|
*/
|
|
main(); /* ok */
|
|
}
|
|
|
|
void dr478(void) {
|
|
int (*fp)(void) = main; /* ok */
|
|
main(); /* ok */
|
|
}
|
|
|
|
/* WG14 DR481: yes
|
|
* Controlling expression of _Generic primary expression
|
|
*/
|
|
void dr481(void) {
|
|
/* The controlling expression undergoes lvalue to rvalue conversion, and that
|
|
* performs array decay and strips qualifiers.
|
|
*/
|
|
(void)_Generic("bla", char *: "blu");
|
|
(void)_Generic((int const){ 0 }, int: "blu"); /* c89only-warning {{compound literals are a C99-specific feature}} */
|
|
(void)_Generic(+(int const){ 0 }, int: "blu"); /* c89only-warning {{compound literals are a C99-specific feature}} */
|
|
|
|
(void)_Generic("bla", /* expected-error {{controlling expression type 'char *' not compatible with any generic association type}} */
|
|
char[4]: "blu"); /* expected-warning {{due to lvalue conversion of the controlling expression, association of type 'char[4]' will never be selected because it is of array type}} */
|
|
|
|
(void)_Generic((int const){ 0 }, /* expected-error {{controlling expression type 'int' not compatible with any generic association type}}
|
|
c89only-warning {{compound literals are a C99-specific feature}}
|
|
*/
|
|
int const: "blu"); /* expected-warning {{due to lvalue conversion of the controlling expression, association of type 'const int' will never be selected because it is qualified}} */
|
|
|
|
(void)_Generic(+(int const){ 0 }, /* expected-error {{controlling expression type 'int' not compatible with any generic association type}}
|
|
c89only-warning {{compound literals are a C99-specific feature}}
|
|
*/
|
|
int const: "blu"); /* expected-warning {{due to lvalue conversion of the controlling expression, association of type 'const int' will never be selected because it is qualified}} */
|
|
}
|
|
|
|
/* WG14 DR489: partial
|
|
* Integer Constant Expression
|
|
*
|
|
* The DR is about whether unevaluated operands have to follow the same
|
|
* restrictions as the rest of the expression in an ICE, and according to the
|
|
* committee, they do.
|
|
*/
|
|
void dr489(void) {
|
|
struct S {
|
|
int bit : 12 || 1.0f; /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} */
|
|
};
|
|
enum E {
|
|
Val = 0 && 1.0f /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} */
|
|
};
|
|
|
|
int i;
|
|
|
|
/* FIXME: mentioning the 'aligned' attribute is confusing, but also, should
|
|
* this be folded as an ICE as a GNU extension? GCC does not fold it.
|
|
*/
|
|
_Alignas(0 ? i++ : 8) char c; /* expected-error {{'aligned' attribute requires integer constant}} */
|
|
|
|
/* FIXME: this should get the constant folding diagnostic as this is not a
|
|
* valid ICE because the floating-point constants are not the immediate
|
|
* operand of a cast. It should then also get a diagnostic about trying to
|
|
* declare a VLA with static storage duration and the C99 extension warning
|
|
* for VLAs in C89.
|
|
*/
|
|
static int vla[sizeof(1.0f + 1.0f)];
|
|
|
|
int val[5] = { [1 ? 0 : i--] = 12 }; /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
|
|
c89only-warning {{designated initializers are a C99 feature}}
|
|
*/
|
|
|
|
/* FIXME: this should be the constant folding diagnostic as this is not a
|
|
* valid ICE because of the / operator.
|
|
*/
|
|
_Static_assert(sizeof(0 / 0), "");
|
|
|
|
/* FIXME: this should also get the constant folding diagnostic as this is not
|
|
* a valid ICE because of the = operator.
|
|
*/
|
|
(void)_Generic(i = 12, int : 0); /* expected-warning {{expression with side effects has no effect in an unevaluated context}} */
|
|
|
|
switch (i) {
|
|
case (int)0.0f: break; /* okay, a valid ICE */
|
|
|
|
/* FIXME: this should be accepted in C23 and up without a diagnostic, as C23
|
|
* added compound literals to the allowed list of things in an ICE. The
|
|
* diagnostic is correct for C17 and earlier though.
|
|
*/
|
|
case (int){ 2 }: break; /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
|
|
c89only-warning {{compound literals are a C99-specific feature}}
|
|
*/
|
|
case 12 || main(): break; /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} */
|
|
}
|
|
}
|
|
|
|
/* WG14 DR492: yes
|
|
* Named Child struct-union with no Member
|
|
*/
|
|
struct dr492_t {
|
|
union U11 { /* expected-warning {{declaration does not declare anything}} */
|
|
int m11;
|
|
float m12;
|
|
};
|
|
int m13;
|
|
} dr492;
|
|
|
|
/* WG14 DR496: yes
|
|
* offsetof questions
|
|
*/
|
|
void dr496(void) {
|
|
struct A { int n, a [2]; };
|
|
struct B { struct A a; };
|
|
struct C { struct A a[1]; };
|
|
|
|
/* Array access & member access expressions are now valid. */
|
|
_Static_assert(__builtin_offsetof(struct B, a.n) == 0, "");
|
|
/* First int below is for 'n' and the second int is for 'a[0]'; this presumes
|
|
* there is no padding involved.
|
|
*/
|
|
_Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), "");
|
|
|
|
/* However, we do not support using the -> operator to access a member, even
|
|
* if that would be a valid expression. FIXME: GCC accepts this, perhaps we
|
|
* should as well.
|
|
*/
|
|
(void)__builtin_offsetof(struct C, a->n); /* expected-error {{expected ')'}} \
|
|
expected-note {{to match this '('}}
|
|
*/
|
|
|
|
/* The DR asked a question about whether defining a new type within offsetof
|
|
* is allowed. C2x N2350 made this explicitly undefined behavior, but GCC and
|
|
* Clang both support it as an extension.
|
|
*/
|
|
(void)__builtin_offsetof(struct S { int a; }, a); /* expected-warning{{defining a type within '__builtin_offsetof' is a Clang extension}} */
|
|
}
|
|
|
|
/* WG14 DR499: yes
|
|
* Anonymous structure in union behavior
|
|
*/
|
|
void dr499(void) {
|
|
union U {
|
|
struct {
|
|
char B1;
|
|
char B2;
|
|
char B3;
|
|
char B4;
|
|
};
|
|
int word;
|
|
} u;
|
|
|
|
/* Validate that B1, B2, B3, and B4 do not have overlapping storage, only the
|
|
* anonymous structure and 'word' overlap.
|
|
*/
|
|
_Static_assert(__builtin_offsetof(union U, B1) == 0, "");
|
|
_Static_assert(__builtin_offsetof(union U, B2) == 1, "");
|
|
_Static_assert(__builtin_offsetof(union U, B3) == 2, "");
|
|
_Static_assert(__builtin_offsetof(union U, B4) == 3, "");
|
|
_Static_assert(__builtin_offsetof(union U, word) == 0, "");
|
|
}
|