Skip to content

SE-0075 Implement canImport #5778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/AST/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/StmtTransformer.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeRepr.h"

Expand Down
13 changes: 8 additions & 5 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1929,8 +1929,7 @@ struct IfConfigDeclClause {

ArrayRef<Decl*> Members;

/// True if this is the active clause of the #if block. Since this is
/// evaluated at parse time, this is always known.
/// True if this is the active clause of the #if block.
bool isActive;

IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef<Decl*> Members,
Expand All @@ -1950,13 +1949,13 @@ class IfConfigDecl : public Decl {
ArrayRef<IfConfigDeclClause> Clauses;
SourceLoc EndLoc;
bool HadMissingEnd;
bool HasBeenResolved = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the extra padding! It's not super important, but if you feel like packing these bools into the spare bits up in Decl in a follow-on PR, you'd have my micro-optimizing thanks

public:

IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigDeclClause> Clauses,
SourceLoc EndLoc, bool HadMissingEnd)
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc),
HadMissingEnd(HadMissingEnd) {
}
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses),
EndLoc(EndLoc), HadMissingEnd(HadMissingEnd) {}

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

Expand All @@ -1966,11 +1965,15 @@ class IfConfigDecl : public Decl {
if (Clause.isActive) return &Clause;
return nullptr;
}

const ArrayRef<Decl*> getActiveMembers() const {
if (auto *Clause = getActiveClause())
return Clause->Members;
return {};
}

bool isResolved() const { return HasBeenResolved; }
void setResolved() { HasBeenResolved = true; }

