diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11587,7 +11587,16 @@ if (E->isTypeDependent() || E->isValueDependent()) return; - if (const auto *UO = dyn_cast(E)) + Expr *SourceExpr = E; + // Examine, but don't traverse into the source expression of an + // OpaqueValueExpr, since it may have multiple parents and we don't want to + // emit duplicate diagnostics. Its fine to examine the form or attempt to + // evaluate it in the context of checking the specific conversion to T though. + if (auto *OVE = dyn_cast(E)) + if (auto *Src = OVE->getSourceExpr()) + SourceExpr = Src; + + if (const auto *UO = dyn_cast(SourceExpr)) if (UO->getOpcode() == UO_Not && UO->getSubExpr()->isKnownToHaveBooleanValue()) S.Diag(UO->getBeginLoc(), diag::warn_bitwise_negation_bool) @@ -11596,21 +11605,20 @@ // For conditional operators, we analyze the arguments as if they // were being fed directly into the output. - if (isa(E)) { - ConditionalOperator *CO = cast(E); + if (auto *CO = dyn_cast(SourceExpr)) { CheckConditionalOperator(S, CO, CC, T); return; } // Check implicit argument conversions for function calls. - if (CallExpr *Call = dyn_cast(E)) + if (CallExpr *Call = dyn_cast(SourceExpr)) CheckImplicitArgumentConversions(S, Call, CC); // Go ahead and check any implicit conversions we might have skipped. // The non-canonical typecheck is just an optimization; // CheckImplicitConversion will filter out dead implicit conversions. - if (E->getType() != T) - CheckImplicitConversion(S, E, T, CC, nullptr, IsListInit); + if (SourceExpr->getType() != T) + CheckImplicitConversion(S, SourceExpr, T, CC, nullptr, IsListInit); // Now continue drilling into this expression. diff --git a/clang/test/SemaObjC/signed-char-bool-conversion.m b/clang/test/SemaObjC/signed-char-bool-conversion.m --- a/clang/test/SemaObjC/signed-char-bool-conversion.m +++ b/clang/test/SemaObjC/signed-char-bool-conversion.m @@ -69,6 +69,11 @@ b = local.nested->unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}} } +void t4(BoolProp *bp) { + BOOL local = YES; + bp.p = 1 ? local : NO; // no warning +} + __attribute__((objc_root_class)) @interface BFIvar { struct has_bf bf;