SourceLocation Loc,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
- // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
- if (S.LangOpts.ObjCRuntime.isNonFragile() && T->isObjCObjectType()) {
+ // Reject sizeof(interface) and sizeof(interface<proto>) if the
+ // runtime doesn't allow it.
+ if (!S.LangOpts.ObjCRuntime.allowsSizeofAlignof() && T->isObjCObjectType()) {
S.Diag(Loc, diag::err_sizeof_nonfragile_interface)
<< T << (TraitKind == UETT_SizeOf)
<< ArgRange;
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
+/// \brief Diagnose if arithmetic on the given ObjC pointer is illegal.
+///
+/// \return true on error
+static bool checkArithmeticOnObjCPointer(Sema &S,
+ SourceLocation opLoc,
+ Expr *op) {
+ assert(op->getType()->isObjCObjectPointerType());
+ if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic())
+ return false;
+
+ S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface)
+ << op->getType()->castAs<ObjCObjectPointerType>()->getPointeeType()
+ << op->getSourceRange();
+ return true;
+}
+
ExprResult
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);
}
-
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
IndexExpr = RHSExp;
ResultType = PTy->getPointeeType();
} else if (const ObjCObjectPointerType *PTy =
- LHSTy->getAs<ObjCObjectPointerType>()) {
+ LHSTy->getAs<ObjCObjectPointerType>()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
- Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
- if (!Result.isInvalid())
- return Owned(Result.take());
+
+ // Use custom logic if this should be the pseudo-object subscript
+ // expression.
+ if (!LangOpts.ObjCRuntime.isSubscriptPointerArithmetic())
+ return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
+
ResultType = PTy->getPointeeType();
+ if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
+ Diag(LLoc, diag::err_subscript_nonfragile_interface)
+ << ResultType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
// Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
+ if (!LangOpts.ObjCRuntime.allowsPointerArithmetic()) {
+ Diag(LLoc, diag::err_subscript_nonfragile_interface)
+ << ResultType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
} else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
diag::err_subscript_incomplete_type, BaseExpr))
return ExprError();
- // Diagnose bad cases where we step over interface counts.
- if (ResultType->isObjCObjectType() && LangOpts.ObjCRuntime.isNonFragile()) {
- Diag(LLoc, diag::err_subscript_nonfragile_interface)
- << ResultType << BaseExpr->getSourceRange();
- return ExprError();
- }
-
assert(VK == VK_RValue || LangOpts.CPlusPlus ||
!ResultType.isCForbiddenLValueType());
/// \returns True if pointer has incomplete type
static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
Expr *Operand) {
- if ((Operand->getType()->isPointerType() &&
- !Operand->getType()->isDependentType()) ||
- Operand->getType()->isObjCObjectPointerType()) {
- QualType PointeeTy = Operand->getType()->getPointeeType();
- if (S.RequireCompleteType(
- Loc, PointeeTy,
- diag::err_typecheck_arithmetic_incomplete_type,
- PointeeTy, Operand->getSourceRange()))
- return true;
- }
- return false;
+ assert(Operand->getType()->isAnyPointerType() &&
+ !Operand->getType()->isDependentType());
+ QualType PointeeTy = Operand->getType()->getPointeeType();
+ return S.RequireCompleteType(Loc, PointeeTy,
+ diag::err_typecheck_arithmetic_incomplete_type,
+ PointeeTy, Operand->getSourceRange());
}
/// \brief Check the validity of an arithmetic pointer operand.
return !S.getLangOpts().CPlusPlus;
}
- if (checkArithmeticIncompletePointerType(S, Loc, LHSExpr)) return false;
- if (checkArithmeticIncompletePointerType(S, Loc, RHSExpr)) return false;
+ if (isLHSPointer && checkArithmeticIncompletePointerType(S, Loc, LHSExpr))
+ return false;
+ if (isRHSPointer && checkArithmeticIncompletePointerType(S, Loc, RHSExpr))
+ return false;
return true;
}
-/// \brief Check bad cases where we step over interface counts.
-static bool checkArithmethicPointerOnNonFragileABI(Sema &S,
- SourceLocation OpLoc,
- Expr *Op) {
- assert(Op->getType()->isAnyPointerType());
- QualType PointeeTy = Op->getType()->getPointeeType();
- if (!PointeeTy->isObjCObjectType() || S.LangOpts.ObjCRuntime.isFragile())
- return true;
-
- S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
- << PointeeTy << Op->getSourceRange();
- return false;
-}
-
/// diagnoseStringPlusInt - Emit a warning when adding an integer to a string
/// literal.
static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
return compType;
}
- // Put any potential pointer into PExp
- Expr* PExp = LHS.get(), *IExp = RHS.get();
- if (IExp->getType()->isAnyPointerType())
- std::swap(PExp, IExp);
+ // Type-checking. Ultimately the pointer's going to be in PExp;
+ // note that we bias towards the LHS being the pointer.
+ Expr *PExp = LHS.get(), *IExp = RHS.get();
- if (!PExp->getType()->isAnyPointerType())
- return InvalidOperands(Loc, LHS, RHS);
+ bool isObjCPointer;
+ if (PExp->getType()->isPointerType()) {
+ isObjCPointer = false;
+ } else if (PExp->getType()->isObjCObjectPointerType()) {
+ isObjCPointer = true;
+ } else {
+ std::swap(PExp, IExp);
+ if (PExp->getType()->isPointerType()) {
+ isObjCPointer = false;
+ } else if (PExp->getType()->isObjCObjectPointerType()) {
+ isObjCPointer = true;
+ } else {
+ return InvalidOperands(Loc, LHS, RHS);
+ }
+ }
+ assert(PExp->getType()->isAnyPointerType());
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
if (!checkArithmeticOpPointerOperand(*this, Loc, PExp))
return QualType();
- // Diagnose bad cases where we step over interface counts.
- if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, PExp))
+ if (isObjCPointer && checkArithmeticOnObjCPointer(*this, Loc, PExp))
return QualType();
// Check array bounds for pointer arithemtic
QualType lpointee = LHS.get()->getType()->getPointeeType();
// Diagnose bad cases where we step over interface counts.
- if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, LHS.get()))
+ if (LHS.get()->getType()->isObjCObjectPointerType() &&
+ checkArithmeticOnObjCPointer(*this, Loc, LHS.get()))
return QualType();
// The result type of a pointer-int computation is the pointer type.
S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
} else if (ResType->isRealType()) {
// OK!
- } else if (ResType->isAnyPointerType()) {
+ } else if (ResType->isPointerType()) {
// C99 6.5.2.4p2, 6.5.6p2
if (!checkArithmeticOpPointerOperand(S, OpLoc, Op))
return QualType();
-
- // Diagnose bad cases where we step over interface counts.
- else if (!checkArithmethicPointerOnNonFragileABI(S, OpLoc, Op))
- return QualType();
+ } else if (ResType->isObjCObjectPointerType()) {
+ // On modern runtimes, ObjC pointer arithmetic is forbidden.
+ // Otherwise, we just need a complete type.
+ if (checkArithmeticIncompletePointerType(S, OpLoc, Op) ||
+ checkArithmeticOnObjCPointer(S, OpLoc, Op))
+ return QualType();
} else if (ResType->isAnyComplexType()) {
// C99 does not support ++/-- on complex types, we allow as an extension.
S.Diag(OpLoc, diag::ext_integer_increment_complex)