Commit e392dcd5 authored by Erik Pilkington's avatar Erik Pilkington
Browse files

[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
parent 603acd96
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -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.
+5 −0
Original line number Diff line number Diff line
@@ -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;