Skip to content

Commit 57a893b

Browse files
authored
Merge pull request #37212 from nkcsgexi/73992299-3
Parser: teach canImport to take an additional parameter indicating the minimum module version
2 parents d38b233 + bbe5b83 commit 57a893b

File tree

15 files changed

+145
-28
lines changed

15 files changed

+145
-28
lines changed

include/swift/AST/ASTContext.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,9 @@ class ASTContext final {
892892
///
893893
/// Note that even if this check succeeds, errors may still occur if the
894894
/// module is loaded in full.
895-
bool canImportModuleImpl(ImportPath::Element ModulePath) const;
895+
bool canImportModuleImpl(ImportPath::Element ModulePath,
896+
llvm::VersionTuple version,
897+
bool underlyingVersion) const;
896898
public:
897899
namelookup::ImportCache &getImportCache() const;
898900

@@ -921,8 +923,12 @@ class ASTContext final {
921923
///
922924
/// Note that even if this check succeeds, errors may still occur if the
923925
/// module is loaded in full.
924-
bool canImportModule(ImportPath::Element ModulePath);
925-
bool canImportModule(ImportPath::Element ModulePath) const;
926+
bool canImportModule(ImportPath::Element ModulePath,
927+
llvm::VersionTuple version = llvm::VersionTuple(),
928+
bool underlyingVersion = false);
929+
bool canImportModule(ImportPath::Element ModulePath,
930+
llvm::VersionTuple version = llvm::VersionTuple(),
931+
bool underlyingVersion = false) const;
926932

927933
/// \returns a module with a given name that was already loaded. If the
928934
/// module was not loaded, returns nullptr.

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,12 @@ WARNING(likely_simulator_platform_condition,none,
17721772
"use 'targetEnvironment(simulator)' instead",
17731773
())
17741774

1775+
ERROR(canimport_two_parameters, none, "canImport can take only two parameters", ())
1776+
1777+
ERROR(canimport_label, none, "2nd parameter of canImport should be labeled as version or underlyingVersion", ())
1778+
1779+
ERROR(canimport_version, none, "cannot parse module version: %0", (StringRef))
1780+
17751781
//------------------------------------------------------------------------------
17761782
// MARK: Availability query parsing diagnostics
17771783
//------------------------------------------------------------------------------

include/swift/AST/ModuleLoader.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/Basic/SourceLoc.h"
2828
#include "llvm/ADT/SetVector.h"
2929
#include "llvm/ADT/TinyPtrVector.h"
30+
#include "llvm/Support/VersionTuple.h"
3031
#include <system_error>
3132

3233
namespace llvm {
@@ -199,7 +200,9 @@ class ModuleLoader {
199200
///
200201
/// Note that even if this check succeeds, errors may still occur if the
201202
/// module is loaded in full.
202-
virtual bool canImportModule(ImportPath::Element named) = 0;
203+
virtual bool canImportModule(ImportPath::Element named,
204+
llvm::VersionTuple version,
205+
bool underlyingVersion) = 0;
203206

204207
/// Import a module with the given module path.
205208
///

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ class ClangImporter final : public ClangModuleLoader {
186186
///
187187
/// Note that even if this check succeeds, errors may still occur if the
188188
/// module is loaded in full.
189-
virtual bool canImportModule(ImportPath::Element named) override;
189+
virtual bool canImportModule(ImportPath::Element named, llvm::VersionTuple version,
190+
bool underlyingVersion) override;
190191

191192
/// Import a module with the given module path.
192193
///

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
150150
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
151151
bool IsFramework) override;
152152

153-
bool canImportModule(ImportPath::Element mID) override;
153+
bool canImportModule(ImportPath::Element mID, llvm::VersionTuple version,
154+
bool underlyingVersion) override;
154155

155156
bool isCached(StringRef DepPath) override { return false; };
156157

include/swift/Sema/SourceLoader.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class SourceLoader : public ModuleLoader {
5757
///
5858
/// Note that even if this check succeeds, errors may still occur if the
5959
/// module is loaded in full.
60-
virtual bool canImportModule(ImportPath::Element named) override;
60+
virtual bool canImportModule(ImportPath::Element named,
61+
llvm::VersionTuple version,
62+
bool underlyingVersion) override;
6163

6264
/// Import a module with the given module path.
6365
///

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ class SerializedModuleLoaderBase : public ModuleLoader {
166166
///
167167
/// Note that even if this check succeeds, errors may still occur if the
168168
/// module is loaded in full.
169-
virtual bool canImportModule(ImportPath::Element named) override;
169+
virtual bool canImportModule(ImportPath::Element named,
170+
llvm::VersionTuple version,
171+
bool underlyingVersion) override;
170172

171173
/// Import a module with the given module path.
172174
///
@@ -274,7 +276,8 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
274276
public:
275277
virtual ~MemoryBufferSerializedModuleLoader();
276278

277-
bool canImportModule(ImportPath::Element named) override;
279+
bool canImportModule(ImportPath::Element named, llvm::VersionTuple version,
280+
bool underlyingVersion) override;
278281
ModuleDecl *
279282
loadModule(SourceLoc importLoc,
280283
ImportPath::Module path) override;

lib/AST/ASTContext.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,7 +1955,9 @@ bool ASTContext::shouldPerformTypoCorrection() {
19551955
return NumTypoCorrections <= LangOpts.TypoCorrectionLimit;
19561956
}
19571957

1958-
bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName) const {
1958+
bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName,
1959+
llvm::VersionTuple version,
1960+
bool underlyingVersion) const {
19591961
// If this module has already been successfully imported, it is importable.
19601962
if (getLoadedModule(ImportPath::Module::Builder(ModuleName).get()) != nullptr)
19611963
return true;
@@ -1966,25 +1968,29 @@ bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName) const {
19661968

19671969
// Otherwise, ask the module loaders.
19681970
for (auto &importer : getImpl().ModuleLoaders) {
1969-
if (importer->canImportModule(ModuleName)) {
1971+
if (importer->canImportModule(ModuleName, version, underlyingVersion)) {
19701972
return true;
19711973
}
19721974
}
19731975

19741976
return false;
19751977
}
19761978

1977-
bool ASTContext::canImportModule(ImportPath::Element ModuleName) {
1978-
if (canImportModuleImpl(ModuleName)) {
1979+
bool ASTContext::canImportModule(ImportPath::Element ModuleName,
1980+
llvm::VersionTuple version,
1981+
bool underlyingVersion) {
1982+
if (canImportModuleImpl(ModuleName, version, underlyingVersion)) {
19791983
return true;
19801984
} else {
19811985
FailedModuleImportNames.insert(ModuleName.Item);
19821986
return false;
19831987
}
19841988
}
19851989

1986-
bool ASTContext::canImportModule(ImportPath::Element ModuleName) const {
1987-
return canImportModuleImpl(ModuleName);
1990+
bool ASTContext::canImportModule(ImportPath::Element ModuleName,
1991+
llvm::VersionTuple version,
1992+
bool underlyingVersion) const {
1993+
return canImportModuleImpl(ModuleName, version, underlyingVersion);
19881994
}
19891995

19901996
ModuleDecl *

lib/ClangImporter/ClangImporter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,9 @@ bool ClangImporter::isModuleImported(const clang::Module *M) {
17311731
return M->NameVisibility == clang::Module::NameVisibilityKind::AllVisible;
17321732
}
17331733

1734-
bool ClangImporter::canImportModule(ImportPath::Element moduleID) {
1734+
bool ClangImporter::canImportModule(ImportPath::Element moduleID,
1735+
llvm::VersionTuple version,
1736+
bool underlyingVersion) {
17351737
// Look up the top-level module to see if it exists.
17361738
// FIXME: This only works with top-level modules.
17371739
auto &clangHeaderSearch = Impl.getClangPreprocessor().getHeaderSearchInfo();

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,7 +1629,7 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
16291629
}
16301630

16311631
bool ExplicitSwiftModuleLoader::canImportModule(
1632-
ImportPath::Element mID) {
1632+
ImportPath::Element mID, llvm::VersionTuple version, bool underlyingVersion) {
16331633
StringRef moduleName = mID.Item.str();
16341634
auto it = Impl.ExplicitModuleMap.find(moduleName);
16351635
// If no provided explicit module matches the name, then it cannot be imported.

lib/Parse/ParseIfConfig.cpp

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,57 @@ static bool isValidVersion(const version::Version &Version,
7676
llvm_unreachable("unsupported unary operator");
7777
}
7878

79+
static llvm::VersionTuple getCanImportVersion(TupleExpr *te,
80+
DiagnosticEngine *D,
81+
bool &underlyingVersion) {
82+
llvm::VersionTuple result;
83+
if (te->getElements().size() != 2) {
84+
if (D) {
85+
D->diagnose(te->getLoc(), diag::canimport_two_parameters);
86+
}
87+
return result;
88+
}
89+
auto label = te->getElementName(1);
90+
auto subE = te->getElement(1);
91+
if (label.str() == "version") {
92+
underlyingVersion = false;
93+
} else if (label.str() == "underlyingVersion") {
94+
underlyingVersion = true;
95+
} else {
96+
if (D) {
97+
D->diagnose(subE->getLoc(), diag::canimport_label);
98+
}
99+
return result;
100+
}
101+
if (auto *nle = dyn_cast<NumberLiteralExpr>(subE)) {
102+
auto digits = nle->getDigitsText();
103+
if (result.tryParse(digits)) {
104+
if (D) {
105+
D->diagnose(nle->getLoc(), diag::canimport_version, digits);
106+
}
107+
}
108+
}
109+
return result;
110+
}
111+
112+
static Expr *getSingleSubExp(Expr *exp, StringRef kindName,
113+
DiagnosticEngine *D) {
114+
if (auto *pe = dyn_cast<ParenExpr>(exp)) {
115+
return pe->getSubExpr();
116+
}
117+
if (kindName == "canImport") {
118+
if (auto *te = dyn_cast<TupleExpr>(exp)) {
119+
bool underlyingVersion;
120+
if (D) {
121+
// Diagnose canImport syntax
122+
(void)getCanImportVersion(te, D, underlyingVersion);
123+
}
124+
return te->getElement(0);
125+
}
126+
}
127+
return nullptr;
128+
}
129+
79130
/// The condition validator.
80131
class ValidateIfConfigCondition :
81132
public ExprVisitor<ValidateIfConfigCondition, Expr*> {
@@ -208,13 +259,11 @@ class ValidateIfConfigCondition :
208259
return nullptr;
209260
}
210261

211-
auto *ArgP = dyn_cast<ParenExpr>(E->getArg());
212-
if (!ArgP) {
262+
Expr *Arg = getSingleSubExp(E->getArg(), *KindName, &D);
263+
if (!Arg) {
213264
D.diagnose(E->getLoc(), diag::platform_condition_expected_one_argument);
214265
return nullptr;
215266
}
216-
Expr *Arg = ArgP->getSubExpr();
217-
218267
// '_compiler_version' '(' string-literal ')'
219268
if (*KindName == "_compiler_version") {
220269
auto SLE = dyn_cast<StringLiteralExpr>(Arg);
@@ -424,8 +473,7 @@ class EvaluateIfConfigCondition :
424473

425474
bool visitCallExpr(CallExpr *E) {
426475
auto KindName = getDeclRefStr(E->getFn());
427-
auto *Arg = cast<ParenExpr>(E->getArg())->getSubExpr();
428-
476+
auto *Arg = getSingleSubExp(E->getArg(), KindName, nullptr);
429477
if (KindName == "_compiler_version") {
430478
auto Str = cast<StringLiteralExpr>(Arg)->getValue();
431479
auto Val = version::Version::parseCompilerVersionString(
@@ -450,7 +498,13 @@ class EvaluateIfConfigCondition :
450498
}
451499
} else if (KindName == "canImport") {
452500
auto Str = extractExprSource(Ctx.SourceMgr, Arg);
453-
return Ctx.canImportModule({ Ctx.getIdentifier(Str) , E->getLoc() });
501+
bool underlyingModule = false;
502+
llvm::VersionTuple version;
503+
if (auto *te = dyn_cast<TupleExpr>(E->getArg())) {
504+
version = getCanImportVersion(te, nullptr, underlyingModule);
505+
}
506+
return Ctx.canImportModule({ Ctx.getIdentifier(Str) , E->getLoc() },
507+
version, underlyingModule);
454508
}
455509

456510
auto Val = getDeclRefStr(Arg);

lib/Sema/SourceLoader.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ void SourceLoader::collectVisibleTopLevelModuleNames(
6262
// TODO: Implement?
6363
}
6464

65-
bool SourceLoader::canImportModule(ImportPath::Element ID) {
65+
bool SourceLoader::canImportModule(ImportPath::Element ID,
66+
llvm::VersionTuple version,
67+
bool underlyingVersion) {
6668
// Search the memory buffers to see if we can find this file on disk.
6769
FileOrError inputFileOrError = findModule(Ctx, ID.Item.str(),
6870
ID.Loc);

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ Optional<ModuleDependencies> SerializedModuleLoaderBase::getModuleDependencies(
192192
assert(isa<PlaceholderSwiftModuleScanner>(scanners[0].get()) &&
193193
"Expected PlaceholderSwiftModuleScanner as the first dependency scanner loader.");
194194
for (auto &scanner : scanners) {
195-
if (scanner->canImportModule({moduleId, SourceLoc()})) {
195+
if (scanner->canImportModule({moduleId, SourceLoc()},
196+
llvm::VersionTuple(), false)) {
196197
// Record the dependencies.
197198
cache.recordDependencies(moduleName, *(scanner->dependencies));
198199
return std::move(scanner->dependencies);

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
948948
}
949949

950950
bool SerializedModuleLoaderBase::canImportModule(
951-
ImportPath::Element mID) {
951+
ImportPath::Element mID, llvm::VersionTuple version, bool underlyingVersion) {
952952
// Look on disk.
953953
SmallVector<char, 0> *unusedModuleInterfacePath = nullptr;
954954
std::unique_ptr<llvm::MemoryBuffer> *unusedModuleBuffer = nullptr;
@@ -962,7 +962,7 @@ bool SerializedModuleLoaderBase::canImportModule(
962962
}
963963

964964
bool MemoryBufferSerializedModuleLoader::canImportModule(
965-
ImportPath::Element mID) {
965+
ImportPath::Element mID, llvm::VersionTuple version, bool underlyingVersion) {
966966
// See if we find it in the registered memory buffers.
967967
return MemoryBuffers.count(mID.Item.str());
968968
}

test/Parse/ifconfig_expr.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,33 @@ func ifconfigExprInExpr(baseExpr: MyStruct) {
125125
#endif
126126
)
127127
}
128+
129+
func canImportVersioned() {
130+
#if canImport(A, version: 2)
131+
let a = 1
132+
#endif
133+
134+
#if canImport(A, version: 2.2)
135+
let a = 1
136+
#endif
137+
138+
#if canImport(A, underlyingVersion: 4)
139+
let a = 1
140+
#endif
141+
142+
#if canImport(A, underlyingVersion: 2.200)
143+
let a = 1
144+
#endif
145+
146+
#if canImport(A, unknown: 2.2) // expected-error {{2nd parameter of canImport should be labeled as version or underlyingVersion}}
147+
let a = 1
148+
#endif
149+
150+
#if canImport(A, 2.2) // expected-error {{2nd parameter of canImport should be labeled as version or underlyingVersion}}
151+
let a = 1
152+
#endif
153+
154+
#if canImport(A, 2.2, 1.1) // expected-error {{canImport can take only two parameters}}
155+
let a = 1
156+
#endif
157+
}

0 commit comments

Comments
 (0)