Skip to content

Commit a060eb5

Browse files
committed
[SE-0075] Transfer the power of config resolution to Namebinding
This completely removes Parse’s ability to make any judgement calls about compilation conditions, instead the parser-relevant parts of ‘evaluateConditionalCompilationExpr’ have been moved into ‘classifyConditionalCompilationExpr’ where they exist to make sure only decls that we want to parse actually parse later. The condition-evaluation parts have been moved into NameBinding in the form of a Walker that evaluates and collapses IfConfigs. This walker is meant as an homage to PlaygroundLogger. It should probably be factored out into a common walker at some point in the future.
1 parent 4426e41 commit a060eb5

File tree

17 files changed

+821
-363
lines changed

17 files changed

+821
-363
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,13 +1929,8 @@ struct IfConfigDeclClause {
19291929

19301930
ArrayRef<Decl*> Members;
19311931

1932-
/// True if this is the active clause of the #if block. Since this is
1933-
/// evaluated at parse time, this is always known.
1934-
bool isActive;
1935-
1936-
IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef<Decl*> Members,
1937-
bool isActive)
1938-
: Loc(Loc), Cond(Cond), Members(Members), isActive(isActive) {
1932+
IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef<Decl*> Members)
1933+
: Loc(Loc), Cond(Cond), Members(Members) {
19391934
}
19401935
};
19411936

@@ -1950,27 +1945,18 @@ class IfConfigDecl : public Decl {
19501945
ArrayRef<IfConfigDeclClause> Clauses;
19511946
SourceLoc EndLoc;
19521947
bool HadMissingEnd;
1948+
bool HasBeenResolved = false;
19531949
public:
19541950

19551951
IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigDeclClause> Clauses,
19561952
SourceLoc EndLoc, bool HadMissingEnd)
1957-
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc),
1958-
HadMissingEnd(HadMissingEnd) {
1959-
}
1953+
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses),
1954+
EndLoc(EndLoc), HadMissingEnd(HadMissingEnd) {}
19601955

19611956
ArrayRef<IfConfigDeclClause> getClauses() const { return Clauses; }
19621957

1963-
/// Return the active clause, or null if there is no active one.
1964-
const IfConfigDeclClause *getActiveClause() const {
1965-
for (auto &Clause : Clauses)
1966-
if (Clause.isActive) return &Clause;
1967-
return nullptr;
1968-
}
1969-
const ArrayRef<Decl*> getActiveMembers() const {
1970-
if (auto *Clause = getActiveClause())
1971-
return Clause->Members;
1972-
return {};
1973-
}
1958+
bool isResolved() { return HasBeenResolved; }
1959+
void setResolved() { HasBeenResolved = true; }
19741960

19751961
SourceLoc getEndLoc() const { return EndLoc; }
19761962
SourceLoc getLoc() const { return Clauses[0].Loc; }

