Skip to content

Commit 84f3164

Browse files
AaronBallmantstellar
authored andcommitted
Stop diagnosing member and array access in offsetof as an extension
This was a mistake from e7300e7 (https://reviews.llvm.org/D133574) caused by us accidentally tracking an older copy of the C DR list for DR496. The text in https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2396.htm#dr_496 makes it clear that subobjects are allowed, which means member and array access expressions are allowed. This backs out the changes from the previous commit that relate to this diagnostic. (cherry picked from commit 63d6b8b)
1 parent 0764636 commit 84f3164

File tree

6 files changed

+11
-33
lines changed

6 files changed

+11
-33
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,21 +2386,19 @@ calculates the offset (in bytes) to a given member of the given type.
23862386
23872387
const int offset_to_i = __builtin_offsetof(struct S, i);
23882388
const int ext1 = __builtin_offsetof(struct U { int i; }, i); // C extension
2389-
const int ext2 = __builtin_offsetof(struct S, t.f[1]); // C & C++ extension
2389+
const int ext2 = __builtin_offsetof(struct S, t.f[1]);
23902390
23912391
**Description**:
23922392
23932393
This builtin is usable in an integer constant expression which returns a value
23942394
of type ``size_t``. The value returned is the offset in bytes to the subobject
23952395
designated by the member-designator from the beginning of an object of type
2396-
``type-name``. Clang extends the required standard functionality in a few ways:
2396+
``type-name``. Clang extends the required standard functionality in the
2397+
following way:
23972398
23982399
* In C language modes, the first argument may be the definition of a new type.
23992400
Any type declared this way is scoped to the nearest scope containing the call
24002401
to the builtin.
2401-
* The second argument may be a member-designator designated by a series of
2402-
member access expressions using the dot (``.``) operator or array subscript
2403-
expressions.
24042402
24052403
Query for this feature with ``__has_builtin(__builtin_offsetof)``.
24062404

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,11 +1607,6 @@ def err_import_in_wrong_fragment : Error<
16071607
def err_export_empty : Error<"export declaration cannot be empty">;
16081608
}
16091609

1610-
def ext_offsetof_member_designator : Extension<
1611-
"using %select{a member access expression|an array subscript expression}0 "
1612-
"within '%select{__builtin_offsetof|offsetof}1' is a Clang extension">,
1613-
InGroup<GNUOffsetofExtensions>;
1614-
16151610
let CategoryName = "Generics Issue" in {
16161611

16171612
def err_objc_expected_type_parameter : Error<

clang/lib/Parse/ParseExpr.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,12 +2629,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
26292629
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
26302630
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
26312631

2632-
enum class Kind { MemberAccess, ArraySubscript };
2633-
auto DiagExt = [&](SourceLocation Loc, Kind K) {
2634-
Diag(Loc, diag::ext_offsetof_member_designator)
2635-
<< (K == Kind::ArraySubscript) << (OOK == Sema::OOK_Macro);
2636-
};
2637-
26382632
// FIXME: This loop leaks the index expressions on error.
26392633
while (true) {
26402634
if (Tok.is(tok::period)) {
@@ -2648,7 +2642,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
26482642
SkipUntil(tok::r_paren, StopAtSemi);
26492643
return ExprError();
26502644
}
2651-
DiagExt(Comps.back().LocStart, Kind::MemberAccess);
26522645
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
26532646
Comps.back().LocEnd = ConsumeToken();
26542647
} else if (Tok.is(tok::l_square)) {
@@ -2666,7 +2659,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
26662659
SkipUntil(tok::r_paren, StopAtSemi);
26672660
return Res;
26682661
}
2669-
DiagExt(Comps.back().LocStart, Kind::ArraySubscript);
26702662
Comps.back().U.E = Res.get();
26712663

26722664
ST.consumeClose();

clang/test/C/C2x/n2350.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ int struct_in_second_param(void) {
3838
int a, b;
3939
int x[20];
4040
};
41-
return __builtin_offsetof(struct A, x[sizeof(struct B{int a;})]); // cpp-error {{'B' cannot be defined in a type specifier}} \
42-
expected-warning {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
41+
return __builtin_offsetof(struct A, x[sizeof(struct B{int a;})]); // cpp-error {{'B' cannot be defined in a type specifier}}
4342
}
4443

4544

clang/test/C/drs/dr4xx.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -331,19 +331,13 @@ void dr496(void) {
331331
struct B { struct A a; };
332332
struct C { struct A a[1]; };
333333

334-
/* The standard does not require either of these examples to work, but we
335-
* support them just the same. The first one is invalid because it's
336-
* referencing a member of a different struct, and the second one is invalid
337-
* because it references an array of another struct. Clang calculates the
338-
* correct offset to each of those fields.
339-
*/
340-
_Static_assert(__builtin_offsetof(struct B, a.n) == 0, ""); /* expected-warning {{using a member access expression within '__builtin_offsetof' is a Clang extension}} */
334+
/* Array access & member access expressions are now valid. */
335+
_Static_assert(__builtin_offsetof(struct B, a.n) == 0, "");
341336
/* First int below is for 'n' and the second int is for 'a[0]'; this presumes
342337
* there is no padding involved.
343338
*/
344-
_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}}
345-
expected-warning {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
346-
*/
339+
_Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), "");
340+
347341
/* However, we do not support using the -> operator to access a member, even
348342
* if that would be a valid expression. FIXME: GCC accepts this, perhaps we
349343
* should as well.

clang/test/CXX/drs/dr4xx.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,9 @@ namespace dr447 { // dr447: yes
687687
U<__builtin_offsetof(A, n)>::type a;
688688
U<__builtin_offsetof(T, n)>::type b; // expected-error +{{}} expected-warning 0+{{}}
689689
// as an extension, we allow the member-designator to include array indices
690-
g(__builtin_offsetof(A, a[0])).h<int>(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
691-
g(__builtin_offsetof(A, a[N])).h<int>(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
692-
U<__builtin_offsetof(A, a[0])>::type c; // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
690+
g(__builtin_offsetof(A, a[0])).h<int>();
691+
g(__builtin_offsetof(A, a[N])).h<int>();
692+
U<__builtin_offsetof(A, a[0])>::type c;
693693
U<__builtin_offsetof(A, a[N])>::type d; // expected-error +{{}} expected-warning 0+{{}}
694694
}
695695
}

0 commit comments

Comments
 (0)