[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai added a comment. Submitted for review https://reviews.llvm.org/D38109 - [fixup][Sema] Allow in C to define tags inside enumerations. Repository: rL LLVM https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
alberto_magni added a comment. Yes, restricting the error to C++ would work. Many thanks. Repository: rL LLVM https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
On Wed, Sep 20, 2017 at 2:17 PM, Volodymyr Sapsai via Phabricator via cfe-commitswrote: > vsapsai added a comment. > > Thanks for following up, Alberto. I haven't expected such a use case. It is > possible to achieve the same with `LSA_SIZEOF_SA = sizeof(((len_and_sockaddr > *)0)->u)` but I don't like it and don't want to force developers using such > approach. > > For solving this problem I think to restrict error only to C++ and to allow > tags inside enums for C. Alberto, what do you think, will it work for you? > And from implementation perspective allowing tags in enums for C should be > safe because things go haywire for C++ while checking access rules and C > doesn't have access rules. That construct is well-formed C code, but isn't in C++ (C++ restricts the places where you can define a new type compared to what C allows). ~Aaron > > > Repository: > rL LLVM > > https://reviews.llvm.org/D37089 > > > > ___ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai added a comment. Thanks for following up, Alberto. I haven't expected such a use case. It is possible to achieve the same with `LSA_SIZEOF_SA = sizeof(((len_and_sockaddr *)0)->u)` but I don't like it and don't want to force developers using such approach. For solving this problem I think to restrict error only to C++ and to allow tags inside enums for C. Alberto, what do you think, will it work for you? And from implementation perspective allowing tags in enums for C should be safe because things go haywire for C++ while checking access rules and C doesn't have access rules. Repository: rL LLVM https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
alberto_magni added a comment. Hi all, this change is causing busybox to fail to compile. The faulty enum is here: https://git.busybox.net/busybox/tree/include/libbb.h#n639 The nested union is inside a sizeof statement. Something like this: enum { A = sizeof(union { int x; int y; }) }; I this behavior expected ? Do you suggest to patch busybox ? Many Thanks Repository: rL LLVM https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
This revision was automatically updated to reflect the committed changes. vsapsai marked an inline comment as done. Closed by commit rL313386: [Sema] Error out early for tags defined inside an enumeration. (authored by vsapsai). Changed prior to commit: https://reviews.llvm.org/D37089?vs=115333=115466#toc Repository: rL LLVM https://reviews.llvm.org/D37089 Files: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/Sema/enum.c cfe/trunk/test/SemaCXX/enum.cpp Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td === --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1335,6 +1335,8 @@ "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; Index: cfe/trunk/test/Sema/enum.c === --- cfe/trunk/test/Sema/enum.c +++ cfe/trunk/test/Sema/enum.c @@ -123,3 +123,14 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +})0 + }; + int makeStructNonEmpty; +}; Index: cfe/trunk/test/SemaCXX/enum.cpp === --- cfe/trunk/test/SemaCXX/enum.cpp +++ cfe/trunk/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -13928,6 +13928,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) { +Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); +Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td === --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1335,6 +1335,8 @@ "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; Index: cfe/trunk/test/Sema/enum.c === --- cfe/trunk/test/Sema/enum.c +++ cfe/trunk/test/Sema/enum.c @@ -123,3 +123,14 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +})0 + }; + int makeStructNonEmpty; +}; Index: cfe/trunk/test/SemaCXX/enum.cpp === --- cfe/trunk/test/SemaCXX/enum.cpp +++ cfe/trunk/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: cfe/trunk/lib/Sema/SemaDecl.cpp === --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -13928,6 +13928,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition &&
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai marked an inline comment as done. vsapsai added inline comments. Comment at: clang/test/Sema/enum.c:128 +// PR28903 +struct PR28903 { // expected-warning {{empty struct is a GNU extension}} + enum { rnk wrote: > This is a simpler test case that fixes the extraneous diagnostics: > struct PR28903 { > enum { > E1 = (enum { // expected-error-re {{...}} > E2, E3 = E2 > })0 > } e; > }; > Removed extraneous diagnostics in slightly different way. Keep enum constants prefixed with PR28903 because in C struct doesn't create a scope for enum constants and I want to avoid polluting test namespace with common names like E1, E2, E3. https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai updated this revision to Diff 115333. vsapsai added a comment. - Remove extraneous diagnostics in test case per Reid Kleckner feedback. https://reviews.llvm.org/D37089 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/Sema/enum.c clang/test/SemaCXX/enum.cpp Index: clang/test/SemaCXX/enum.cpp === --- clang/test/SemaCXX/enum.cpp +++ clang/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: clang/test/Sema/enum.c === --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -123,3 +123,14 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +})0 + }; + int makeStructNonEmpty; +}; Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -13928,6 +13928,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) { +Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); +Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { Index: clang/include/clang/Basic/DiagnosticSemaKinds.td === --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1333,6 +1333,8 @@ "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; Index: clang/test/SemaCXX/enum.cpp === --- clang/test/SemaCXX/enum.cpp +++ clang/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: clang/test/Sema/enum.c === --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -123,3 +123,14 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +})0 + }; + int makeStructNonEmpty; +}; Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -13928,6 +13928,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) { +Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); +Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { Index: clang/include/clang/Basic/DiagnosticSemaKinds.td === --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1333,6 +1333,8 @@ "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; ___ cfe-commits mailing
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
doug.gregor accepted this revision. doug.gregor added a comment. This revision is now accepted and ready to land. Looks good to me; sorry for the delay. https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
rnk added a comment. I think this looks good, even without fixing the access control crash, this seems like a diagnostic improvement. Comment at: clang/test/Sema/enum.c:128 +// PR28903 +struct PR28903 { // expected-warning {{empty struct is a GNU extension}} + enum { This is a simpler test case that fixes the extraneous diagnostics: struct PR28903 { enum { E1 = (enum { // expected-error-re {{...}} E2, E3 = E2 })0 } e; }; https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai added a comment. Ping. If you don't have time to review the change in depth, please say if the approach is wrong on high level. https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai added a comment. It occurred to me that another approach for fixing the crash can be setting `IsTypeSpecifier` to `true` while we ParseCastExpression. According to cast-expression: unary-expression ( type-id ) cast-expression type-id: type-specifier-seq abstract-declarator[opt] it looks reasonable to require `IsTypeSpecifier` during parsing part of cast expression inside parentheses. What do you think? Is this approach worth pursuing? Does it sound better than the one offered initially? https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai added a comment. I have also considered adding tests for structs and unions defined inside an enumeration but decided it doesn't add much value, given the code is working for all TagDecl. Another option I had in mind is having a note pointing to outer enum. But the nesting is done in the same file so the outer enum shouldn't be hard to find. So I decided that complexity outweighs the added value. If anybody thinks the aforementioned changes are valuable, please tell so. https://reviews.llvm.org/D37089 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37089: [Sema] Error out early for tags defined inside an enumeration.
vsapsai created this revision. This fixes PR28903 by avoiding access check for inner enum constant. We are performing access check because one enum constant references another and because enum is defined in CXXRecordDecl. But access check doesn't work because FindDeclaringClass doesn't expect more than one EnumDecl and because inner enum has access AS_none due to not being an immediate child of a record. The change detects an enum is defined in wrong place and allows to skip parsing its body. Access check is skipped together with body parsing. There was no crash in C, added test case to cover the new error. rdar://problem/28530809 https://reviews.llvm.org/D37089 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/Sema/enum.c clang/test/SemaCXX/enum.cpp Index: clang/test/SemaCXX/enum.cpp === --- clang/test/SemaCXX/enum.cpp +++ clang/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: clang/test/Sema/enum.c === --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -123,3 +123,13 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { // expected-warning {{empty struct is a GNU extension}} + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; // expected-error {{expected expression}} +}; Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -13929,6 +13929,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) { +Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); +Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { Index: clang/include/clang/Basic/DiagnosticSemaKinds.td === --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1329,6 +1329,8 @@ "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; Index: clang/test/SemaCXX/enum.cpp === --- clang/test/SemaCXX/enum.cpp +++ clang/test/SemaCXX/enum.cpp @@ -110,3 +110,13 @@ // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} #endif + +// PR28903 +struct PR28903 { + enum { +PR28903_A = (enum { // expected-error-re {{'PR28903::(anonymous enum at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; +}; Index: clang/test/Sema/enum.c === --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -123,3 +123,13 @@ // PR24610 enum Color { Red, Green, Blue }; // expected-note{{previous use is here}} typedef struct Color NewColor; // expected-error {{use of 'Color' with tag type that does not match previous declaration}} + +// PR28903 +struct PR28903 { // expected-warning {{empty struct is a GNU extension}} + enum { +PR28903_A = (enum { // expected-error-re {{'enum PR28903::(anonymous at {{.*}})' cannot be defined in an enumeration}} + PR28903_B, + PR28903_C = PR28903_B +}) + }; // expected-error {{expected expression}} +}; Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -13929,6 +13929,12 @@ Invalid = true; } + if (!Invalid && TUK == TUK_Definition && DC->getDeclKind() == Decl::Enum) { +Diag(New->getLocation(), diag::err_type_defined_in_enum) + << Context.getTagDeclType(New); +Invalid = true; + } + // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet())