@@ -437,6 +437,154 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
437
437
}
438
438
}
439
439
440
+ /**
441
+ * A C/C++ '(not) consteval if'. For example, the `if consteval` statement
442
+ * in the following code:
443
+ * ```cpp
444
+ * if consteval {
445
+ * ...
446
+ * }
447
+ * ```
448
+ */
449
+ class ConstevalIfStmt extends Stmt , @stmt_consteval_or_not_consteval_if {
450
+ override string getAPrimaryQlClass ( ) { result = "ConstevalIfStmt" }
451
+
452
+ override string toString ( ) {
453
+ if this .isNot ( ) then result = "if ! consteval ..." else result = "if consteval ..."
454
+ }
455
+
456
+ /**
457
+ * Holds if this is a 'not consteval if' statement.
458
+ *
459
+ * For example, this holds for
460
+ * ```cpp
461
+ * if ! consteval { return true; }
462
+ * ```
463
+ * but not for
464
+ * ```cpp
465
+ * if consteval { return true; }
466
+ * ```
467
+ */
468
+ predicate isNot ( ) { this instanceof @stmt_not_consteval_if }
469
+
470
+ /**
471
+ * Gets the 'then' statement of this '(not) consteval if' statement.
472
+ *
473
+ * For example, for
474
+ * ```cpp
475
+ * if consteval { return true; }
476
+ * ```
477
+ * the result is the `BlockStmt` `{ return true; }`.
478
+ */
479
+ Stmt getThen ( ) { consteval_if_then ( underlyingElement ( this ) , unresolveElement ( result ) ) }
480
+
481
+ /**
482
+ * Gets the 'else' statement of this '(not) constexpr if' statement, if any.
483
+ *
484
+ * For example, for
485
+ * ```cpp
486
+ * if consteval { return true; } else { return false; }
487
+ * ```
488
+ * the result is the `BlockStmt` `{ return false; }`, and for
489
+ * ```cpp
490
+ * if consteval { return true; }
491
+ * ```
492
+ * there is no result.
493
+ */
494
+ Stmt getElse ( ) { consteval_if_else ( underlyingElement ( this ) , unresolveElement ( result ) ) }
495
+
496
+ /**
497
+ * Holds if this '(not) constexpr if' statement has an 'else' statement.
498
+ *
499
+ * For example, this holds for
500
+ * ```cpp
501
+ * if consteval { return true; } else { return false; }
502
+ * ```
503
+ * but not for
504
+ * ```cpp
505
+ * if consteval { return true; }
506
+ * ```
507
+ */
508
+ predicate hasElse ( ) { exists ( this .getElse ( ) ) }
509
+
510
+ override predicate mayBeImpure ( ) {
511
+ this .getThen ( ) .mayBeImpure ( ) or
512
+ this .getElse ( ) .mayBeImpure ( )
513
+ }
514
+
515
+ override predicate mayBeGloballyImpure ( ) {
516
+ this .getThen ( ) .mayBeGloballyImpure ( ) or
517
+ this .getElse ( ) .mayBeGloballyImpure ( )
518
+ }
519
+
520
+ override MacroInvocation getGeneratingMacro ( ) {
521
+ this .getThen ( ) .getGeneratingMacro ( ) = result and
522
+ ( this .hasElse ( ) implies this .getElse ( ) .getGeneratingMacro ( ) = result )
523
+ }
524
+
525
+ /**
526
+ * Gets the statement of this '(not) consteval if' statement evaluated during compile time, if any.
527
+ *
528
+ * For example, for
529
+ * ```cpp
530
+ * if ! consteval { return true; } else { return false; }
531
+ * ```
532
+ * the result is the `BlockStmt` `{ return false; }`, and for
533
+ * ```cpp
534
+ * if ! consteval { return true; }
535
+ * ```
536
+ * there is no result.
537
+ */
538
+ Stmt getCompileTimeEvaluatedBranch ( ) {
539
+ if this .isNot ( ) then result = this .getElse ( ) else result = this .getThen ( )
540
+ }
541
+
542
+ /**
543
+ * Holds if this '(not) constexpr if' statement has a compile time evaluated statement.
544
+ *
545
+ * For example, this holds for
546
+ * ```cpp
547
+ * if ! consteval { return true; } else { return false; }
548
+ * ```
549
+ * but not for
550
+ * ```cpp
551
+ * if ! consteval { return true; }
552
+ * ```
553
+ */
554
+ predicate hasCompileTimeEvaluatedBranch ( ) { exists ( this .getCompileTimeEvaluatedBranch ( ) ) }
555
+
556
+ /**
557
+ * Gets the statement of this '(not) consteval if' statement evaluated during runtime, if any.
558
+ *
559
+ * For example, for
560
+ * ```cpp
561
+ * if consteval { return true; } else { return false; }
562
+ * ```
563
+ * the result is the `BlockStmt` `{ return false; }`, and for
564
+ * ```cpp
565
+ * if consteval { return true; }
566
+ * ```
567
+ * there is no result.
568
+ */
569
+ Stmt getRuntimeEvaluatedBranch ( ) {
570
+ if this .isNot ( ) then result = this .getThen ( ) else result = this .getElse ( )
571
+ }
572
+
573
+ /**
574
+ * Holds if this '(not) constexpr if' statement has a runtime evaluated statement.
575
+ *
576
+ * For example, this holds for
577
+ * ```cpp
578
+ * if consteval { return true; } else { return false; }
579
+ * ```
580
+ * but not for
581
+ * ```cpp
582
+ * if consteval { return true; }
583
+ * ```
584
+ */
585
+ predicate hasRuntimeEvaluatedBranch ( ) { exists ( this .getRuntimeEvaluatedBranch ( ) ) }
586
+ }
587
+
440
588
private class TLoop = @stmt_while or @stmt_end_test_while or @stmt_range_based_for or @stmt_for;
441
589
442
590
/**
0 commit comments