|
26 | 26 | #include "swift/AST/TypeLoc.h"
|
27 | 27 | #include "swift/AST/Availability.h"
|
28 | 28 | #include "llvm/Support/TrailingObjects.h"
|
| 29 | +#include <utility> |
29 | 30 |
|
30 | 31 | namespace llvm {
|
31 | 32 | struct fltSemantics;
|
@@ -409,13 +410,10 @@ class alignas(8) Expr {
|
409 | 410 | friend class KeyPathExpr;
|
410 | 411 | unsigned : NumExprBits;
|
411 | 412 |
|
412 |
| - /// The number of components in the selector path. |
413 |
| - unsigned NumComponents : 8; |
414 |
| - |
415 |
| - /// Whether the names have corresponding source locations. |
416 |
| - unsigned HaveSourceLocations : 1; |
| 413 | + /// Whether this is an ObjC stringified keypath. |
| 414 | + unsigned IsObjC : 1; |
417 | 415 | };
|
418 |
| - enum { NumKeyPathExprBits = NumExprBits + 9 }; |
| 416 | + enum { NumKeyPathExprBits = NumExprBits + 2 }; |
419 | 417 | static_assert(NumKeyPathExprBits <= 32, "fits in an unsigned");
|
420 | 418 |
|
421 | 419 | protected:
|
@@ -4546,96 +4544,203 @@ class KeyPathExpr : public Expr {
|
4546 | 4544 | SourceLoc KeywordLoc;
|
4547 | 4545 | SourceLoc LParenLoc;
|
4548 | 4546 | SourceLoc RParenLoc;
|
4549 |
| - Expr *SemanticExpr = nullptr; |
4550 |
| - |
4551 |
| - /// A single stored component, which will be either an identifier or |
4552 |
| - /// a resolved declaration. |
4553 |
| - typedef llvm::PointerUnion<Identifier, ValueDecl *> StoredComponent; |
4554 |
| - |
4555 |
| - KeyPathExpr(SourceLoc keywordLoc, SourceLoc lParenLoc, |
4556 |
| - ArrayRef<Identifier> names, |
4557 |
| - ArrayRef<SourceLoc> nameLocs, |
4558 |
| - SourceLoc rParenLoc); |
4559 |
| - |
4560 |
| - /// Retrieve a mutable version of the "components" array, for |
4561 |
| - /// initialization purposes. |
4562 |
| - MutableArrayRef<StoredComponent> getComponentsMutable() { |
4563 |
| - return { reinterpret_cast<StoredComponent *>(this + 1), getNumComponents() }; |
4564 |
| - } |
4565 |
| - |
4566 |
| - /// Retrieve the "components" storage. |
4567 |
| - ArrayRef<StoredComponent> getComponents() const { |
4568 |
| - return { reinterpret_cast<StoredComponent const *>(this + 1), |
4569 |
| - getNumComponents() }; |
4570 |
| - } |
| 4547 | + Expr *ObjCStringLiteralExpr = nullptr; |
4571 | 4548 |
|
4572 |
| - /// Retrieve a mutable version of the name locations array, for |
4573 |
| - /// initialization purposes. |
4574 |
| - MutableArrayRef<SourceLoc> getNameLocsMutable() { |
4575 |
| - if (!KeyPathExprBits.HaveSourceLocations) return { }; |
| 4549 | +public: |
| 4550 | + /// A single stored component, which will be one of: |
| 4551 | + /// - an unresolved DeclName, which has to be type-checked |
| 4552 | + /// - a resolved ValueDecl, referring to |
| 4553 | + /// - a subscript index expression, which may or may not be resolved |
| 4554 | + /// - an optional chaining, forcing, or wrapping component |
| 4555 | + class Component { |
| 4556 | + public: |
| 4557 | + enum class Kind: unsigned { |
| 4558 | + UnresolvedProperty, |
| 4559 | + UnresolvedSubscript, |
| 4560 | + Property, |
| 4561 | + Subscript, |
| 4562 | + OptionalForce, |
| 4563 | + OptionalChain, |
| 4564 | + OptionalWrap |
| 4565 | + }; |
| 4566 | + |
| 4567 | + private: |
| 4568 | + union DeclNameOrRef { |
| 4569 | + DeclName UnresolvedName; |
| 4570 | + ConcreteDeclRef ResolvedDecl; |
| 4571 | + |
| 4572 | + DeclNameOrRef() : UnresolvedName{} {} |
| 4573 | + DeclNameOrRef(DeclName un) : UnresolvedName(un) {} |
| 4574 | + DeclNameOrRef(ConcreteDeclRef rd) : ResolvedDecl(rd) {} |
| 4575 | + } Decl; |
| 4576 | + |
| 4577 | + |
| 4578 | + llvm::PointerIntPair<Expr *, 3, Kind> SubscriptIndexExprAndKind; |
| 4579 | + Type ComponentType; |
| 4580 | + |
| 4581 | + explicit Component(DeclNameOrRef decl, |
| 4582 | + Expr *indexExpr, |
| 4583 | + Kind kind, |
| 4584 | + Type type) |
| 4585 | + : Decl(decl), SubscriptIndexExprAndKind(indexExpr, kind), |
| 4586 | + ComponentType(type) |
| 4587 | + {} |
| 4588 | + |
| 4589 | + public: |
| 4590 | + Component() : Component({}, nullptr, (Kind)0, Type()) {} |
| 4591 | + |
| 4592 | + /// Create an unresolved component for a property. |
| 4593 | + static Component forUnresolvedProperty(DeclName UnresolvedName) { |
| 4594 | + return Component(UnresolvedName, nullptr, |
| 4595 | + Kind::UnresolvedProperty, |
| 4596 | + Type()); |
| 4597 | + } |
| 4598 | + |
| 4599 | + /// Create an unresolved component for a subscript. |
| 4600 | + static Component forUnresolvedSubscript(Expr *UnresolvedSubscriptIndex) { |
| 4601 | + return Component({}, UnresolvedSubscriptIndex, |
| 4602 | + Kind::UnresolvedSubscript, |
| 4603 | + Type()); |
| 4604 | + } |
| 4605 | + |
| 4606 | + /// Create an unresolved optional force `!` component. |
| 4607 | + static Component forUnresolvedOptionalForce() { |
| 4608 | + return Component({}, nullptr, |
| 4609 | + Kind::OptionalForce, |
| 4610 | + Type()); |
| 4611 | + } |
| 4612 | + |
| 4613 | + /// Create an unresolved optional chain `?` component. |
| 4614 | + static Component forUnresolvedOptionalChain() { |
| 4615 | + return Component({}, nullptr, |
| 4616 | + Kind::OptionalChain, |
| 4617 | + Type()); |
| 4618 | + } |
| 4619 | + |
| 4620 | + /// Create a component for a property. |
| 4621 | + static Component forProperty(ConcreteDeclRef property, |
| 4622 | + Type propertyType) { |
| 4623 | + return Component(property, nullptr, Kind::Property, |
| 4624 | + propertyType); |
| 4625 | + } |
| 4626 | + |
| 4627 | + /// Create a component for a subscript. |
| 4628 | + static Component forSubscript(ConcreteDeclRef subscript, |
| 4629 | + Expr *indexExpr, |
| 4630 | + Type elementType) { |
| 4631 | + return Component(subscript, indexExpr, Kind::Subscript, elementType); |
| 4632 | + } |
| 4633 | + |
| 4634 | + /// Create an optional-forcing `!` component. |
| 4635 | + static Component forOptionalForce(Type forcedType) { |
| 4636 | + return Component({}, nullptr, Kind::OptionalForce, forcedType); |
| 4637 | + } |
| 4638 | + |
| 4639 | + /// Create an optional-chaining `?` component. |
| 4640 | + static Component forOptionalChain(Type unwrappedType) { |
| 4641 | + return Component({}, nullptr, Kind::OptionalChain, unwrappedType); |
| 4642 | + } |
| 4643 | + |
| 4644 | + /// Create an optional-wrapping component. This doesn't have a surface |
| 4645 | + /// syntax but may appear when the non-optional result of an optional chain |
| 4646 | + /// is implicitly wrapped. |
| 4647 | + static Component forOptionalWrap(Type wrappedType) { |
| 4648 | + return Component({}, nullptr, Kind::OptionalWrap, wrappedType); |
| 4649 | + } |
| 4650 | + |
| 4651 | + Kind getKind() const { |
| 4652 | + return SubscriptIndexExprAndKind.getInt(); |
| 4653 | + } |
| 4654 | + |
| 4655 | + Expr *getIndexExpr() const { |
| 4656 | + switch (getKind()) { |
| 4657 | + case Kind::Subscript: |
| 4658 | + case Kind::UnresolvedSubscript: |
| 4659 | + return SubscriptIndexExprAndKind.getPointer(); |
| 4660 | + |
| 4661 | + case Kind::OptionalChain: |
| 4662 | + case Kind::OptionalWrap: |
| 4663 | + case Kind::OptionalForce: |
| 4664 | + case Kind::UnresolvedProperty: |
| 4665 | + case Kind::Property: |
| 4666 | + llvm_unreachable("no index expr for this kind"); |
| 4667 | + } |
| 4668 | + } |
| 4669 | + |
| 4670 | + DeclName getUnresolvedDeclName() const { |
| 4671 | + switch (getKind()) { |
| 4672 | + case Kind::UnresolvedProperty: |
| 4673 | + return Decl.UnresolvedName; |
| 4674 | + |
| 4675 | + case Kind::Subscript: |
| 4676 | + case Kind::UnresolvedSubscript: |
| 4677 | + case Kind::OptionalChain: |
| 4678 | + case Kind::OptionalWrap: |
| 4679 | + case Kind::OptionalForce: |
| 4680 | + case Kind::Property: |
| 4681 | + llvm_unreachable("no unresolved name for this kind"); |
| 4682 | + } |
| 4683 | + } |
| 4684 | + |
| 4685 | + ConcreteDeclRef getDeclRef() const { |
| 4686 | + switch (getKind()) { |
| 4687 | + case Kind::Property: |
| 4688 | + case Kind::Subscript: |
| 4689 | + return Decl.ResolvedDecl; |
| 4690 | + |
| 4691 | + case Kind::UnresolvedProperty: |
| 4692 | + case Kind::UnresolvedSubscript: |
| 4693 | + case Kind::OptionalChain: |
| 4694 | + case Kind::OptionalWrap: |
| 4695 | + case Kind::OptionalForce: |
| 4696 | + llvm_unreachable("no decl ref for this kind"); |
| 4697 | + } |
| 4698 | + } |
| 4699 | + |
| 4700 | + Type getComponentType() const { |
| 4701 | + return ComponentType; |
| 4702 | + } |
| 4703 | + }; |
4576 | 4704 |
|
4577 |
| - auto mutableComponents = getComponentsMutable(); |
4578 |
| - return { reinterpret_cast<SourceLoc *>(mutableComponents.end()), |
4579 |
| - mutableComponents.size() }; |
4580 |
| - } |
| 4705 | + using ComponentAndLoc = std::pair<Component, SourceLoc>; |
| 4706 | + |
| 4707 | +private: |
| 4708 | + llvm::MutableArrayRef<ComponentAndLoc> Components; |
4581 | 4709 |
|
4582 | 4710 | public:
|
4583 | 4711 | /// Create a new #keyPath expression.
|
4584 |
| - /// |
4585 |
| - /// \param nameLocs The locations of the names in the key-path, |
4586 |
| - /// which must either have the same number of entries as \p names or |
4587 |
| - /// must be empty. |
4588 |
| - static KeyPathExpr *create(ASTContext &ctx, |
4589 |
| - SourceLoc keywordLoc, SourceLoc lParenLoc, |
4590 |
| - ArrayRef<Identifier> names, |
4591 |
| - ArrayRef<SourceLoc> nameLocs, |
4592 |
| - SourceLoc rParenLoc); |
| 4712 | + KeyPathExpr(ASTContext &C, |
| 4713 | + SourceLoc keywordLoc, SourceLoc lParenLoc, |
| 4714 | + ArrayRef<ComponentAndLoc> components, |
| 4715 | + SourceLoc rParenLoc, |
| 4716 | + bool isObjC, |
| 4717 | + bool isImplicit = false); |
4593 | 4718 |
|
4594 | 4719 | SourceLoc getLoc() const { return KeywordLoc; }
|
4595 | 4720 | SourceRange getSourceRange() const {
|
4596 | 4721 | return SourceRange(KeywordLoc, RParenLoc);
|
4597 | 4722 | }
|
4598 | 4723 |
|
4599 |
| - /// Retrieve the number of components in the key-path. |
4600 |
| - unsigned getNumComponents() const { |
4601 |
| - return KeyPathExprBits.NumComponents; |
| 4724 | + /// Get the components array. |
| 4725 | + ArrayRef<ComponentAndLoc> getComponents() const { |
| 4726 | + return Components; |
4602 | 4727 | }
|
4603 |
| - |
4604 |
| - /// Retrieve's the name for the (i)th component; |
4605 |
| - Identifier getComponentName(unsigned i) const; |
4606 |
| - |
4607 |
| - /// Retrieve's the declaration corresponding to the (i)th component, |
4608 |
| - /// or null if this component has not yet been resolved. |
4609 |
| - ValueDecl *getComponentDecl(unsigned i) const { |
4610 |
| - return getComponents()[i].dyn_cast<ValueDecl *>(); |
4611 |
| - } |
4612 |
| - |
4613 |
| - /// Retrieve the location corresponding to the (i)th name. |
4614 |
| - /// |
4615 |
| - /// If no location information is available, returns an empty |
4616 |
| - /// \c DeclNameLoc. |
4617 |
| - SourceLoc getComponentNameLoc(unsigned i) const { |
4618 |
| - if (!KeyPathExprBits.HaveSourceLocations) return { }; |
4619 |
| - |
4620 |
| - auto components = getComponents(); |
4621 |
| - ArrayRef<SourceLoc> nameLocs( |
4622 |
| - reinterpret_cast<SourceLoc const *>(components.end()), |
4623 |
| - components.size()); |
4624 |
| - |
4625 |
| - return nameLocs[i]; |
4626 |
| - } |
4627 |
| - |
4628 |
| - /// Retrieve the semantic expression, which will be \c NULL prior to |
4629 |
| - /// type checking and a string literal after type checking. |
4630 |
| - Expr *getSemanticExpr() const { return SemanticExpr; } |
| 4728 | + |
| 4729 | + /// Resolve the components of an un-type-checked expr. This copies over the |
| 4730 | + /// components from the argument array. |
| 4731 | + void resolveComponents(ASTContext &C, |
| 4732 | + ArrayRef<Component> resolvedComponents); |
| 4733 | + |
| 4734 | + /// Retrieve the string literal expression, which will be \c NULL prior to |
| 4735 | + /// type checking and a string literal after type checking for an |
| 4736 | + /// @objc key path. |
| 4737 | + Expr *getObjCStringLiteralExpr() const { return ObjCStringLiteralExpr; } |
4631 | 4738 |
|
4632 | 4739 | /// Set the semantic expression.
|
4633 |
| - void setSemanticExpr(Expr *expr) { SemanticExpr = expr; } |
4634 |
| - |
4635 |
| - /// Resolve the given component to the given declaration. |
4636 |
| - void resolveComponent(unsigned idx, ValueDecl *decl) { |
4637 |
| - getComponentsMutable()[idx] = decl; |
4638 |
| - } |
| 4740 | + void setObjCStringLiteralExpr(Expr *expr) { ObjCStringLiteralExpr = expr; } |
| 4741 | + |
| 4742 | + /// True if this is an ObjC key path expression. |
| 4743 | + bool isObjC() const { return KeyPathExprBits.IsObjC; } |
4639 | 4744 |
|
4640 | 4745 | static bool classof(const Expr *E) {
|
4641 | 4746 | return E->getKind() == ExprKind::KeyPath;
|
|
0 commit comments