[clang] e392dcd - [Sema] Look through OpaqueValueExpr when checking implicit conversions

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 2 11:25:06 PST 2020


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;


        


More information about the cfe-commits mailing list