Submitted by:
Reviewed by:
- implement Type::functionTypesAreCompatible().
- fix bug in Sema::CheckAssignmentOperands(). Spec allows any pointer type
to be assigned to _Bool.

llvm-svn: 39428
This commit is contained in:
Steve Naroff 2007-05-02 19:22:16 +00:00
parent dd92b932e0
commit 38a9dae33f
5 changed files with 80 additions and 10 deletions

View File

@ -646,10 +646,14 @@ Action::ExprResult Sema::CheckAssignmentOperands(
}
} else if (rhsType->isPointerType()) {
if (lhsType->isIntegerType()) {
Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
if (lhsType != Context.BoolTy)
Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
return new BinaryOperator(lex, rex, (BOP)code, lhsType);
}
// FIXME: make sure the qualifier are matching
// - both operands are pointers to qualified or unqualified versions of
// compatible types, and the type pointed to by the left has *all* the
// qualifiers of the type pointed to by the right;
if (lhsType->isPointerType()) {
if (!Type::pointerTypesAreCompatible(lhsType, rhsType))
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer);

View File

@ -106,7 +106,45 @@ bool Type::pointerTypesAreCompatible(QualType lhs, QualType rhs) {
}
bool Type::functionTypesAreCompatible(QualType lhs, QualType rhs) {
return true; // FIXME: add more checking
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) {
@ -123,6 +161,8 @@ bool Type::arrayTypesAreCompatible(QualType lhs, QualType rhs) {
bool Type::typesAreCompatible(QualType lcanon, QualType rcanon) {
// If two types are identical, they are are compatible
// C99 6.7.3p9: For two qualified types to be compatible, both shall have
// the identically qualified version of a compatible type.
if (lcanon == rcanon)
return true;

View File

@ -646,10 +646,14 @@ Action::ExprResult Sema::CheckAssignmentOperands(
}
} else if (rhsType->isPointerType()) {
if (lhsType->isIntegerType()) {
Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
if (lhsType != Context.BoolTy)
Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
return new BinaryOperator(lex, rex, (BOP)code, lhsType);
}
// FIXME: make sure the qualifier are matching
// - both operands are pointers to qualified or unqualified versions of
// compatible types, and the type pointed to by the left has *all* the
// qualifiers of the type pointed to by the right;
if (lhsType->isPointerType()) {
if (!Type::pointerTypesAreCompatible(lhsType, rhsType))
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer);

View File

@ -94,6 +94,23 @@
DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXBuildStyle section */
847E78660BE8363100F1DB4C /* Development */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = NO;
};
name = Development;
};
847E78670BE8363100F1DB4C /* Deployment */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = YES;
};
name = Deployment;
};
/* End PBXBuildStyle section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76F690486A84900D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
@ -476,10 +493,15 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
buildSettings = {
};
buildStyles = (
847E78660BE8363100F1DB4C /* Development */,
847E78670BE8363100F1DB4C /* Deployment */,
);
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76F620486A84900D96B5E /* clang */,
);

View File

@ -215,7 +215,6 @@ public:
bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
bool isVoidType() const; // C99 6.2.5p19
/// Derived types (C99 6.2.5p20). isFunctionType() is also a derived type.
bool isDerivedType() const;
@ -224,8 +223,9 @@ public:
bool isStructureType() const;
bool isUnionType() const;
bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
bool isVoidType() const; // C99 6.2.5p19
bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
bool isLvalue() const; // C99 6.3.2.1