================
@@ -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);
----------------
ojhunt wrote:

I don't understand why we're still traversing both paths? e.g. why is this not:

```cpp
if (!TrueIsKnownUnreachable)
  CheckConditionalOperand(S, TrueExpr, T, CC, Suspicious);
if (!FalseIsKnownUnreachable)
  CheckConditionalOperand(S, FalseExpr, T, CC, Suspicious);
```


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