include/swift/AST/Module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ class SourceFile final : public FileUnit {
831831
std::vector<Decl*> Decls;
832832

833833
/// The list of local type declarations in the source file.
834-
TinyPtrVector<TypeDecl*> LocalTypeDecls;
834+
SmallPtrSet<TypeDecl *, 4> LocalTypeDecls;
835835

836836
/// A set of special declaration attributes which require the
837837
/// Foundation module to be imported to work. If the foundation

include/swift/AST/Stmt.h

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -667,28 +667,31 @@ struct IfConfigStmtClause {
667667

668668
/// Elements inside the clause
669669
ArrayRef<ASTNode> Elements;
670-
671-
/// True if this is the active clause of the #if block. Since this is
672-
/// evaluated at parse time, this is always known.
673-
bool isActive;
674-
670+
671+
/// Whether or not name binding has resolved this statement.
672+
bool HasBeenResolved = false;
673+
675674
IfConfigStmtClause(SourceLoc Loc, Expr *Cond,
676-
ArrayRef<ASTNode> Elements, bool isActive)
677-
: Loc(Loc), Cond(Cond), Elements(Elements), isActive(isActive) {
675+
ArrayRef<ASTNode> Elements)
676+
: Loc(Loc), Cond(Cond), Elements(Elements) {
678677
}
678+
679+
public:
680+
bool isResolved() const { return HasBeenResolved; }
681+
void setResolved() { HasBeenResolved = true; }
679682
};
680683

681684
/// IfConfigStmt - This class models the statement-side representation of
682685
/// #if/#else/#endif blocks.
683686
class IfConfigStmt : public Stmt {
684687
/// An array of clauses controlling each of the #if/#elseif/#else conditions.
685688
/// The array is ASTContext allocated.
686-
ArrayRef<IfConfigStmtClause> Clauses;
689+
MutableArrayRef<IfConfigStmtClause> Clauses;
687690
SourceLoc EndLoc;
688691
bool HadMissingEnd;
689692

690693
public:
691-
IfConfigStmt(ArrayRef<IfConfigStmtClause> Clauses, SourceLoc EndLoc,
694+
IfConfigStmt(MutableArrayRef<IfConfigStmtClause> Clauses, SourceLoc EndLoc,
692695
bool HadMissingEnd)
693696
: Stmt(StmtKind::IfConfig, /*implicit=*/false),
694697
Clauses(Clauses), EndLoc(EndLoc), HadMissingEnd(HadMissingEnd) {}
@@ -700,14 +703,7 @@ class IfConfigStmt : public Stmt {
700703

701704
bool hadMissingEnd() const { return HadMissingEnd; }
702705

703-
const ArrayRef<IfConfigStmtClause> &getClauses() const { return Clauses; }
704-
705-
ArrayRef<ASTNode> getActiveClauseElements() const {
706-
for (auto &Clause : Clauses)
707-
if (Clause.isActive)
708-
return Clause.Elements;
709-
return ArrayRef<ASTNode>();
710-
}
706+
const MutableArrayRef<IfConfigStmtClause> &getClauses() const { return Clauses; }
711707

712708
// Implement isa/cast/dyncast/etc.
713709
static bool classof(const Stmt *S) {

include/swift/Parse/Parser.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ namespace swift {
5959
TopLevelCode,
6060
/// The top-level of a file, when in parse-as-library mode.
6161
TopLevelLibrary,
62-
/// The body of the inactive clause of an #if/#else/#endif block
63-
InactiveConditionalBlock,
64-
/// The body of the active clause of an #if/#else/#endif block
65-
ActiveConditionalBlock
62+
/// The body of the clause of an #if/#else/#endif block
63+
ConditionalBlock,
6664
};
6765

6866

@@ -617,10 +615,9 @@ class Parser {
617615
BraceItemListKind::Brace,
618616
BraceItemListKind ConditionalBlockKind =
619617
BraceItemListKind::Brace);
620-
ParserResult<BraceStmt> parseBraceItemList(Diag<> ID);
618+
ParserResult<BraceStmt> parseBraceItemList(Diag<> ID, bool inConfig = false);
621619

622-
void parseIfConfigClauseElements(bool isActive,
623-
BraceItemListKind Kind,
620+
void parseIfConfigClauseElements(BraceItemListKind Kind,
624621
SmallVectorImpl<ASTNode> &Elements);
625622

626623
void parseTopLevelCodeDeclDelayed();
@@ -646,7 +643,8 @@ class Parser {
646643
PD_InExtension = 1 << 8,
647644
PD_InStruct = 1 << 9,
648645
PD_InEnum = 1 << 10,
649-
PD_InLoop = 1 << 11
646+
PD_InLoop = 1 << 11,
647+
PD_InIfConfig = 1 << 12,
650648
};
651649

652650
/// Options that control the parsing of declarations.
@@ -695,7 +693,7 @@ class Parser {
695693
/// 'isLine = true' indicates parsing #line instead of #sourcelocation
696694
ParserStatus parseLineDirective(bool isLine = false);
697695

698-
void setLocalDiscriminator(ValueDecl *D);
696+
void setLocalDiscriminator(ParseDeclOptions Flags, ValueDecl *D);
699697

700698
/// Parse the optional attributes before a declaration.
701699
bool parseDeclAttributeList(DeclAttributes &Attributes,
@@ -1229,9 +1227,9 @@ class Parser {
12291227
ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo);
12301228
ParserResult<CaseStmt> parseStmtCase();
12311229

1232-
/// Evaluate the condition of an #if directive.
1233-
ConditionalCompilationExprState
1234-
evaluateConditionalCompilationExpr(Expr *condition);
1230+
/// Classify the condition of an #if directive.
1231+
ConditionalCompilationExprKind
1232+
classifyConditionalCompilationExpr(Expr *condition);
12351233

12361234
//===--------------------------------------------------------------------===//
12371235
// Generics Parsing

include/swift/Parse/ParserResult.h

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ enum class ConditionalCompilationExprKind {
222222
Error,
223223
OS,
224224
Arch,
225-
Import,
226225
LanguageVersion,
227226
CompilerVersion,
228227
Binary,
@@ -232,60 +231,6 @@ enum class ConditionalCompilationExprKind {
232231
Integer
233232
};
234233

235-
class ConditionalCompilationExprState {
236-
237-
uint8_t ConditionActive : 1;
238-
uint8_t Kind : 7;
239-
public:
240-
ConditionalCompilationExprState() : ConditionActive(false) {
241-
setKind(ConditionalCompilationExprKind::Unknown);
242-
}
243-
244-
ConditionalCompilationExprState(bool ConditionActive,
245-
ConditionalCompilationExprKind Kind)
246-
: ConditionActive(ConditionActive) {
247-
setKind(Kind);
248-
}
249-
250-
bool isConditionActive() const {
251-
return ConditionActive;
252-
}
253-
254-
void setConditionActive(bool A) {
255-
ConditionActive = A;
256-
}
257-
258-
ConditionalCompilationExprKind getKind() const {
259-
return static_cast<ConditionalCompilationExprKind>(Kind);
260-
}
261-
262-
void setKind(ConditionalCompilationExprKind K) {
263-
Kind = static_cast<uint8_t>(K);
264-
assert(getKind() == K);
265-
}
266-
267-
bool shouldParse() const {
268-
if (getKind() == ConditionalCompilationExprKind::Error)
269-
return true;
270-
return ConditionActive ||
271-
(getKind() != ConditionalCompilationExprKind::CompilerVersion &&
272-
getKind() != ConditionalCompilationExprKind::LanguageVersion);
273-
}
274-
275-
static ConditionalCompilationExprState error() {
276-
return {false, ConditionalCompilationExprKind::Error};
277-
}
278-
};
279-
280-
ConditionalCompilationExprState
281-
operator&&(const ConditionalCompilationExprState lhs,
282-
const ConditionalCompilationExprState rhs);
283-
ConditionalCompilationExprState
284-
operator||(const ConditionalCompilationExprState lhs,
285-
const ConditionalCompilationExprState rhs);
286-
ConditionalCompilationExprState
287-
operator!(const ConditionalCompilationExprState Result);
288-
289234
} // namespace swift
290235

291236
#endif // LLVM_SWIFT_PARSER_PARSER_RESULT_H

include/swift/Parse/Scope.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ class ScopeInfo {
5454
/// scope.
5555
void addToScope(ValueDecl *D, Parser &TheParser);
5656

57-
bool isInactiveConfigBlock() const;
58-
5957
SavedScope saveCurrentScope();
6058
};
6159

@@ -91,7 +89,6 @@ class SavedScope {
9189
ScopeInfo::ScopedHTDetachedScopeTy HTDetachedScope;
9290
unsigned Depth;
9391
ScopeKind Kind;
94-
bool IsInactiveConfigBlock;
9592

9693
SavedScope() = delete;
9794
SavedScope(const SavedScope &) = delete;
@@ -103,9 +100,8 @@ class SavedScope {
103100
~SavedScope() = default;
104101

105102
SavedScope(ScopeInfo::ScopedHTDetachedScopeTy &&HTDetachedScope,
106-
unsigned Depth, ScopeKind Kind, bool IsInactiveConfigBlock)
107-
: HTDetachedScope(std::move(HTDetachedScope)), Depth(Depth), Kind(Kind),
108-
IsInactiveConfigBlock(IsInactiveConfigBlock) {}
103+
unsigned Depth, ScopeKind Kind)
104+
: HTDetachedScope(std::move(HTDetachedScope)), Depth(Depth), Kind(Kind) {}
109105
};
110106

111107
/// Scope - This class represents lexical scopes. These objects are created
@@ -125,12 +121,11 @@ class Scope {
125121
unsigned PrevResolvableDepth;
126122
unsigned Depth;
127123
ScopeKind Kind;
128-
bool IsInactiveConfigBlock;
129124

130125
/// \brief Save this scope so that it can be re-entered later. Transfers the
131126
/// ownership of the scope frame to returned object.
132127
SavedScope saveScope() {
133-
return SavedScope(HTScope.detach(), Depth, Kind, IsInactiveConfigBlock);
128+
return SavedScope(HTScope.detach(), Depth, Kind);
134129
}
135130

136131
unsigned getDepth() const {
@@ -141,7 +136,7 @@ class Scope {
141136

142137
public:
143138
/// \brief Create a lexical scope of the specified kind.
144-
Scope(Parser *P, ScopeKind SC, bool IsInactiveConfigBlock = false);
139+
Scope(Parser *P, ScopeKind SC);
145140

146141
/// \brief Re-enter the specified scope, transferring the ownership of the
147142
/// scope frame to the new object.
@@ -174,12 +169,6 @@ inline ValueDecl *ScopeInfo::lookupValueName(DeclName Name) {
174169
return Res.second;
175170
}
176171

177-
inline bool ScopeInfo::isInactiveConfigBlock() const {
178-
if (!CurScope)
179-
return false;
180-
return CurScope->IsInactiveConfigBlock;
181-
}
182-
183172
inline SavedScope ScopeInfo::saveCurrentScope() {
184173
return CurScope->saveScope();
185174
}

0 commit comments

Comments
 (0)