IdStructType = rec;
}
+bool ASTContext::builtinTypesAreCompatible(QualType lhs, QualType rhs) {
+ const BuiltinType *lBuiltin = lhs->getAsBuiltinType();
+ const BuiltinType *rBuiltin = rhs->getAsBuiltinType();
+
+ return lBuiltin->getKind() == rBuiltin->getKind();
+}
+
+
+bool ASTContext::objcTypesAreCompatible(QualType lhs, QualType rhs) {
+ if (lhs->isObjcInterfaceType() && isObjcIdType(rhs))
+ return true;
+ else if (isObjcIdType(lhs) && rhs->isObjcInterfaceType())
+ return true;
+ return false;
+}
+
+bool ASTContext::interfaceTypesAreCompatible(QualType lhs, QualType rhs) {
+ return true; // FIXME: IMPLEMENT.
+}
+
+// C99 6.2.7p1: If both are complete types, then the following additional
+// requirements apply...FIXME (handle compatibility across source files).
+bool ASTContext::tagTypesAreCompatible(QualType lhs, QualType rhs) {
+ TagDecl *ldecl = cast<TagType>(lhs.getCanonicalType())->getDecl();
+ TagDecl *rdecl = cast<TagType>(rhs.getCanonicalType())->getDecl();
+
+ if (ldecl->getKind() == Decl::Struct && rdecl->getKind() == Decl::Struct) {
+ if (ldecl->getIdentifier() == rdecl->getIdentifier())
+ return true;
+ }
+ if (ldecl->getKind() == Decl::Union && rdecl->getKind() == Decl::Union) {
+ if (ldecl->getIdentifier() == rdecl->getIdentifier())
+ return true;
+ }
+ return false;
+}
+
+bool ASTContext::pointerTypesAreCompatible(QualType lhs, QualType rhs) {
+ // C99 6.7.5.1p2: For two pointer types to be compatible, both shall be
+ // identically qualified and both shall be pointers to compatible types.
+ if (lhs.getQualifiers() != rhs.getQualifiers())
+ return false;
+
+ QualType ltype = cast<PointerType>(lhs.getCanonicalType())->getPointeeType();
+ QualType rtype = cast<PointerType>(rhs.getCanonicalType())->getPointeeType();
+
+ return typesAreCompatible(ltype, rtype);
+}
+
+// C++ 5.17p6: When the left opperand of an assignment operator denotes a
+// reference to T, the operation assigns to the object of type T denoted by the
+// reference.
+bool ASTContext::referenceTypesAreCompatible(QualType lhs, QualType rhs) {
+ QualType ltype = lhs;
+
+ if (lhs->isReferenceType())
+ ltype = cast<ReferenceType>(lhs.getCanonicalType())->getReferenceeType();
+
+ QualType rtype = rhs;
+
+ if (rhs->isReferenceType())
+ rtype = cast<ReferenceType>(rhs.getCanonicalType())->getReferenceeType();
+
+ return typesAreCompatible(ltype, rtype);
+}
+
+bool ASTContext::functionTypesAreCompatible(QualType lhs, QualType rhs) {
+ const FunctionType *lbase = cast<FunctionType>(lhs.getCanonicalType());
+ const FunctionType *rbase = cast<FunctionType>(rhs.getCanonicalType());
+ const FunctionTypeProto *lproto = dyn_cast<FunctionTypeProto>(lbase);
+ const FunctionTypeProto *rproto = dyn_cast<FunctionTypeProto>(rbase);
+
+ // first check the return types (common between C99 and K&R).
+ if (!typesAreCompatible(lbase->getResultType(), rbase->getResultType()))
+ return false;
+
+ if (lproto && rproto) { // two C99 style function prototypes
+ unsigned lproto_nargs = lproto->getNumArgs();
+ unsigned rproto_nargs = rproto->getNumArgs();
+
+ if (lproto_nargs != rproto_nargs)
+ return false;
+
+ // both prototypes have the same number of arguments.
+ if ((lproto->isVariadic() && !rproto->isVariadic()) ||
+ (rproto->isVariadic() && !lproto->isVariadic()))
+ return false;
+
+ // The use of ellipsis agree...now check the argument types.
+ for (unsigned i = 0; i < lproto_nargs; i++)
+ if (!typesAreCompatible(lproto->getArgType(i), rproto->getArgType(i)))
+ return false;
+ return true;
+ }
+ if (!lproto && !rproto) // two K&R style function decls, nothing to do.
+ return true;
+
+ // we have a mixture of K&R style with C99 prototypes
+ const FunctionTypeProto *proto = lproto ? lproto : rproto;
+
+ if (proto->isVariadic())
+ return false;
+
+ // FIXME: Each parameter type T in the prototype must be compatible with the
+ // type resulting from applying the usual argument conversions to T.
+ return true;
+}
+
+bool ASTContext::arrayTypesAreCompatible(QualType lhs, QualType rhs) {
+ QualType ltype = cast<ArrayType>(lhs.getCanonicalType())->getElementType();
+ QualType rtype = cast<ArrayType>(rhs.getCanonicalType())->getElementType();
+
+ if (!typesAreCompatible(ltype, rtype))
+ return false;
+
+ // FIXME: If both types specify constant sizes, then the sizes must also be
+ // the same. Even if the sizes are the same, GCC produces an error.
+ return true;
+}
+
+/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
+/// both shall have the identically qualified version of a compatible type.
+/// C99 6.2.7p1: Two types have compatible types if their types are the
+/// same. See 6.7.[2,3,5] for additional rules.
+bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) {
+ QualType lcanon = lhs.getCanonicalType();
+ QualType rcanon = rhs.getCanonicalType();
+
+ // If two types are identical, they are are compatible
+ if (lcanon == rcanon)
+ return true;
+
+ // If the canonical type classes don't match, they can't be compatible
+ if (lcanon->getTypeClass() != rcanon->getTypeClass()) {
+ // For Objective-C, it is possible for two types to be compatible
+ // when their classes don't match (when dealing with "id"). If either type
+ // is an interface, we defer to objcTypesAreCompatible().
+ if (lcanon->isObjcInterfaceType() || rcanon->isObjcInterfaceType())
+ return objcTypesAreCompatible(lcanon, rcanon);
+ return false;
+ }
+ switch (lcanon->getTypeClass()) {
+ case Type::Pointer:
+ return pointerTypesAreCompatible(lcanon, rcanon);
+ case Type::Reference:
+ return referenceTypesAreCompatible(lcanon, rcanon);
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ return arrayTypesAreCompatible(lcanon, rcanon);
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ return functionTypesAreCompatible(lcanon, rcanon);
+ case Type::Tagged: // handle structures, unions
+ return tagTypesAreCompatible(lcanon, rcanon);
+ case Type::Builtin:
+ return builtinTypesAreCompatible(lcanon, rcanon);
+ case Type::ObjcInterface:
+ return interfaceTypesAreCompatible(lcanon, rcanon);
+ default:
+ assert(0 && "unexpected type");
+ }
+ return true; // should never get here...
+}
const TypesCompatibleExpr *TCE = cast<TypesCompatibleExpr>(this);
Result.zextOrTrunc(
static_cast<uint32_t>(Ctx.getTypeSize(getType(), TCE->getLocStart())));
- Result = TCE->typesAreCompatible();
+ Result = Ctx.typesAreCompatible(TCE->getArgType1(), TCE->getArgType2());
break;
}
case CallExprClass: {
return 0;
}
-bool Type::builtinTypesAreCompatible(QualType lhs, QualType rhs) {
- const BuiltinType *lBuiltin = lhs->getAsBuiltinType();
- const BuiltinType *rBuiltin = rhs->getAsBuiltinType();
-
- return lBuiltin->getKind() == rBuiltin->getKind();
-}
-
-// FIXME: Devise a way to do this without using strcmp.
-// Would like to say..."return getAsStructureType() == IdStructType;", but
-// we don't have a pointer to ASTContext.
-bool Type::isObjcIdType() const {
- if (const RecordType *RT = getAsStructureType())
- return !strcmp(RT->getDecl()->getName(), "objc_object");
- return false;
-}
-
-bool Type::objcTypesAreCompatible(QualType lhs, QualType rhs) {
- if (lhs->isObjcInterfaceType() && rhs->isObjcIdType())
- return true;
- else if (lhs->isObjcIdType() && rhs->isObjcInterfaceType())
- return true;
- return false;
-}
-
-bool Type::interfaceTypesAreCompatible(QualType lhs, QualType rhs) {
- return true; // FIXME: IMPLEMENT.
-}
-
-// C99 6.2.7p1: If both are complete types, then the following additional
-// requirements apply...FIXME (handle compatibility across source files).
-bool Type::tagTypesAreCompatible(QualType lhs, QualType rhs) {
- TagDecl *ldecl = cast<TagType>(lhs.getCanonicalType())->getDecl();
- TagDecl *rdecl = cast<TagType>(rhs.getCanonicalType())->getDecl();
-
- if (ldecl->getKind() == Decl::Struct && rdecl->getKind() == Decl::Struct) {
- if (ldecl->getIdentifier() == rdecl->getIdentifier())
- return true;
- }
- if (ldecl->getKind() == Decl::Union && rdecl->getKind() == Decl::Union) {
- if (ldecl->getIdentifier() == rdecl->getIdentifier())
- return true;
- }
- return false;
-}
-
-bool Type::pointerTypesAreCompatible(QualType lhs, QualType rhs) {
- // C99 6.7.5.1p2: For two pointer types to be compatible, both shall be
- // identically qualified and both shall be pointers to compatible types.
- if (lhs.getQualifiers() != rhs.getQualifiers())
- return false;
-
- QualType ltype = cast<PointerType>(lhs.getCanonicalType())->getPointeeType();
- QualType rtype = cast<PointerType>(rhs.getCanonicalType())->getPointeeType();
-
- return typesAreCompatible(ltype, rtype);
-}
-
-// C++ 5.17p6: When the left opperand of an assignment operator denotes a
-// reference to T, the operation assigns to the object of type T denoted by the
-// reference.
-bool Type::referenceTypesAreCompatible(QualType lhs, QualType rhs) {
- QualType ltype = lhs;
-
- if (lhs->isReferenceType())
- ltype = cast<ReferenceType>(lhs.getCanonicalType())->getReferenceeType();
-
- QualType rtype = rhs;
-
- if (rhs->isReferenceType())
- rtype = cast<ReferenceType>(rhs.getCanonicalType())->getReferenceeType();
-
- return typesAreCompatible(ltype, rtype);
-}
-
-bool Type::functionTypesAreCompatible(QualType lhs, QualType rhs) {
- const FunctionType *lbase = cast<FunctionType>(lhs.getCanonicalType());
- const FunctionType *rbase = cast<FunctionType>(rhs.getCanonicalType());
- const FunctionTypeProto *lproto = dyn_cast<FunctionTypeProto>(lbase);
- const FunctionTypeProto *rproto = dyn_cast<FunctionTypeProto>(rbase);
-
- // first check the return types (common between C99 and K&R).
- if (!typesAreCompatible(lbase->getResultType(), rbase->getResultType()))
- return false;
-
- if (lproto && rproto) { // two C99 style function prototypes
- unsigned lproto_nargs = lproto->getNumArgs();
- unsigned rproto_nargs = rproto->getNumArgs();
-
- if (lproto_nargs != rproto_nargs)
- return false;
-
- // both prototypes have the same number of arguments.
- if ((lproto->isVariadic() && !rproto->isVariadic()) ||
- (rproto->isVariadic() && !lproto->isVariadic()))
- return false;
-
- // The use of ellipsis agree...now check the argument types.
- for (unsigned i = 0; i < lproto_nargs; i++)
- if (!typesAreCompatible(lproto->getArgType(i), rproto->getArgType(i)))
- return false;
- return true;
- }
- if (!lproto && !rproto) // two K&R style function decls, nothing to do.
- return true;
-
- // we have a mixture of K&R style with C99 prototypes
- const FunctionTypeProto *proto = lproto ? lproto : rproto;
-
- if (proto->isVariadic())
- return false;
-
- // FIXME: Each parameter type T in the prototype must be compatible with the
- // type resulting from applying the usual argument conversions to T.
- return true;
-}
-
-bool Type::arrayTypesAreCompatible(QualType lhs, QualType rhs) {
- QualType ltype = cast<ArrayType>(lhs.getCanonicalType())->getElementType();
- QualType rtype = cast<ArrayType>(rhs.getCanonicalType())->getElementType();
-
- if (!typesAreCompatible(ltype, rtype))
- return false;
-
- // FIXME: If both types specify constant sizes, then the sizes must also be
- // the same. Even if the sizes are the same, GCC produces an error.
- return true;
-}
-
-/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
-/// both shall have the identically qualified version of a compatible type.
-/// C99 6.2.7p1: Two types have compatible types if their types are the
-/// same. See 6.7.[2,3,5] for additional rules.
-bool Type::typesAreCompatible(QualType lhs, QualType rhs) {
- QualType lcanon = lhs.getCanonicalType();
- QualType rcanon = rhs.getCanonicalType();
-
- // If two types are identical, they are are compatible
- if (lcanon == rcanon)
- return true;
-
- // If the canonical type classes don't match, they can't be compatible
- if (lcanon->getTypeClass() != rcanon->getTypeClass()) {
- // For Objective-C, it is possible for two types to be compatible
- // when their classes don't match (when dealing with "id"). If either type
- // is an interface, we defer to objcTypesAreCompatible().
- if (lcanon->isObjcInterfaceType() || rcanon->isObjcInterfaceType())
- return objcTypesAreCompatible(lcanon, rcanon);
- return false;
- }
- switch (lcanon->getTypeClass()) {
- case Type::Pointer:
- return pointerTypesAreCompatible(lcanon, rcanon);
- case Type::Reference:
- return referenceTypesAreCompatible(lcanon, rcanon);
- case Type::ConstantArray:
- case Type::VariableArray:
- return arrayTypesAreCompatible(lcanon, rcanon);
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- return functionTypesAreCompatible(lcanon, rcanon);
- case Type::Tagged: // handle structures, unions
- return tagTypesAreCompatible(lcanon, rcanon);
- case Type::Builtin:
- return builtinTypesAreCompatible(lcanon, rcanon);
- case Type::ObjcInterface:
- return interfaceTypesAreCompatible(lcanon, rcanon);
- default:
- assert(0 && "unexpected type");
- }
- return true; // should never get here...
-}
-
bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
}
Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
return llvm::ConstantInt::get(ConvertType(E->getType()),
- E->typesAreCompatible());
+ CGF.getContext().typesAreCompatible(
+ E->getArgType1(), E->getArgType2()));
}
Value *VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
return EmitSizeAlignOf(E->getArgumentType(), E->getType(), E->isSizeOf());
(lhptee->isObjectType() || lhptee->isIncompleteType()))
return rexT;
- if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(),
- rhptee.getUnqualifiedType())) {
+ if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType())) {
Diag(questionLoc, diag::ext_typecheck_cond_incompatible_pointers,
lexT.getAsString(), rexT.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
;
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
// unqualified versions of compatible types, ...
- else if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(),
- rhptee.getUnqualifiedType()))
+ else if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType()))
r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
return r;
}
return Compatible;
if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
- if (Type::referenceTypesAreCompatible(lhsType, rhsType))
+ if (Context.referenceTypesAreCompatible(lhsType, rhsType))
return Compatible;
} else if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
if (lhsType->isVectorType() || rhsType->isVectorType()) {
if (lhsType->isPointerType())
return CheckPointerTypesForAssignment(lhsType, rhsType);
} else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
- if (Type::tagTypesAreCompatible(lhsType, rhsType))
+ if (Context.tagTypesAreCompatible(lhsType, rhsType))
return Compatible;
}
return Incompatible;
// errors (when -pedantic-errors is enabled).
if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
if (!LHSIsNull && !RHSIsNull &&
- !Type::pointerTypesAreCompatible(lType.getUnqualifiedType(),
- rType.getUnqualifiedType())) {
+ !Context.pointerTypesAreCompatible(lType.getUnqualifiedType(),
+ rType.getUnqualifiedType())) {
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
lType.getAsString(), rType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
/// 'typeSize' is a real floating point or complex type.
QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
QualType typeDomain) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Compatibility Predicates
+ //===--------------------------------------------------------------------===//
+
+ /// Compatibility predicates used to check assignment expressions.
+ bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
+ bool tagTypesAreCompatible(QualType, QualType); // C99 6.2.7p1
+ bool pointerTypesAreCompatible(QualType, QualType); // C99 6.7.5.1p2
+ bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
+ bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
+ bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
+ bool builtinTypesAreCompatible(QualType, QualType);
+
+ /// Objective-C specific type checking.
+ bool interfaceTypesAreCompatible(QualType, QualType);
+ bool objcTypesAreCompatible(QualType, QualType);
+ bool isObjcIdType(QualType T) const {
+ return T->getAsStructureType() == IdStructType;
+ }
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
QualType getArgType1() const { return Type1; }
QualType getArgType2() const { return Type2; }
-
- int typesAreCompatible() const {return Type::typesAreCompatible(Type1,Type2);}
-
+
virtual SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);
}
bool isVectorType() const; // GCC vector type.
bool isOCUVectorType() const; // OCU vector type.
bool isObjcInterfaceType() const; // includes conforming protocol type
- bool isObjcIdType() const;
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs, and return a pointer to the best type
/// the location of the subexpression that makes it a vla type. It is not
/// legal to call this on incomplete types.
bool isConstantSizeType(ASTContext &Ctx, SourceLocation *Loc = 0) const;
-
- /// Compatibility predicates used to check assignment expressions.
- static bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
- static bool tagTypesAreCompatible(QualType, QualType); // C99 6.2.7p1
- static bool pointerTypesAreCompatible(QualType, QualType); // C99 6.7.5.1p2
- static bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
- static bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
- static bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
- static bool builtinTypesAreCompatible(QualType, QualType);
- static bool interfaceTypesAreCompatible(QualType, QualType);
- static bool objcTypesAreCompatible(QualType, QualType);
private:
QualType getCanonicalTypeInternal() const { return CanonicalType; }
friend class QualType;