| //===--- AccessScope.h - Swift Access Scope ---------------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_ACCESSSCOPE_H |
| #define SWIFT_ACCESSSCOPE_H |
| |
| #include "swift/AST/AttrKind.h" |
| #include "swift/AST/DeclContext.h" |
| #include "swift/Basic/Debug.h" |
| #include "llvm/ADT/PointerIntPair.h" |
| |
| namespace swift { |
| |
| /// The wrapper around the outermost DeclContext from which |
| /// a particular declaration can be accessed. |
| class AccessScope { |
| /// The declaration context (if not public) along with a bit saying |
| /// whether this scope is private, SPI or not. |
| /// If the declaration context is set, the bit means that the scope is |
| /// private or not. If the declaration context is null, the bit means that |
| /// this scope is SPI or not. |
| llvm::PointerIntPair<const DeclContext *, 1, bool> Value; |
| |
| public: |
| AccessScope(const DeclContext *DC, bool isPrivate = false, bool isSPI = false); |
| |
| static AccessScope getPublic(bool isSPI = false) { return AccessScope(nullptr, false, isSPI); } |
| |
| /// Check if private access is allowed. This is a lexical scope check in Swift |
| /// 3 mode. In Swift 4 mode, declarations and extensions of the same type will |
| /// also allow access. |
| static bool allowsPrivateAccess(const DeclContext *useDC, const DeclContext *sourceDC); |
| |
| /// Returns nullptr if access scope is public. |
| const DeclContext *getDeclContext() const { return Value.getPointer(); } |
| |
| bool operator==(AccessScope RHS) const { return Value == RHS.Value; } |
| bool operator!=(AccessScope RHS) const { return !(*this == RHS); } |
| bool hasEqualDeclContextWith(AccessScope RHS) const { |
| return getDeclContext() == RHS.getDeclContext(); |
| } |
| |
| bool isPublic() const { return !Value.getPointer(); } |
| bool isPrivate() const { return Value.getPointer() && Value.getInt(); } |
| bool isFileScope() const; |
| bool isInternal() const; |
| |
| // Is this a public scope |
| bool isSPI() const { return !Value.getPointer() && Value.getInt(); } |
| |
| /// Returns true if this is a child scope of the specified other access scope. |
| /// |
| /// \see DeclContext::isChildContextOf |
| bool isChildOf(AccessScope AS) const { |
| if (!isPublic() && !AS.isPublic()) |
| return allowsPrivateAccess(getDeclContext(), AS.getDeclContext()); |
| if (isPublic() && AS.isPublic()) { |
| if (isSPI() != AS.isSPI()) |
| return isSPI(); |
| return false; |
| } |
| return AS.isPublic(); |
| } |
| |
| /// Returns the associated access level for diagnostic purposes. |
| AccessLevel accessLevelForDiagnostics() const; |
| |
| /// Returns the minimum access level required to access |
| /// associated DeclContext for diagnostic purposes. |
| AccessLevel requiredAccessForDiagnostics() const { |
| return isFileScope() |
| ? AccessLevel::FilePrivate |
| : accessLevelForDiagnostics(); |
| } |
| |
| /// Returns the narrowest access scope if this and the specified access scope |
| /// have common intersection, or None if scopes don't intersect. |
| const Optional<AccessScope> intersectWith(AccessScope accessScope) const { |
| if (hasEqualDeclContextWith(accessScope)) { |
| if (isSPI()) |
| return *this; |
| if (isPrivate()) |
| return *this; |
| return accessScope; |
| } |
| if (isChildOf(accessScope)) |
| return *this; |
| if (accessScope.isChildOf(*this)) |
| return accessScope; |
| |
| return None; |
| } |
| |
| SWIFT_DEBUG_DUMP; |
| }; |
| |
| } // end namespace swift |
| |
| #endif |