Skip to content

Commit

Permalink
Stop diagnosing member and array access in offsetof as an extension
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
AaronBallman authored and tstellar committed Jan 28, 2023
1 parent 0764636 commit 84f3164
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 33 deletions.
8 changes: 3 additions & 5 deletions clang/docs/LanguageExtensions.rst
Expand Up @@ -2386,21 +2386,19 @@ calculates the offset (in bytes) to a given member of the given type.
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)``.
Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Expand Up @@ -1607,11 +1607,6 @@ def err_import_in_wrong_fragment : Error<
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<GNUOffsetofExtensions>;

let CategoryName = "Generics Issue" in {

def err_objc_expected_type_parameter : Error<
Expand Down
8 changes: 0 additions & 8 deletions clang/lib/Parse/ParseExpr.cpp
Expand Up @@ -2629,12 +2629,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
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)) {
Expand All @@ -2648,7 +2642,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
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)) {
Expand All @@ -2666,7 +2659,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return Res;
}
DiagExt(Comps.back().LocStart, Kind::ArraySubscript);
Comps.back().U.E = Res.get();

ST.consumeClose();
Expand Down
3 changes: 1 addition & 2 deletions clang/test/C/C2x/n2350.c
Expand Up @@ -38,8 +38,7 @@ int struct_in_second_param(void) {
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}}
}


Expand Down
14 changes: 4 additions & 10 deletions clang/test/C/drs/dr4xx.c
Expand Up @@ -331,19 +331,13 @@ void dr496(void) {
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.
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CXX/drs/dr4xx.cpp
Expand Up @@ -687,9 +687,9 @@ namespace dr447 { // dr447: yes
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<int>(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
g(__builtin_offsetof(A, a[N])).h<int>(); // 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<int>();
g(__builtin_offsetof(A, a[N])).h<int>();
U<__builtin_offsetof(A, a[0])>::type c;
U<__builtin_offsetof(A, a[N])>::type d; // expected-error +{{}} expected-warning 0+{{}}
}
}
Expand Down

0 comments on commit 84f3164

Please sign in to comment.