зеркало из https://github.com/microsoft/clang-1.git
Move composite type finding of two objective-c expressions
into its own helper method. No change in functionality. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91056 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0966f35898
Коммит
eebc4750fd
|
@ -3638,6 +3638,9 @@ public:
|
|||
Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
|
||||
QualType FindCompositePointerType(Expr *&E1, Expr *&E2); // C++ 5.9
|
||||
|
||||
QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
|
||||
SourceLocation questionLoc);
|
||||
|
||||
/// type checking for vector binary operators.
|
||||
inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
|
||||
inline QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
|
||||
|
|
|
@ -3920,41 +3920,14 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
|||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown);
|
||||
return RHSTy;
|
||||
}
|
||||
// Handle things like Class and struct objc_class*. Here we case the result
|
||||
// to the pseudo-builtin, because that will be implicitly cast back to the
|
||||
// redefinition type if an attempt is made to access its fields.
|
||||
if (LHSTy->isObjCClassType() &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (RHSTy->isObjCClassType() &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
// And the same for struct objc_object* / id
|
||||
if (LHSTy->isObjCIdType() &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (RHSTy->isObjCIdType() &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
// And the same for struct objc_selector* / SEL
|
||||
if (Context.isObjCSelType(LHSTy) &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (Context.isObjCSelType(RHSTy) &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
|
||||
// All objective-c pointer type analysis is done here.
|
||||
QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
|
||||
QuestionLoc);
|
||||
if (!compositeType.isNull())
|
||||
return compositeType;
|
||||
|
||||
|
||||
// Handle block pointer types.
|
||||
if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
|
||||
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
|
||||
|
@ -3994,6 +3967,126 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
|||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
|
||||
// Check constraints for C object pointers types (C99 6.5.15p3,6).
|
||||
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
|
||||
// get the "pointed to" types
|
||||
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
|
||||
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
|
||||
|
||||
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
|
||||
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
|
||||
// Figure out necessary qualifiers (C99 6.5.15p6)
|
||||
QualType destPointee
|
||||
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
|
||||
QualType destType = Context.getPointerType(destPointee);
|
||||
// Add qualifiers if necessary.
|
||||
ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
|
||||
// Promote to void*.
|
||||
ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
|
||||
return destType;
|
||||
}
|
||||
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
|
||||
QualType destPointee
|
||||
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
|
||||
QualType destType = Context.getPointerType(destPointee);
|
||||
// Add qualifiers if necessary.
|
||||
ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
|
||||
// Promote to void*.
|
||||
ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
|
||||
return destType;
|
||||
}
|
||||
|
||||
if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
|
||||
// Two identical pointer types are always compatible.
|
||||
return LHSTy;
|
||||
}
|
||||
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
||||
rhptee.getUnqualifiedType())) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
// In this situation, we assume void* type. No especially good
|
||||
// reason, but this is what gcc does, and we do have to pick
|
||||
// to get a consistent AST.
|
||||
QualType incompatTy = Context.getPointerType(Context.VoidTy);
|
||||
ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
|
||||
ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
|
||||
return incompatTy;
|
||||
}
|
||||
// The pointer types are compatible.
|
||||
// C99 6.5.15p6: If both operands are pointers to compatible types *or* to
|
||||
// differently qualified versions of compatible types, the result type is
|
||||
// a pointer to an appropriately qualified version of the *composite*
|
||||
// type.
|
||||
// FIXME: Need to calculate the composite type.
|
||||
// FIXME: Need to add qualifiers
|
||||
ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
|
||||
// GCC compatibility: soften pointer/integer mismatch.
|
||||
if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);
|
||||
return RHSTy;
|
||||
}
|
||||
if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);
|
||||
return LHSTy;
|
||||
}
|
||||
|
||||
// Otherwise, the operands are not compatible.
|
||||
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
/// FindCompositeObjCPointerType - Helper method to find composite type of
|
||||
/// two objective-c pointer types of the two input expressions.
|
||||
QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
|
||||
SourceLocation QuestionLoc) {
|
||||
QualType LHSTy = LHS->getType();
|
||||
QualType RHSTy = RHS->getType();
|
||||
|
||||
// Handle things like Class and struct objc_class*. Here we case the result
|
||||
// to the pseudo-builtin, because that will be implicitly cast back to the
|
||||
// redefinition type if an attempt is made to access its fields.
|
||||
if (LHSTy->isObjCClassType() &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (RHSTy->isObjCClassType() &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
// And the same for struct objc_object* / id
|
||||
if (LHSTy->isObjCIdType() &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (RHSTy->isObjCIdType() &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
// And the same for struct objc_selector* / SEL
|
||||
if (Context.isObjCSelType(LHSTy) &&
|
||||
(RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
if (Context.isObjCSelType(RHSTy) &&
|
||||
(LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
|
||||
return RHSTy;
|
||||
}
|
||||
// Check constraints for Objective-C object pointers types.
|
||||
if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
|
||||
|
||||
|
@ -4074,80 +4167,6 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
|||
ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
|
||||
return destType;
|
||||
}
|
||||
// Check constraints for C object pointers types (C99 6.5.15p3,6).
|
||||
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
|
||||
// get the "pointed to" types
|
||||
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
|
||||
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
|
||||
|
||||
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
|
||||
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
|
||||
// Figure out necessary qualifiers (C99 6.5.15p6)
|
||||
QualType destPointee
|
||||
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
|
||||
QualType destType = Context.getPointerType(destPointee);
|
||||
// Add qualifiers if necessary.
|
||||
ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
|
||||
// Promote to void*.
|
||||
ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
|
||||
return destType;
|
||||
}
|
||||
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
|
||||
QualType destPointee
|
||||
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
|
||||
QualType destType = Context.getPointerType(destPointee);
|
||||
// Add qualifiers if necessary.
|
||||
ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
|
||||
// Promote to void*.
|
||||
ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
|
||||
return destType;
|
||||
}
|
||||
|
||||
if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
|
||||
// Two identical pointer types are always compatible.
|
||||
return LHSTy;
|
||||
}
|
||||
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
||||
rhptee.getUnqualifiedType())) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
// In this situation, we assume void* type. No especially good
|
||||
// reason, but this is what gcc does, and we do have to pick
|
||||
// to get a consistent AST.
|
||||
QualType incompatTy = Context.getPointerType(Context.VoidTy);
|
||||
ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
|
||||
ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
|
||||
return incompatTy;
|
||||
}
|
||||
// The pointer types are compatible.
|
||||
// C99 6.5.15p6: If both operands are pointers to compatible types *or* to
|
||||
// differently qualified versions of compatible types, the result type is
|
||||
// a pointer to an appropriately qualified version of the *composite*
|
||||
// type.
|
||||
// FIXME: Need to calculate the composite type.
|
||||
// FIXME: Need to add qualifiers
|
||||
ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
|
||||
return LHSTy;
|
||||
}
|
||||
|
||||
// GCC compatibility: soften pointer/integer mismatch.
|
||||
if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);
|
||||
return RHSTy;
|
||||
}
|
||||
if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
|
||||
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);
|
||||
return LHSTy;
|
||||
}
|
||||
|
||||
// Otherwise, the operands are not compatible.
|
||||
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче