This revision was automatically updated to reflect the committed changes. Closed by commit rGe392dcd5708b: [Sema] Look through OpaqueValueExpr when checking implicit conversions (authored by erik.pilkington). Herald added a project: clang.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75387/new/ https://reviews.llvm.org/D75387 Files: clang/lib/Sema/SemaChecking.cpp clang/test/SemaObjC/signed-char-bool-conversion.m Index: clang/test/SemaObjC/signed-char-bool-conversion.m =================================================================== --- clang/test/SemaObjC/signed-char-bool-conversion.m +++ 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; Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -11587,7 +11587,16 @@ 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 @@ // 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.
Index: clang/test/SemaObjC/signed-char-bool-conversion.m =================================================================== --- clang/test/SemaObjC/signed-char-bool-conversion.m +++ 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; Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -11587,7 +11587,16 @@ 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 @@ // 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits