aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-04 06:07:12 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-04 06:07:12 +0000
commit0c6db9417dceeb082296c4e097be5de3ee1c5eb7 (patch)
treed9d087d431c9c75775098bd66cddf0213f06adf5 /lib/Sema/SemaExprCXX.cpp
parent885c27bfd33c92412a3fb071c3f0fffc6b671783 (diff)
Implement support for comparing pointers with <, >, <=, >=, ==, and !=
in C++, taking into account conversions to the "composite pointer type" so that we can compare, e.g., a pointer to a derived class to a pointer to a base class. Also, upgrade the "comparing distinct pointer types" from a warning to an error for C++, since this is clearly an error. Turns out that we hadn't gone through and audited this code for C++, ever. Fixes <rdar://problem/6816420>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70829 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4c3c85bbf5..d407f77c28 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -768,6 +768,77 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
return false;
}
+/// \brief Determine the composite pointer type (C++ [expr.rel]p2)
+/// given the left- and right-hand expressions in a relational
+/// operation.
+///
+/// While the notion of a composite pointer type is only described for
+/// relational operators (<, >, <=, >=), the same computation is used
+/// to determine the "common type" used for the equality operators
+/// (==, !=) when comparing pointers.
+///
+/// \param LHS the left-hand operand.
+/// \param RHS the right-hand operand.
+/// \param LHSIsNull whether \p LHS is the NULL pointer constant
+/// \param RHSIsNull whether \p RHS is the NULL pointer constant
+///
+/// \returns the composite pointer type, if any, or the null type if
+/// no such type exists. It is the caller's responsibility to emit
+/// diagnostic.
+QualType Sema::CompositePointerType(Expr *LHS, Expr *RHS,
+ bool LHSIsNull, bool RHSIsNull) {
+ // First, determine whether LHS and RHS have pointer types, and what
+ // types they point to.
+ QualType LHSPointee;
+ QualType RHSPointee;
+ if (const PointerType *LHSPtr = LHS->getType()->getAsPointerType())
+ LHSPointee = LHSPtr->getPointeeType();
+ if (const PointerType *RHSPtr = RHS->getType()->getAsPointerType())
+ RHSPointee = RHSPtr->getPointeeType();
+
+ // C++ [expr.rel]p2:
+ // [...] If one operand is a null pointer constant, the composite
+ // pointer type is the type of the other operand.
+ if (LHSIsNull && !RHSPointee.isNull())
+ return RHS->getType();
+ if (RHSIsNull && !LHSPointee.isNull())
+ return LHS->getType();
+
+ // If neither LHS nor RHS has pointer type, we're done.
+ if (LHSPointee.isNull() && RHSPointee.isNull())
+ return QualType();
+
+ // [...] Otherwise, if one of the operands has type "pointer to cv1
+ // void", then the other has type "pointer to cv2 T" and the
+ // composite pointer type is "pointer to cv12 void", where cv12 is
+ // the union of cv1 and cv2.
+ QualType LHSPointeeCanon = Context.getCanonicalType(LHSPointee);
+ QualType RHSPointeeCanon = Context.getCanonicalType(RHSPointee);
+ unsigned CVQuals =
+ (LHSPointeeCanon.getCVRQualifiers() | RHSPointeeCanon.getCVRQualifiers());
+ if (LHSPointeeCanon->isVoidType() || RHSPointeeCanon->isVoidType())
+ return Context.getPointerType(Context.VoidTy.getQualifiedType(CVQuals));
+
+ // [...] Otherwise, the composite pointer type is a pointer type
+ // similar (4.4) to the type of one of the operands, with a
+ // cv-qualification signature (4.4) that is the union of the
+ // cv-qualification signatures of the operand types.
+ QualType FullyQualifiedLHSType
+ = Context.getPointerType(LHSPointee.getQualifiedType(CVQuals));
+ QualType CompositePointerType;
+ bool IncompatibleObjC = false;
+ if (IsPointerConversion(RHS, RHS->getType(), FullyQualifiedLHSType,
+ CompositePointerType, IncompatibleObjC))
+ return CompositePointerType;
+ QualType FullyQualifiedRHSType
+ = Context.getPointerType(RHSPointee.getQualifiedType(CVQuals));
+ if (IsPointerConversion(LHS, LHS->getType(), FullyQualifiedRHSType,
+ CompositePointerType, IncompatibleObjC))
+ return CompositePointerType;
+
+ return QualType();
+}
+
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType. Returns true if there was an
/// error, false otherwise. The expression From is replaced with the