@@ -386,7 +386,47 @@ class DeferStmt : public Stmt {
386
386
static bool classof (const Stmt *S) { return S->getKind () == StmtKind::Defer; }
387
387
};
388
388
389
-
389
+ // / Represent `let`/`var` optional binding, or `case` pattern matching in
390
+ // / conditional statements (i.e. `if`, `guard`, `while`).
391
+ class alignas (8 ) ConditionalPatternBindingInfo
392
+ : public ASTAllocated<ConditionalPatternBindingInfo> {
393
+ public:
394
+ // / Location of the var/let/case keyword.
395
+ SourceLoc IntroducerLoc;
396
+
397
+ // / Pattern being matched. In the case of an "implicit optional" pattern, the
398
+ // / OptionalSome pattern is explicitly added to this as an 'implicit' pattern.
399
+ Pattern *ThePattern;
400
+
401
+ // / The value for matching.
402
+ Expr *Initializer;
403
+
404
+ ConditionalPatternBindingInfo (SourceLoc IntroducerLoc, Pattern *ThePattern,
405
+ Expr *Initializer)
406
+ : IntroducerLoc (IntroducerLoc), ThePattern (ThePattern),
407
+ Initializer (Initializer) {}
408
+
409
+ public:
410
+ static ConditionalPatternBindingInfo *create (ASTContext &ctx,
411
+ SourceLoc IntroducerLoc,
412
+ Pattern *ThePattern,
413
+ Expr *Initializer) {
414
+ return new (ctx)
415
+ ConditionalPatternBindingInfo (IntroducerLoc, ThePattern, Initializer);
416
+ }
417
+
418
+ SourceLoc getIntroducerLoc () const { return IntroducerLoc; }
419
+ void setIntroducerLoc (SourceLoc Loc) { IntroducerLoc = Loc; }
420
+ Pattern *getPattern () const { return ThePattern; }
421
+ void setPattern (Pattern *P) { ThePattern = P; }
422
+ Expr *getInitializer () const { return Initializer; }
423
+ void setInitializer (Expr *E) { Initializer = E; }
424
+
425
+ SourceRange getSourceRange () const ;
426
+ SourceLoc getStartLoc () const { return getSourceRange ().Start ; };
427
+ SourceLoc getEndLoc () const { return getSourceRange ().End ; };
428
+ };
429
+
390
430
// / An expression that guards execution based on whether the run-time
391
431
// / configuration supports a given API, e.g.,
392
432
// / #available(OSX >= 10.9, iOS >= 7.0).
@@ -505,46 +545,39 @@ class PoundHasSymbolInfo final : public ASTAllocated<PoundHasSymbolInfo> {
505
545
}
506
546
};
507
547
508
- // / This represents an entry in an "if" or "while" condition. Pattern bindings
509
- // / can bind any number of names in the pattern binding decl, and may have an
510
- // / associated where clause. When "if let" is involved, an arbitrary number of
511
- // / pattern bindings and conditional expressions are permitted, e.g.:
548
+ // / This represents an entry in an "if" or "while" condition.
549
+ // / Either a boolean expression, optional binding, pattern matching,
550
+ // / `#available`, or `#_hasSymbol`.
512
551
// /
513
- // / if let x = ..., y = ... where x > y,
514
- // / let z = ...
515
- // / which would be represented as four StmtConditionElement entries, one for
516
- // / the "x" binding, one for the "y" binding, one for the where clause, one for
517
- // / "z"'s binding. A simple "if" statement is represented as a single binding.
552
+ // / E.g. this 'if' statement has 5 'StmtConditionElement'.
553
+ // / if
554
+ // / list.count == 1, // CK_Boolean
555
+ // / let firstElem = list.first, // CK_PatternBinding
556
+ // / case .foo(let value?, "int") = firstElem, // CK_PatternBinding
557
+ // / #available(myOS 13), // CK_Availability
558
+ // / #_hasSymbol(MyStruct.peform(operation:)) // CK_HasSymbol
559
+ // / { ... }
518
560
// /
519
561
class alignas (1 << PatternAlignInBits) StmtConditionElement {
520
- // / If this is a pattern binding, it may be the first one in a declaration, in
521
- // / which case this is the location of the var/let/case keyword. If this is
522
- // / the second pattern (e.g. for 'y' in "var x = ..., y = ...") then this
523
- // / location is invalid.
524
- SourceLoc IntroducerLoc;
525
-
526
- // / In a pattern binding, this is pattern being matched. In the case of an
527
- // / "implicit optional" pattern, the OptionalSome pattern is explicitly added
528
- // / to this as an 'implicit' pattern.
529
- Pattern *ThePattern = nullptr ;
530
-
531
- // / This is either the boolean condition, the #available information, or
532
- // / the #_hasSymbol information.
533
- llvm::PointerUnion<Expr *, PoundAvailableInfo *, PoundHasSymbolInfo *>
562
+ private:
563
+ llvm::PointerUnion<Expr *, ConditionalPatternBindingInfo *,
564
+ PoundAvailableInfo *, PoundHasSymbolInfo *>
534
565
Condition;
535
566
536
567
public:
537
- StmtConditionElement () {}
538
- StmtConditionElement (SourceLoc IntroducerLoc, Pattern *ThePattern, Expr *Init)
539
- : IntroducerLoc (IntroducerLoc), ThePattern (ThePattern), Condition (Init) {}
568
+ StmtConditionElement () : Condition (nullptr ) {}
540
569
StmtConditionElement (Expr *cond) : Condition (cond) {}
541
-
570
+ StmtConditionElement (ConditionalPatternBindingInfo *Info) : Condition (Info) {}
542
571
StmtConditionElement (PoundAvailableInfo *Info) : Condition (Info) {}
543
-
544
572
StmtConditionElement (PoundHasSymbolInfo *Info) : Condition (Info) {}
545
573
546
- SourceLoc getIntroducerLoc () const { return IntroducerLoc; }
547
- void setIntroducerLoc (SourceLoc loc) { IntroducerLoc = loc; }
574
+ static StmtConditionElement fromOpaqueValue (void *opaque) {
575
+ StmtConditionElement val;
576
+ val.Condition = decltype (Condition)::getFromOpaqueValue (opaque);
577
+ return val;
578
+ }
579
+
580
+ void *getOpaqueValue () const { return Condition.getOpaqueValue (); }
548
581
549
582
// / ConditionKind - This indicates the sort of condition this is.
550
583
enum ConditionKind {
@@ -555,20 +588,19 @@ class alignas(1 << PatternAlignInBits) StmtConditionElement {
555
588
};
556
589
557
590
ConditionKind getKind () const {
558
- if (ThePattern)
559
- return CK_PatternBinding;
560
591
if (Condition.is <Expr *>())
561
592
return CK_Boolean;
593
+ if (Condition.is <ConditionalPatternBindingInfo *>())
594
+ return CK_PatternBinding;
562
595
if (Condition.is <PoundAvailableInfo *>())
563
596
return CK_Availability;
564
- assert (Condition.is <PoundHasSymbolInfo *>());
565
- return CK_HasSymbol;
597
+ if (Condition.is <PoundHasSymbolInfo *>())
598
+ return CK_HasSymbol;
599
+ return CK_Boolean;
566
600
}
567
601
568
602
// / Boolean Condition Accessors.
569
- Expr *getBooleanOrNull () const {
570
- return getKind () == CK_Boolean ? Condition.get <Expr *>() : nullptr ;
571
- }
603
+ Expr *getBooleanOrNull () const { return Condition.dyn_cast <Expr *>(); }
572
604
573
605
Expr *getBoolean () const {
574
606
assert (getKind () == CK_Boolean && " Not a condition" );
@@ -580,35 +612,43 @@ class alignas(1 << PatternAlignInBits) StmtConditionElement {
580
612
}
581
613
582
614
// / Pattern Binding Accessors.
583
- Pattern * getPatternOrNull () const {
584
- return ThePattern ;
615
+ ConditionalPatternBindingInfo * getPatternBindingOrNull () const {
616
+ return Condition. dyn_cast <ConditionalPatternBindingInfo *>() ;
585
617
}
586
618
587
- Pattern * getPattern () const {
619
+ ConditionalPatternBindingInfo * getPatternBinding () const {
588
620
assert (getKind () == CK_PatternBinding && " Not a pattern binding condition" );
589
- return ThePattern ;
621
+ return Condition. get <ConditionalPatternBindingInfo *>() ;
590
622
}
591
623
592
- void setPattern (Pattern *P) {
593
- assert (getKind () == CK_PatternBinding && " Not a pattern binding condition" );
594
- ThePattern = P;
624
+ SourceLoc getIntroducerLoc () const {
625
+ return getPatternBinding ()->getIntroducerLoc ();
595
626
}
596
-
597
- // / Pattern Binding Accessors.
598
- Expr *getInitializerOrNull () const {
599
- return getKind () == CK_PatternBinding ? Condition.get <Expr *>() : nullptr ;
627
+
628
+ void setIntroducerLoc (SourceLoc loc) {
629
+ getPatternBinding ()->setIntroducerLoc (loc);
600
630
}
601
631
602
- Expr *getInitializer () const {
603
- assert (getKind () == CK_PatternBinding && " Not a pattern binding condition" );
604
- return Condition.get <Expr *>();
632
+ Pattern *getPatternOrNull () const {
633
+ if (auto *binding = getPatternBindingOrNull ())
634
+ return binding->getPattern ();
635
+ return nullptr ;
605
636
}
606
-
607
- void setInitializer (Expr *E) {
608
- assert (getKind () == CK_PatternBinding && " Not a pattern binding condition" );
609
- Condition = E;
637
+
638
+ Pattern *getPattern () const { return getPatternBinding ()->getPattern (); }
639
+
640
+ void setPattern (Pattern *P) { getPatternBinding ()->setPattern (P); }
641
+
642
+ Expr *getInitializerOrNull () const {
643
+ if (auto *binding = getPatternBindingOrNull ())
644
+ return binding->getInitializer ();
645
+ return nullptr ;
610
646
}
611
-
647
+
648
+ Expr *getInitializer () const { return getPatternBinding ()->getInitializer (); }
649
+
650
+ void setInitializer (Expr *E) { getPatternBinding ()->setInitializer (E); }
651
+
612
652
// Availability Accessors
613
653
PoundAvailableInfo *getAvailability () const {
614
654
assert (getKind () == CK_Availability && " Not an #available condition" );
0 commit comments