From e392dcd5708b3bb188ff4043b09ae151472a7632 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Mon, 2 Mar 2020 10:27:41 -0800 Subject: [PATCH] [Sema] Look through OpaqueValueExpr when checking implicit conversions Specifically, this fixes a false-positive in -Wobjc-signed-char-bool. rdar://57372317 Differential revision: https://reviews.llvm.org/D75387 --- clang/lib/Sema/SemaChecking.cpp | 20 ++++++++++++++------ clang/test/SemaObjC/signed-char-bool-conversion.m | 5 +++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2a66303..cda6910 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11587,7 +11587,16 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, 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 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, // 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 index 6945d86..183f60f 100644 --- a/clang/test/SemaObjC/signed-char-bool-conversion.m +++ b/clang/test/SemaObjC/signed-char-bool-conversion.m @@ -69,6 +69,11 @@ void t3(struct has_bf *bf) { 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; -- 2.7.4