diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-04 06:07:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-04 06:07:12 +0000 |
commit | 0c6db9417dceeb082296c4e097be5de3ee1c5eb7 (patch) | |
tree | d9d087d431c9c75775098bd66cddf0213f06adf5 /lib/Sema/SemaExprCXX.cpp | |
parent | 885c27bfd33c92412a3fb071c3f0fffc6b671783 (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.cpp | 71 |
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 |