Skip to content

[Version] Don't allow effective sub-versions, only major versions #5275

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 3 commits into from
Oct 19, 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
5 changes: 5 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ ERROR(error_no_source_location_scope_map,none,
"-dump-scope-maps argument must be 'expanded' or a list of source locations",
())

NOTE(note_swift_version_major, none,
"use major version, as in '-swift-version %0'", (unsigned))
NOTE(note_valid_swift_versions, none,
"valid arguments to '-swift-version' are %0", (StringRef))

ERROR(error_mode_cannot_emit_dependencies,none,
"this mode does not support emitting dependency files", ())
ERROR(error_mode_cannot_emit_header,none,
Expand Down
9 changes: 9 additions & 0 deletions include/swift/Basic/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class Version {
/// Whether this version is in the Swift 3 family
bool isVersion3() const { return !empty() && Components[0] == 3; }

/// Return this Version struct with minor and sub-minor components stripped
Version asMajorVersion() const;

/// Parse a version in the form used by the _compiler_version \#if condition.
static Version parseCompilerVersionString(StringRef VersionString,
SourceLoc Loc,
Expand All @@ -124,6 +127,12 @@ class Version {
/// Returns a version from the currently defined SWIFT_VERSION_MAJOR and
/// SWIFT_VERSION_MINOR.
static Version getCurrentLanguageVersion();

// Whitelist of backward-compatibility versions that we permit passing as
// -swift-version <vers>
static std::array<StringRef, 2> getValidEffectiveVersions() {
return {{"3", "4"}};
};
};

bool operator>=(const Version &lhs, const Version &rhs);
Expand Down
27 changes: 11 additions & 16 deletions lib/Basic/Version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,29 +310,24 @@ Version::operator clang::VersionTuple() const
}
}

bool
Version::isValidEffectiveLanguageVersion() const
{
// Whitelist of backward-compatibility versions that we permit passing as
// -swift-version <vers>
char const *whitelist[] = {
// Swift 3 family
"3",
"3.0",

// Swift 4 family
"4",
"4.0",
};
for (auto const i : whitelist) {
auto v = parseVersionString(i, SourceLoc(), nullptr);
bool Version::isValidEffectiveLanguageVersion() const {
for (auto verStr : getValidEffectiveVersions()) {
auto v = parseVersionString(verStr, SourceLoc(), nullptr);
assert(v.hasValue());
if (v == *this)
return true;
}
return false;
}

Version Version::asMajorVersion() const {
if (empty())
return {};
Version res;
res.Components.push_back(Components[0]);
return res;
}

bool operator>=(const class Version &lhs,
const class Version &rhs) {

Expand Down
23 changes: 21 additions & 2 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,26 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
return false;
}

static void diagnoseSwiftVersion(Optional<version::Version> &vers, Arg *verArg,
ArgList &Args, DiagnosticEngine &diags) {
// General invalid version error
diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
verArg->getAsString(Args), verArg->getValue());

// Check for an unneeded minor version, otherwise just list valid verions
if (vers.hasValue() && !vers.getValue().empty() &&
vers.getValue().asMajorVersion().isValidEffectiveLanguageVersion()) {
diags.diagnose(SourceLoc(), diag::note_swift_version_major,
vers.getValue()[0]);
} else {
// Note valid versions instead
auto validVers = version::Version::getValidEffectiveVersions();
auto versStr =
"'" + llvm::join(validVers.begin(), validVers.end(), "', '") + "'";
diags.diagnose(SourceLoc(), diag::note_valid_swift_versions, versStr);
}
}

static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
DiagnosticEngine &Diags,
const FrontendOptions &FrontendOpts) {
Expand All @@ -773,8 +793,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
vers.getValue().isValidEffectiveLanguageVersion()) {
Opts.EffectiveLanguageVersion = vers.getValue();
} else {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
A->getAsString(Args), A->getValue());
diagnoseSwiftVersion(vers, A, Args, Diags);
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/APINotes/versioned.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: rm -rf %t && mkdir -p %t

// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -print-regular-comments -swift-version 4.0 | %FileCheck -check-prefix=CHECK-SWIFT-4 %s
// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -print-regular-comments -swift-version 4 | %FileCheck -check-prefix=CHECK-SWIFT-4 %s

// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -print-regular-comments -swift-version 3.0 | %FileCheck -check-prefix=CHECK-SWIFT-3 %s
// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-module -source-filename %s -module-to-print=APINotesFrameworkTest -function-definitions=false -print-regular-comments -swift-version 3 | %FileCheck -check-prefix=CHECK-SWIFT-3 %s

// CHECK-SWIFT-4: func jumpTo(x: Double, y: Double, z: Double)
// CHECK-SWIFT-3: func jumpTo(x: Double, y: Double, z: Double)
Expand Down
9 changes: 8 additions & 1 deletion test/Driver/swift-version.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
// RUN: %target-swiftc_driver -swift-version 3 %s
// RUN: %target-swiftc_driver -swift-version 3.0 %s
// RUN: not %target-swiftc_driver -swift-version foo %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 1 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 2 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 2.3 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 7 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 7.2 %s 2>&1 | %FileCheck --check-prefix BAD %s
// RUN: not %target-swiftc_driver -swift-version 3.0 %s 2>&1 | %FileCheck --check-prefix FIXIT_3 %s
// RUN: not %target-swiftc_driver -swift-version 3.3 %s 2>&1 | %FileCheck --check-prefix FIXIT_3 %s
// RUN: not %target-swiftc_driver -swift-version 4.3 %s 2>&1 | %FileCheck --check-prefix FIXIT_4 %s

// BAD: invalid value
// BAD: note: valid arguments to '-swift-version' are '3', '4'

// FIXIT_3: use major version, as in '-swift-version 3'
// FIXIT_4: use major version, as in '-swift-version 4'

let x = 1
4 changes: 2 additions & 2 deletions test/api-digester/compare-dump.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: rm -rf %t.module-cache && mkdir -p %t.module-cache
// RUN: %swift -emit-module -o %t.mod/cake1.swiftmodule %S/Inputs/cake1.swift -parse-as-library
// RUN: %swift -emit-module -o %t.mod/cake2.swiftmodule %S/Inputs/cake2.swift -parse-as-library
// RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3.0 -I %t.mod
// RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3.0 -I %t.mod
// RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %t.mod
// RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %t.mod
// RUN: %api-digester -diagnose-sdk --input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result
// RUN: diff -u %S/Outputs/Cake.txt %t.result
2 changes: 1 addition & 1 deletion test/api-digester/dump-module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// RUN: rm -rf %t.sdk && mkdir -p %t.sdk
// RUN: rm -rf %t.module-cache && mkdir -p %t.module-cache
// RUN: %swift -emit-module -o %t.mod/cake.swiftmodule %S/Inputs/cake.swift -parse-as-library
// RUN: %api-digester -dump-sdk -module cake -o %t.dump.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3.0 -I %t.mod
// RUN: %api-digester -dump-sdk -module cake -o %t.dump.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %t.mod
// RUN: diff -u %t.dump.json %S/Outputs/cake.json
// RUN: %api-digester -diagnose-sdk --input-paths %t.dump.json -input-paths %S/Outputs/cake.json
2 changes: 1 addition & 1 deletion test/api-digester/source-stability.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// REQUIRES: OS=macosx
// RUN: rm -rf %S/tmp && mkdir %S/tmp && mkdir %S/tmp/module-cache && mkdir %S/tmp/dummy.sdk
// RUN: %api-digester -dump-sdk -module Swift -o %S/tmp/current-stdlib.json -module-cache-path %S/tmp/module-cache -sdk %S/tmp/dummy.sdk -swift-version 3.0
// RUN: %api-digester -dump-sdk -module Swift -o %S/tmp/current-stdlib.json -module-cache-path %S/tmp/module-cache -sdk %S/tmp/dummy.sdk -swift-version 3
// RUN: %api-digester -diagnose-sdk -input-paths %S/stdlib-stable.json -input-paths %S/tmp/current-stdlib.json >> %S/tmp/changes.txt
// RUN: %clang -E -P -x c %S/source-stability.swift.expected -o - | sed '/^\s*$/d' > %S/tmp/source-stability.swift.expected
// RUN: %clang -E -P -x c %S/tmp/changes.txt -o - | sed '/^\s*$/d' > %S/tmp/changes.txt.tmp
Expand Down
4 changes: 2 additions & 2 deletions test/attr/attr_availability_swift_deserialize.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/OldAndNew.swiftmodule -module-name OldAndNew %S/Inputs/OldAndNew.swift
// RUN: not %target-swift-frontend -parse -I %t -swift-version 3.0 %s 2>&1 | %FileCheck -check-prefix THREE %s
// RUN: not %target-swift-frontend -parse -I %t -swift-version 4.0 %s 2>&1 | %FileCheck -check-prefix FOUR %s
// RUN: not %target-swift-frontend -parse -I %t -swift-version 3 %s 2>&1 | %FileCheck -check-prefix THREE %s
// RUN: not %target-swift-frontend -parse -I %t -swift-version 4 %s 2>&1 | %FileCheck -check-prefix FOUR %s

import OldAndNew

Expand Down