Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -2386,21 +2386,19 @@ const int offset_to_i = __builtin_offsetof(struct S, i); const int ext1 = __builtin_offsetof(struct U { int i; }, i); // C extension - const int ext2 = __builtin_offsetof(struct S, t.f[1]); // C & C++ extension + const int ext2 = __builtin_offsetof(struct S, t.f[1]); **Description**: This builtin is usable in an integer constant expression which returns a value of type ``size_t``. The value returned is the offset in bytes to the subobject designated by the member-designator from the beginning of an object of type -``type-name``. Clang extends the required standard functionality in a few ways: +``type-name``. Clang extends the required standard functionality in the +following way: * In C language modes, the first argument may be the definition of a new type. Any type declared this way is scoped to the nearest scope containing the call to the builtin. -* The second argument may be a member-designator designated by a series of - member access expressions using the dot (``.``) operator or array subscript - expressions. Query for this feature with ``__has_builtin(__builtin_offsetof)``. Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1607,11 +1607,6 @@ def err_export_empty : Error<"export declaration cannot be empty">; } -def ext_offsetof_member_designator : Extension< - "using %select{a member access expression|an array subscript expression}0 " - "within '%select{__builtin_offsetof|offsetof}1' is a Clang extension">, - InGroup; - let CategoryName = "Generics Issue" in { def err_objc_expected_type_parameter : Error< Index: clang/lib/Parse/ParseExpr.cpp =================================================================== --- clang/lib/Parse/ParseExpr.cpp +++ clang/lib/Parse/ParseExpr.cpp @@ -2629,12 +2629,6 @@ Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken(); - enum class Kind { MemberAccess, ArraySubscript }; - auto DiagExt = [&](SourceLocation Loc, Kind K) { - Diag(Loc, diag::ext_offsetof_member_designator) - << (K == Kind::ArraySubscript) << (OOK == Sema::OOK_Macro); - }; - // FIXME: This loop leaks the index expressions on error. while (true) { if (Tok.is(tok::period)) { @@ -2648,7 +2642,6 @@ SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - DiagExt(Comps.back().LocStart, Kind::MemberAccess); Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocEnd = ConsumeToken(); } else if (Tok.is(tok::l_square)) { @@ -2666,7 +2659,6 @@ SkipUntil(tok::r_paren, StopAtSemi); return Res; } - DiagExt(Comps.back().LocStart, Kind::ArraySubscript); Comps.back().U.E = Res.get(); ST.consumeClose(); Index: clang/test/C/C2x/n2350.c =================================================================== --- clang/test/C/C2x/n2350.c +++ clang/test/C/C2x/n2350.c @@ -38,8 +38,7 @@ int a, b; int x[20]; }; - return __builtin_offsetof(struct A, x[sizeof(struct B{int a;})]); // cpp-error {{'B' cannot be defined in a type specifier}} \ - expected-warning {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}} + return __builtin_offsetof(struct A, x[sizeof(struct B{int a;})]); // cpp-error {{'B' cannot be defined in a type specifier}} } Index: clang/test/C/drs/dr4xx.c =================================================================== --- clang/test/C/drs/dr4xx.c +++ clang/test/C/drs/dr4xx.c @@ -331,19 +331,13 @@ struct B { struct A a; }; struct C { struct A a[1]; }; - /* The standard does not require either of these examples to work, but we - * support them just the same. The first one is invalid because it's - * referencing a member of a different struct, and the second one is invalid - * because it references an array of another struct. Clang calculates the - * correct offset to each of those fields. - */ - _Static_assert(__builtin_offsetof(struct B, a.n) == 0, ""); /* expected-warning {{using a member access expression within '__builtin_offsetof' is a Clang extension}} */ + /* Array access & member access expressions are now valid. */ + _Static_assert(__builtin_offsetof(struct B, a.n) == 0, ""); /* First int below is for 'n' and the second int is for 'a[0]'; this presumes * there is no padding involved. */ - _Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), ""); /* expected-warning {{using a member access expression within '__builtin_offsetof' is a Clang extension}} - expected-warning {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}} - */ + _Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), ""); + /* However, we do not support using the -> operator to access a member, even * if that would be a valid expression. FIXME: GCC accepts this, perhaps we * should as well. Index: clang/test/CXX/drs/dr4xx.cpp =================================================================== --- clang/test/CXX/drs/dr4xx.cpp +++ clang/test/CXX/drs/dr4xx.cpp @@ -687,9 +687,9 @@ U<__builtin_offsetof(A, n)>::type a; U<__builtin_offsetof(T, n)>::type b; // expected-error +{{}} expected-warning 0+{{}} // as an extension, we allow the member-designator to include array indices - g(__builtin_offsetof(A, a[0])).h(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}} - g(__builtin_offsetof(A, a[N])).h(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}} - U<__builtin_offsetof(A, a[0])>::type c; // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}} + g(__builtin_offsetof(A, a[0])).h(); + g(__builtin_offsetof(A, a[N])).h(); + U<__builtin_offsetof(A, a[0])>::type c; U<__builtin_offsetof(A, a[N])>::type d; // expected-error +{{}} expected-warning 0+{{}} } }