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