mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[InterfaceGen] Print property initializers in resilient, fixed-layout types (#19619)
Augment the ASTPrinter to print the name and text of initializer expressions if a property has an initializer and the type is @_fixed_layout and resides in a resilient module, and serialize the text for partial modules. With this change, all .swiftinterface files in the project (except for SwiftLang) compile to swiftmodules on macOS. rdar://43774580 rdar://43812188
This commit is contained in:
@@ -1864,38 +1864,49 @@ public:
|
||||
/// Pattern and Initialization expression. The pattern is always present, but
|
||||
/// the initializer can be null if there is none.
|
||||
class PatternBindingEntry {
|
||||
Pattern *ThePattern;
|
||||
|
||||
/// The location of the equal '=' token.
|
||||
SourceLoc EqualLoc;
|
||||
|
||||
enum class Flags {
|
||||
Checked = 1 << 0,
|
||||
Removed = 1 << 1,
|
||||
Lazy = 1 << 2,
|
||||
Lazy = 1 << 2
|
||||
};
|
||||
llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;
|
||||
|
||||
struct ExprAndEqualLoc {
|
||||
// When the initializer is removed we don't actually clear the pointer
|
||||
// because we might need to get initializer's source range. Since the
|
||||
// initializer is ASTContext-allocated it is safe.
|
||||
Expr *Node;
|
||||
/// The location of the equal '=' token.
|
||||
SourceLoc EqualLoc;
|
||||
};
|
||||
|
||||
// When the initializer is removed we don't actually clear the pointer
|
||||
// because we might need to get initializer's source range. Since the
|
||||
// initializer is ASTContext-allocated it is safe.
|
||||
llvm::PointerIntPair<Expr *, 3, OptionSet<Flags>> InitAndFlags;
|
||||
union {
|
||||
/// The initializer expression and its '=' token loc.
|
||||
ExprAndEqualLoc InitExpr;
|
||||
|
||||
/// The text of the initializer expression if deserialized from a module.
|
||||
StringRef InitStringRepresentation;
|
||||
};
|
||||
|
||||
/// The initializer context used for this pattern binding entry.
|
||||
DeclContext *InitContext = nullptr;
|
||||
llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;
|
||||
|
||||
friend class PatternBindingInitializer;
|
||||
|
||||
public:
|
||||
PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
|
||||
DeclContext *InitContext)
|
||||
: ThePattern(P), EqualLoc(EqualLoc), InitAndFlags(E, {}),
|
||||
InitContext(InitContext) {}
|
||||
: PatternAndFlags(P, {}), InitExpr({E, EqualLoc}),
|
||||
InitContextAndIsText({InitContext, false}) {
|
||||
}
|
||||
|
||||
Pattern *getPattern() const { return ThePattern; }
|
||||
void setPattern(Pattern *P) { ThePattern = P; }
|
||||
Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
|
||||
void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }
|
||||
Expr *getInit() const {
|
||||
return (InitAndFlags.getInt().contains(Flags::Removed))
|
||||
? nullptr : InitAndFlags.getPointer();
|
||||
if (PatternAndFlags.getInt().contains(Flags::Removed) ||
|
||||
InitContextAndIsText.getInt())
|
||||
return nullptr;
|
||||
return InitExpr.Node;
|
||||
}
|
||||
Expr *getNonLazyInit() const {
|
||||
return isInitializerLazy() ? nullptr : getInit();
|
||||
@@ -1903,37 +1914,64 @@ public:
|
||||
SourceRange getOrigInitRange() const;
|
||||
void setInit(Expr *E);
|
||||
|
||||
/// Gets the text of the initializer expression, stripping out inactive
|
||||
/// branches of any #ifs inside the expression.
|
||||
StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;
|
||||
|
||||
/// Sets the initializer string representation to the string that was
|
||||
/// deserialized from a partial module.
|
||||
void setInitStringRepresentation(StringRef str) {
|
||||
InitStringRepresentation = str;
|
||||
InitContextAndIsText.setInt(true);
|
||||
}
|
||||
|
||||
/// Whether this pattern entry can generate a string representation of its
|
||||
/// initializer expression.
|
||||
bool hasInitStringRepresentation() const;
|
||||
|
||||
/// Retrieve the location of the equal '=' token.
|
||||
SourceLoc getEqualLoc() const { return EqualLoc; }
|
||||
SourceLoc getEqualLoc() const {
|
||||
return InitContextAndIsText.getInt() ? SourceLoc() : InitExpr.EqualLoc;
|
||||
}
|
||||
|
||||
/// Set the location of the equal '=' token.
|
||||
void setEqualLoc(SourceLoc equalLoc) { EqualLoc = equalLoc; }
|
||||
void setEqualLoc(SourceLoc equalLoc) {
|
||||
assert(!InitContextAndIsText.getInt() &&
|
||||
"cannot set equal loc for textual initializer");
|
||||
InitExpr.EqualLoc = equalLoc;
|
||||
}
|
||||
|
||||
/// Retrieve the initializer as it was written in the source.
|
||||
Expr *getInitAsWritten() const { return InitAndFlags.getPointer(); }
|
||||
Expr *getInitAsWritten() const {
|
||||
return InitContextAndIsText.getInt() ? nullptr : InitExpr.Node;
|
||||
}
|
||||
|
||||
bool isInitializerChecked() const {
|
||||
return InitAndFlags.getInt().contains(Flags::Checked);
|
||||
return PatternAndFlags.getInt().contains(Flags::Checked);
|
||||
}
|
||||
void setInitializerChecked() {
|
||||
InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Checked);
|
||||
PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
|
||||
}
|
||||
|
||||
bool isInitializerLazy() const {
|
||||
return InitAndFlags.getInt().contains(Flags::Lazy);
|
||||
return PatternAndFlags.getInt().contains(Flags::Lazy);
|
||||
}
|
||||
void setInitializerLazy() {
|
||||
InitAndFlags.setInt(InitAndFlags.getInt() | Flags::Lazy);
|
||||
PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Lazy);
|
||||
}
|
||||
|
||||
// Return the first variable initialized by this pattern.
|
||||
VarDecl *getAnchoringVarDecl() const;
|
||||
|
||||
// Retrieve the declaration context for the initializer.
|
||||
DeclContext *getInitContext() const { return InitContext; }
|
||||
DeclContext *getInitContext() const {
|
||||
return InitContextAndIsText.getPointer();
|
||||
}
|
||||
|
||||
/// Override the initializer context.
|
||||
void setInitContext(DeclContext *dc) { InitContext = dc; }
|
||||
void setInitContext(DeclContext *dc) {
|
||||
InitContextAndIsText.setPointer(dc);
|
||||
}
|
||||
|
||||
/// Retrieve the source range covered by this pattern binding.
|
||||
///
|
||||
@@ -2007,6 +2045,10 @@ public:
|
||||
return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
|
||||
}
|
||||
|
||||
void setInitStringRepresentation(unsigned i, StringRef str) {
|
||||
getMutablePatternList()[i].setInitStringRepresentation(str);
|
||||
}
|
||||
|
||||
Expr *getInit(unsigned i) const {
|
||||
return getPatternList()[i].getInit();
|
||||
}
|
||||
@@ -2039,7 +2081,8 @@ public:
|
||||
|
||||
/// Return the PatternEntry (a pattern + initializer pair) for the specified
|
||||
/// VarDecl.
|
||||
PatternBindingEntry getPatternEntryForVarDecl(const VarDecl *VD) const {
|
||||
const PatternBindingEntry &getPatternEntryForVarDecl(
|
||||
const VarDecl *VD) const {
|
||||
return getPatternList()[getPatternEntryIndexForVarDecl(VD)];
|
||||
}
|
||||
|
||||
@@ -2097,7 +2140,7 @@ public:
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == DeclKind::PatternBinding;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
|
||||
// Pattern entries are tail allocated.
|
||||
@@ -4606,6 +4649,14 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return whether this VarDecl has an initial value, either by checking
|
||||
// if it has an initializer in its parent pattern binding or if it has
|
||||
// the @_hasInitialValue attribute.
|
||||
bool hasInitialValue() const {
|
||||
return getAttrs().hasAttribute<HasInitialValueAttr>() ||
|
||||
getParentInitializer();
|
||||
}
|
||||
|
||||
VarDecl *getOverriddenDecl() const {
|
||||
return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
|
||||
}
|
||||
@@ -4687,6 +4738,13 @@ public:
|
||||
void setHasNonPatternBindingInit(bool V = true) {
|
||||
Bits.VarDecl.HasNonPatternBindingInit = V;
|
||||
}
|
||||
|
||||
/// Determines if this var has an initializer expression that should be
|
||||
/// exposed to clients.
|
||||
/// There's a very narrow case when we would: if the decl is an instance
|
||||
/// member with an initializer expression and the parent type is
|
||||
/// @_fixed_layout and resides in a resilient module.
|
||||
bool isInitExposedToClients() const;
|
||||
|
||||
/// Is this a special debugger variable?
|
||||
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
|
||||
|
||||
Reference in New Issue
Block a user