brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.1 KiB · 113ecf7 Raw
518 lines · c
1// RUN: %clang_cc1 -fsyntax-only -std=c23 -pedantic -Wall -Wno-comment -verify=both,c23 %s2// RUN: %clang_cc1 -fsyntax-only -std=c17 -pedantic -Wall -Wno-comment -Wno-c23-extensions -verify=both,c17 %s3 4/* WG14 N3037: Clang 215 * Improved tag compatibility6 *7 * Identical tag types have always been compatible across TU boundaries. This8 * paper made identical tag types compatible within the same TU.9 */10 11struct foo { int a; } p;12 13void baz(struct foo f); // c17-note {{passing argument to parameter 'f' here}}14 15void bar(void) {16  struct foo { int a; } q = {};17  baz(q); // c17-error {{passing 'struct foo' to parameter of incompatible type 'struct foo'}}18}19 20#define PRODUCT(A ,B) struct prod { A a; B b; }                   // expected-note 2 {{expanded from macro 'PRODUCT'}}21#define SUM(A, B) struct sum { _Bool flag; union { A a; B b; }; } // expected-note 2 {{expanded from macro 'SUM'}}22 23void func1(PRODUCT(int, SUM(float, double)) x); // c17-warning {{declaration of 'struct prod' will not be visible outside of this function}} \24                                                   c17-warning {{declaration of 'struct sum' will not be visible outside of this function}} \25                                                   c17-note {{passing argument to parameter 'x' here}}26void func2(PRODUCT(int, SUM(float, double)) y) { // c17-warning {{declaration of 'struct prod' will not be visible outside of this function}} \27                                                    c17-warning {{declaration of 'struct sum' will not be visible outside of this function}}28  func1(y); // c17-error {{passing 'struct prod' to parameter of incompatible type 'struct prod'}}29}30 31struct foop { struct { int x; }; }; // c17-note {{previous definition is here}}32struct foop { struct { int x; }; }; // c17-error {{redefinition of 'foop'}}33// Test the field lookup compatibility isn't sufficient, the structure of types should be compatible.34struct AnonymousStructNotMatchingFields { // c17-note {{previous definition is here}}35  struct { // c23-note {{field has name '' here}}36    int x;37  };38};39struct AnonymousStructNotMatchingFields { // c23-error {{type 'struct AnonymousStructNotMatchingFields' has incompatible definitions}} \40                                             c17-error {{redefinition of 'AnonymousStructNotMatchingFields'}}41  int x; // c23-note {{field has name 'x' here}}42};43 44union barp { int x; float y; };     // c17-note {{previous definition is here}}45union barp { int x; float y; };     // c17-error {{redefinition of 'barp'}}46typedef struct q { int x; } q_t;    // c17-note 2 {{previous definition is here}}47typedef struct q { int x; } q_t;    // c17-error {{redefinition of 'q'}} \48                                       c17-error-re {{typedef redefinition with different types ('struct (unnamed struct at {{.*}})' vs 'struct q')}}49typedef struct { int x; } untagged_q_t; // both-note {{previous definition is here}}50typedef struct { int x; } untagged_q_t; // both-error {{typedef redefinition with different types}}51void func3(void) {52  struct S { int x; };       // c17-note {{previous definition is here}}53  struct T { struct S s; };  // c17-note {{previous definition is here}}54  struct S { int x; };       // c17-error {{redefinition of 'S'}}55  struct T { struct S s; };  // c17-error {{redefinition of 'T'}}56}57 58struct food { int (*p)[3]; }; // c23-note {{field 'p' has type 'int (*)[3]' here}} \59                                 c17-note {{previous definition is here}}60struct food { int (*p)[]; };  // c23-error {{type 'struct food' has incompatible definitions}} \61                                 c23-note {{field 'p' has type 'int (*)[]' here}} \62                                 c17-error {{redefinition of 'food'}}63union bard { int x; float y; }; // c23-note {{field has name 'x' here}} \64                                   c17-note {{previous definition is here}}65union bard { int z; float y; }; // c23-error {{type 'union bard' has incompatible definitions}} \66                                   c23-note {{field has name 'z' here}} \67                                   c17-error {{redefinition of 'bard'}}68union purr { int x; float y; }; // c23-note {{field has name 'x' here}} \69                                   c17-note {{previous definition is here}}70union purr { float y; int x; }; // c23-error {{type 'union purr' has incompatible definitions}} \71                                   c23-note {{field has name 'y' here}} \72                                   c17-error {{redefinition of 'purr'}}73 74// The presence of an attribute makes two types not compatible.75struct [[gnu::packed]] attr_test { // c17-note {{previous definition is here}} \76                                      c23-note {{attribute 'gnu::packed' here}}77  int x;78};79 80struct attr_test { // c17-error {{redefinition of 'attr_test'}} \81                      c23-error {{type 'struct attr_test' has an attribute which currently causes the types to be treated as though they are incompatible}}82  int x;83};84 85struct attr_test_2 { // c17-note {{previous definition is here}}86  int x;87};88 89struct [[gnu::packed]] attr_test_2 { // c17-error {{redefinition of 'attr_test_2'}} \90                                        c23-error {{type 'struct attr_test_2' has an attribute which currently causes the types to be treated as though they are incompatible}} \91                                        c23-note {{attribute 'gnu::packed' here}}92  int x;93};94 95// This includes the same attribute on both types.96struct [[gnu::packed]] attr_test_3 { // c17-note {{previous definition is here}} \97                                       c23-note {{attribute 'gnu::packed' here}}98  int x;99};100 101struct [[gnu::packed]] attr_test_3 { // c17-error {{redefinition of 'attr_test_3'}} \102                                        c23-error {{type 'struct attr_test_3' has an attribute which currently causes the types to be treated as though they are incompatible}} \103                                        c23-note {{attribute 'gnu::packed' here}}104  int x;105};106 107// Everything which applies to the tag itself also applies to fields.108struct field_attr_test_1 { // c17-note {{previous definition is here}}109  int x;110  [[gnu::packed]] int y; // c23-note {{attribute 'gnu::packed' here}}111};112 113struct field_attr_test_1 { // c17-error {{redefinition of 'field_attr_test_1'}} \114                              c23-error {{type 'struct field_attr_test_1' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}115  int x;116  int y;117};118 119struct field_attr_test_2 { // c17-note {{previous definition is here}}120  [[gnu::packed]] int x; // c23-note {{attribute 'gnu::packed' here}}121  int y;122};123 124struct field_attr_test_2 { // c17-error {{redefinition of 'field_attr_test_2'}} \125                              c23-error {{type 'struct field_attr_test_2' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}126  int x;127  int y;128};129 130struct field_attr_test_3 { // c17-note {{previous definition is here}}131  [[gnu::packed]] int x;   // c23-note {{attribute 'gnu::packed' here}}132  int y;133};134 135struct field_attr_test_3 { // c17-error {{redefinition of 'field_attr_test_3'}} \136                              c23-error {{type 'struct field_attr_test_3' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}137  int x [[gnu::packed]];   // c23-note {{attribute 'gnu::packed' here}}138  int y;139};140 141// Show that equivalent field types are not an issue.142typedef int typedef_of_type_int;143struct equivalent_field_types { // c17-note {{previous definition is here}}144  int x;145};146 147struct equivalent_field_types { // c17-error {{redefinition of 'equivalent_field_types'}}148  typedef_of_type_int x;149};150 151struct quals_matter { // c17-note {{previous definition is here}}152  int x;              // c23-note {{field 'x' has type 'int' here}}153};154 155struct quals_matter { // c17-error {{redefinition of 'quals_matter'}} \156                         c23-error {{type 'struct quals_matter' has incompatible definitions}}157  const int x;        // c23-note {{field 'x' has type 'const int' here}}158};159 160struct qual_order_does_not_matter { // c17-note {{previous definition is here}}161  const volatile int x;162};163 164struct qual_order_does_not_matter { // c17-error {{redefinition of 'qual_order_does_not_matter'}}165  volatile const int x;166};167 168struct nested { // both-note {{previous definition is here}}169  int x;170  struct nested { // both-error {{nested redefinition of 'nested'}}171    int x;172  };173};174 175// Show that bit-field order does matter, including anonymous bit-fields.176struct bit_field_1 { // c17-note 2 {{previous definition is here}}177  int a : 1;178  int : 0;           // c23-note {{field has name '' here}}179  int b : 1;180};181 182struct bit_field_1 { // c17-error {{redefinition of 'bit_field_1'}}183  int a : 1;184  int : 0;185  int b : 1;186};187 188struct bit_field_1 { // c17-error {{redefinition of 'bit_field_1'}} \189                        c23-error {{type 'struct bit_field_1' has incompatible definitions}}190  int a : 1;191  int b : 1;	     // c23-note {{field has name 'b' here}}192};193 194struct bit_field_2 { // c17-note {{previous definition is here}}195  int a : 1;196  int b : 1;         // c23-note {{bit-field 'b' has bit-width 1 here}}197};198 199struct bit_field_2 { // c17-error {{redefinition of 'bit_field_2'}} \200                        c23-error {{type 'struct bit_field_2' has incompatible definitions}}201  int a : 1;202  int b : 2;         // c23-note {{bit-field 'b' has bit-width 2 here}}203};204 205// Test a bit-field with an attribute.206struct bit_field_3 { // c17-note {{previous definition is here}}207  int a : 1;208  int b : 1;209};210 211struct bit_field_3 { // c17-error {{redefinition of 'bit_field_3'}} \212                        c23-error {{type 'struct bit_field_3' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}213  int a : 1;214  [[deprecated]] int b : 1; // c23-note {{attribute 'deprecated' here}}215};216 217struct bit_field_4 { // c17-note {{previous definition is here}}218  int a : 1;219  int b : 1;         // c23-note {{bit-field 'b' has bit-width 1 here}}220};221 222struct bit_field_4 { // c17-error {{redefinition of 'bit_field_4'}} \223                        c23-error {{type 'struct bit_field_4' has incompatible definitions}}224  int a : 1;225  int b;             // c23-note {{field 'b' is not a bit-field}}226};227 228struct bit_field_5 { // c17-note {{previous definition is here}}229  int a : 1;230  int b;             // c23-note {{field 'b' is not a bit-field}}231};232 233struct bit_field_5 { // c17-error {{redefinition of 'bit_field_5'}} \234                        c23-error {{type 'struct bit_field_5' has incompatible definitions}}235  int a : 1;236  int b : 1;         // c23-note {{bit-field 'b' has bit-width 1 here}}237};238 239struct bit_field_6 { // c17-note {{previous definition is here}}240  int a : 2;241};242 243struct bit_field_6 { // c17-error {{redefinition of 'bit_field_6'}}244  int a : 1 + 1;245};246 247enum E { A }; // c17-note 2 {{previous definition is here}}248enum E { A }; // c17-error {{redefinition of 'E'}} \249                 c17-error {{redefinition of enumerator 'A'}}250 251enum Q { D = 1 }; // c17-note 2 {{previous definition is here}}252enum Q { D = D }; // c17-error {{redefinition of 'Q'}} \253                     c17-error {{redefinition of enumerator 'D'}}254 255// The order of the enumeration constants does not matter, only the values do.256enum X { B = 1, C = 1 + 1 }; // c17-note 3 {{previous definition is here}}257enum X { C = 2, B = 1 };     // c17-error {{redefinition of 'X'}} \258                                c17-error {{redefinition of enumerator 'C'}} \259                                c17-error {{redefinition of enumerator 'B'}}260 261// Different enumeration constants.262enum Y { YA = 1, YB = 2 }; // c23-note {{enumerator 'YB' with value 2 here}} \263                              c17-note 3 {{previous definition is here}}264enum Y { YA = 1, YB = 3 }; // c23-error {{type 'enum Y' has incompatible definitions}} \265                              c23-note {{enumerator 'YB' with value 3 here}} \266                              c17-error {{redefinition of 'Y'}} \267							  c17-error {{redefinition of enumerator 'YA'}} \268                              c17-error {{redefinition of enumerator 'YB'}}269 270// Different enumeration names, same named constants.271enum Z1 { ZC = 1 }; // both-note {{previous definition is here}}272enum Z2 { ZC = 1 }; // both-error {{redefinition of enumerator 'ZC'}}273 274// Test attributes on the enumeration and enumerators.275enum [[deprecated]] enum_attr_test_1 { // c17-note {{previous definition is here}} \276                                          c23-note {{attribute 'deprecated' here}}277  EAT1 [[deprecated]] // c17-note {{previous definition is here}} \278                         c23-note {{attribute 'deprecated' here}}279};280 281enum [[deprecated]] enum_attr_test_1 { // c17-error {{redefinition of 'enum_attr_test_1'}} \282                                          c23-error {{type 'enum enum_attr_test_1' has an attribute which currently causes the types to be treated as though they are incompatible}} \283                                          c23-error {{type 'enum enum_attr_test_1' has a member with an attribute which currently causes the types to be treated as though they are incompatible}} \284                                          c23-note {{attribute 'deprecated' here}}285  EAT1 [[deprecated]] // c17-error {{redefinition of enumerator 'EAT1'}} \286                         c23-note {{attribute 'deprecated' here}}287};288 289enum [[deprecated]] enum_attr_test_2 { // c17-note {{previous definition is here}} \290                                          c23-note {{attribute 'deprecated' here}}291  EAT2 // c17-note {{previous definition is here}}292};293 294enum enum_attr_test_2 { // c17-error {{redefinition of 'enum_attr_test_2'}} \295                           c23-error {{type 'enum enum_attr_test_2' has an attribute which currently causes the types to be treated as though they are incompatible}}296  EAT2 // c17-error {{redefinition of enumerator 'EAT2'}}297};298 299enum enum_attr_test_3 { // c17-note {{previous definition is here}}300  EAT3 // c17-note {{previous definition is here}}301};302 303enum [[deprecated]] enum_attr_test_3 { // c17-error {{redefinition of 'enum_attr_test_3'}} \304                                          c23-error {{type 'enum enum_attr_test_3' has an attribute which currently causes the types to be treated as though they are incompatible}} \305                                          c23-note {{attribute 'deprecated' here}}306  EAT3 // c17-error {{redefinition of enumerator 'EAT3'}}307};308 309// You cannot declare one with a fixed underlying type and the other without a310// fixed underlying type, or a different underlying type. However, it's worth311// showing that the underlying type doesn't change the redefinition behavior.312enum fixed_test_1 : int { FT1 }; // c17-note 2 {{previous definition is here}}313enum fixed_test_1 : int { FT1 }; // c17-error {{redefinition of 'fixed_test_1'}} \314                                    c17-error {{redefinition of enumerator 'FT1'}}315 316enum fixed_test_2 : int { FT2 };                 // c17-note 2 {{previous definition is here}}317enum fixed_test_2 : typedef_of_type_int { FT2 }; // c17-error {{redefinition of 'fixed_test_2'}} \318                                                    c17-error {{redefinition of enumerator 'FT2'}}319 320// Test more bizarre situations in terms of where the type is declared. This321// has always been allowed.322struct declared_funny_1 { int x; }323declared_funny_func(struct declared_funny_1 { int x; } arg) { // c17-warning {{declaration of 'struct declared_funny_1' will not be visible outside of this function}}324  return declared_funny_func((__typeof__(arg)){ 0 });325}326 327// However, this is new.328struct Outer {329  struct Inner { // c17-note {{previous definition is here}}330    int x;331  } i;332 333  enum InnerEnum { // c17-note {{previous definition is here}}334    IE1            // c17-note {{previous definition is here}}335  } j;336};337 338struct Inner {   // c17-error {{redefinition of 'Inner'}}339  int x;340};341 342enum InnerEnum { // c17-error {{redefinition of 'InnerEnum'}}343  IE1            // c17-error {{redefinition of enumerator 'IE1'}}344};345 346void hidden(void) {347  struct hidden_struct { int x; };348}349 350struct hidden_struct { // This is fine because the previous declaration is not visible.351  int y;352  int z;353};354 355struct array { int y; int x[]; };    // c17-note {{previous definition is here}} \356                                        c23-note {{field 'x' has type 'int[]' here}}357struct array { int y; int x[0]; };   // c17-error {{redefinition of 'array'}} \358                                        c23-error {{type 'struct array' has incompatible definitions}} \359                                        c23-note {{field 'x' has type 'int[0]' here}} \360                                        both-warning {{zero size arrays are an extension}}361 362// So long as the bounds are the same value, everything is fine. They do not363// have to be token equivalent.364struct array_2 { int y; int x[3]; };         // c17-note {{previous definition is here}}365struct array_2 { int y; int x[1 + 1 + 1]; }; // c17-error {{redefinition of 'array_2'}}366 367struct alignment { // c17-note {{previous definition is here}}368  _Alignas(int) int x; // c23-note {{attribute '_Alignas' here}}369};370 371struct alignment { // c17-error {{redefinition of 'alignment'}} \372                      c23-error {{type 'struct alignment' has a member with an attribute which currently causes the types to be treated as though they are incompatible}}373  int x;374};375 376// Both structures need to have a tag in order to be compatible within the same377// translation unit.378struct     {int i;} nontag;379struct tag {int i;} tagged; // c17-note 2 {{previous definition is here}}380 381_Static_assert(1 == _Generic(tagged, struct tag {int i;}:1, default:0)); // c17-error {{redefinition of 'tag'}} \382                                                                            c17-error {{static assertion failed}}383_Static_assert(0 == _Generic(tagged, struct     {int i;}:1, default:0));384_Static_assert(0 == _Generic(nontag, struct tag {int i;}:1, default:0)); // c17-error {{redefinition of 'tag'}}385// That means these two structures are not actually compatible; see GH141724.386_Static_assert(0 == _Generic(nontag, struct     {int i;}:1, default:0));387 388// Also test the behavior within a function (so the declaration context is not389// at the translation unit level).390void nontag_func_test(void) {391  struct { int i; } test;392  _Static_assert(0 == _Generic(test, struct { int i; } : 1, default : 0));393}394 395// Same kind of test, but this time for a declaration in the parameter list.396void nontag_param_test(struct { int i; } herp) {397  _Static_assert(0 == _Generic(herp, struct { int i; } : 1, default : 0));398}399 400// Same kind of test, but demonstrating that these still aren't compatible.401void nontag_both_in_params(struct { int i; } Arg1, struct { int i; } Arg2) {402  _Static_assert(0 == _Generic(__typeof__(Arg1), __typeof__(Arg2) : 1, default : 0)); // both-warning {{passing a type argument as the first operand to '_Generic' is a C2y extension}}403}404 405struct InnerUnnamedStruct {406  struct {407    int i;408  } untagged;409} inner_unnamed_tagged;410_Static_assert(0 == _Generic(inner_unnamed_tagged.untagged, struct { int i; } : 1, default : 0));411 412struct InnerUnnamedStruct_same {413  struct {414    int i;415  } untagged;416};417struct InnerUnnamedStruct_differentNaming {418  struct {419    int i;420  } untaggedDifferent;421};422struct InnerUnnamedStruct_differentShape {423  float x;424  struct {425    int i;426  } untagged;427  int y;428};429void compare_unnamed_struct_from_different_outer_type(430    struct InnerUnnamedStruct sameOuterType,431    struct InnerUnnamedStruct_same matchingType,432    struct InnerUnnamedStruct_differentNaming differentFieldName,433    struct InnerUnnamedStruct_differentShape differentType) {434  inner_unnamed_tagged.untagged = sameOuterType.untagged;435  inner_unnamed_tagged.untagged = matchingType.untagged; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}436  inner_unnamed_tagged.untagged = differentFieldName.untaggedDifferent; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}437  inner_unnamed_tagged.untagged = differentType.untagged; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}438}439 440// Test the same thing with enumerations (test for unions is omitted because441// unions and structures are both RecordDecl objects, whereas EnumDecl is not).442enum { E_Untagged1 } nontag_enum; // both-note {{previous definition is here}}443_Static_assert(0 == _Generic(nontag_enum, enum { E_Untagged1 } : 1, default : 0)); // both-error {{redefinition of enumerator 'E_Untagged1'}}444 445// Test that enumerations with mixed underlying types are properly handled.446enum GH150594_E1 : int { GH150594_Val1 };447enum GH150594_E2 : int { GH150594_Val2 };448enum GH150594_E3 { GH150594_Val3 };449enum GH150594_E4 : int { GH150594_Val4 };450void GH150594(void) {451  extern enum GH150594_E1 Fn1(void); // both-note {{previous declaration is here}}452  extern enum GH150594_E2 Fn2(void); // c17-note {{previous declaration is here}}453  extern enum GH150594_E3 Fn3(void); // both-note {{previous declaration is here}}454  extern enum GH150594_E4 Fn4(void); // both-note {{previous declaration is here}}455  enum GH150594_E1 { GH150594_Val1 };456  enum GH150594_E2 : int { GH150594_Val2 };457  enum GH150594_E3 : int { GH150594_Val3 };458  enum GH150594_E4 : short { GH150594_Val4 };459  extern enum GH150594_E1 Fn1(void); // both-error {{conflicting types for 'Fn1'}}460  extern enum GH150594_E2 Fn2(void); // c17-error {{conflicting types for 'Fn2'}}461  extern enum GH150594_E3 Fn3(void); // both-error {{conflicting types for 'Fn3'}}462  extern enum GH150594_E4 Fn4(void); // both-error {{conflicting types for 'Fn4'}}463 464  // Show that two declarations in the same scope give expected diagnostics.465  enum E1 { e1 };       // both-note {{previous declaration is here}}466  enum E1 : int { e1 }; // both-error {{enumeration previously declared with nonfixed underlying type}}467 468  enum E2 : int { e2 }; // both-note {{previous declaration is here}}469  enum E2 { e2 };       // both-error {{enumeration previously declared with fixed underlying type}}470 471  enum E3 : int { e3 };   // both-note {{previous declaration is here}}472  enum E3 : short { e3 }; // both-error {{enumeration redeclared with different underlying type 'short' (was 'int')}}473 474  typedef short foo;475  enum E4 : foo { e4 };   // c17-note 2 {{previous definition is here}}476  enum E4 : short { e4 }; // c17-error {{redefinition of 'E4'}} \477                             c17-error {{redefinition of enumerator 'e4'}}478 479  enum E5 : foo { e5 }; // both-note {{previous declaration is here}}480  enum E5 : int { e5 }; // both-error {{enumeration redeclared with different underlying type 'int' (was 'foo' (aka 'short'))}}481}482 483// Test that enumerations are compatible with their underlying type, but still484// diagnose when "same type" is required rather than merely "compatible type".485enum E1 : int { e1 }; // Fixed underlying type486enum E2 { e2 };       // Unfixed underlying type, defaults to int or unsigned int487 488struct GH149965_1 { int h; };489// This typeof trick is used to get the underlying type of the enumeration in a490// platform agnostic way.491struct GH149965_2 { __typeof__(+(enum E2){}) h; };492void gh149965(void) {493  extern struct GH149965_1 x1; // c17-note {{previous declaration is here}}494  extern struct GH149965_2 x2; // c17-note {{previous declaration is here}}495 496  // Both the structure and the variable declarations are fine because only a497  // compatible type is required, not the same type, because the structures are498  // declared in different scopes.499  struct GH149965_1 { enum E1 h; };500  struct GH149965_2 { enum E2 h; };501 502  extern struct GH149965_1 x1; // c17-error {{redeclaration of 'x1'}}503  extern struct GH149965_2 x2; // c17-error {{redeclaration of 'x2'}}504 505  // However, in the same scope, the same type is required, not just compatible506  // types.507  // FIXME: this should be an error in both C17 and C23 mode.508  struct GH149965_3 { int h; };     // c17-note {{previous definition is here}}509  struct GH149965_3 { enum E1 h; }; // c17-error {{redefinition of 'GH149965_3'}}510 511  // For Clang, the composite type after declaration merging is the enumeration512  // type rather than an integer type.513  enum E1 *eptr;514  [[maybe_unused]] __typeof__(x1.h) *ptr = eptr;515  enum E2 *eptr2;516  [[maybe_unused]] __typeof__(x2.h) *ptr2 = eptr2;517}518