| From 596f76a799c933927eec4d8ac8a83c44efff9854 Mon Sep 17 00:00:00 2001 |
| From: Yingchi Long <i@lyc.dev> |
| Date: Mon, 16 Jan 2023 16:52:50 +0800 |
| Subject: [PATCH] Revert "[C2x] reject type definitions in offsetof" |
| |
| This reverts commit e327b52766ed497e4779f4e652b9ad237dfda8e6. |
| --- |
| clang/docs/ReleaseNotes.rst | 3 - |
| .../clang/Basic/DiagnosticSemaKinds.td | 2 - |
| clang/include/clang/Parse/Parser.h | 3 - |
| .../clang/Parse/RAIIObjectsForParser.h | 13 ---- |
| clang/include/clang/Sema/Sema.h | 12 +--- |
| clang/lib/Parse/ParseDecl.cpp | 2 +- |
| clang/lib/Parse/ParseDeclCXX.cpp | 2 +- |
| clang/lib/Parse/ParseExpr.cpp | 19 ++---- |
| clang/lib/Sema/SemaDecl.cpp | 12 +--- |
| clang/lib/Sema/SemaDeclCXX.cpp | 6 +- |
| clang/lib/Sema/SemaTemplate.cpp | 13 ++-- |
| clang/test/C/C2x/n2350.c | 67 ------------------- |
| clang/test/C/drs/dr4xx.c | 7 +- |
| clang/test/Parser/declarators.c | 4 ++ |
| clang/test/SemaCXX/offsetof.cpp | 17 ----- |
| 15 files changed, 28 insertions(+), 154 deletions(-) |
| delete mode 100644 clang/test/C/C2x/n2350.c |
| |
| diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst |
| index a75bc1df2d7c..09133f967f01 100644 |
| --- a/clang/docs/ReleaseNotes.rst |
| +++ b/clang/docs/ReleaseNotes.rst |
| @@ -670,9 +670,6 @@ C2x Feature Support |
| va_start(list); // Invalid in C17 and earlier, valid in C2x and later. |
| va_end(list); |
| } |
| - |
| -- Reject type definitions in the ``type`` argument of ``__builtin_offsetof`` |
| - according to `WG14 N2350 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm>`_. |
| |
| C++ Language Changes in Clang |
| ----------------------------- |
| diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td |
| index 862ac845bda4..02afb098b239 100644 |
| --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td |
| +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td |
| @@ -1650,8 +1650,6 @@ 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 err_type_defined_in_offsetof : Error< |
| - "%0 cannot be defined in '%select{__builtin_offsetof|offsetof}1'">; |
| |
| def note_pure_virtual_function : Note< |
| "unimplemented pure virtual method %0 in %1">; |
| diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h |
| index 6f9581b9ea1f..7a33532eec14 100644 |
| --- a/clang/include/clang/Parse/Parser.h |
| +++ b/clang/include/clang/Parse/Parser.h |
| @@ -62,7 +62,6 @@ class Parser : public CodeCompletionHandler { |
| friend class ColonProtectionRAIIObject; |
| friend class ParsingOpenMPDirectiveRAII; |
| friend class InMessageExpressionRAIIObject; |
| - friend class OffsetOfStateRAIIObject; |
| friend class PoisonSEHIdentifiersRAIIObject; |
| friend class ObjCDeclContextSwitch; |
| friend class ParenBraceBracketBalancer; |
| @@ -249,8 +248,6 @@ class Parser : public CodeCompletionHandler { |
| /// function call. |
| bool CalledSignatureHelp = false; |
| |
| - Sema::OffsetOfKind OffsetOfState = Sema::OffsetOfKind::OOK_Outside; |
| - |
| /// The "depth" of the template parameters currently being parsed. |
| unsigned TemplateParameterDepth; |
| |
| diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h |
| index cb525c9d0edd..5ae609e60073 100644 |
| --- a/clang/include/clang/Parse/RAIIObjectsForParser.h |
| +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h |
| @@ -341,19 +341,6 @@ namespace clang { |
| } |
| }; |
| |
| - class OffsetOfStateRAIIObject { |
| - Sema::OffsetOfKind &OffsetOfState; |
| - Sema::OffsetOfKind OldValue; |
| - |
| - public: |
| - OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value) |
| - : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) { |
| - OffsetOfState = Value; |
| - } |
| - |
| - ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; } |
| - }; |
| - |
| /// RAII object that makes sure paren/bracket/brace count is correct |
| /// after declaration/statement parsing, even when there's a parsing error. |
| class ParenBraceBracketBalancer { |
| diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h |
| index 35e319879a98..30c5ea608f7a 100644 |
| --- a/clang/include/clang/Sema/Sema.h |
| +++ b/clang/include/clang/Sema/Sema.h |
| @@ -3304,16 +3304,6 @@ public: |
| TUK_Friend // Friend declaration: 'friend struct foo;' |
| }; |
| |
| - enum OffsetOfKind { |
| - // Not parsing a type within __builtin_offsetof. |
| - OOK_Outside, |
| - // Parsing a type within __builtin_offsetof. |
| - OOK_Builtin, |
| - // Parsing a type within macro "offsetof", defined in __buitin_offsetof |
| - // To improve our diagnostic message. |
| - OOK_Macro, |
| - }; |
| - |
| Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, |
| SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, |
| SourceLocation NameLoc, const ParsedAttributesView &Attr, |
| @@ -3322,7 +3312,7 @@ public: |
| bool &IsDependent, SourceLocation ScopedEnumKWLoc, |
| bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, |
| bool IsTypeSpecifier, bool IsTemplateParamOrArg, |
| - OffsetOfKind OOK, SkipBodyInfo *SkipBody = nullptr); |
| + SkipBodyInfo *SkipBody = nullptr); |
| |
| Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, |
| unsigned TagSpec, SourceLocation TagLoc, |
| diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp |
| index 75937c0d6a95..56fe9c3ac7ba 100644 |
| --- a/clang/lib/Parse/ParseDecl.cpp |
| +++ b/clang/lib/Parse/ParseDecl.cpp |
| @@ -4972,7 +4972,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, |
| DSC == DeclSpecContext::DSC_type_specifier, |
| DSC == DeclSpecContext::DSC_template_param || |
| DSC == DeclSpecContext::DSC_template_type_arg, |
| - OffsetOfState, &SkipBody); |
| + &SkipBody); |
| |
| if (SkipBody.ShouldSkip) { |
| assert(TUK == Sema::TUK_Definition && "can only skip a definition"); |
| diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp |
| index 227c1df2bddd..5d721f48140f 100644 |
| --- a/clang/lib/Parse/ParseDeclCXX.cpp |
| +++ b/clang/lib/Parse/ParseDeclCXX.cpp |
| @@ -2074,7 +2074,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, |
| DSC == DeclSpecContext::DSC_type_specifier, |
| DSC == DeclSpecContext::DSC_template_param || |
| DSC == DeclSpecContext::DSC_template_type_arg, |
| - OffsetOfState, &SkipBody); |
| + &SkipBody); |
| |
| // If ActOnTag said the type was dependent, try again with the |
| // less common call. |
| diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp |
| index e8bdf5f421af..b1bf988307b1 100644 |
| --- a/clang/lib/Parse/ParseExpr.cpp |
| +++ b/clang/lib/Parse/ParseExpr.cpp |
| @@ -2592,21 +2592,10 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { |
| } |
| case tok::kw___builtin_offsetof: { |
| SourceLocation TypeLoc = Tok.getLocation(); |
| - auto K = Sema::OffsetOfKind::OOK_Builtin; |
| - if (Tok.getLocation().isMacroID()) { |
| - StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( |
| - Tok.getLocation(), PP.getSourceManager(), getLangOpts()); |
| - if (MacroName == "offsetof") |
| - K = Sema::OffsetOfKind::OOK_Macro; |
| - } |
| - TypeResult Ty; |
| - { |
| - OffsetOfStateRAIIObject InOffsetof(*this, K); |
| - Ty = ParseTypeName(); |
| - if (Ty.isInvalid()) { |
| - SkipUntil(tok::r_paren, StopAtSemi); |
| - return ExprError(); |
| - } |
| + TypeResult Ty = ParseTypeName(); |
| + if (Ty.isInvalid()) { |
| + SkipUntil(tok::r_paren, StopAtSemi); |
| + return ExprError(); |
| } |
| |
| if (ExpectAndConsume(tok::comma)) { |
| diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp |
| index 072bc9b5dc26..e3fd4045e8bb 100644 |
| --- a/clang/lib/Sema/SemaDecl.cpp |
| +++ b/clang/lib/Sema/SemaDecl.cpp |
| @@ -16592,7 +16592,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, |
| SourceLocation ScopedEnumKWLoc, |
| bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, |
| bool IsTypeSpecifier, bool IsTemplateParamOrArg, |
| - OffsetOfKind OOK, SkipBodyInfo *SkipBody) { |
| + SkipBodyInfo *SkipBody) { |
| // If this is not a definition, it must have a name. |
| IdentifierInfo *OrigName = Name; |
| assert((Name != nullptr || TUK == TUK_Definition) && |
| @@ -17365,16 +17365,10 @@ CreateNewDecl: |
| cast_or_null<RecordDecl>(PrevDecl)); |
| } |
| |
| - if (OOK != OOK_Outside && TUK == TUK_Definition) { |
| - Diag(New->getLocation(), diag::err_type_defined_in_offsetof) |
| - << Context.getTagDeclType(New) << static_cast<int>(OOK == OOK_Macro); |
| - Invalid = true; |
| - } |
| - |
| // C++11 [dcl.type]p3: |
| // A type-specifier-seq shall not define a class or enumeration [...]. |
| - if (!Invalid && getLangOpts().CPlusPlus && |
| - (IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TUK_Definition) { |
| + if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) && |
| + TUK == TUK_Definition) { |
| Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) |
| << Context.getTagDeclType(New); |
| Invalid = true; |
| diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp |
| index ea52b703b563..0d7e3e893878 100644 |
| --- a/clang/lib/Sema/SemaDeclCXX.cpp |
| +++ b/clang/lib/Sema/SemaDeclCXX.cpp |
| @@ -16962,15 +16962,15 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, |
| if (SS.isEmpty()) { |
| bool Owned = false; |
| bool IsDependent = false; |
| - return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, |
| - AS_public, |
| + return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, |
| + Attr, AS_public, |
| /*ModulePrivateLoc=*/SourceLocation(), |
| MultiTemplateParamsArg(), Owned, IsDependent, |
| /*ScopedEnumKWLoc=*/SourceLocation(), |
| /*ScopedEnumUsesClassTag=*/false, |
| /*UnderlyingType=*/TypeResult(), |
| /*IsTypeSpecifier=*/false, |
| - /*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside); |
| + /*IsTemplateParamOrArg=*/false); |
| } |
| |
| NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); |
| diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp |
| index 31c2bf5d8127..17f0d0263a3d 100644 |
| --- a/clang/lib/Sema/SemaTemplate.cpp |
| +++ b/clang/lib/Sema/SemaTemplate.cpp |
| @@ -10181,12 +10181,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, |
| |
| bool Owned = false; |
| bool IsDependent = false; |
| - Decl *TagD = ActOnTag( |
| - S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr, AS_none, |
| - /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, |
| - IsDependent, SourceLocation(), false, TypeResult(), |
| - /*IsTypeSpecifier*/ false, |
| - /*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside); |
| + Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, |
| + KWLoc, SS, Name, NameLoc, Attr, AS_none, |
| + /*ModulePrivateLoc=*/SourceLocation(), |
| + MultiTemplateParamsArg(), Owned, IsDependent, |
| + SourceLocation(), false, TypeResult(), |
| + /*IsTypeSpecifier*/false, |
| + /*IsTemplateParamOrArg*/false); |
| assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); |
| |
| if (!TagD) |
| diff --git a/clang/test/C/C2x/n2350.c b/clang/test/C/C2x/n2350.c |
| deleted file mode 100644 |
| index 3b4bdec26bf7..000000000000 |
| --- a/clang/test/C/C2x/n2350.c |
| +++ /dev/null |
| @@ -1,67 +0,0 @@ |
| -// RUN: %clang_cc1 -fsyntax-only -verify %s |
| -// RUN: %clang_cc1 -fsyntax-only -std=c89 -verify %s |
| -// RUN: %clang_cc1 -fsyntax-only -std=c99 -verify %s |
| -// RUN: %clang_cc1 -fsyntax-only -std=c11 -verify %s |
| -// RUN: %clang_cc1 -fsyntax-only -std=c17 -verify %s |
| -// RUN: %clang_cc1 -fsyntax-only -std=c2x -verify %s |
| - |
| -// Reject definitions in __builtin_offsetof |
| -// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm |
| -int simple(void) { |
| - return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} |
| - { |
| - int a; |
| - struct B // expected-error{{'struct B' cannot be defined in '__builtin_offsetof'}} |
| - { |
| - int c; |
| - int d; |
| - } x; |
| - }, a); |
| -} |
| - |
| -int anonymous_struct() { |
| - return __builtin_offsetof(struct // expected-error-re{{'struct (unnamed at {{.*}})' cannot be defined in '__builtin_offsetof'}} |
| - { |
| - int a; |
| - int b; |
| - }, a); |
| -} |
| - |
| -int struct_in_second_param() { |
| - struct A { |
| - int a, b; |
| - int x[20]; |
| - }; |
| - return __builtin_offsetof(struct A, x[sizeof(struct B{int a;})]); // no-error |
| -} |
| - |
| - |
| -#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) |
| - |
| - |
| -int macro(void) { |
| - return offsetof(struct A // expected-error{{'struct A' cannot be defined in 'offsetof'}} |
| - // expected-error@-1{{'struct B' cannot be defined in 'offsetof'}} |
| - { |
| - int a; |
| - struct B // verifier seems to think the error is emitted by the macro |
| - // In fact the location of the error is "B" on the line above |
| - { |
| - int c; |
| - int d; |
| - } x; |
| - }, a); |
| -} |
| - |
| -#undef offsetof |
| - |
| -#define offsetof(TYPE, MEMBER) (&((TYPE *)0)->MEMBER) |
| - |
| -// no warning for traditional offsetof as a function-like macro |
| -int * macro_func(void) { |
| - return offsetof(struct A // no-warning |
| - { |
| - int a; |
| - int b; |
| - }, a); |
| -} |
| diff --git a/clang/test/C/drs/dr4xx.c b/clang/test/C/drs/dr4xx.c |
| index f5ad1b82bec4..768897cd4f2b 100644 |
| --- a/clang/test/C/drs/dr4xx.c |
| +++ b/clang/test/C/drs/dr4xx.c |
| @@ -352,10 +352,11 @@ void dr496(void) { |
| */ |
| |
| /* The DR asked a question about whether defining a new type within offsetof |
| - * is allowed. C2x N2350 made this explicitly undefined behavior, but GCC |
| - * supports it, Clang diagnoses this a UB and rejects it. |
| + * is allowed. C2x N2350 made this explicitly undefined behavior, but Clang |
| + * has always supported defining a type in this location, and GCC also |
| + * supports it. |
| */ |
| - (void)__builtin_offsetof(struct S { int a; }, a); /* expected-error{{'struct S' cannot be defined in '__builtin_offsetof'}} */ |
| + (void)__builtin_offsetof(struct S { int a; }, a); |
| } |
| |
| /* WG14 DR499: yes |
| diff --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c |
| index 3af09817e6b6..464fafeaa0d2 100644 |
| --- a/clang/test/Parser/declarators.c |
| +++ b/clang/test/Parser/declarators.c |
| @@ -80,6 +80,10 @@ struct test9 { |
| struct test10 { int a; } static test10x; |
| struct test11 { int a; } const test11x; |
| |
| +// PR6216 |
| +void test12(void) { |
| + (void)__builtin_offsetof(struct { char c; int i; }, i); |
| +} |
| |
| // rdar://7608537 |
| struct test13 { int a; } (test13x); |
| diff --git a/clang/test/SemaCXX/offsetof.cpp b/clang/test/SemaCXX/offsetof.cpp |
| index 3eee6fb41d33..c4b288aa05d4 100644 |
| --- a/clang/test/SemaCXX/offsetof.cpp |
| +++ b/clang/test/SemaCXX/offsetof.cpp |
| @@ -83,20 +83,3 @@ struct Derived : virtual Base { |
| expected-error {{invalid application of 'offsetof' to a field of a virtual base}} |
| }; |
| } |
| - |
| -// Reject definitions in __builtin_offsetof |
| -// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm |
| -int test_definition(void) { |
| - return __builtin_offsetof(struct A // expected-error{{'A' cannot be defined in '__builtin_offsetof'}} |
| - { |
| - int a; |
| - struct B // FIXME: error diagnostic message for nested definitions |
| - // https://reviews.llvm.org/D133574 |
| - // fixme-error{{'A' cannot be defined in '__builtin_offsetof'}} |
| - { |
| - int c; |
| - int d; |
| - }; |
| - B x; |
| - }, a); |
| -} |
| -- |
| 2.30.2 |
| |