diff options
author | Renato Golin <renato.golin@linaro.org> | 2016-10-21 08:03:49 +0000 |
---|---|---|
committer | Renato Golin <renato.golin@linaro.org> | 2016-10-21 08:03:49 +0000 |
commit | 41189656ed5ef78c8ad507444b39e2dd2c013762 (patch) | |
tree | d5b700c22884a4fef18e679e1f933ed652b8fe6a /clang/lib/Sema/SemaExpr.cpp | |
parent | 032fa65606e26b2e5ccf43e0ff91cf0c2abf370f (diff) | |
download | bcm5719-llvm-41189656ed5ef78c8ad507444b39e2dd2c013762.tar.gz bcm5719-llvm-41189656ed5ef78c8ad507444b39e2dd2c013762.zip |
Revert "DR583, DR1512: Implement a rewrite to C++'s 'composite pointer type' rules."
This reverts commit r284800, as it failed all ARM/AArch64 bots.
llvm-svn: 284811
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 193 |
1 files changed, 82 insertions, 111 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index eddc4207dfc..15564918b37 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8929,21 +8929,35 @@ static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc, // C++ [expr.eq]p1 uses the same notion for (in)equality // comparisons of pointers. + // C++ [expr.eq]p2: + // In addition, pointers to members can be compared, or a pointer to + // member and a null pointer constant. Pointer to member conversions + // (4.11) and qualification conversions (4.4) are performed to bring + // them to a common type. If one operand is a null pointer constant, + // the common type is the type of the other operand. Otherwise, the + // common type is a pointer to member 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 LHSType = LHS.get()->getType(); QualType RHSType = RHS.get()->getType(); - assert(LHSType->isPointerType() || RHSType->isPointerType() || - LHSType->isMemberPointerType() || RHSType->isMemberPointerType()); + assert((LHSType->isPointerType() && RHSType->isPointerType()) || + (LHSType->isMemberPointerType() && RHSType->isMemberPointerType())); - QualType T = S.FindCompositePointerType(Loc, LHS, RHS); + bool NonStandardCompositeType = false; + bool *BoolPtr = S.isSFINAEContext() ? nullptr : &NonStandardCompositeType; + QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr); if (T.isNull()) { - if ((LHSType->isPointerType() || LHSType->isMemberPointerType()) && - (RHSType->isPointerType() || RHSType->isMemberPointerType())) - diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true); - else - S.InvalidOperands(Loc, LHS, RHS); + diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true); return true; } + if (NonStandardCompositeType) + S.Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) + << LHSType << RHSType << T << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + LHS = S.ImpCastExprToType(LHS.get(), T, CK_BitCast); RHS = S.ImpCastExprToType(RHS.get(), T, CK_BitCast); return false; @@ -9300,53 +9314,41 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, LHS.get()->getSourceRange()); } - if ((LHSType->isIntegerType() && !LHSIsNull) || - (RHSType->isIntegerType() && !RHSIsNull)) { - // Skip normal pointer conversion checks in this case; we have better - // diagnostics for this below. - } else if (getLangOpts().CPlusPlus) { - // Equality comparison of a function pointer to a void pointer is invalid, - // but we allow it as an extension. - // FIXME: If we really want to allow this, should it be part of composite - // pointer type computation so it works in conditionals too? - if (!IsRelational && - ((LHSType->isFunctionPointerType() && RHSType->isVoidPointerType()) || - (RHSType->isFunctionPointerType() && LHSType->isVoidPointerType()))) { - // This is a gcc extension compatibility comparison. - // In a SFINAE context, we treat this as a hard error to maintain - // conformance with the C++ standard. - diagnoseFunctionPointerToVoidComparison( - *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext()); - - if (isSFINAEContext()) - return QualType(); - - RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); - return ResultTy; - } + // All of the following pointer-related warnings are GCC extensions, except + // when handling null pointer constants. + if (LHSType->isPointerType() && RHSType->isPointerType()) { // C99 6.5.8p2 + QualType LCanPointeeTy = + LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType(); + QualType RCanPointeeTy = + RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType(); + + if (getLangOpts().CPlusPlus) { + if (LCanPointeeTy == RCanPointeeTy) + return ResultTy; + if (!IsRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + // This is a gcc extension compatibility comparison. + // In a SFINAE context, we treat this as a hard error to maintain + // conformance with the C++ standard. + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + diagnoseFunctionPointerToVoidComparison( + *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext()); + + if (isSFINAEContext()) + return QualType(); + + RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); + return ResultTy; + } + } - // C++ [expr.eq]p2: - // If at least one operand is a pointer [...] bring them to their - // composite pointer type. - // C++ [expr.rel]p2: - // If both operands are pointers, [...] bring them to their composite - // pointer type. - if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >= - (IsRelational ? 2 : 1)) { if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) return QualType(); else return ResultTy; } - } else if (LHSType->isPointerType() && - RHSType->isPointerType()) { // C99 6.5.8p2 - // All of the following pointer-related warnings are GCC extensions, except - // when handling null pointer constants. - QualType LCanPointeeTy = - LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType(); - QualType RCanPointeeTy = - RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType(); - // C99 6.5.9p2 and C99 6.5.8p2 if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), RCanPointeeTy.getUnqualifiedType())) { @@ -9391,63 +9393,36 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, } if (getLangOpts().CPlusPlus) { - // C++ [expr.eq]p4: - // Two operands of type std::nullptr_t or one operand of type - // std::nullptr_t and the other a null pointer constant compare equal. - if (!IsRelational && LHSIsNull && RHSIsNull) { - if (LHSType->isNullPtrType()) { - RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - return ResultTy; - } - if (RHSType->isNullPtrType()) { - LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; - } - } - - // Comparison of Objective-C pointers and block pointers against nullptr_t. - // These aren't covered by the composite pointer type rules. - if (!IsRelational && RHSType->isNullPtrType() && - (LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) { - RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); + // Comparison of nullptr_t with itself. + if (LHSType->isNullPtrType() && RHSType->isNullPtrType()) return ResultTy; - } - if (!IsRelational && LHSType->isNullPtrType() && - (RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) { - LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); + + // Comparison of pointers with null pointer constants and equality + // comparisons of member pointers to null pointer constants. + if (RHSIsNull && + ((LHSType->isAnyPointerType() || LHSType->isNullPtrType()) || + (!IsRelational && + (LHSType->isMemberPointerType() || LHSType->isBlockPointerType())))) { + RHS = ImpCastExprToType(RHS.get(), LHSType, + LHSType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); return ResultTy; } - - if (IsRelational && - ((LHSType->isNullPtrType() && RHSType->isPointerType()) || - (RHSType->isNullPtrType() && LHSType->isPointerType()))) { - // HACK: Relational comparison of nullptr_t against a pointer type is - // invalid per DR583, but we allow it within std::less<> and friends, - // since otherwise common uses of it break. - // FIXME: Consider removing this hack once LWG fixes std::less<> and - // friends to have std::nullptr_t overload candidates. - DeclContext *DC = CurContext; - if (isa<FunctionDecl>(DC)) - DC = DC->getParent(); - if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { - if (CTSD->isInStdNamespace() && - llvm::StringSwitch<bool>(CTSD->getName()) - .Cases("less", "less_equal", "greater", "greater_equal", true) - .Default(false)) { - if (RHSType->isNullPtrType()) - RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer); - else - LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer); - return ResultTy; - } - } + if (LHSIsNull && + ((RHSType->isAnyPointerType() || RHSType->isNullPtrType()) || + (!IsRelational && + (RHSType->isMemberPointerType() || RHSType->isBlockPointerType())))) { + LHS = ImpCastExprToType(LHS.get(), RHSType, + RHSType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); + return ResultTy; } - // C++ [expr.eq]p2: - // If at least one operand is a pointer to member, [...] bring them to - // their composite pointer type. + // Comparison of member pointers. if (!IsRelational && - (LHSType->isMemberPointerType() || RHSType->isMemberPointerType())) { + LHSType->isMemberPointerType() && RHSType->isMemberPointerType()) { if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) return QualType(); else @@ -9556,19 +9531,15 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, // Under a debugger, allow the comparison of pointers to integers, // since users tend to want to compare addresses. } else if ((LHSIsNull && LHSType->isIntegerType()) || - (RHSIsNull && RHSType->isIntegerType())) { - if (IsRelational) { - isError = getLangOpts().CPlusPlus; - DiagID = - isError ? diag::err_typecheck_ordered_comparison_of_pointer_and_zero - : diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; - } - } else if (getLangOpts().CPlusPlus) { + (RHSIsNull && RHSType->isIntegerType())) { + if (IsRelational && !getLangOpts().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; + } else if (IsRelational && !getLangOpts().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + else if (getLangOpts().CPlusPlus) { DiagID = diag::err_typecheck_comparison_of_pointer_integer; isError = true; - } else if (IsRelational) - DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; - else + } else DiagID = diag::ext_typecheck_comparison_of_pointer_integer; if (DiagID) { |