if (ArgTy.isNull())
return ExprError();
- if (getLangOptions().CPlusPlus) {
- if (!ArgTInfo)
- ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
-
- return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
- RPLoc);
- }
-
- // FIXME: The code below is marked for death, once we have proper CodeGen
- // support for non-constant OffsetOf expressions.
-
- bool Dependent = ArgTy->isDependentType();
-
- // We must have at least one component that refers to the type, and the first
- // one is known to be a field designator. Verify that the ArgTy represents
- // a struct/union/class.
- if (!Dependent && !ArgTy->isRecordType())
- return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy);
-
- // FIXME: Type must be complete per C99 7.17p3 because a declaring a variable
- // with an incomplete type would be illegal.
-
- // Otherwise, create a null pointer as the base, and iteratively process
- // the offsetof designators.
- QualType ArgTyPtr = Context.getPointerType(ArgTy);
- Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
- Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref,
- ArgTy, SourceLocation());
-
- // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
- // GCC extension, diagnose them.
- // FIXME: This diagnostic isn't actually visible because the location is in
- // a system header!
- if (NumComponents != 1)
- Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
-
- if (!Dependent) {
- bool DidWarnAboutNonPOD = false;
-
- if (RequireCompleteType(TypeLoc, Res->getType(),
- diag::err_offsetof_incomplete_type))
- return ExprError();
-
- // FIXME: Dependent case loses a lot of information here. And probably
- // leaks like a sieve.
- for (unsigned i = 0; i != NumComponents; ++i) {
- const OffsetOfComponent &OC = CompPtr[i];
- if (OC.isBrackets) {
- // Offset of an array sub-field. TODO: Should we allow vector elements?
- const ArrayType *AT = Context.getAsArrayType(Res->getType());
- if (!AT)
- return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
- << Res->getType());
-
- // FIXME: C++: Verify that operator[] isn't overloaded.
-
- // Promote the array so it looks more like a normal array subscript
- // expression.
- DefaultFunctionArrayLvalueConversion(Res);
-
- // C99 6.5.2.1p1
- Expr *Idx = static_cast<Expr*>(OC.U.E);
- // FIXME: Leaks Res
- if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())
- return ExprError(Diag(Idx->getLocStart(),
- diag::err_typecheck_subscript_not_integer)
- << Idx->getSourceRange());
-
- Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(),
- OC.LocEnd);
- continue;
- }
-
- const RecordType *RC = Res->getType()->getAs<RecordType>();
- if (!RC)
- return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
- << Res->getType());
-
- // Get the decl corresponding to this.
- RecordDecl *RD = RC->getDecl();
- if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc,
- PDiag(diag::warn_offsetof_non_pod_type)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
- << Res->getType()))
- DidWarnAboutNonPOD = true;
- }
-
- LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
- LookupQualifiedName(R, RD);
-
- FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
- // FIXME: Leaks Res
- if (!MemberDecl)
- return ExprError(Diag(BuiltinLoc, diag::err_no_member)
- << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
-
- // C99 7.17p3:
- // (If the specified member is a bit-field, the behavior is undefined.)
- //
- // We diagnose this as an error.
- if (MemberDecl->getBitWidth()) {
- Diag(OC.LocEnd, diag::err_offsetof_bitfield)
- << MemberDecl->getDeclName()
- << SourceRange(BuiltinLoc, RPLoc);
- Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
- return ExprError();
- }
-
- // FIXME: C++: Verify that MemberDecl isn't a static field.
- // FIXME: Verify that MemberDecl isn't a bitfield.
- if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
- Res = BuildAnonymousStructUnionMemberReference(
- OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
- } else {
- PerformObjectMemberConversion(Res, /*Qualifier=*/0,
- *R.begin(), MemberDecl);
- // MemberDecl->getType() doesn't get the right qualifiers, but it
- // doesn't matter here.
- Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
- MemberDecl->getType().getNonReferenceType());
- }
- }
- }
-
- return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf,
- Context.getSizeType(), BuiltinLoc));
+ if (!ArgTInfo)
+ ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
+
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
+ RPLoc);
}