@@ -386,7 +386,47 @@ class DeferStmt : public Stmt {
386386 static bool classof (const Stmt *S) { return S->getKind () == StmtKind::Defer; }
387387};
388388
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+
390430// / An expression that guards execution based on whether the run-time
391431// / configuration supports a given API, e.g.,
392432// / #available(OSX >= 10.9, iOS >= 7.0).
@@ -505,46 +545,39 @@ class PoundHasSymbolInfo final : public ASTAllocated<PoundHasSymbolInfo> {
505545 }
506546};
507547
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`.
512551// /
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+ // / { ... }
518560// /
519561class 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 *>
534565 Condition;
535566
536567public:
537- StmtConditionElement () {}
538- StmtConditionElement (SourceLoc IntroducerLoc, Pattern *ThePattern, Expr *Init)
539- : IntroducerLoc (IntroducerLoc), ThePattern (ThePattern), Condition (Init) {}
568+ StmtConditionElement () : Condition (nullptr ) {}
540569 StmtConditionElement (Expr *cond) : Condition (cond) {}
541-
570+ StmtConditionElement (ConditionalPatternBindingInfo *Info) : Condition (Info) {}
542571 StmtConditionElement (PoundAvailableInfo *Info) : Condition (Info) {}
543-
544572 StmtConditionElement (PoundHasSymbolInfo *Info) : Condition (Info) {}
545573
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 (); }
548581
549582 // / ConditionKind - This indicates the sort of condition this is.
550583 enum ConditionKind {
@@ -555,20 +588,19 @@ class alignas(1 << PatternAlignInBits) StmtConditionElement {
555588 };
556589
557590 ConditionKind getKind () const {
558- if (ThePattern)
559- return CK_PatternBinding;
560591 if (Condition.is <Expr *>())
561592 return CK_Boolean;
593+ if (Condition.is <ConditionalPatternBindingInfo *>())
594+ return CK_PatternBinding;
562595 if (Condition.is <PoundAvailableInfo *>())
563596 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;
566600 }
567601
568602 // / 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 *>(); }
572604
573605 Expr *getBoolean () const {
574606 assert (getKind () == CK_Boolean && " Not a condition" );
@@ -580,35 +612,43 @@ class alignas(1 << PatternAlignInBits) StmtConditionElement {
580612 }
581613
582614 // / Pattern Binding Accessors.
583- Pattern * getPatternOrNull () const {
584- return ThePattern ;
615+ ConditionalPatternBindingInfo * getPatternBindingOrNull () const {
616+ return Condition. dyn_cast <ConditionalPatternBindingInfo *>() ;
585617 }
586618
587- Pattern * getPattern () const {
619+ ConditionalPatternBindingInfo * getPatternBinding () const {
588620 assert (getKind () == CK_PatternBinding && " Not a pattern binding condition" );
589- return ThePattern ;
621+ return Condition. get <ConditionalPatternBindingInfo *>() ;
590622 }
591623
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 ();
595626 }
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);
600630 }
601631
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 ;
605636 }
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 ;
610646 }
611-
647+
648+ Expr *getInitializer () const { return getPatternBinding ()->getInitializer (); }
649+
650+ void setInitializer (Expr *E) { getPatternBinding ()->setInitializer (E); }
651+
612652 // Availability Accessors
613653 PoundAvailableInfo *getAvailability () const {
614654 assert (getKind () == CK_Availability && " Not an #available condition" );
0 commit comments