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)``.
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<
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)) {
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)) {
SkipUntil(tok::r_paren, StopAtSemi);
return Res;
}
- DiagExt(Comps.back().LocStart, Kind::ArraySubscript);
Comps.back().U.E = Res.get();
ST.consumeClose();
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}}
}
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.
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+{{}}
}
}