SourceLoc getEndLoc() const { return EndLoc; }
SourceLoc getLoc() const { return Clauses[0].Loc; }
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,8 @@ ERROR(unsupported_conditional_compilation_binary_expression,none,
ERROR(unsupported_conditional_compilation_unary_expression,none,
"expected unary '!' expression", ())
ERROR(unsupported_platform_condition_expression,none,
"unexpected platform condition (expected 'os', 'arch', or 'swift')",
"unexpected platform condition "
"(expected 'canImport', 'os', 'arch', or 'swift')",
())
ERROR(platform_condition_expected_one_argument,none,
"expected only one argument to platform condition",
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -831,13 +831,13 @@ class SourceFile final : public FileUnit {
std::vector<Decl*> Decls;

/// The list of local type declarations in the source file.
TinyPtrVector<TypeDecl*> LocalTypeDecls;
llvm::SetVector<TypeDecl *> LocalTypeDecls;

/// A set of special declaration attributes which require the
/// Foundation module to be imported to work. If the foundation
/// module is still not imported by the time type checking is
/// complete, we diagnose.
std::map<DeclAttrKind, const DeclAttribute *> AttrsRequiringFoundation;
llvm::SetVector<const DeclAttribute *> AttrsRequiringFoundation;

/// A mapping from Objective-C selectors to the methods that have
/// those selectors.
Expand Down
13 changes: 8 additions & 5 deletions include/swift/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,10 @@ struct IfConfigStmtClause {

/// Elements inside the clause
ArrayRef<ASTNode> Elements;

/// True if this is the active clause of the #if block. Since this is
/// evaluated at parse time, this is always known.

/// True if this is the active clause of the #if block.
bool isActive;

IfConfigStmtClause(SourceLoc Loc, Expr *Cond,
ArrayRef<ASTNode> Elements, bool isActive)
: Loc(Loc), Cond(Cond), Elements(Elements), isActive(isActive) {
Expand All @@ -686,6 +685,7 @@ class IfConfigStmt : public Stmt {
ArrayRef<IfConfigStmtClause> Clauses;
SourceLoc EndLoc;
bool HadMissingEnd;
bool HasBeenResolved = false;

public:
IfConfigStmt(ArrayRef<IfConfigStmtClause> Clauses, SourceLoc EndLoc,
Expand All @@ -700,8 +700,11 @@ class IfConfigStmt : public Stmt {

bool hadMissingEnd() const { return HadMissingEnd; }

const ArrayRef<IfConfigStmtClause> &getClauses() const { return Clauses; }
bool isResolved() { return HasBeenResolved; }
void setResolved() { HasBeenResolved = true; }

const ArrayRef<IfConfigStmtClause> &getClauses() const { return Clauses; }

ArrayRef<ASTNode> getActiveClauseElements() const {
for (auto &Clause : Clauses)
if (Clause.isActive)
Expand Down
70 changes: 70 additions & 0 deletions include/swift/AST/StmtTransformer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===--- StmtTransformer.h - Class for transforming Stmts -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the StmtTransformer class.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_STMTTRANSFORMER_H
#define SWIFT_AST_STMTTRANSFORMER_H

#include "swift/AST/ASTWalker.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Expr.h"

#include <forward_list>

namespace swift {
class StmtTransformer {
protected:
class ClosureFinder : public ASTWalker {
StmtTransformer &StmtTrans;
public:
ClosureFinder(StmtTransformer &CCR) : StmtTrans(CCR) { }
virtual std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) {
if (isa<BraceStmt>(S)) {
// To respect nesting, don't walk into brace statements.
return { false, S };
} else {
return { true, S };
}
}
virtual std::pair<bool, Expr *> walkToExprPre(Expr *E) {
if (ClosureExpr *CE = dyn_cast<ClosureExpr>(E)) {
BraceStmt *B = CE->getBody();
if (B) {
BraceStmt *NB = StmtTrans.transformBraceStmt(B, false);
CE->setBody(NB, CE->hasSingleExpressionBody());
}
}
return { true, E };
}
};
ClosureFinder CF;

public:
StmtTransformer() : CF(*this) {}
virtual ~StmtTransformer() {}

const ASTWalker &getClosureFinder() const {
return CF;
}

virtual Stmt *transformStmt(Stmt *S);
virtual BraceStmt *transformBraceStmt(BraceStmt *BS, bool TopLevel);
#define STMT(CLASS, PARENT) \
virtual CLASS##Stmt *transform##CLASS##Stmt(CLASS##Stmt *S);
#include "swift/AST/StmtNodes.def"
};
};

#endif /* SWIFT_AST_STMTTRANSFORMER_H */
24 changes: 15 additions & 9 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ namespace swift {
TopLevelCode,
/// The top-level of a file, when in parse-as-library mode.
TopLevelLibrary,
/// The body of the inactive clause of an #if/#else/#endif block
InactiveConditionalBlock,
/// The body of the active clause of an #if/#else/#endif block
ActiveConditionalBlock
/// The body of the clause of an #if/#else/#endif block
ConditionalBlock,
/// The body of the clause of an #if/#else/#endif block that was statically
/// determined to be inactive.
StaticallyInactiveConditionalBlock,
};


Expand Down Expand Up @@ -619,7 +620,7 @@ class Parser {
BraceItemListKind::Brace);
ParserResult<BraceStmt> parseBraceItemList(Diag<> ID);

void parseIfConfigClauseElements(bool isActive,
void parseIfConfigClauseElements(bool isInactive,
BraceItemListKind Kind,
SmallVectorImpl<ASTNode> &Elements);

Expand All @@ -646,7 +647,7 @@ class Parser {
PD_InExtension = 1 << 8,
PD_InStruct = 1 << 9,
PD_InEnum = 1 << 10,
PD_InLoop = 1 << 11
PD_InLoop = 1 << 11,
};

/// Options that control the parsing of declarations.
Expand Down Expand Up @@ -1229,9 +1230,14 @@ class Parser {
ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo);
ParserResult<CaseStmt> parseStmtCase();

/// Evaluate the condition of an #if directive.
ConditionalCompilationExprState
evaluateConditionalCompilationExpr(Expr *condition);
/// Classify the condition of an #if directive according to whether it can
/// be evaluated statically. If evaluation is not possible, the result is
/// 'None'.
static Optional<bool>
classifyConditionalCompilationExpr(Expr *condition,
ASTContext &context,
DiagnosticEngine &diags,
bool fullCheck = false);

//===--------------------------------------------------------------------===//
// Generics Parsing
Expand Down
68 changes: 0 additions & 68 deletions include/swift/Parse/ParserResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,74 +217,6 @@ template <typename T> ParserResult<T>::ParserResult(ParserStatus Status) {
setHasCodeCompletion();
}

enum class ConditionalCompilationExprKind {
Unknown,
Error,
OS,
Arch,
LanguageVersion,
CompilerVersion,
Binary,
Paren,
DeclRef,
Boolean,
Integer
};

class ConditionalCompilationExprState {

uint8_t ConditionActive : 1;
uint8_t Kind : 7;
public:
ConditionalCompilationExprState() : ConditionActive(false) {
setKind(ConditionalCompilationExprKind::Unknown);
}

ConditionalCompilationExprState(bool ConditionActive,
ConditionalCompilationExprKind Kind)
: ConditionActive(ConditionActive) {
setKind(Kind);
}

bool isConditionActive() const {
return ConditionActive;
}

void setConditionActive(bool A) {
ConditionActive = A;
}

ConditionalCompilationExprKind getKind() const {
return static_cast<ConditionalCompilationExprKind>(Kind);
}

void setKind(ConditionalCompilationExprKind K) {
Kind = static_cast<uint8_t>(K);
assert(getKind() == K);
}

bool shouldParse() const {
if (getKind() == ConditionalCompilationExprKind::Error)
return true;
return ConditionActive ||
(getKind() != ConditionalCompilationExprKind::CompilerVersion &&
getKind() != ConditionalCompilationExprKind::LanguageVersion);
}

static ConditionalCompilationExprState error() {
return {false, ConditionalCompilationExprKind::Error};
}
};

ConditionalCompilationExprState
operator&&(const ConditionalCompilationExprState lhs,
const ConditionalCompilationExprState rhs);
ConditionalCompilationExprState
operator||(const ConditionalCompilationExprState lhs,
const ConditionalCompilationExprState rhs);
ConditionalCompilationExprState
operator!(const ConditionalCompilationExprState Result);

} // namespace swift

#endif // LLVM_SWIFT_PARSER_PARSER_RESULT_H
Expand Down
30 changes: 18 additions & 12 deletions include/swift/Parse/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class ScopeInfo {
/// scope.
void addToScope(ValueDecl *D, Parser &TheParser);

bool isInactiveConfigBlock() const;

bool isStaticallyInactiveConfigBlock() const;
SavedScope saveCurrentScope();
};

Expand Down Expand Up @@ -91,7 +91,7 @@ class SavedScope {
ScopeInfo::ScopedHTDetachedScopeTy HTDetachedScope;
unsigned Depth;
ScopeKind Kind;
bool IsInactiveConfigBlock;
bool IsStaticallyInactiveConfigBlock;

SavedScope() = delete;
SavedScope(const SavedScope &) = delete;
Expand All @@ -103,9 +103,9 @@ class SavedScope {
~SavedScope() = default;

SavedScope(ScopeInfo::ScopedHTDetachedScopeTy &&HTDetachedScope,
unsigned Depth, ScopeKind Kind, bool IsInactiveConfigBlock)
unsigned Depth, ScopeKind Kind, bool IsStaticallyInactiveConfigBlock)
: HTDetachedScope(std::move(HTDetachedScope)), Depth(Depth), Kind(Kind),
IsInactiveConfigBlock(IsInactiveConfigBlock) {}
IsStaticallyInactiveConfigBlock(IsStaticallyInactiveConfigBlock) {}
};

/// Scope - This class represents lexical scopes. These objects are created
Expand All @@ -125,12 +125,13 @@ class Scope {
unsigned PrevResolvableDepth;
unsigned Depth;
ScopeKind Kind;
bool IsInactiveConfigBlock;
bool IsStaticallyInactiveConfigBlock;

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

unsigned getDepth() const {
Expand All @@ -141,7 +142,7 @@ class Scope {

public:
/// \brief Create a lexical scope of the specified kind.
Scope(Parser *P, ScopeKind SC, bool IsInactiveConfigBlock = false);
Scope(Parser *P, ScopeKind SC, bool IsStaticallyInactiveConfigBlock = false);

/// \brief Re-enter the specified scope, transferring the ownership of the
/// scope frame to the new object.
Expand Down Expand Up @@ -174,10 +175,15 @@ inline ValueDecl *ScopeInfo::lookupValueName(DeclName Name) {
return Res.second;
}

inline bool ScopeInfo::isInactiveConfigBlock() const {
if (!CurScope)
return false;
return CurScope->IsInactiveConfigBlock;
inline bool ScopeInfo::isStaticallyInactiveConfigBlock() const {
auto scope = CurScope;
while (scope) {
if (scope->IsStaticallyInactiveConfigBlock) {
return true;
}
scope = scope->PrevScope;
}
return false;
}

inline SavedScope ScopeInfo::saveCurrentScope() {
Expand Down
Loading