================
@@ -13997,34 +14015,65 @@ void Sema::CheckImplicitConversion(Expr *E, QualType 
T, SourceLocation CC,
 }
 
 static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
-                                     SourceLocation CC, QualType T);
+                                     SourceLocation CC, QualType T,
+                                     bool IsKnownUnreachable);
 
 static void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
-                                    SourceLocation CC, bool &ICContext) {
+                                    SourceLocation CC, bool &ICContext,
+                                    bool IsKnownUnreachable) {
   E = E->IgnoreParenImpCasts();
   // Diagnose incomplete type for second or third operand in C.
   if (!S.getLangOpts().CPlusPlus && E->getType()->isRecordType())
     S.RequireCompleteExprType(E, diag::err_incomplete_type);
 
   if (auto *CO = dyn_cast<AbstractConditionalOperator>(E))
-    return CheckConditionalOperator(S, CO, CC, T);
+    return CheckConditionalOperator(S, CO, CC, T, IsKnownUnreachable);
 
-  AnalyzeImplicitConversions(S, E, CC);
+  AnalyzeImplicitConversions(S, E, CC, /*IsListInit=*/false,
+                             IsKnownUnreachable);
   if (E->getType() != T)
-    return S.CheckImplicitConversion(E, T, CC, &ICContext);
+    return S.CheckImplicitConversion(E, T, CC, &ICContext,
+                                     /*IsListInit=*/false, IsKnownUnreachable);
 }
 
 static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
-                                     SourceLocation CC, QualType T) {
-  AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc());
+                                     SourceLocation CC, QualType T,
+                                     bool IsKnownUnreachable) {
+  AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc(),
+                             /*IsListInit=*/false, IsKnownUnreachable);
+
+  bool CondValue;
+  bool CondIsKnown = E->getCond()->EvaluateAsBooleanCondition(
+      CondValue, S.Context, S.isConstantEvaluatedContext());
+  if (CondIsKnown && !S.isConstantEvaluatedContext()) {
+    // The condition may also be evaluated at compile time, for example in a
+    // constexpr function. Only prune an operand if both evaluations agree;
+    // __builtin_is_constant_evaluated() can produce different results.
+    bool ConstantCondValue;
+    CondIsKnown =
+        E->getCond()->EvaluateAsBooleanCondition(ConstantCondValue, S.Context,
+                                                 /*InConstantContext=*/true) &&
+        ConstantCondValue == CondValue;
+  }
 
   Expr *TrueExpr = E->getTrueExpr();
-  if (auto *BCO = dyn_cast<BinaryConditionalOperator>(E))
+  bool TrueIsKnownUnreachable =
+      IsKnownUnreachable || (CondIsKnown && !CondValue);
+  bool FalseIsKnownUnreachable =
+      IsKnownUnreachable || (CondIsKnown && CondValue);
+
+  if (auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
+    // The common expression supplies the condition as well as the true value,
+    // so its subexpressions are evaluated even when the condition is false.
     TrueExpr = BCO->getCommon();
+    TrueIsKnownUnreachable = IsKnownUnreachable;
+  }
 
   bool Suspicious = false;
-  CheckConditionalOperand(S, TrueExpr, T, CC, Suspicious);
-  CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
+  CheckConditionalOperand(S, TrueExpr, T, CC, Suspicious,
+                          TrueIsKnownUnreachable);
+  CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious,
+                          FalseIsKnownUnreachable);
----------------
filaka771 wrote:

I think the useful distinction here is what each warning is telling the user. A 
warning about `~b` can still point out a likely mistaken operator in an untaken 
branch. In the reported initializer, though, the selected result fits the 
destination type, and the value Clang complains about never reaches the 
conversion. That’s why I see this particular diagnostic as a false positive.

So I’m not sure that consistent behavior necessarily means applying the same 
reachability rule to every warning. Whether a warning remains useful in an 
untaken branch depends on what it diagnoses. I think that deserves 
consideration for each diagnostic rather than assuming that either all or none 
should be suppressed.

This PR addresses that specific conversion case while preserving the other 
checks. Your proposed option would affect more than this diagnostic, and its 
defaults and treatment of different kinds of branches would need a separate 
discussion. I’d prefer to discuss that broader policy separately and keep this 
PR focused on the reported conversion issue..


https://github.com/llvm/llvm-project/pull/226775
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to