Author: Erik Pilkington Date: 2020-03-02T11:24:36-08:00 New Revision: e392dcd5708b3bb188ff4043b09ae151472a7632
URL: https://github.com/llvm/llvm-project/commit/e392dcd5708b3bb188ff4043b09ae151472a7632 DIFF: https://github.com/llvm/llvm-project/commit/e392dcd5708b3bb188ff4043b09ae151472a7632.diff LOG: [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 Added: Modified: clang/lib/Sema/SemaChecking.cpp clang/test/SemaObjC/signed-char-bool-conversion.m Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2a66303d6d9a..cda6910364e5 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<UnaryOperator>(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<OpaqueValueExpr>(E)) + if (auto *Src = OVE->getSourceExpr()) + SourceExpr = Src; + + if (const auto *UO = dyn_cast<UnaryOperator>(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<ConditionalOperator>(E)) { - ConditionalOperator *CO = cast<ConditionalOperator>(E); + if (auto *CO = dyn_cast<ConditionalOperator>(SourceExpr)) { CheckConditionalOperator(S, CO, CC, T); return; } // Check implicit argument conversions for function calls. - if (CallExpr *Call = dyn_cast<CallExpr>(E)) + if (CallExpr *Call = dyn_cast<CallExpr>(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 6945d86fc26d..183f60fafcd5 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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits