Merge "Cherrypick upstream revert for "[C2x] reject type definitions in offsetof""
diff --git a/patches/PATCHES.json b/patches/PATCHES.json
index 7a8813a..801376f 100644
--- a/patches/PATCHES.json
+++ b/patches/PATCHES.json
@@ -688,6 +688,21 @@
     {
         "metadata": {
             "info": [],
+            "title": "[UPSTREAM] Revert \"[C2x] reject type definitions in offsetof\""
+        },
+        "platforms": [
+            "android",
+            "chromiumos"
+        ],
+        "rel_patch_path": "cherry/596f76a799c933927eec4d8ac8a83c44efff9854.patch",
+        "version_range": {
+            "from": 486419,
+            "until": 486533
+        }
+    },
+    {
+        "metadata": {
+            "info": [],
             "title": "Add stubs and headers for nl_types APIs."
         },
         "platforms": [
diff --git a/patches/cherry/596f76a799c933927eec4d8ac8a83c44efff9854.patch b/patches/cherry/596f76a799c933927eec4d8ac8a83c44efff9854.patch
new file mode 100644
index 0000000..f470337
--- /dev/null
+++ b/patches/cherry/596f76a799c933927eec4d8ac8a83c44efff9854.patch
@@ -0,0 +1,397 @@
+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
+