<div class="gmail_quote">On Thu, Sep 1, 2011 at 7:55 PM, Richard Trieu <span dir="ltr"><<a href="mailto:rtrieu@google.com">rtrieu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+/// \brief Diagnose bad pointer comparisons.<br>
+static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,<br>
+ ExprResult &lex, ExprResult &rex,<br></blockquote><div><br></div><div>I would prefer 'LHS' and 'RHS' over 'lex' and 'rex'. The latter aren't very consistent with the style rules, and I find 'lex' particularly confusing in a compiler. =]</div>
<div><br></div><div>Also, "IsError" would be more conforming with the new style rules.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+ bool isError) {<br>
+ S.Diag(Loc, isError ? diag::err_typecheck_comparison_of_distinct_pointers<br>
+ : diag::ext_typecheck_comparison_of_distinct_pointers)<br>
+ << lex.get()->getType() << rex.get()->getType()<br>
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();<br>
+}<br>
+<br>
+/// \brief Returns false if the pointers are converted to a composite type,<br>
+/// true otherwise.<br>
+static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,<br>
+ ExprResult &lex,<br>
+ ExprResult &rex) {<br>
+ // C++ [expr.rel]p2:<br>
+ // [...] Pointer conversions (4.10) and qualification<br>
+ // conversions (4.4) are performed on pointer operands (or on<br>
+ // a pointer operand and a null pointer constant) to bring<br>
+ // them to their composite pointer type. [...]<br>
+ //<br>
+ // C++ [expr.eq]p1 uses the same notion for (in)equality<br>
+ // comparisons of pointers.<br>
+<br>
+ // C++ [expr.eq]p2:<br>
+ // In addition, pointers to members can be compared, or a pointer to<br>
+ // member and a null pointer constant. Pointer to member conversions<br>
+ // (4.11) and qualification conversions (4.4) are performed to bring<br>
+ // them to a common type. If one operand is a null pointer constant,<br>
+ // the common type is the type of the other operand. Otherwise, the<br>
+ // common type is a pointer to member type similar (4.4) to the type<br>
+ // of one of the operands, with a cv-qualification signature (4.4)<br>
+ // that is the union of the cv-qualification signatures of the operand<br>
+ // types.<br>
+<br>
+ QualType lType = lex.get()->getType();<br>
+ QualType rType = rex.get()->getType();<br>
+ assert((lType->isPointerType() && rType->isPointerType()) ||<br>
+ (lType->isMemberPointerType() && rType->isMemberPointerType()));<br>
+<br>
+ bool NonStandardCompositeType = false;<br>
+ QualType T = S.FindCompositePointerType(Loc, lex, rex,<br>
+ S.isSFINAEContext() ? 0 : &NonStandardCompositeType);<br>
+ if (T.isNull()) {<br>
+ diagnoseDistinctPointerComparison(S, Loc, lex, rex, /*isError*/true);<br>
+ return true;<br>
+ }<br>
+<br>
+ if (NonStandardCompositeType)<br>
+ S.Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)<br>
+ << lType << rType << T << lex.get()->getSourceRange()<br>
+ << rex.get()->getSourceRange();<br>
+<br>
+ lex = S.ImpCastExprToType(lex.take(), T, CK_BitCast);<br>
+ rex = S.ImpCastExprToType(rex.take(), T, CK_BitCast);<br>
+ return false;<br>
+}<br>
+<br>
+static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc,<br>
+ ExprResult &lex,<br>
+ ExprResult &rex,<br>
+ bool isError) {<br>
+ S.Diag(Loc,isError ? diag::err_typecheck_comparison_of_fptr_to_void<br>
+ : diag::ext_typecheck_comparison_of_fptr_to_void)<br>
+ << lex.get()->getType() << rex.get()->getType()<br>
+ << lex.get()->getSourceRange() << rex.get()->getSourceRange();<br>
+}<br>
+<br>
// C99 6.5.8, C++ [expr.rel]<br>
QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex,<br>
SourceLocation Loc, unsigned OpaqueOpc,<br>
@@ -6348,12 +6416,8 @@<br>
// conformance with the C++ standard.<br>
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())<br>
&& !LHSIsNull && !RHSIsNull) {<br>
- Diag(Loc,<br>
- isSFINAEContext()?<br>
- diag::err_typecheck_comparison_of_fptr_to_void<br>
- : diag::ext_typecheck_comparison_of_fptr_to_void)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ diagnoseFunctionPointerToVoidComparison(<br>
+ *this, Loc, lex, rex, /*isError*/ isSFINAEContext());<br>
<br>
if (isSFINAEContext())<br>
return QualType();<br>
@@ -6363,32 +6427,10 @@<br>
}<br>
}<br>
<br>
- // C++ [expr.rel]p2:<br>
- // [...] Pointer conversions (4.10) and qualification<br>
- // conversions (4.4) are performed on pointer operands (or on<br>
- // a pointer operand and a null pointer constant) to bring<br>
- // them to their composite pointer type. [...]<br>
- //<br>
- // C++ [expr.eq]p1 uses the same notion for (in)equality<br>
- // comparisons of pointers.<br>
- bool NonStandardCompositeType = false;<br>
- QualType T = FindCompositePointerType(Loc, lex, rex,<br>
- isSFINAEContext()? 0 : &NonStandardCompositeType);<br>
- if (T.isNull()) {<br>
- Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ if (convertPointersToCompositeType(*this, Loc, lex, rex))<br>
return QualType();<br>
- } else if (NonStandardCompositeType) {<br>
- Diag(Loc,<br>
- diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)<br>
- << lType << rType << T<br>
- << lex.get()->getSourceRange() << rex.get()->getSourceRange();<br>
- }<br>
-<br>
- lex = ImpCastExprToType(lex.take(), T, CK_BitCast);<br>
- rex = ImpCastExprToType(rex.take(), T, CK_BitCast);<br>
- return ResultTy;<br>
+ else<br>
+ return ResultTy;<br>
}<br>
// C99 6.5.9p2 and C99 6.5.8p2<br>
if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),<br>
@@ -6403,16 +6445,12 @@<br>
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {<br>
// Valid unless comparison between non-null pointer and function pointer<br>
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())<br>
- && !LHSIsNull && !RHSIsNull) {<br>
- Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
- }<br>
+ && !LHSIsNull && !RHSIsNull)<br>
+ diagnoseFunctionPointerToVoidComparison(*this, Loc, lex, rex,<br>
+ /*isError*/false);<br>
} else {<br>
// Invalid<br>
- Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ diagnoseDistinctPointerComparison(*this, Loc, lex, rex, /*isError*/false);<br>
}<br>
if (LCanPointeeTy != RCanPointeeTy) {<br>
if (LHSIsNull && !RHSIsNull)<br>
@@ -6454,34 +6492,10 @@<br>
// Comparison of member pointers.<br>
if (!isRelational &&<br>
lType->isMemberPointerType() && rType->isMemberPointerType()) {<br>
- // C++ [expr.eq]p2:<br>
- // In addition, pointers to members can be compared, or a pointer to<br>
- // member and a null pointer constant. Pointer to member conversions<br>
- // (4.11) and qualification conversions (4.4) are performed to bring<br>
- // them to a common type. If one operand is a null pointer constant,<br>
- // the common type is the type of the other operand. Otherwise, the<br>
- // common type is a pointer to member type similar (4.4) to the type<br>
- // of one of the operands, with a cv-qualification signature (4.4)<br>
- // that is the union of the cv-qualification signatures of the operand<br>
- // types.<br>
- bool NonStandardCompositeType = false;<br>
- QualType T = FindCompositePointerType(Loc, lex, rex,<br>
- isSFINAEContext()? 0 : &NonStandardCompositeType);<br>
- if (T.isNull()) {<br>
- Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ if (convertPointersToCompositeType(*this, Loc, lex, rex))<br>
return QualType();<br>
- } else if (NonStandardCompositeType) {<br>
- Diag(Loc,<br>
- diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)<br>
- << lType << rType << T<br>
- << lex.get()->getSourceRange() << rex.get()->getSourceRange();<br>
- }<br>
-<br>
- lex = ImpCastExprToType(lex.take(), T, CK_BitCast);<br>
- rex = ImpCastExprToType(rex.take(), T, CK_BitCast);<br>
- return ResultTy;<br>
+ else<br>
+ return ResultTy;<br>
}<br>
<br>
// Handle scoped enumeration types specifically, since they don't promote<br>
@@ -6537,9 +6551,8 @@<br>
<br>
if (!LPtrToVoid && !RPtrToVoid &&<br>
!Context.typesAreCompatible(lType, rType)) {<br>
- Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ diagnoseDistinctPointerComparison(*this, Loc, lex, rex,<br>
+ /*isError*/false);<br>
}<br>
if (LHSIsNull && !RHSIsNull)<br>
lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);<br>
@@ -6549,9 +6562,8 @@<br>
}<br>
if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {<br>
if (!Context.areComparableObjCPointerTypes(lType, rType))<br>
- Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)<br>
- << lType << rType << lex.get()->getSourceRange()<br>
- << rex.get()->getSourceRange();<br>
+ diagnoseDistinctPointerComparison(*this, Loc, lex, rex,<br>
+ /*isError*/false);<br>
if (LHSIsNull && !RHSIsNull)<br>
lex = ImpCastExprToType(lex.take(), rType, CK_BitCast);<br>
else<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>