Skip to content

Commit

Permalink
Merge pull request #878 from apple/57372317-cherry-pick
Browse files Browse the repository at this point in the history
[Sema] Look through OpaqueValueExpr when checking implicit conversions
  • Loading branch information
epilk committed Mar 6, 2020
2 parents e6ce0dd + 89b1a46 commit 8b0c9cc
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
20 changes: 14 additions & 6 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -12376,7 +12376,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)
Expand All @@ -12385,21 +12394,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.

Expand Down
5 changes: 5 additions & 0 deletions clang/test/SemaObjC/signed-char-bool-conversion.m
Expand Up @@ -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;
Expand Down

0 comments on commit 8b0c9cc

Please sign in to comment.