[cfe-commits] r39440 - in /cfe/cfe/trunk: AST/Sema.h AST/SemaExpr.cpp AST/Type.cpp Sema/Sema.h Sema/SemaExpr.cpp
Steve Naroff
snaroff at apple.com
Wed Jul 11 09:44:25 PDT 2007
Author: snaroff
Date: Wed Jul 11 11:44:25 2007
New Revision: 39440
URL: http://llvm.org/viewvc/llvm-project?rev=39440&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
This check-in should finally "nail" complex pointer assignments (involving
qualifiers, etc.).
- Replaced pointerTypeQualifiersAlign() with CheckPointerTypesForAssignment()
This also simplified UsualAssignmentConversions().
- Fixed Type::pointerTypesAreCompatible() and Type::typesAreCompatible()
to closely reflect the spec. They were (unfortunately) compensating for some of the
missing logic in the assignment checking code.
Modified:
cfe/cfe/trunk/AST/Sema.h
cfe/cfe/trunk/AST/SemaExpr.cpp
cfe/cfe/trunk/AST/Type.cpp
cfe/cfe/trunk/Sema/Sema.h
cfe/cfe/trunk/Sema/SemaExpr.cpp
Modified: cfe/cfe/trunk/AST/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.h?rev=39440&r1=39439&r2=39440&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:44:25 2007
@@ -244,8 +244,9 @@
// CheckSimpleAssignment, CheckCompoundAssignment and ParseCallExpr.
QualType UsualAssignmentConversions(QualType lhs, QualType rhs, // C99 6.5.16
AssignmentConversionResult &r);
- // Helper function for UsualAssignmentConversions
- bool pointerTypeQualifiersAlign(QualType lhsType, QualType rhsType);
+ // Helper function for UsualAssignmentConversions (C99 6.5.16.1p1)
+ QualType CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType,
+ AssignmentConversionResult &r);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39440&r1=39439&r2=39440&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:25 2007
@@ -452,37 +452,46 @@
return Context.maxIntegerType(lhs, rhs);
}
-// C99 6.5.16.1p1: 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;
-bool Sema::pointerTypeQualifiersAlign(QualType lhsType, QualType rhsType) {
- QualType lPointee, rPointee;
+// CheckPointerTypesForAssignment - This is a very tricky routine (despite
+// being closely modeled after the C99 spec:-). The odd characteristic of this
+// routine is it effectively iqnores the qualifiers on the top level pointee.
+// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
+// FIXME: add a couple examples in this comment.
+QualType Sema::CheckPointerTypesForAssignment(QualType lhsType,
+ QualType rhsType,
+ AssignmentConversionResult &r) {
+ QualType lhptee, rhptee;
// get the "pointed to" type (ignoring qualifiers at the top level)
- lPointee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
- rPointee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
+ lhptee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
+ rhptee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
// make sure we operate on the canonical type
- lPointee = lPointee.getCanonicalType();
- rPointee = rPointee.getCanonicalType();
-
- while (!rPointee.isNull() && !lPointee.isNull()) {
- unsigned rightQuals = rPointee.getQualifiers();
- if (rightQuals && (rightQuals != lPointee.getQualifiers()))
- return false;
-
- // if necessary, continue checking pointees...
- if (const PointerType *rPtr = dyn_cast<PointerType>(rPointee))
- rPointee = rPtr->getPointeeType().getCanonicalType();
- else
- rPointee = QualType();
-
- if (const PointerType *lPtr = dyn_cast<PointerType>(lPointee))
- lPointee = lPtr->getPointeeType().getCanonicalType();
- else
- rPointee = QualType();
- }
- return true;
+ lhptee = lhptee.getCanonicalType();
+ rhptee = rhptee.getCanonicalType();
+
+ // C99 6.5.16.1p1: This following citation is common to constraints
+ // 3 & 4 (below). ...and the type *pointed to* by the left has all the
+ // qualifiers of the type *pointed to* by the right;
+ if ((lhptee.getQualifiers() & rhptee.getQualifiers()) !=
+ rhptee.getQualifiers())
+ r = CompatiblePointerDiscardsQualifiers;
+
+ // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
+ // incomplete type and the other is a pointer to a qualified or unqualified
+ // version of void...
+ if (lhptee.getUnqualifiedType()->isVoidType() &&
+ (rhptee->isObjectType() || rhptee->isIncompleteType()))
+ ;
+ else if (rhptee.getUnqualifiedType()->isVoidType() &&
+ (lhptee->isObjectType() || lhptee->isIncompleteType()))
+ ;
+ // 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()))
+ r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+ return rhsType;
}
/// UsualAssignmentConversions (C99 6.5.16) - This routine currently
@@ -519,14 +528,8 @@
r = PointerFromInt;
return rhsType;
}
- if (rhsType->isPointerType()) {
- if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
- if (!pointerTypeQualifiersAlign(lhsType, rhsType))
- r = CompatiblePointerDiscardsQualifiers;
- } else
- r = IncompatiblePointer;
- return rhsType;
- }
+ if (rhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType, r);
} else if (rhsType->isPointerType()) {
if (lhsType->isIntegerType()) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
@@ -534,14 +537,8 @@
r = IntFromPointer;
return rhsType;
}
- if (lhsType->isPointerType()) {
- if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
- if (!pointerTypeQualifiersAlign(lhsType, rhsType))
- r = CompatiblePointerDiscardsQualifiers;
- } else
- r = IncompatiblePointer;
- return rhsType;
- }
+ if (lhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType, r);
} else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
if (Type::tagTypesAreCompatible(lhsType, rhsType))
return rhsType;
@@ -789,6 +786,14 @@
if (dcl && isa<FunctionDecl>(dcl))
; // C99 6.5.3.2p1: Allow function designators.
else {
+ /* FIXME: The following produces an (incorrect) error. The
+ Type::isModifiableLvalue() predicate is causing problems.
+
+ const char **cpp;
+ const char c = 'A';
+
+ int main() { *cpp = &c; // valid }
+ */
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof);
return QualType();
}
Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39440&r1=39439&r2=39440&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:44:25 2007
@@ -90,12 +90,14 @@
}
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();
-
- // handle void first (not sure this is the best place to check for this).
- if (ltype->isVoidType() || rtype->isVoidType())
- return true;
+
return typesAreCompatible(ltype, rtype);
}
@@ -167,8 +169,6 @@
switch (lcanon->getTypeClass()) {
case Type::Pointer:
- // C99 6.7.3p9: For two qualified types to be compatible, both shall have
- // the identically qualified version of a compatible type. ??
return pointerTypesAreCompatible(lcanon, rcanon);
case Type::Array:
return arrayTypesAreCompatible(lcanon, rcanon);
@@ -178,10 +178,16 @@
case Type::Tagged: // handle structures, unions
return tagTypesAreCompatible(lcanon, rcanon);
case Type::Builtin:
- // exclude type qualifiers...
+ // C99 6.7.3p9: For two qualified types to be compatible, both shall
+ // have the identically qualified version of a compatible type.
+ if (lhs.getQualifiers() != rhs.getQualifiers())
+ return false;
+
+ // C99 6.2.7p1: Two types have compatible types if their types are the
+ // same. See 6.7.[2,3,5] for additional rules.
if (lcanon.getTypePtr() == rcanon.getTypePtr())
return true;
- return false; // C99 6.2.7p1
+ return false;
default:
assert(0 && "unexpected type");
}
Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39440&r1=39439&r2=39440&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:44:25 2007
@@ -244,8 +244,9 @@
// CheckSimpleAssignment, CheckCompoundAssignment and ParseCallExpr.
QualType UsualAssignmentConversions(QualType lhs, QualType rhs, // C99 6.5.16
AssignmentConversionResult &r);
- // Helper function for UsualAssignmentConversions
- bool pointerTypeQualifiersAlign(QualType lhsType, QualType rhsType);
+ // Helper function for UsualAssignmentConversions (C99 6.5.16.1p1)
+ QualType CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType,
+ AssignmentConversionResult &r);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39440&r1=39439&r2=39440&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:25 2007
@@ -452,37 +452,46 @@
return Context.maxIntegerType(lhs, rhs);
}
-// C99 6.5.16.1p1: 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;
-bool Sema::pointerTypeQualifiersAlign(QualType lhsType, QualType rhsType) {
- QualType lPointee, rPointee;
+// CheckPointerTypesForAssignment - This is a very tricky routine (despite
+// being closely modeled after the C99 spec:-). The odd characteristic of this
+// routine is it effectively iqnores the qualifiers on the top level pointee.
+// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
+// FIXME: add a couple examples in this comment.
+QualType Sema::CheckPointerTypesForAssignment(QualType lhsType,
+ QualType rhsType,
+ AssignmentConversionResult &r) {
+ QualType lhptee, rhptee;
// get the "pointed to" type (ignoring qualifiers at the top level)
- lPointee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
- rPointee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
+ lhptee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
+ rhptee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
// make sure we operate on the canonical type
- lPointee = lPointee.getCanonicalType();
- rPointee = rPointee.getCanonicalType();
-
- while (!rPointee.isNull() && !lPointee.isNull()) {
- unsigned rightQuals = rPointee.getQualifiers();
- if (rightQuals && (rightQuals != lPointee.getQualifiers()))
- return false;
-
- // if necessary, continue checking pointees...
- if (const PointerType *rPtr = dyn_cast<PointerType>(rPointee))
- rPointee = rPtr->getPointeeType().getCanonicalType();
- else
- rPointee = QualType();
-
- if (const PointerType *lPtr = dyn_cast<PointerType>(lPointee))
- lPointee = lPtr->getPointeeType().getCanonicalType();
- else
- rPointee = QualType();
- }
- return true;
+ lhptee = lhptee.getCanonicalType();
+ rhptee = rhptee.getCanonicalType();
+
+ // C99 6.5.16.1p1: This following citation is common to constraints
+ // 3 & 4 (below). ...and the type *pointed to* by the left has all the
+ // qualifiers of the type *pointed to* by the right;
+ if ((lhptee.getQualifiers() & rhptee.getQualifiers()) !=
+ rhptee.getQualifiers())
+ r = CompatiblePointerDiscardsQualifiers;
+
+ // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
+ // incomplete type and the other is a pointer to a qualified or unqualified
+ // version of void...
+ if (lhptee.getUnqualifiedType()->isVoidType() &&
+ (rhptee->isObjectType() || rhptee->isIncompleteType()))
+ ;
+ else if (rhptee.getUnqualifiedType()->isVoidType() &&
+ (lhptee->isObjectType() || lhptee->isIncompleteType()))
+ ;
+ // 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()))
+ r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+ return rhsType;
}
/// UsualAssignmentConversions (C99 6.5.16) - This routine currently
@@ -519,14 +528,8 @@
r = PointerFromInt;
return rhsType;
}
- if (rhsType->isPointerType()) {
- if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
- if (!pointerTypeQualifiersAlign(lhsType, rhsType))
- r = CompatiblePointerDiscardsQualifiers;
- } else
- r = IncompatiblePointer;
- return rhsType;
- }
+ if (rhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType, r);
} else if (rhsType->isPointerType()) {
if (lhsType->isIntegerType()) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
@@ -534,14 +537,8 @@
r = IntFromPointer;
return rhsType;
}
- if (lhsType->isPointerType()) {
- if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
- if (!pointerTypeQualifiersAlign(lhsType, rhsType))
- r = CompatiblePointerDiscardsQualifiers;
- } else
- r = IncompatiblePointer;
- return rhsType;
- }
+ if (lhsType->isPointerType())
+ return CheckPointerTypesForAssignment(lhsType, rhsType, r);
} else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
if (Type::tagTypesAreCompatible(lhsType, rhsType))
return rhsType;
@@ -789,6 +786,14 @@
if (dcl && isa<FunctionDecl>(dcl))
; // C99 6.5.3.2p1: Allow function designators.
else {
+ /* FIXME: The following produces an (incorrect) error. The
+ Type::isModifiableLvalue() predicate is causing problems.
+
+ const char **cpp;
+ const char c = 'A';
+
+ int main() { *cpp = &c; // valid }
+ */
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof);
return QualType();
}
More information about the cfe-commits
mailing list