diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index d6d417d6e7922..ef28ed87b2483 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -108,6 +108,7 @@ set(SWIFT_BENCH_MODULES single-source/LuhnAlgoLazy single-source/MapReduce single-source/Memset + single-source/Mirror single-source/MonteCarloE single-source/MonteCarloPi single-source/NSDictionaryCastToSwift diff --git a/benchmark/single-source/Mirror.swift b/benchmark/single-source/Mirror.swift new file mode 100644 index 0000000000000..94e9de21153ae --- /dev/null +++ b/benchmark/single-source/Mirror.swift @@ -0,0 +1,105 @@ +//===--- Mirror.swift ------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// This test measures performance of Mirror and related things. +import TestsUtils + +public let TypeName = BenchmarkInfo( + name: "TypeName", + runFunction: run_TypeName, + tags: [.api, .String]) + +public let MirrorDefault = BenchmarkInfo( + name: "MirrorDefault", + runFunction: run_MirrorDefault, + tags: [.api, .String]) + +struct S1 { var s: String; var d: Double } +struct S2 { var i: Int; var a: [Range] } + +class C { var i: Int = 0 } +class D: C { var s: String = "" } + +enum E { + case a,b(Int) +} + +struct G { var t: T } +class H: C { var t: T; init(_ t: T) { self.t = t }} + +public func run_MirrorDefault(scale: Int) { + let N = 100*scale + + let s1 = S1(s: "foo", d: 3.14) + let s2 = S2(i: 42, a: [0..<4]) + let c = C() + let d = D() + let e = E.a + let f = E.b(99) + let g = G(t: 12.3) + let h = H<[Int]>([1,2,3]) + + var str = "" + + for _ in 0..(t: 12.3),Mirror.H>") +} + +func typename(of: T.Type) -> String { + "\(T.self)" +} + +public func run_TypeName(scale: Int) { + let N = 1_000*scale + var a: [String] = [] + a.reserveCapacity(16) + + for _ in 0...self)) + a.append(typename(of: G.self)) + a.append(typename(of: G.self)) + a.append(typename(of: H.self)) + a.append(typename(of: [S1].self)) + a.append(typename(of: [G].self)) + a.append(typename(of: [H].self)) + a.append(typename(of: S1?.self)) + a.append(typename(of: C?.self)) + blackHole(a) + } + + let expected = ["S1", + "S2", + "C", + "D", + "G", + "G", + "G", + "H", + "Array", + "Array>", + "Array>", + "Optional", + "Optional", + ] + CheckResults(a == expected) +} diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift index b999acb8b41ac..cbf8aaedaa25c 100644 --- a/benchmark/utils/main.swift +++ b/benchmark/utils/main.swift @@ -96,6 +96,7 @@ import LuhnAlgoEager import LuhnAlgoLazy import MapReduce import Memset +import Mirror import MonteCarloE import MonteCarloPi import NibbleSort @@ -281,6 +282,7 @@ registerBenchmark(LuhnAlgoEager) registerBenchmark(LuhnAlgoLazy) registerBenchmark(MapReduce) registerBenchmark(Memset) +registerBenchmark(MirrorDefault) registerBenchmark(MonteCarloE) registerBenchmark(MonteCarloPi) registerBenchmark(NSDictionaryCastToSwift) @@ -366,6 +368,7 @@ registerBenchmark(Suffix) registerBenchmark(SuperChars) registerBenchmark(TwoSum) registerBenchmark(TypeFlood) +registerBenchmark(TypeName) registerBenchmark(UTF8Decode) registerBenchmark(Walsh) registerBenchmark(WordCount) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 6ac3c62315c9f..5ed289be208f7 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -75,25 +75,10 @@ function(_set_target_prefix_and_suffix target kind sdk) endif() endfunction() -function(is_darwin_based_sdk sdk_name out_var) - if ("${sdk_name}" STREQUAL "OSX" OR - "${sdk_name}" STREQUAL "IOS" OR - "${sdk_name}" STREQUAL "IOS_SIMULATOR" OR - "${sdk_name}" STREQUAL "TVOS" OR - "${sdk_name}" STREQUAL "TVOS_SIMULATOR" OR - "${sdk_name}" STREQUAL "WATCHOS" OR - "${sdk_name}" STREQUAL "WATCHOS_SIMULATOR") - set(${out_var} TRUE PARENT_SCOPE) - else() - set(${out_var} FALSE PARENT_SCOPE) - endif() -endfunction() - # Usage: # _add_host_variant_c_compile_link_flags(name) function(_add_host_variant_c_compile_link_flags name) - is_darwin_based_sdk("${SWIFT_HOST_VARIANT_SDK}" IS_DARWIN) - if(IS_DARWIN) + if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS) set(DEPLOYMENT_VERSION "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_DEPLOYMENT_VERSION}") endif() @@ -107,7 +92,7 @@ function(_add_host_variant_c_compile_link_flags name) set(_sysroot "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCH_${SWIFT_HOST_VARIANT_ARCH}_PATH}") - if(IS_DARWIN) + if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS) target_compile_options(${name} PRIVATE -isysroot;${_sysroot}) elseif(NOT SWIFT_COMPILER_IS_MSVC_LIKE AND NOT "${_sysroot}" STREQUAL "/") target_compile_options(${name} PRIVATE --sysroot=${_sysroot}) @@ -122,7 +107,7 @@ function(_add_host_variant_c_compile_link_flags name) endif() endif() - if(IS_DARWIN) + if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS) # We collate -F with the framework path to avoid unwanted deduplication # of options by target_compile_options -- this way no undesired # side effects are introduced should a new search path be added. @@ -546,14 +531,10 @@ function(add_swift_host_library name) "LINKER:-current_version,${SWIFT_COMPILER_VERSION}") endif() - set(DEPLOYMENT_VERSION "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_DEPLOYMENT_VERSION}") - # MSVC, clang-cl, gcc don't understand -target. - if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT SWIFT_COMPILER_IS_MSVC_LIKE) - get_target_triple(target target_variant "${SWIFT_HOST_VARIANT_SDK}" "${SWIFT_HOST_VARIANT_ARCH}" - MACCATALYST_BUILD_FLAVOR "" - DEPLOYMENT_VERSION "${DEPLOYMENT_VERSION}") - target_link_options(${name} PRIVATE -target;${target}) - endif() + get_target_triple(target target_variant "${SWIFT_HOST_VARIANT_SDK}" "${SWIFT_HOST_VARIANT_ARCH}" + MACCATALYST_BUILD_FLAVOR "" + DEPLOYMENT_VERSION "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_DEPLOYMENT_VERSION}") + target_link_options(${name} PRIVATE -target;${target}) endif() add_dependencies(dev ${name}) diff --git a/docs/Branches.md b/docs/Branches.md index e533c3af5e351..083f89610419d 100644 --- a/docs/Branches.md +++ b/docs/Branches.md @@ -58,15 +58,22 @@ You can use any of the branch names as the argument to `--scheme`, such as `mast - LLVM Project: the destination branch depends on the kind of change that must be made: - 1) LLVM Project changes that don't depend on Swift: New commits go to `master` in the upstream [llvm-project](https://github.com/llvm/llvm-project). + 1) LLVM Project changes that don't depend on Swift + + - New commits go to `master` in the upstream [llvm-project](https://github.com/llvm/llvm-project). - ... then these commits can be cherry-picked to an appropriate, `swift/master` aligned `apple/stable/*` branch in Apple's fork of [llvm-project](https://github.com/apple/llvm-project). Please see - [Apple's branching scheme](https://github.com/apple/llvm-project/blob/apple/master/apple-docs/AppleBranchingScheme.md) - document to determine which `apple/stable/*` branch you should cherry-pick to. + - Then cherry-pick these commits to an appropriate, `swift/master` aligned `apple/stable/*` branch in Apple's fork of [llvm-project](https://github.com/apple/llvm-project). Please see [Apple's branching scheme](https://github.com/apple/llvm-project/blob/apple/master/apple-docs/AppleBranchingScheme.md) document to determine which `apple/stable/*` branch you should cherry-pick to. + + Note that **no new changes should be submitted directly to `apple/master`**. We are actively working on eliminating the differences from upstream LLVM. - 2) Changes that depend on Swift (this only applies to LLDB): new commits go to `swift/master-next` + 2) Changes that depend on Swift (this only applies to LLDB) + - New commits go to `swift/master` (_not_ an `apple/stable/*` branch, as these shouldn't contain changes that depend on Swift). - ...then cherry-pick to the release branch (`swift/swift-x.y-branch`) if necessary, following the appropriate release process. (Usually this means filling out a standard template, finding someone to review your code if that hasn't already happened, and getting approval from that repo's *release manager.)* + - Then cherry-pick these commits to `swift/master-next`. + + - If necessary, cherry-pick to the release branch (`swift/release/x.y`), following the appropriate release process. (Usually this means filling out a standard template, finding someone to review your code if that hasn't already happened, and getting approval from that repo's *release manager.)* + + In the long term we want to eliminate the differences from upstream LLVM for these changes as well, but for now there is no concrete plan. So, submitting to `swift/master-next` continues to be allowed. ## Automerging diff --git a/docs/DebuggingTheCompiler.md b/docs/DebuggingTheCompiler.md index 51c6fe0440c90..061ed609780a3 100644 --- a/docs/DebuggingTheCompiler.md +++ b/docs/DebuggingTheCompiler.md @@ -64,19 +64,19 @@ Here is how to dump the IR after the main phases of the Swift compiler * **Parser** To print the AST after parsing: -```bash +```sh swiftc -dump-ast -O file.swift ``` * **SILGen** To print the SIL immediately after SILGen: -```bash +```sh swiftc -emit-silgen -O file.swift ``` * **Mandatory SIL passes** To print the SIL after the mandatory passes: -```bash +```sh swiftc -emit-sil -Onone file.swift ``` @@ -87,25 +87,25 @@ swiftc -emit-sil -Onone file.swift * **Performance SIL passes** To print the SIL after the complete SIL optimization pipeline: -```bash +```sh swiftc -emit-sil -O file.swift ``` * **IRGen** To print the LLVM IR after IR generation: -```bash +```sh swiftc -emit-ir -Xfrontend -disable-llvm-optzns -O file.swift ``` * **LLVM passes** To print the LLVM IR after LLVM passes: -```bash +```sh swiftc -emit-ir -O file.swift ``` * **Code generation** To print the final generated code: -```bash +```sh swiftc -S -O file.swift ``` diff --git a/docs/HowToGuides/RunningIncludeWhatYouUse.md b/docs/HowToGuides/RunningIncludeWhatYouUse.md new file mode 100644 index 0000000000000..1ffa7e2e7571f --- /dev/null +++ b/docs/HowToGuides/RunningIncludeWhatYouUse.md @@ -0,0 +1,286 @@ +# How to run include-what-you-use (IWYU) on the Swift project + +[include-what-you-use (IWYU)](https://include-what-you-use.org) is a +Clang-based tool that analyzes `#include`s in a file and makes suggestions to +add or remove `#include`s based on usage in the code. This has two key benefits: + +- Removing unused `#include` statements reduces work for the compiler. +- Adding `#include` statements for usage avoids a refactoring in a header + file from breaking downstream implementation files due to accidental + transitive usage. + +Running IWYU is a bit tricky, so this how-to guide provides the steps for how +to get it up and running on the Swift project for macOS. +If you get IWYU working on a different platform and some steps need to be +changed, please update this document with platform-specific steps. + +- [Pre-requisites](#pre-requisites) +- [Cloning and branch checkout](#cloning-and-branch-checkout) +- [Building IWYU](#building-iwyu) +- [Running IWYU](#running-iwyu) +- [Debugging](#debugging) + +## Pre-requisites + +- A built Swift project with exported compilation commands. + By default, compilation commands are generated in the file + `build/[BuildSystem]-[BuildVariant]/swift-[target]/compile_commands.json`. + Check that this file is present before proceeding. + - If this file is missing, try building with + `CMAKE_EXPORT_COMPILATION_COMMANDS=ON`. If you use `build-script` to + manage your builds, you can do this with + ``` + swift/utils/build-script \ + --extra-cmake-options='-DCMAKE_EXPORT_COMPILATION_COMMANDS=ON' + ``` +- Install [`jq`](https://stedolan.github.io/jq/). It's not strictly necessary, + but we will use it for some JSON munging. + +## Cloning and branch checkout + +The directory structure we will be using is + +``` +swift-project/ + |--- build/ + | |--- [BuildSystem]-[BuildVariant]/ + | | |--- swift-[target]/ + | | | |--- compile_commands.json + | | | `--- ... + | | |--- iwyu-[target]/ + | | `--- ... + | `--- ... + |--- swift/ + |--- iwyu/ + | |--- src/ + | |--- logs/ + | `--- scripts/ + `--- ... +``` + +As a running example, the description below uses `[BuildSystem] = Ninja`, +`[BuildVariant] = ReleaseAssert` and `[target] = macosx-x86_64`. + +Start with `swift-project` as the working directory. + +1. Check out IWYU. + ``` + mkdir -p iwyu/src + git clone https://github.com/include-what-you-use/include-what-you-use.git iwyu/src + ``` +2. Find out the version of the `clang` built recently. + ``` + build/Ninja-ReleaseAssert/llvm-macosx-x86_64/bin/clang --version + ``` + This should say something like `clang version 10.0.0` or similar. +3. Based on the `clang` version, make sure you check out the correct branch. + ``` + git -C iwyu/src checkout clang_10 + ``` + +## Building IWYU + +1. Configure IWYU with CMake. + ``` + cmake -G Ninja \ + -DCMAKE_PREFIX_PATH=build/Ninja-ReleaseAssert/llvm-macosx-x86_64 \ + -DCMAKE_CXX_STANDARD=14 \ + -B build/Ninja-ReleaseAssert/iwyu-macosx-x86_64 \ + iwyu/src + ``` +2. Build IWYU + ``` + cmake --build build/Ninja-ReleaseAssert/iwyu-macosx-x86_64 + ``` +3. Create an extra symlink so IWYU can find necessary Clang headers: + ``` + ln -sF build/Ninja-ReleaseAssert/llvm-macosx-x86_64/lib build/Ninja-ReleaseAssert/iwyu-macosx-x86_64/lib + ``` +4. Spot check IWYU for a basic C example. + ``` + echo '#include ' > tmp.c + ./bin/include-what-you-use tmp.c -E -o /dev/null \ + -I "$(xcrun --show-sdk-path)/usr/include" + rm tmp.c + ``` + You should see output like: + ``` + tmp.c should add these lines: + + tmp.c should remove these lines: + - #include // lines 1-1 + + The full include-list for tmp.c: + --- + ``` +5. Spot check IWYU for a basic C++ example. Notice the extra C++-specific + include path. + ``` + echo '#include \n#include ' > tmp.cpp + ./bin/include-what-you-use tmp.cpp -E -o /dev/null \ + -I "$(clang++ -print-resource-dir)/../../../include/c++/v1" \ + -I "$(xcrun --show-sdk-path)/usr/include" + rm tmp.cpp + ``` + You should see output like: + ``` + tmp.cpp should add these lines: + + tmp.cpp should remove these lines: + - #include // lines 2-2 + - #include // lines 1-1 + + The full include-list for tmp.cpp: + --- + ``` + +## Running IWYU + +1. Create a directory, say `iwyu/scripts`, and copy the following script there. + + ``` + #!/usr/bin/env bash + + # iwyu_run.sh + set -eu + + SWIFT_PROJECT_DIR="$HOME/swift-project" + SWIFT_BUILD_DIR="$SWIFT_PROJECT_DIR/build/Ninja-ReleaseAssert/swift-macosx-x86_64" + + pushd "$SWIFT_BUILD_DIR" + + if [ -f original_compile_commands.json ]; then + mv original_compile_commands.json compile_commands.json + fi + + # HACK: The additional include path needs to be added before other include + # paths, it doesn't seem to work if we add it at the end. + # It is ok to rely on the presence of `-D__STDC_LIMIT_MACROS` flag, since + # it is added by the LLVM CMake configuration for all compilation commands. + ( EXTRA_CXX_INCLUDE_DIR="$(clang++ -print-resource-dir)/../../../include/c++/v1"; + cat compile_commands.json \ + | jq '[.[] | select(.file | test("\\.mm" | "\\.m") | not) | {directory: .directory, command: (.command + " -Wno-everything -ferror-limit=1"), file: .file}]' \ + | sed -e "s|-D__STDC_LIMIT_MACROS |-D__STDC_LIMIT_MACROS -I $EXTRA_CXX_INCLUDE_DIR |" \ + ) > filtered_compile_commands.json + + mv compile_commands.json original_compile_commands.json + mv filtered_compile_commands.json compile_commands.json + + mkdir -p "$SWIFT_PROJECT_DIR/iwyu/logs" + + ( PATH="$SWIFT_PROJECT_DIR/iwyu/build/bin:$PATH"; \ + "$SWIFT_PROJECT_DIR/iwyu/include-what-you-use/iwyu_tool.py" -p "$SWIFT_BUILD_DIR" + ) | tee "$SWIFT_PROJECT_DIR/iwyu/logs/suggestions.log" + + popd + + ``` + + We filter out Objective-C files because IWYU does not support Objective-C. + If that step is missed, you might hit errors like: + ``` + iwyu.cc:2097: Assertion failed: TODO(csilvers): for objc and clang lang extensions + ``` + +2. Update the `SWIFT_PROJECT_DIR` and `SWIFT_BUILD_DIR` variables based on + your project and build directories. + +3. Run the script. + ``` + chmod +x iwyu/scripts/iwyu_run.sh + iwyu/scripts/iwyu_run.sh + ``` + This will generate a log file under `iwyu/logs/suggestions.log`. + Note that IWYU might take several hours to run, depending on your system. + +NOTE: The IWYU README suggests several different ways of running IWYU on a +CMake project, including using the `CMAKE_CXX_INCLUDE_WHAT_YOU_USE` and +`CMAKE_C_INCLUDE_WHAT_YOU_USE` variables. At the time of writing, those did +not reliably work on macOS; suggestions were generated only for specific +subprojects (e.g. the stdlib) and not others (e.g. the compiler). +Using CMake variables also requires reconfiguring and rebuilding, which makes +debugging much more time-consuming. + +## Debugging + +While the above steps should work, in case you run into issues, you might find +the following steps for debugging helpful. + +### Try different include path ordering + +If you see errors with ``, or similar system headers, one thing that might +be happening is that the include paths are in the wrong order. Try moving the +include paths for the corresponding header before/after all other include paths. + +### Iterate on files one at a time + +Instead of trying to make changes to the CMake configuration and recompiling +the whole project, first try working on individual compilation commands as +emitted in `compile_commands.json` and see if IWYU works as expected. + +For each command, try replacing the compiler with the `include-what-you-use` +binary or `iwyu_stub.py` (below) to see if the behavior is as expected. +You may need to manually add some include paths as in `iwyu_run.sh` above. +Make sure you update paths in the script before it works. + +``` +#!/usr/bin/env python3 + +# iwyu_stub.py + +import os +import re +import subprocess +import sys + +clang_path = "/usr/bin/clang" +clangxx_path = "/usr/bin/clang++" +project_dir = "/Users/username/swift-project/" +iwyu_bin_path = project_dir + "iwyu/build/bin/include-what-you-use" +log_dir = project_dir + "iwyu/logs/" + +log_file = open(log_dir + "passthrough.log", "a+") + +argv = sys.argv + +def call_with_args(executable_path, args=argv): + new_argv = args[:] + new_argv[0] = executable_path + log_file.write("# about to run:\n{}\n#---\n".format(' '.join(new_argv))) + sys.exit(subprocess.call(new_argv)) + +# HACK: Relies on the compilation commands generated by CMake being +# of the form: +# +# /path/to/compiler -c MyFile.ext +# +def try_using_iwyu(argv): + return (argv[-2] == "-c") and ("/swift/" in argv[-1]) + +# Flag for quickly switching between IWYU and Clang for iteration. +# Useful for checking behavior for different include path combinations. +if argv[1] == "--forward-to-clangxx": + call_with_args(clangxx_path, args=([argv[0]] + argv[2:])) + +# Check that we are getting a compilation command. +if try_using_iwyu(argv): + _, ext = os.path.splitext(argv[-1]) + if ext == ".m": + call_with_args(clang_path) + elif ext == ".mm": + call_with_args(clangxx_path) + elif ext in [".cxx", ".cc", ".cpp", ".c"]: + call_with_args(iwyu_bin_path) + log_file.write( + "# Got a strange file extension.\n{}\n#---\n".format(' '.join(argv))) + call_with_args(iwyu_bin_path) +else: + # got something else, just forward to clang/clang++ + log_file.write( + "# Not going to try using iwyu.\n{}\n#---\n".format(' '.join(argv))) + _, ext = os.path.splitext(argv[-1]) + if ext == ".m" or ext == ".c": + call_with_args(clang_path) + else: + call_with_args(clangxx_path) +``` diff --git a/docs/Lexicon.md b/docs/Lexicon.md index ae8dc28224711..32e2d4acd8dfa 100644 --- a/docs/Lexicon.md +++ b/docs/Lexicon.md @@ -162,6 +162,25 @@ written "dupe". Pronounced the same way as the first syllable of A value whose type is a protocol composition (including a single protocol and *zero* protocols; the latter is the `Any` type). +## explicit module build + +A module build where all dependency modules (including Clang modules) are +passed to the compiler explicitly by an external build system, including +any modules in caches. See also: [implicit module build](#implicit-module-build) +and [fast dependency scanner](#fast-dependency-scanner). + +## fast dependency scanner + +A Swift compiler mode that scans a Swift module for import declarations and +resolves which modules will be loaded. It is based on the +[clang-scan-deps](https://llvm.org/devmtg/2019-04/slides/TechTalk-Lorenz-clang-scan-deps_Fast_dependency_scanning_for_explicit_modules.pdf) +library within Clang, for (Objective-)C modules, but is extended to also +understand textual Swift modules (.swiftinterface files). + +The fast dependency scanner outputs a graph of compilation steps which can be +used by a build system to schedule +[explicit module builds](#explicit-module-builds). + ## fragile Describes a type or function where making changes will break binary @@ -193,6 +212,17 @@ compared directly. ["if and only if"](https://en.wikipedia.org/wiki/If_and_only_if). This term comes from mathematics. +## implicit module build + +A module build where the compiler is free to transparently build dependent +modules (including Clang modules), and access modules in different caches as +necessary. For example, if a textual Swift module (.swiftinterface file) for +a dependency does not have a corresponding binary Swift module (.swiftmodulea +file), the compiler may transparently build a binary Swift module from the +textual one as a cache for future compiler jobs, without involving any external +build system that invoked the compiler. See also: +[explicit module build](#explicit-module-build). + ## interface type The type of a value or declaration outside its generic context. These types diff --git a/docs/README.md b/docs/README.md index 2d3f5d4d46d91..dceb55fa82bda 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,6 +69,9 @@ documentation, please create a thread on the Swift forums under the How to build Swift on Windows using Visual Studio. - [WindowsCrossCompile.md](/docs/WindowsCrossCompile.md): How to cross compile Swift for Windows on a non-Windows host OS. +- [RunningIncludeWhatYouUse.md](/docs/RunningIncludeWhatYouUse.md): + Describes how to run [include-what-you-use](https://include-what-you-use.org) + on the Swift project. ## Explanations diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 8049387c4e191..aa5ece97b10c2 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -2660,7 +2660,7 @@ struct TargetContextDescriptor { using ContextDescriptor = TargetContextDescriptor; -inline bool isCImportedModuleName(StringRef name) { +inline bool isCImportedModuleName(llvm::StringRef name) { // This does not include MANGLING_MODULE_CLANG_IMPORTER because that's // used only for synthesized declarations and not actual imported // declarations. @@ -2757,7 +2757,7 @@ class TargetGenericRequirementDescriptor { /// Retrieve the generic parameter that is the subject of this requirement, /// as a mangled type name. - StringRef getParam() const { + llvm::StringRef getParam() const { return swift::Demangle::makeSymbolicMangledNameStringRef(Param.get()); } @@ -2768,7 +2768,7 @@ class TargetGenericRequirementDescriptor { } /// Retrieve the right-hand type for a SameType or BaseClass requirement. - StringRef getMangledTypeName() const { + llvm::StringRef getMangledTypeName() const { assert(getKind() == GenericRequirementKind::SameType || getKind() == GenericRequirementKind::BaseClass); return swift::Demangle::makeSymbolicMangledNameStringRef(Type.get()); @@ -2999,7 +2999,7 @@ struct TargetExtensionContextDescriptor final using TrailingGenericContextObjects::getGenericContext; - StringRef getMangledExtendedContext() const { + llvm::StringRef getMangledExtendedContext() const { return Demangle::makeSymbolicMangledNameStringRef(ExtendedContext.get()); } @@ -3223,13 +3223,13 @@ struct TargetOpaqueTypeDescriptor final return (this ->template getTrailingObjects>())[i]; } - - StringRef getUnderlyingTypeArgument(unsigned i) const { + + llvm::StringRef getUnderlyingTypeArgument(unsigned i) const { assert(i < getNumUnderlyingTypeArguments()); const char *ptr = getUnderlyingTypeArgumentMangledName(i); return Demangle::makeSymbolicMangledNameStringRef(ptr); } - + static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::OpaqueType; } diff --git a/include/swift/ABI/TypeIdentity.h b/include/swift/ABI/TypeIdentity.h index dadbd27abc73a..68a326f8c0c43 100644 --- a/include/swift/ABI/TypeIdentity.h +++ b/include/swift/ABI/TypeIdentity.h @@ -114,7 +114,7 @@ class TypeImportInfo { /// /// \return true if collection was successful. template - bool collect(StringRef value) { + bool collect(llvm::StringRef value) { #define check(CONDITION, COMMENT) \ do { \ if (!Asserting) { \ @@ -177,17 +177,17 @@ class TypeImportInfo { class ParsedTypeIdentity { public: /// The user-facing name of the type. - StringRef UserFacingName; + llvm::StringRef UserFacingName; /// The full identity of the type. /// Note that this may include interior '\0' characters. - StringRef FullIdentity; + llvm::StringRef FullIdentity; /// Any extended information that type might have. - llvm::Optional> ImportInfo; + llvm::Optional> ImportInfo; /// The ABI name of the type. - StringRef getABIName() const { + llvm::StringRef getABIName() const { if (ImportInfo && !ImportInfo->ABIName.empty()) return ImportInfo->ABIName; return UserFacingName; @@ -202,11 +202,11 @@ class ParsedTypeIdentity { return ImportInfo && !ImportInfo->RelatedEntityName.empty(); } - bool isRelatedEntity(StringRef entityName) const { + bool isRelatedEntity(llvm::StringRef entityName) const { return ImportInfo && ImportInfo->RelatedEntityName == entityName; } - StringRef getRelatedEntityName() const { + llvm::StringRef getRelatedEntityName() const { assert(isAnyRelatedEntity()); return ImportInfo->RelatedEntityName; } diff --git a/include/swift/AST/ASTWalker.h b/include/swift/AST/ASTWalker.h index d29b3c3f60c88..af4308ecd8db4 100644 --- a/include/swift/AST/ASTWalker.h +++ b/include/swift/AST/ASTWalker.h @@ -37,6 +37,7 @@ enum class SemaReferenceKind : uint8_t { TypeRef, EnumElementRef, SubscriptRef, + DynamicMemberRef, }; struct ReferenceMetaData { diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 5598cc8d660b4..7aa018966646b 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -326,6 +326,8 @@ ERROR(error_extracting_version_from_module_interface,none, ERROR(unsupported_version_of_module_interface,none, "unsupported version of module interface '%0': '%1'", (StringRef, llvm::VersionTuple)) +ERROR(error_opening_explicit_module_file,none, + "failed to open explicit Swift module: %0", (StringRef)) ERROR(error_extracting_flags_from_module_interface,none, "error extracting flags from module interface", ()) REMARK(rebuilding_module_from_interface,none, diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index d39c68ab1bcae..95730fffc812c 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -243,10 +243,7 @@ class Evaluator { public: /// Construct a new evaluator that can emit cyclic-dependency /// diagnostics through the given diagnostics engine. - Evaluator(DiagnosticEngine &diags, - bool debugDumpCycles, - bool buildDependencyGraph, - bool enableExperimentalPrivateDeps); + Evaluator(DiagnosticEngine &diags, const LangOptions &opts); /// Emit GraphViz output visualizing the request graph. void emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath); diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 9168f0583e618..34f94465a8ec0 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -3774,7 +3774,7 @@ class ClosureExpr : public AbstractClosureExpr { /// The bit indicates whether this closure has had a function builder /// applied to it. llvm::PointerIntPair CapturedSelfDeclAndAppliedBuilder; - + /// The location of the "throws", if present. SourceLoc ThrowsLoc; @@ -3786,7 +3786,8 @@ class ClosureExpr : public AbstractClosureExpr { SourceLoc InLoc; /// The explicitly-specified result type. - TypeExpr *ExplicitResultType; + llvm::PointerIntPair + ExplicitResultTypeAndEnclosingChecked; /// The body of the closure, along with a bit indicating whether it /// was originally just a single expression. @@ -3801,7 +3802,8 @@ class ClosureExpr : public AbstractClosureExpr { BracketRange(bracketRange), CapturedSelfDeclAndAppliedBuilder(capturedSelfDecl, false), ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc), - ExplicitResultType(explicitResultType), Body(nullptr) { + ExplicitResultTypeAndEnclosingChecked(explicitResultType, false), + Body(nullptr) { setParameterList(params); Bits.ClosureExpr.HasAnonymousClosureVars = false; } @@ -3855,13 +3857,15 @@ class ClosureExpr : public AbstractClosureExpr { Type getExplicitResultType() const { assert(hasExplicitResultType() && "No explicit result type"); - return ExplicitResultType->getInstanceType(); + return ExplicitResultTypeAndEnclosingChecked.getPointer() + ->getInstanceType(); } void setExplicitResultType(Type ty); TypeRepr *getExplicitResultTypeRepr() const { assert(hasExplicitResultType() && "No explicit result type"); - return ExplicitResultType->getTypeRepr(); + return ExplicitResultTypeAndEnclosingChecked.getPointer() + ->getTypeRepr(); } /// Determine whether the closure has a single expression for its @@ -3918,6 +3922,16 @@ class ClosureExpr : public AbstractClosureExpr { CapturedSelfDeclAndAppliedBuilder.setInt(flag); } + /// Whether this closure's body was type checked within the enclosing + /// context. + bool wasTypeCheckedInEnclosingContext() const { + return ExplicitResultTypeAndEnclosingChecked.getInt(); + } + + void setTypeCheckedInEnclosingContext(bool flag = true) { + ExplicitResultTypeAndEnclosingChecked.setInt(flag); + } + static bool classof(const Expr *E) { return E->getKind() == ExprKind::Closure; } diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 52ffcc34aca36..279fdcefb3c4e 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -190,10 +190,6 @@ class IRGenOptions { /// Whether we should run LLVM SLP vectorizer. unsigned DisableLLVMSLPVectorizer : 1; - /// Disable frame pointer elimination? - unsigned DisableFPElimLeaf : 1; - unsigned DisableFPElim : 1; - /// Special codegen for playgrounds. unsigned Playground : 1; @@ -320,8 +316,7 @@ class IRGenOptions { DisableClangModuleSkeletonCUs(false), UseJIT(false), DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false), DisableLLVMSLPVectorizer(false), - DisableFPElimLeaf(false), - DisableFPElim(true), Playground(false), EmitStackPromotionChecks(false), + Playground(false), EmitStackPromotionChecks(false), FunctionSections(false), PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), HasValueNamesSetting(false), ValueNames(false), EnableReflectionMetadata(true), EnableReflectionNames(true), diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index a83c89a7f003c..cea3d769704b2 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -548,6 +548,10 @@ class ModuleDecl : public DeclContext, public TypeDecl { return Bits.ModuleDecl.IsMainModule; } + /// For the main module, retrieves the list of primary source files being + /// compiled, that is, the files we're generating code for. + ArrayRef getPrimarySourceFiles() const; + /// Retrieve the top-level module. If this module is already top-level, this /// returns itself. If this is a submodule such as \c Foo.Bar.Baz, this /// returns the module \c Foo. diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 6252cbc0ddceb..8846c849c8da6 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -437,6 +437,9 @@ struct PrintOptions { /// The information for converting archetypes to specialized types. llvm::Optional TransformContext; + /// Whether to display (Clang-)imported module names; + bool QualifyImportedTypes = false; + /// Whether cross-import overlay modules are printed with their own name (e.g. /// _MyFrameworkYourFrameworkAdditions) or that of their underlying module /// (e.g. MyFramework). diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 86d9567553186..36fc930d589ef 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -82,6 +82,9 @@ class SearchPathOptions { /// would for a non-system header. bool DisableModulesValidateSystemDependencies = false; + /// The paths to a set of explicitly built modules from interfaces. + std::vector ExplicitSwiftModules; + private: static StringRef pathStringFromFrameworkSearchPath(const FrameworkSearchPath &next) { diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index fb68e8564a44f..0b0a17f56bd58 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -158,6 +158,9 @@ class SourceFile final : public FileUnit { /// The parsing options for the file. ParsingOptions ParsingOpts; + /// Whether this is a primary source file which we'll be generating code for. + bool IsPrimary; + /// The scope map that describes this source file. std::unique_ptr Scope; @@ -232,6 +235,10 @@ class SourceFile final : public FileUnit { /// Retrieve the parsing options for the file. ParsingOptions getParsingOptions() const { return ParsingOpts; } + /// Whether this source file is a primary file, meaning that we're generating + /// code for it. Note this method returns \c false in WMO. + bool isPrimary() const { return IsPrimary; } + /// A cache of syntax nodes that can be reused when creating the syntax tree /// for this file. swift::SyntaxParsingCache *SyntaxParsingCache = nullptr; @@ -307,7 +314,7 @@ class SourceFile final : public FileUnit { SourceFile(ModuleDecl &M, SourceFileKind K, Optional bufferID, bool KeepParsedTokens = false, bool KeepSyntaxTree = false, - ParsingOptions parsingOpts = {}); + ParsingOptions parsingOpts = {}, bool isPrimary = false); ~SourceFile(); diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 8fffe1e39a6ba..cedeea5866a0c 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -867,14 +867,13 @@ class LazyStoragePropertyRequest : bool isCached() const { return true; } }; -/// Request to type check the body of the given function up to the given -/// source location. +/// Request to type check the body of the given function. /// /// Produces true if an error occurred, false otherwise. /// FIXME: it would be far better to return the type-checked body. -class TypeCheckFunctionBodyUntilRequest : - public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -883,9 +882,7 @@ class TypeCheckFunctionBodyUntilRequest : friend SimpleRequest; // Evaluation. - bool - evaluate(Evaluator &evaluator, AbstractFunctionDecl *func, - SourceLoc endTypeCheckLoc) const; + bool evaluate(Evaluator &evaluator, AbstractFunctionDecl *func) const; public: bool isCached() const { return true; } @@ -896,6 +893,24 @@ class TypeCheckFunctionBodyUntilRequest : readDependencySource(const evaluator::DependencyRecorder &) const; }; +/// Request to typecheck a function body element at the given source location. +/// +/// Produces true if an error occurred, false otherwise. +class TypeCheckFunctionBodyAtLocRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + bool evaluate(Evaluator &evaluator, AbstractFunctionDecl *func, + SourceLoc Loc) const; +}; + /// Request to obtain a list of stored properties in a nominal type. /// /// This will include backing storage for lazy properties and @@ -2459,6 +2474,45 @@ class CheckInconsistentImplementationOnlyImportsRequest bool isCached() const { return true; } }; +/// Retrieves the primary source files in the main module. +// FIXME: This isn't really a type-checking request, if we ever split off a +// zone for more basic AST requests, this should be moved there. +class PrimarySourceFilesRequest + : public SimpleRequest(ModuleDecl *), + RequestFlags::Cached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + ArrayRef evaluate(Evaluator &evaluator, ModuleDecl *mod) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Retrieve the file being used for code completion in the main module. +// FIXME: This isn't really a type-checking request, if we ever split off a +// zone for more basic AST requests, this should be moved there. +class CodeCompletionFileRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + SourceFile *evaluate(Evaluator &evaluator, ModuleDecl *mod) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + // Allow AnyValue to compare two Type values, even though Type doesn't // support ==. template<> diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index f69a109bf4693..f1b71d2d25a83 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -36,6 +36,8 @@ SWIFT_REQUEST(TypeChecker, CheckRedeclarationRequest, Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ClassAncestryFlagsRequest, AncestryFlags(ClassDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, CodeCompletionFileRequest, + SourceFile *(ModuleDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, CompareDeclSpecializationRequest, bool (DeclContext *, ValueDecl *, ValueDecl *, bool), Cached, NoLocationInfo) @@ -151,6 +153,8 @@ SWIFT_REQUEST(TypeChecker, OverriddenDeclsRequest, SWIFT_REQUEST(TypeChecker, PatternBindingEntryRequest, const PatternBindingEntry *(PatternBindingDecl *, unsigned), SeparatelyCached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, PrimarySourceFilesRequest, + ArrayRef(ModuleDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, PropertyWrapperBackingPropertyInfoRequest, PropertyWrapperBackingPropertyInfo(VarDecl *), Cached, NoLocationInfo) @@ -196,9 +200,11 @@ SWIFT_REQUEST(TypeChecker, SuperclassTypeRequest, SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest, AccessorDecl *(AbstractStorageDecl *, AccessorKind), SeparatelyCached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyUntilRequest, +SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyRequest, + bool(AbstractFunctionDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyAtLocRequest, bool(AbstractFunctionDecl *, SourceLoc), - Cached, NoLocationInfo) + Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *), diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 016b16706ab3b..e894dd1855535 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -473,6 +473,7 @@ class ClangImporter final : public ClangModuleLoader { bool isSerializable(const clang::Type *type, bool checkCanonical) const override; + ArrayRef getExtraClangArgs() const; }; ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN, diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h index 14e593daf88a0..173abc210f560 100644 --- a/include/swift/ClangImporter/ClangImporterOptions.h +++ b/include/swift/ClangImporter/ClangImporterOptions.h @@ -103,6 +103,10 @@ class ClangImporterOptions { /// DWARFImporter delegate. bool DisableSourceImport = false; + /// When set, use ExtraArgs alone to configure clang instance because ExtraArgs + /// contains the full option set. + bool ExtraArgsOnly = false; + /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index ce3a4b5d439c3..4d809e7268078 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -42,7 +42,6 @@ std::string genericParameterName(uint64_t depth, uint64_t index); /// Display style options for the demangler. struct DemangleOptions { bool SynthesizeSugarOnTypes = false; - bool DisplayDebuggerGeneratedModule = true; bool QualifyEntities = true; bool DisplayExtensionContexts = true; bool DisplayUnmangledSuffix = true; @@ -57,6 +56,12 @@ struct DemangleOptions { bool ShortenArchetype = false; bool ShowPrivateDiscriminators = true; bool ShowFunctionArgumentTypes = true; + bool DisplayDebuggerGeneratedModule = true; + bool DisplayStdlibModule = true; + bool DisplayObjCModule = true; + /// If this is nonempty, entities in this module name will not be qualified. + llvm::StringRef HidingCurrentModule; + /// A function to render generic parameter names. std::function GenericParameterName = genericParameterName; diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 33d62e639499f..c955bb3061eaf 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -451,14 +451,6 @@ class CompilerInstance { /// considered primaries. llvm::SetVector PrimaryBufferIDs; - /// Identifies the set of SourceFiles that are considered primaries. An - /// invariant is that any SourceFile in this set with an associated - /// buffer will also have its buffer ID in PrimaryBufferIDs. - std::vector PrimarySourceFiles; - - /// The file that has been registered for code completion. - NullablePtr CodeCompletionFile; - /// Return whether there is an entry in PrimaryInputs for buffer \p BufID. bool isPrimaryInput(unsigned BufID) const { return PrimaryBufferIDs.count(BufID) != 0; @@ -514,8 +506,13 @@ class CompilerInstance { UnifiedStatsReporter *getStatsReporter() const { return Stats.get(); } + /// Retrieve the main module containing the files being compiled. ModuleDecl *getMainModule() const; + /// Replace the current main module with a new one. This is used for top-level + /// cached code completion. + void setMainModule(ModuleDecl *newMod); + MemoryBufferSerializedModuleLoader * getMemoryBufferSerializedModuleLoader() const { return MemoryBufferLoader; @@ -536,7 +533,7 @@ class CompilerInstance { /// Gets the set of SourceFiles which are the primary inputs for this /// CompilerInstance. ArrayRef getPrimarySourceFiles() const { - return PrimarySourceFiles; + return getMainModule()->getPrimarySourceFiles(); } /// Gets the SourceFile which is the primary input for this CompilerInstance. @@ -546,11 +543,12 @@ class CompilerInstance { /// FIXME: This should be removed eventually, once there are no longer any /// codepaths that rely on a single primary file. SourceFile *getPrimarySourceFile() const { - if (PrimarySourceFiles.empty()) { + auto primaries = getPrimarySourceFiles(); + if (primaries.empty()) { return nullptr; } else { - assert(PrimarySourceFiles.size() == 1); - return *PrimarySourceFiles.begin(); + assert(primaries.size() == 1); + return *primaries.begin(); } } @@ -561,12 +559,7 @@ class CompilerInstance { /// If a code completion buffer has been set, returns the corresponding source /// file. - NullablePtr getCodeCompletionFile() { return CodeCompletionFile; } - - /// Set a new file that we're performing code completion on. - void setCodeCompletionFile(SourceFile *file) { - CodeCompletionFile = file; - } + SourceFile *getCodeCompletionFile() const; private: /// Set up the file system by loading and validating all VFS overlay YAML @@ -646,10 +639,11 @@ class CompilerInstance { public: void freeASTContext(); -private: - /// Load stdlib & return true if should continue, i.e. no error - bool loadStdlib(); + /// If an implicit standard library import is expected, loads the standard + /// library, returning \c false if we should continue, i.e. no error. + bool loadStdlibIfNeeded(); +private: /// Retrieve a description of which modules should be implicitly imported. ImplicitImportInfo getImplicitImportInfo() const; diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 710efc42f9368..201202cd983a1 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -258,6 +258,10 @@ class FrontendOptions { /// By default, we include ImplicitObjCHeaderPath directly. llvm::Optional BridgingHeaderDirForPrint; + /// Disable implicitly built Swift modules because they are explicitly + /// built and given to the compiler invocation. + bool DisableImplicitModules = false; + /// The different modes for validating TBD against the LLVM IR. enum class TBDValidationMode { Default, ///< Do the default validation for the current platform. diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 61d265d3a775b..22c183beb2c69 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -127,6 +127,49 @@ class LangOptions; class SearchPathOptions; class CompilerInvocation; +/// A ModuleLoader that loads explicitly built Swift modules specified via +/// -swift-module-file +class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase { + explicit ExplicitSwiftModuleLoader(ASTContext &ctx, DependencyTracker *tracker, + ModuleLoadingMode loadMode, + bool IgnoreSwiftSourceInfoFile); + std::error_code findModuleFilesInDirectory( + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer) override; + + bool isCached(StringRef DepPath) override { return false; }; + + struct Implementation; + Implementation &Impl; +public: + static std::unique_ptr + create(ASTContext &ctx, + DependencyTracker *tracker, ModuleLoadingMode loadMode, + ArrayRef ExplicitModulePaths, + bool IgnoreSwiftSourceInfoFile); + + /// Append visible module names to \p names. Note that names are possibly + /// duplicated, and not guaranteed to be ordered in any way. + void collectVisibleTopLevelModuleNames( + SmallVectorImpl &names) const override; + ~ExplicitSwiftModuleLoader(); +}; + +struct ModuleInterfaceLoaderOptions { + bool remarkOnRebuildFromInterface = false; + bool disableInterfaceLock = false; + bool disableImplicitSwiftModule = false; + ModuleInterfaceLoaderOptions(const FrontendOptions &Opts): + remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), + disableInterfaceLock(Opts.DisableInterfaceFileLock), + disableImplicitSwiftModule(Opts.DisableImplicitModules) {} + ModuleInterfaceLoaderOptions() = default; +}; + /// A ModuleLoader that runs a subordinate \c CompilerInvocation and /// \c CompilerInstance to convert .swiftinterface files to .swiftmodule /// files on the fly, caching the resulting .swiftmodules in the module cache @@ -137,21 +180,17 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules, - bool RemarkOnRebuildFromInterface, bool IgnoreSwiftSourceInfoFile, - bool DisableInterfaceFileLock) + bool IgnoreSwiftSourceInfoFile, ModuleInterfaceLoaderOptions Opts) : SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir), - RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface), - DisableInterfaceFileLock(DisableInterfaceFileLock), - PreferInterfaceForModules(PreferInterfaceForModules) - {} + PreferInterfaceForModules(PreferInterfaceForModules), + Opts(Opts) {} std::string CacheDir; std::string PrebuiltCacheDir; - bool RemarkOnRebuildFromInterface; - bool DisableInterfaceFileLock; ArrayRef PreferInterfaceForModules; + ModuleInterfaceLoaderOptions Opts; std::error_code findModuleFilesInDirectory( AccessPathElem ModuleID, @@ -168,16 +207,14 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules = {}, - bool RemarkOnRebuildFromInterface = false, - bool IgnoreSwiftSourceInfoFile = false, - bool DisableInterfaceFileLock = false) { + ModuleInterfaceLoaderOptions Opts = ModuleInterfaceLoaderOptions(), + bool IgnoreSwiftSourceInfoFile = false) { return std::unique_ptr( new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir, tracker, loadMode, PreferInterfaceForModules, - RemarkOnRebuildFromInterface, IgnoreSwiftSourceInfoFile, - DisableInterfaceFileLock)); + Opts)); } /// Append visible module names to \p names. Note that names are possibly @@ -192,10 +229,11 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { static bool buildSwiftModuleFromSwiftInterface( SourceManager &SourceMgr, DiagnosticEngine &Diags, const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts, + const ClangImporterOptions &ClangOpts, StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock); + ModuleInterfaceLoaderOptions Opts); }; struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { @@ -231,14 +269,13 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { DiagnosticEngine &Diags, const SearchPathOptions &searchPathOpts, const LangOptions &langOpts, + ModuleInterfaceLoaderOptions LoaderOpts, ClangModuleLoader *clangImporter, bool buildModuleCacheDirIfAbsent, StringRef moduleCachePath, StringRef prebuiltCachePath, bool serializeDependencyHashes, - bool trackSystemDependencies, - bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock); + bool trackSystemDependencies); bool runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, @@ -258,6 +295,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { llvm::SmallString<256> &OutPath, StringRef &CacheHash); std::string getCacheHash(StringRef useInterfacePath); + void addExtraClangArg(StringRef Arg); }; } diff --git a/include/swift/IDE/CompletionInstance.h b/include/swift/IDE/CompletionInstance.h index 3dfcf56b31299..51687b974b9c0 100644 --- a/include/swift/IDE/CompletionInstance.h +++ b/include/swift/IDE/CompletionInstance.h @@ -43,7 +43,6 @@ class CompletionInstance { std::mutex mtx; std::unique_ptr CachedCI; - ModuleDecl *CurrentModule = nullptr; llvm::hash_code CachedArgHash; llvm::sys::TimePoint<> DependencyCheckedTimestamp; llvm::StringMap InMemoryDependencyHash; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 177f97dd5cae3..9ba2fc6ed4fe8 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -214,6 +214,12 @@ def disable_objc_attr_requires_foundation_module : def enable_resilience : Flag<["-"], "enable-resilience">, HelpText<"Deprecated, use -enable-library-evolution instead">; +def disable_implicit_swift_modules: Flag<["-"], "disable-implicit-swift-modules">, + HelpText<"Disable building Swift modules explicitly by the compiler">; + +def swift_module_file + : Separate<["-"], "swift-module-file">, MetaVarName<"">, + HelpText<"Specify Swift module explicitly built from textual interface">; } @@ -712,4 +718,6 @@ def target_sdk_version : Separate<["-"], "target-sdk-version">, def target_variant_sdk_version : Separate<["-"], "target-variant-sdk-version">, HelpText<"The version of target variant SDK used for compilation">; +def extra_clang_options_only : Flag<["-"], "only-use-extra-clang-opts">, + HelpText<"Options passed via -Xcc are sufficient for Clang configuration">; } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden] diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 96cea8b35cded..b771b48b3895d 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1017,10 +1017,6 @@ def enable_private_imports : Flag<["-"], "enable-private-imports">, Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>, HelpText<"Allows this module's internal and private API to be accessed">; -def disable_leaf_frame_pointer_elim : Flag<["-"], "no-omit-leaf-frame-pointer">, - Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>, - HelpText<"Don't omit the frame pointer for leaf functions">; - def sanitize_EQ : CommaJoined<["-"], "sanitize=">, Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"">, HelpText<"Turn on runtime checks for erroneous behavior.">; diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 72a89ea2762a7..38672aa3f9492 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -928,9 +928,8 @@ class Parser { std::pair, Optional> parseDeclListDelayed(IterableDeclContext *IDC); - bool parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, - SourceLoc PosBeforeLB, - Diag<> ErrorDiag, + bool parseMemberDeclList(SourceLoc &LBLoc, SourceLoc &RBLoc, + Diag<> LBraceDiag, Diag<> RBraceDiag, IterableDeclContext *IDC); bool canDelayMemberDeclParsing(bool &HasOperatorDeclarations, diff --git a/include/swift/Remote/Failure.h b/include/swift/Remote/Failure.h index bc2c5557937d3..908e6357c0261 100644 --- a/include/swift/Remote/Failure.h +++ b/include/swift/Remote/Failure.h @@ -255,7 +255,7 @@ class Failure { result.append(text, next - text); // Skip the '%'. - next++; + ++next; // Do something based on the character after '%'. char c = *next++; diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 1f091dfd66065..963bcf6386691 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -33,6 +33,8 @@ #include #include +#include + namespace swift { namespace remote { diff --git a/include/swift/Runtime/Concurrent.h b/include/swift/Runtime/Concurrent.h index 4d2f040db8805..7e4ed718b131b 100644 --- a/include/swift/Runtime/Concurrent.h +++ b/include/swift/Runtime/Concurrent.h @@ -434,7 +434,7 @@ template struct ConcurrentReadableArray { } void deallocate() { - for (size_t i = 0; i < Count; i++) { + for (size_t i = 0; i < Count; ++i) { data()[i].~ElemTy(); } free(this); diff --git a/include/swift/Runtime/EnvironmentVariables.h b/include/swift/Runtime/EnvironmentVariables.h new file mode 100644 index 0000000000000..affcbd07baff8 --- /dev/null +++ b/include/swift/Runtime/EnvironmentVariables.h @@ -0,0 +1,41 @@ +//===--- EnvironmentVariables.h - Debug variables. --------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Debug behavior conditionally enabled using environment variables. +// +//===----------------------------------------------------------------------===// + +#include "../Basic/Lazy.h" + +namespace swift { +namespace runtime { +namespace environment { + +void initialize(void *); + +extern OnceToken_t initializeToken; + +// Declare backing variables. +#define VARIABLE(name, type, defaultValue, help) extern type name ## _variable; +#include "../../../stdlib/public/runtime/EnvironmentVariables.def" + +// Define getter functions. +#define VARIABLE(name, type, defaultValue, help) \ + inline type name() { \ + SWIFT_ONCE_F(initializeToken, initialize, nullptr); \ + return name ## _variable; \ + } +#include "../../../stdlib/public/runtime/EnvironmentVariables.def" + +} // end namespace environment +} // end namespace runtime +} // end namespace Swift diff --git a/include/swift/SIL/OwnershipUtils.h b/include/swift/SIL/OwnershipUtils.h index a66c74221aefb..35d11727a9f75 100644 --- a/include/swift/SIL/OwnershipUtils.h +++ b/include/swift/SIL/OwnershipUtils.h @@ -498,6 +498,10 @@ struct OwnedValueIntroducerKind { /// branch predecessors. Phi, + /// An owned value that is from a struct that has multiple operands that are + /// owned. + Struct, + /// An owned value that is a function argument. FunctionArgument, @@ -522,6 +526,8 @@ struct OwnedValueIntroducerKind { return OwnedValueIntroducerKind(Apply); case ValueKind::BeginApplyResult: return OwnedValueIntroducerKind(BeginApply); + case ValueKind::StructInst: + return OwnedValueIntroducerKind(Struct); case ValueKind::SILPhiArgument: { auto *phiArg = cast(value); if (dyn_cast_or_null(phiArg->getSingleTerminator())) { @@ -598,8 +604,12 @@ struct OwnedValueIntroducer { } /// Returns true if this owned introducer is able to be converted into a - /// guaranteed form if none of its uses are consuming uses (looking through - /// forwarding uses). + /// guaranteed form if none of its direct uses are consuming uses (looking + /// through forwarding uses). + /// + /// NOTE: Since the direct uses must be non-consuming, this means that any + /// "ownership phis" (e.x. branch, struct) must return false here since we can + /// not analyze them without analyzing their operands/incoming values. bool isConvertableToGuaranteed() const { switch (kind) { case OwnedValueIntroducerKind::Copy: @@ -610,6 +620,7 @@ struct OwnedValueIntroducer { case OwnedValueIntroducerKind::TryApply: case OwnedValueIntroducerKind::LoadTake: case OwnedValueIntroducerKind::Phi: + case OwnedValueIntroducerKind::Struct: case OwnedValueIntroducerKind::FunctionArgument: case OwnedValueIntroducerKind::PartialApplyInit: case OwnedValueIntroducerKind::AllocBoxInit: @@ -619,6 +630,29 @@ struct OwnedValueIntroducer { llvm_unreachable("Covered switch isn't covered?!"); } + /// Returns true if this introducer when converted to guaranteed is expected + /// to have guaranteed operands that are consumed by the instruction. + /// + /// E.x.: phi, struct. + bool hasConsumingGuaranteedOperands() const { + switch (kind) { + case OwnedValueIntroducerKind::Phi: + return true; + case OwnedValueIntroducerKind::Struct: + case OwnedValueIntroducerKind::Copy: + case OwnedValueIntroducerKind::LoadCopy: + case OwnedValueIntroducerKind::Apply: + case OwnedValueIntroducerKind::BeginApply: + case OwnedValueIntroducerKind::TryApply: + case OwnedValueIntroducerKind::LoadTake: + case OwnedValueIntroducerKind::FunctionArgument: + case OwnedValueIntroducerKind::PartialApplyInit: + case OwnedValueIntroducerKind::AllocBoxInit: + case OwnedValueIntroducerKind::AllocRefInit: + return false; + } + } + bool operator==(const OwnedValueIntroducer &other) const { return value == other.value; } diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h index 323708f44200a..ec2afdbe555c2 100644 --- a/include/swift/SIL/SILArgument.h +++ b/include/swift/SIL/SILArgument.h @@ -148,6 +148,14 @@ class SILArgument : public ValueBase { bool getIncomingPhiOperands(SmallVectorImpl &returnedPhiOperands) const; + /// If this argument is a true phi, for each operand in each predecessor block + /// associated with an incoming value, call visitor(op). Visitor must return + /// true for iteration to continue. False to stop it. + /// + /// Returns false if this is not a true phi or that a visitor signaled error + /// by returning false. + bool visitIncomingPhiOperands(function_ref visitor) const; + /// Returns true if we were able to find a single terminator operand value for /// each predecessor of this arguments basic block. The found values are /// stored in OutArray. @@ -248,6 +256,13 @@ class SILPhiArgument : public SILArgument { bool getIncomingPhiOperands(SmallVectorImpl &returnedPhiOperands) const; + /// If this argument is a phi, call visitor for each passing the operand for + /// each incoming phi values for each predecessor BB. If this argument is not + /// a phi, return false. + /// + /// If visitor returns false, iteration is stopped and we return false. + bool visitIncomingPhiOperands(function_ref visitor) const; + /// Returns true if we were able to find a single terminator operand value for /// each predecessor of this arguments basic block. The found values are /// stored in OutArray. @@ -442,6 +457,17 @@ inline bool SILArgument::getIncomingPhiOperands( llvm_unreachable("Covered switch is not covered?!"); } +inline bool SILArgument::visitIncomingPhiOperands( + function_ref visitor) const { + switch (getKind()) { + case SILArgumentKind::SILPhiArgument: + return cast(this)->visitIncomingPhiOperands(visitor); + case SILArgumentKind::SILFunctionArgument: + return false; + } + llvm_unreachable("Covered switch is not covered?!"); +} + } // end swift namespace #endif diff --git a/include/swift/SIL/SILVTable.h b/include/swift/SIL/SILVTable.h index c266b762cf810..54dc2aec4cb5b 100644 --- a/include/swift/SIL/SILVTable.h +++ b/include/swift/SIL/SILVTable.h @@ -53,6 +53,9 @@ class SILVTable : public llvm::ilist_node, enum Kind : uint8_t { /// The vtable entry is for a method defined directly in this class. Normal, + /// The vtable entry is for a method defined directly in this class, and is never overridden + /// by subclasses. + NormalNonOverridden, /// The vtable entry is inherited from the superclass. Inherited, /// The vtable entry is inherited from the superclass, and overridden diff --git a/include/swift/SILOptimizer/Analysis/FunctionOrder.h b/include/swift/SILOptimizer/Analysis/FunctionOrder.h index 6863cee08b4b6..8a443a886cbc7 100644 --- a/include/swift/SILOptimizer/Analysis/FunctionOrder.h +++ b/include/swift/SILOptimizer/Analysis/FunctionOrder.h @@ -31,7 +31,6 @@ class BottomUpFunctionOrder { typedef TinyPtrVector SCC; private: - SILModule &M; llvm::SmallVector TheSCCs; llvm::SmallVector TheFunctions; @@ -44,24 +43,29 @@ class BottomUpFunctionOrder { llvm::SmallSetVector DFSStack; public: - BottomUpFunctionOrder(SILModule &M, BasicCalleeAnalysis *BCA) - : M(M), BCA(BCA), NextDFSNum(0) {} + BottomUpFunctionOrder(BasicCalleeAnalysis *BCA) + : BCA(BCA), NextDFSNum(0) {} + + /// DFS on 'F' to compute bottom up order + void computeBottomUpOrder(SILFunction *F) { + DFS(F); + } + + /// DFS on all functions in the module to compute bottom up order + void computeBottomUpOrder(SILModule *M) { + for (auto &F : *M) + DFS(&F); + } /// Get the SCCs in bottom-up order. ArrayRef getSCCs() { - if (!TheSCCs.empty()) - return TheSCCs; - - FindSCCs(M); return TheSCCs; } - /// Get a flattened view of all functions in all the SCCs in - /// bottom-up order - ArrayRef getFunctions() { + /// Get a flattened view of all functions in all the SCCs in bottom-up order + ArrayRef getBottomUpOrder() { if (!TheFunctions.empty()) return TheFunctions; - for (auto SCC : getSCCs()) for (auto *F : SCC) TheFunctions.push_back(F); @@ -71,7 +75,6 @@ class BottomUpFunctionOrder { private: void DFS(SILFunction *F); - void FindSCCs(SILModule &M); }; } // end namespace swift diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 6ca626a75f608..da3a8b269b702 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -132,9 +132,9 @@ namespace swift { /// Typecheck the given expression. bool typeCheckExpression(DeclContext *DC, Expr *&parsedExpr); - /// Partially typecheck the specified function body. - bool typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc); + /// Type check a function body element which is at \p TagetLoc . + bool typeCheckAbstractFunctionBodyAtLoc(AbstractFunctionDecl *AFD, + SourceLoc TargetLoc); /// Typecheck top-level code parsed during code completion. /// diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 83af39e5fc41a..558b1891bad02 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -138,6 +138,9 @@ class SerializedModuleLoaderBase : public ModuleLoader { /// Scan the given serialized module file to determine dependencies. llvm::ErrorOr scanModuleFile(Twine modulePath); + /// Load the module file into a buffer and also collect its module name. + static std::unique_ptr + getModuleName(ASTContext &Ctx, StringRef modulePath, std::string &Name); public: virtual ~SerializedModuleLoaderBase(); SerializedModuleLoaderBase(const SerializedModuleLoaderBase &) = delete; diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h index 3834872d793f3..e97d686e45da3 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h @@ -486,7 +486,7 @@ swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Con LOAD(dumpInfoForTypeRef); Library->IsLegacy = IsLegacy; - Context->LibraryCount++; + ++Context->LibraryCount; return 1; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8d6e5295cc654..01e94203cffe6 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -549,10 +549,7 @@ ASTContext::ASTContext(LangOptions &langOpts, TypeCheckerOptions &typeckOpts, : LangOpts(langOpts), TypeCheckerOpts(typeckOpts), SearchPathOpts(SearchPathOpts), SourceMgr(SourceMgr), Diags(Diags), - evaluator(Diags, - langOpts.DebugDumpCycles, - langOpts.BuildRequestDependencyGraph, - langOpts.EnableExperientalPrivateIntransitiveDependencies), + evaluator(Diags, langOpts), TheBuiltinModule(createBuiltinModule(*this)), StdlibModuleName(getIdentifier(STDLIB_NAME)), SwiftShimsModuleName(getIdentifier(SWIFT_SHIMS_NAME)), @@ -3846,7 +3843,7 @@ void SubstitutionMap::Storage::Profile( id.AddPointer(replacementTypes[i].getPointer()); else id.AddPointer(nullptr); - i++; + ++i; }); // Conformances. diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 558452d3af46e..a0f083c9f50d1 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -304,7 +304,7 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl, auto *aliasDecl = cast(decl); auto genericSig = aliasDecl->getGenericSignature(); - for (unsigned i = 0, e = args.size(); i < e; i++) { + for (unsigned i = 0, e = args.size(); i < e; ++i) { auto origTy = genericSig->getInnermostGenericParams()[i]; auto substTy = args[i]; @@ -609,20 +609,35 @@ Type ASTBuilder::createGenericTypeParameterType(unsigned depth, Type ASTBuilder::createDependentMemberType(StringRef member, Type base) { - if (!base->isTypeParameter()) - return Type(); + auto identifier = Ctx.getIdentifier(member); + + if (auto *archetype = base->getAs()) { + if (archetype->hasNestedType(identifier)) + return archetype->getNestedType(identifier); + + } + + if (base->isTypeParameter()) { + return DependentMemberType::get(base, identifier); + } - return DependentMemberType::get(base, Ctx.getIdentifier(member)); + return Type(); } Type ASTBuilder::createDependentMemberType(StringRef member, Type base, ProtocolDecl *protocol) { - if (!base->isTypeParameter()) - return Type(); + auto identifier = Ctx.getIdentifier(member); - if (auto assocType = protocol->getAssociatedType(Ctx.getIdentifier(member))) - return DependentMemberType::get(base, assocType); + if (auto *archetype = base->getAs()) { + if (archetype->hasNestedType(identifier)) + return archetype->getNestedType(identifier); + } + + if (base->isTypeParameter()) { + if (auto assocType = protocol->getAssociatedType(identifier)) + return DependentMemberType::get(base, assocType); + } return Type(); } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index af02d2e0d37c9..cd7c1b627e887 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -2496,11 +2496,7 @@ class PrintExpr : public ExprVisitor { } OS << '\n'; - if (E->hasSingleExpressionBody()) { - printRec(E->getSingleExpressionBody()); - } else { - printRec(E->getBody(), E->getASTContext()); - } + printRec(E->getBody(), E->getASTContext()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } void visitAutoClosureExpr(AutoClosureExpr *E) { diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index fb1d6472fc5b8..b3815525627ee 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -1436,7 +1436,7 @@ void PrintAST::printGenericSignature( // Move index to genericParams. unsigned lastParamIdx = paramIdx; do { - lastParamIdx++; + ++lastParamIdx; } while (lastParamIdx < numParam && genericParams[lastParamIdx]->getDepth() == depth); @@ -3650,11 +3650,12 @@ class TypePrinter : public TypeVisitor { return false; // Don't print qualifiers for imported types. - for (auto File : M->getFiles()) { - if (File->getKind() == FileUnitKind::ClangModule || - File->getKind() == FileUnitKind::DWARFModule) - return false; - } + if (!Options.QualifyImportedTypes) + for (auto File : M->getFiles()) { + if (File->getKind() == FileUnitKind::ClangModule || + File->getKind() == FileUnitKind::DWARFModule) + return false; + } return true; } diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 1ad1f9e509a42..5dcc06c745e57 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -1692,7 +1692,7 @@ class Verifier : public ASTWalker { // Look through optional evaluations. if (auto *optionalEval = dyn_cast(subExpr)) { subExpr = optionalEval->getSubExpr(); - optionalDepth++; + ++optionalDepth; continue; } @@ -2734,8 +2734,8 @@ class Verifier : public ASTWalker { const DeclContext *DC = GTPD->getDeclContext(); // Skip verification of deserialized generic param decls that have the - // the file set as their parent. This happens when they have not yet had - // their correct parent set. + // file set as their parent. This happens when they have not yet had their + // correct parent set. // FIXME: This is a hack to workaround the fact that we don't necessarily // parent a GenericTypeParamDecl if we just deserialize its type. if (auto *fileDC = dyn_cast(DC)) { @@ -3165,7 +3165,7 @@ class Verifier : public ASTWalker { unsigned NumDestructors = 0; for (auto Member : CD->getMembers()) { if (isa(Member)) { - NumDestructors++; + ++NumDestructors; } } if (NumDestructors > 1) { diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index c5580e34748b4..32516e69f9a5b 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -195,7 +195,7 @@ getBuiltinGenericFunction(Identifier Id, DeclContext *DC = &M->getMainFile(FileUnitKind::Builtin); SmallVector params; - for (unsigned i = 0, e = ArgParamTypes.size(); i < e; i++) { + for (unsigned i = 0, e = ArgParamTypes.size(); i < e; ++i) { auto paramIfaceType = ArgParamTypes[i].getPlainType(); auto specifier = ParamDecl::getParameterSpecifierForValueOwnership( @@ -2004,11 +2004,11 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) { // Accept weak, volatile, and singlethread if present. if (NextPart != Parts.end() && *NextPart == "weak") - NextPart++; + ++NextPart; if (NextPart != Parts.end() && *NextPart == "volatile") - NextPart++; + ++NextPart; if (NextPart != Parts.end() && *NextPart == "singlethread") - NextPart++; + ++NextPart; // Nothing else is allowed in the name. if (NextPart != Parts.end()) return nullptr; diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index eb639bf06e478..a0c7e71393b7e 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -359,7 +359,7 @@ clang::QualType ClangTypeConverter::visitTupleType(TupleType *type) { return ClangASTContext.VoidTy; Type eltTy = type->getElementType(0); - for (unsigned i = 1; i < tupleNumElements; i++) { + for (unsigned i = 1; i < tupleNumElements; ++i) { if (!eltTy->isEqual(type->getElementType(i))) // Only tuples where all element types are equal map to fixed-size // arrays. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 979f6ffcbaa35..19fb3aca7c390 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5036,7 +5036,7 @@ ProtocolDecl::setLazyRequirementSignature(LazyMemberLoader *lazyLoader, ++NumLazyRequirementSignatures; // FIXME: (transitional) increment the redundant "always-on" counter. if (auto *Stats = getASTContext().Stats) - Stats->getFrontendCounters().NumLazyRequirementSignatures++; + ++Stats->getFrontendCounters().NumLazyRequirementSignatures; } ArrayRef ProtocolDecl::getCachedRequirementSignature() const { @@ -5196,7 +5196,7 @@ AbstractStorageDecl::AccessorRecord::create(ASTContext &ctx, case AccessorKind::ID: \ if (!has##ID) { \ has##ID = true; \ - numMissingOpaque--; \ + --numMissingOpaque; \ } \ continue; #include "swift/AST/AccessorKinds.def" diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index ae7af87bef744..00ab8b60e553e 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -924,7 +924,7 @@ void IterableDeclContext::loadAllMembers() const { --NumUnloadedLazyIterableDeclContexts; // FIXME: (transitional) decrement the redundant "always-on" counter. if (auto s = ctx.Stats) - s->getFrontendCounters().NumUnloadedLazyIterableDeclContexts--; + --s->getFrontendCounters().NumUnloadedLazyIterableDeclContexts; } bool IterableDeclContext::wasDeserialized() const { diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index aed3da09cd4a6..f0d5f76df87c9 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -993,7 +993,7 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) { SmallString<128> notePath(getDiagnosticDocumentationPath()); llvm::sys::path::append(notePath, *associatedNotes); educationalNotePaths.push_back(notePath.str().str()); - associatedNotes++; + ++associatedNotes; } info->EducationalNotePaths = educationalNotePaths; diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index 472a5387e0f5d..785b0d99ff277 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "swift/AST/Evaluator.h" #include "swift/AST/DiagnosticEngine.h" +#include "swift/Basic/LangOptions.h" #include "swift/Basic/Range.h" #include "swift/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" @@ -62,21 +63,20 @@ void Evaluator::registerRequestFunctions( } static evaluator::DependencyRecorder::Mode -computeDependencyModeFromFlags(bool enableExperimentalPrivateDeps) { +computeDependencyModeFromFlags(const LangOptions &opts) { using Mode = evaluator::DependencyRecorder::Mode; - if (enableExperimentalPrivateDeps) { + if (opts.EnableExperientalPrivateIntransitiveDependencies) { return Mode::ExperimentalPrivateDependencies; } return Mode::StatusQuo; } -Evaluator::Evaluator(DiagnosticEngine &diags, bool debugDumpCycles, - bool buildDependencyGraph, - bool enableExperimentalPrivateDeps) - : diags(diags), debugDumpCycles(debugDumpCycles), - buildDependencyGraph(buildDependencyGraph), - recorder{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} {} +Evaluator::Evaluator(DiagnosticEngine &diags, const LangOptions &opts) + : diags(diags), + debugDumpCycles(opts.DebugDumpCycles), + buildDependencyGraph(opts.BuildRequestDependencyGraph), + recorder{computeDependencyModeFromFlags(opts)} {} void Evaluator::emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath) { std::error_code error; @@ -383,7 +383,7 @@ void evaluator::DependencyRecorder::realize( const DependencyCollector::Reference &ref) { auto *source = getActiveDependencySourceOrNull(); assert(source && "cannot realize dependency without associated file!"); - if (!source->hasInterfaceHash()) { + if (!source->isPrimary()) { return; } fileReferences[source].insert(ref); @@ -434,7 +434,7 @@ void evaluator::DependencyRecorder::record( llvm::function_ref rec) { assert(!isRecording && "Probably not a good idea to allow nested recording"); auto *source = getActiveDependencySourceOrNull(); - if (!source || !source->hasInterfaceHash()) { + if (!source || !source->isPrimary()) { return; } @@ -466,7 +466,7 @@ void evaluator::DependencyRecorder::replay(const swift::ActiveRequest &req) { assert(!isRecording && "Probably not a good idea to allow nested recording"); auto *source = getActiveDependencySourceOrNull(); - if (mode == Mode::StatusQuo || !source || !source->hasInterfaceHash()) { + if (mode == Mode::StatusQuo || !source || !source->isPrimary()) { return; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 79ea2455f9eb0..34d70a3ad815c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1923,7 +1923,8 @@ bool ClosureExpr::capturesSelfEnablingImplictSelf() const { void ClosureExpr::setExplicitResultType(Type ty) { assert(ty && !ty->hasTypeVariable()); - ExplicitResultType->setType(MetatypeType::get(ty)); + ExplicitResultTypeAndEnclosingChecked.getPointer() + ->setType(MetatypeType::get(ty)); } FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body) @@ -2364,11 +2365,7 @@ void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) { return; } - if (CE->hasSingleExpressionBody()) { - out << "single expression closure"; - } else { - out << "closure"; - } + out << "closure"; } void swift::simple_display(llvm::raw_ostream &out, diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index a1a36e38096a4..a8858e687c021 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -65,7 +65,7 @@ GenericSignatureImpl::GenericSignatureImpl( count = 0; } assert(param->getIndex() == count && "Generic parameter index mismatch"); - count++; + ++count; } #endif @@ -76,18 +76,22 @@ GenericSignatureImpl::GenericSignatureImpl( TypeArrayView GenericSignatureImpl::getInnermostGenericParams() const { - auto params = getGenericParams(); + const auto params = getGenericParams(); - // Find the point at which the depth changes. - unsigned depth = params.back()->getDepth(); - for (unsigned n = params.size(); n > 0; --n) { - if (params[n-1]->getDepth() != depth) { - return params.slice(n); - } + const unsigned maxDepth = params.back()->getDepth(); + if (params.front()->getDepth() == maxDepth) + return params; + + // There is a depth change. Count the number of elements + // to slice off the front. + unsigned sliceCount = params.size() - 1; + while (true) { + if (params[sliceCount - 1]->getDepth() != maxDepth) + break; + --sliceCount; } - // All parameters are at the same depth. - return params; + return params.slice(sliceCount); } void GenericSignatureImpl::forEachParam( diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index ee348386c1007..08414cae27b50 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -3432,7 +3432,7 @@ EquivalenceClass::EquivalenceClass(PotentialArchetype *representative) } void EquivalenceClass::modified(GenericSignatureBuilder &builder) { - builder.Impl->Generation++; + ++builder.Impl->Generation; // Transfer any delayed requirements to the primary queue, because they // might be resolvable now. @@ -3445,7 +3445,7 @@ GenericSignatureBuilder::GenericSignatureBuilder( ASTContext &ctx) : Context(ctx), Diags(Context.Diags), Impl(new Implementation) { if (auto *Stats = Context.Stats) - Stats->getFrontendCounters().NumGenericSignatureBuilders++; + ++Stats->getFrontendCounters().NumGenericSignatureBuilders; } GenericSignatureBuilder::GenericSignatureBuilder( @@ -3823,7 +3823,7 @@ static ConstraintResult visitInherited( unsigned index = 0; for (auto memberType : compositionType->getMembers()) { visitInherited(memberType, composition->getTypes()[index]); - index++; + ++index; } return; diff --git a/lib/AST/ImportCache.cpp b/lib/AST/ImportCache.cpp index ce79064c7e27b..352b582990f59 100644 --- a/lib/AST/ImportCache.cpp +++ b/lib/AST/ImportCache.cpp @@ -109,12 +109,12 @@ ImportCache::getImportSet(ASTContext &ctx, if (ImportSet *result = ImportSets.FindNodeOrInsertPos(ID, InsertPos)) { if (ctx.Stats) - ctx.Stats->getFrontendCounters().ImportSetFoldHit++; + ++ctx.Stats->getFrontendCounters().ImportSetFoldHit; return *result; } if (ctx.Stats) - ctx.Stats->getFrontendCounters().ImportSetFoldMiss++; + ++ctx.Stats->getFrontendCounters().ImportSetFoldMiss; SmallVector stack; for (auto next : topLevelImports) { @@ -166,12 +166,12 @@ ImportSet &ImportCache::getImportSet(const DeclContext *dc) { auto found = ImportSetForDC.find(dc); if (found != ImportSetForDC.end()) { if (ctx.Stats) - ctx.Stats->getFrontendCounters().ImportSetCacheHit++; + ++ctx.Stats->getFrontendCounters().ImportSetCacheHit; return *found->second; } if (ctx.Stats) - ctx.Stats->getFrontendCounters().ImportSetCacheMiss++; + ++ctx.Stats->getFrontendCounters().ImportSetCacheMiss; SmallVector imports; @@ -213,12 +213,12 @@ ImportCache::getAllVisibleAccessPaths(const ModuleDecl *mod, auto found = VisibilityCache.find(key); if (found != VisibilityCache.end()) { if (ctx.Stats) - ctx.Stats->getFrontendCounters().ModuleVisibilityCacheHit++; + ++ctx.Stats->getFrontendCounters().ModuleVisibilityCacheHit; return found->second; } if (ctx.Stats) - ctx.Stats->getFrontendCounters().ModuleVisibilityCacheMiss++; + ++ctx.Stats->getFrontendCounters().ModuleVisibilityCacheMiss; SmallVector accessPaths; for (auto next : getImportSet(dc).getAllImports()) { @@ -251,12 +251,12 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod, auto found = ShadowCache.find(key); if (found != ShadowCache.end()) { if (ctx.Stats) - ctx.Stats->getFrontendCounters().ModuleShadowCacheHit++; + ++ctx.Stats->getFrontendCounters().ModuleShadowCacheHit; return found->second; } if (ctx.Stats) - ctx.Stats->getFrontendCounters().ModuleShadowCacheMiss++; + ++ctx.Stats->getFrontendCounters().ModuleShadowCacheMiss; SmallVector stack; llvm::SmallDenseSet visited; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 6b1ae78787496..41c4ac32330e0 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -511,6 +511,41 @@ void ModuleDecl::addFile(FileUnit &newFile) { clearLookupCache(); } +ArrayRef +PrimarySourceFilesRequest::evaluate(Evaluator &evaluator, + ModuleDecl *mod) const { + assert(mod->isMainModule() && "Only the main module can have primaries"); + + SmallVector primaries; + for (auto *file : mod->getFiles()) { + if (auto *SF = dyn_cast(file)) { + if (SF->isPrimary()) + primaries.push_back(SF); + } + } + return mod->getASTContext().AllocateCopy(primaries); +} + +ArrayRef ModuleDecl::getPrimarySourceFiles() const { + auto &eval = getASTContext().evaluator; + auto *mutableThis = const_cast(this); + return evaluateOrDefault(eval, PrimarySourceFilesRequest{mutableThis}, {}); +} + +SourceFile *CodeCompletionFileRequest::evaluate(Evaluator &evaluator, + ModuleDecl *mod) const { + const auto &SM = mod->getASTContext().SourceMgr; + assert(mod->isMainModule() && "Can only do completion in the main module"); + assert(SM.hasCodeCompletionBuffer() && "Not performing code completion?"); + + for (auto *file : mod->getFiles()) { + auto *SF = dyn_cast(file); + if (SF && SF->getBufferID() == SM.getCodeCompletionBufferID()) + return SF; + } + llvm_unreachable("Couldn't find the completion file?"); +} + #define FORWARD(name, args) \ for (const FileUnit *file : getFiles()) \ file->name args; @@ -554,7 +589,7 @@ void ModuleDecl::lookupValue(DeclName Name, NLKind LookupKind, SmallVectorImpl &Result) const { auto *stats = getASTContext().Stats; if (stats) - stats->getFrontendCounters().NumModuleLookupValue++; + ++stats->getFrontendCounters().NumModuleLookupValue; if (isParsedModule(this)) { getSourceLookupCache().lookupValue(Name, LookupKind, Result); @@ -710,7 +745,7 @@ void ModuleDecl::lookupClassMember(AccessPathTy accessPath, SmallVectorImpl &results) const { auto *stats = getASTContext().Stats; if (stats) - stats->getFrontendCounters().NumModuleLookupClassMember++; + ++stats->getFrontendCounters().NumModuleLookupClassMember; if (isParsedModule(this)) { FrontendStatsTracer tracer(getASTContext().Stats, @@ -2182,12 +2217,15 @@ ModuleDecl::computeMagicFileStringMap(bool shouldDiagnose) const { SourceFile::SourceFile(ModuleDecl &M, SourceFileKind K, Optional bufferID, bool KeepParsedTokens, bool BuildSyntaxTree, - ParsingOptions parsingOpts) + ParsingOptions parsingOpts, bool isPrimary) : FileUnit(FileUnitKind::Source, M), BufferID(bufferID ? *bufferID : -1), - ParsingOpts(parsingOpts), Kind(K), + ParsingOpts(parsingOpts), IsPrimary(isPrimary), Kind(K), SyntaxInfo(new SourceFileSyntaxInfo(BuildSyntaxTree)) { M.getASTContext().addDestructorCleanup(*this); + assert(!IsPrimary || M.isMainModule() && + "A primary cannot appear outside the main module"); + if (isScriptMode()) { bool problem = M.registerEntryPointFile(this, SourceLoc(), None); assert(!problem && "multiple main files?"); diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index c6f36c1522a67..5da65daf1d014 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -78,7 +78,7 @@ void LookupResult::filter( Results.erase(std::remove_if(Results.begin(), Results.end(), [&](LookupResultEntry result) -> bool { auto isInner = index < originalFirstOuter; - index++; + ++index; if (pred(result, !isInner)) return false; @@ -86,7 +86,7 @@ void LookupResult::filter( // an inner result, the outer results need to // shift down. if (isInner) - IndexOfFirstOuterResult--; + --IndexOfFirstOuterResult; return true; }), Results.end()); diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp index 765eeb67d2527..bd4f710bfeaa8 100644 --- a/lib/AST/RequirementEnvironment.cpp +++ b/lib/AST/RequirementEnvironment.cpp @@ -73,7 +73,7 @@ RequirementEnvironment::RequirementEnvironment( // appear in the synthetic signature. unsigned depth = 0; if (covariantSelf) { - depth++; + ++depth; } if (conformanceSig) { depth += conformanceSig->getGenericParams().back()->getDepth() + 1; diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 074e432f4893c..4e7e13ac21204 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -333,7 +333,7 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { reqt.getSecondType()->isEqual(proto->getDeclaredType())) return getConformances()[index]; - index++; + ++index; } } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index cb44104a71dfe..d8ab0842fa9c1 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -4008,7 +4008,7 @@ TypeBase::getContextSubstitutions(const DeclContext *dc, // Continue looking into the parent. if (auto protocolTy = baseTy->getAs()) { baseTy = protocolTy->getParent(); - n--; + --n; continue; } diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 91d3a48763dae..f6313796e1fc4 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1455,11 +1455,11 @@ void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const { } //----------------------------------------------------------------------------// -// TypeCheckFunctionBodyUntilRequest computation. +// TypeCheckFunctionBodyRequest computation. //----------------------------------------------------------------------------// evaluator::DependencySource -TypeCheckFunctionBodyUntilRequest::readDependencySource( +TypeCheckFunctionBodyRequest::readDependencySource( const evaluator::DependencyRecorder &e) const { // We're going under a function body scope, unconditionally flip the scope // to private. diff --git a/lib/Basic/Mangler.cpp b/lib/Basic/Mangler.cpp index fcf7d26037f33..4f92c1787cafe 100644 --- a/lib/Basic/Mangler.cpp +++ b/lib/Basic/Mangler.cpp @@ -59,7 +59,7 @@ static llvm::StringMap OpStats; void Mangler::recordOpStatImpl(StringRef op, size_t OldPos) { if (PrintSwiftManglingStats) { OpStatEntry &E = OpStats[op]; - E.num++; + ++E.num; E.size += Storage.size() - OldPos; } } @@ -218,7 +218,7 @@ bool Mangler::tryMangleSubstitution(const void *ptr) { void Mangler::mangleSubstitution(unsigned Idx) { if (Idx >= 26) { #ifndef NDEBUG - numLargeSubsts++; + ++numLargeSubsts; #endif return appendOperator("A", Index(Idx - 26)); } @@ -226,7 +226,7 @@ void Mangler::mangleSubstitution(unsigned Idx) { char Subst = Idx + 'A'; if (SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ false)) { #ifndef NDEBUG - mergedSubsts++; + ++mergedSubsts; #endif } else { appendOperator("A", StringRef(&Subst, 1)); diff --git a/lib/Basic/PrimitiveParsing.cpp b/lib/Basic/PrimitiveParsing.cpp index 433bdb32792e9..ee266a3923e10 100644 --- a/lib/Basic/PrimitiveParsing.cpp +++ b/lib/Basic/PrimitiveParsing.cpp @@ -30,7 +30,7 @@ unsigned swift::measureNewline(const char *BufferPtr, const char *BufferEnd) { assert(*BufferPtr == '\r'); unsigned Bytes = 1; if (BufferPtr != BufferEnd && *BufferPtr == '\n') - Bytes++; + ++Bytes; return Bytes; } diff --git a/lib/Basic/Statistic.cpp b/lib/Basic/Statistic.cpp index 30509f4b6270f..4881e84a5121a 100644 --- a/lib/Basic/Statistic.cpp +++ b/lib/Basic/Statistic.cpp @@ -162,7 +162,7 @@ class UnifiedStatsReporter::RecursionSafeTimers { if (T.RecursionDepth == 0) { T.Timer.emplace(Name); } - T.RecursionDepth++; + ++T.RecursionDepth; } void endTimer(StringRef Name) { @@ -170,7 +170,7 @@ class UnifiedStatsReporter::RecursionSafeTimers { assert(I != Timers.end()); RecursionSafeTimer &T = I->getValue(); assert(T.RecursionDepth != 0); - T.RecursionDepth--; + --T.RecursionDepth; if (T.RecursionDepth == 0) { T.Timer.reset(); } @@ -651,10 +651,10 @@ UnifiedStatsReporter::~UnifiedStatsReporter() if (currentProcessExitStatus != EXIT_SUCCESS) { if (FrontendCounters) { auto &C = getFrontendCounters(); - C.NumProcessFailures++; + ++C.NumProcessFailures; } else { auto &C = getDriverCounters(); - C.NumProcessFailures++; + ++C.NumProcessFailures; } } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 6b11ca1992bd9..142ab1d3b358a 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -908,6 +908,9 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions, std::vector ClangImporter::getClangArguments(ASTContext &ctx, const ClangImporterOptions &importerOpts) { + if (importerOpts.ExtraArgsOnly) { + return importerOpts.ExtraArgs; + } std::vector invocationArgStrs; // Clang expects this to be like an actual command line. So we need to pass in // "clang" for argv[0] @@ -957,6 +960,10 @@ ClangImporter::createClangInvocation(ClangImporter *importer, nullptr, false, CC1Args); } +ArrayRef ClangImporter::getExtraClangArgs() const { + return Impl.ExtraClangArgs; +} + std::unique_ptr ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, std::string swiftPCHHash, DependencyTracker *tracker, @@ -965,7 +972,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)}; importer->Impl.ClangArgs = getClangArguments(ctx, importerOpts); ArrayRef invocationArgStrs = importer->Impl.ClangArgs; - + importer->Impl.ExtraClangArgs = importerOpts.ExtraArgs; if (importerOpts.DumpClangDiagnostics) { llvm::errs() << "'"; llvm::interleave( @@ -1779,8 +1786,7 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang( if (!clangModule) return nullptr; - return finishLoadingClangModule(importLoc, clangModule, - /*preferOverlay=*/false); + return finishLoadingClangModule(clangModule, importLoc); } ModuleDecl * @@ -1800,59 +1806,30 @@ ModuleDecl *ClangImporter::Implementation::loadModule( } ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( - SourceLoc importLoc, const clang::Module *clangModule, bool findOverlay) { + const clang::Module *clangModule, SourceLoc importLoc) { assert(clangModule); // Bump the generation count. bumpGeneration(); - auto &cacheEntry = ModuleWrappers[clangModule]; - ModuleDecl *result; - ClangModuleUnit *wrapperUnit; - if ((wrapperUnit = cacheEntry.getPointer())) { - result = wrapperUnit->getParentModule(); - if (!cacheEntry.getInt()) { - // Force load overlays for all imported modules. - // FIXME: This forces the creation of wrapper modules for all imports as - // well, and may do unnecessary work. - cacheEntry.setInt(true); - (void) namelookup::getAllImports(result); - } - } else { - // Build the representation of the Clang module in Swift. - // FIXME: The name of this module could end up as a key in the ASTContext, - // but that's not correct for submodules. - Identifier name = SwiftContext.getIdentifier((*clangModule).Name); - result = ModuleDecl::create(name, SwiftContext); - result->setIsSystemModule(clangModule->IsSystem); - result->setIsNonSwiftModule(); - result->setHasResolvedImports(); - - wrapperUnit = - new (SwiftContext) ClangModuleUnit(*result, *this, clangModule); - result->addFile(*wrapperUnit); - SwiftContext.getClangModuleLoader() - ->findOverlayFiles(importLoc, result, wrapperUnit); - cacheEntry.setPointerAndInt(wrapperUnit, true); - - // Force load overlays for all imported modules. - // FIXME: This forces the creation of wrapper modules for all imports as - // well, and may do unnecessary work. + // Force load overlays for all imported modules. + // FIXME: This forces the creation of wrapper modules for all imports as + // well, and may do unnecessary work. + ClangModuleUnit *wrapperUnit = getWrapperForModule(clangModule, importLoc); + ModuleDecl *result = wrapperUnit->getParentModule(); + if (!ModuleWrappers[clangModule].getInt()) { + ModuleWrappers[clangModule].setInt(true); (void) namelookup::getAllImports(result); } if (clangModule->isSubModule()) { - finishLoadingClangModule(importLoc, clangModule->getTopLevelModule(), true); + finishLoadingClangModule(clangModule->getTopLevelModule(), importLoc); } else { ModuleDecl *&loaded = SwiftContext.LoadedModules[result->getName()]; if (!loaded) loaded = result; } - if (findOverlay) - if (ModuleDecl *overlay = wrapperUnit->getOverlayModule()) - result = overlay; - return result; } @@ -1876,8 +1853,7 @@ void ClangImporter::Implementation::handleDeferredImports(SourceLoc diagLoc) { // officially supported with bridging headers: app targets and unit tests // only. Unfortunately that's not enforced. for (size_t i = 0; i < ImportedHeaderExports.size(); ++i) { - (void)finishLoadingClangModule(diagLoc, ImportedHeaderExports[i], - /*preferOverlay=*/true); + (void)finishLoadingClangModule(ImportedHeaderExports[i], diagLoc); } } @@ -2018,7 +1994,7 @@ ClangImporter::Implementation::~Implementation() { } ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule( - const clang::Module *underlying) { + const clang::Module *underlying, SourceLoc diagLoc) { auto &cacheEntry = ModuleWrappers[underlying]; if (ClangModuleUnit *cached = cacheEntry.getPointer()) return cached; @@ -2033,7 +2009,7 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule( auto file = new (SwiftContext) ClangModuleUnit(*wrapper, *this, underlying); wrapper->addFile(*file); - SwiftContext.getClangModuleLoader()->findOverlayFiles(SourceLoc(), wrapper, file); + SwiftContext.getClangModuleLoader()->findOverlayFiles(diagLoc, wrapper, file); cacheEntry.setPointer(file); return file; diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 3d2b1d256137e..739aa8444d22a 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -188,20 +188,6 @@ static ClangModuleDependenciesCacheImpl *getOrCreateClangImpl( return clangImpl; } -static std::string getModuleFilePath(StringRef moduleCacheDir, - StringRef moduleName, - StringRef contextHash) { - SmallString<128> outputPath(moduleCacheDir); - llvm::sys::path::append(outputPath, (llvm::Twine(moduleName) - + "-" + contextHash + ".pcm").str()); - return outputPath.str().str(); -} - -static std::string getModuleFilePath(StringRef moduleCacheDir, - const ModuleDeps &dep) { - return getModuleFilePath(moduleCacheDir, dep.ModuleName, dep.ContextHash); -} - /// Record the module dependencies we found by scanning Clang modules into /// the module dependencies cache. void ClangImporter::recordModuleDependencies( @@ -213,23 +199,7 @@ void ClangImporter::recordModuleDependencies( }; auto ModuleCacheDir = swift::getModuleCachePathFromClang(getClangInstance()); - // A map keyed by module name and context hash. - llvm::StringMap> moduleInfoMap; - - // Traverse all Clang modules to populate moduleInfoMap for cross - // referencing later. - for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { - moduleInfoMap[clangModuleDep.ModuleName][clangModuleDep.ContextHash] = - { - // Keep track of pcm path for output. - getModuleFilePath(ModuleCacheDir, clangModuleDep), - // Keep track of modulemap file for input. - clangModuleDep.ClangModuleMapFile - }; - } for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { - assert(moduleInfoMap[clangModuleDep.ModuleName] - .count(clangModuleDep.ContextHash)); // If we've already cached this information, we're done. if (cache.hasDependencies(clangModuleDep.ModuleName, ModuleDependenciesKind::Clang)) @@ -241,48 +211,32 @@ void ClangImporter::recordModuleDependencies( fileDeps.push_back(fileDep.getKey().str()); } // Inherit all Clang driver args when creating the clang importer. - std::vector allArgs = Impl.ClangArgs; + ArrayRef allArgs = Impl.ClangArgs; ClangImporterOptions Opts; - std::vector cc1Args; - // Calling this to convert driver args to CC1 args. - createClangInvocation(this, Opts, allArgs, &cc1Args); + // Ensure the arguments we collected is sufficient to create a Clang + // invocation. + assert(createClangInvocation(this, Opts, allArgs)); + std::vector swiftArgs; // We are using Swift frontend mode. swiftArgs.push_back("-frontend"); + // We pass the entire argument list via -Xcc, so the invocation should + // use extra clang options alone. + swiftArgs.push_back("-only-use-extra-clang-opts"); auto addClangArg = [&](StringRef arg) { - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back("-Xclang"); swiftArgs.push_back("-Xcc"); swiftArgs.push_back(arg.str()); }; // Add all args inheritted from creating the importer. - for (auto arg: cc1Args) { - addClangArg(arg); - } - // Add all args reported from the Clang dependencies scanner. - for(auto arg: clangModuleDep.NonPathCommandLine) { + for (auto arg: allArgs) { addClangArg(arg); } - - // Add -fmodule-map-file and -fmodule-file for direct dependencies. - for (auto &dep: clangModuleDep.ClangModuleDeps) { - assert(moduleInfoMap[dep.ModuleName].count(dep.ContextHash)); - addClangArg((llvm::Twine("-fmodule-map-file=") - + moduleInfoMap[dep.ModuleName][dep.ContextHash].ModuleMapPath).str()); - addClangArg((llvm::Twine("-fmodule-file=") - + moduleInfoMap[dep.ModuleName][dep.ContextHash].PCMPath).str()); - } // Swift frontend action: -emit-pcm swiftArgs.push_back("-emit-pcm"); swiftArgs.push_back("-module-name"); swiftArgs.push_back(clangModuleDep.ModuleName); - // Swift frontend option for output file path (Foo.pcm). - swiftArgs.push_back("-o"); - swiftArgs.push_back(moduleInfoMap[clangModuleDep.ModuleName] - [clangModuleDep.ContextHash].PCMPath); - // Swift frontend option for input file path (Foo.modulemap). swiftArgs.push_back(clangModuleDep.ClangModuleMapFile); // Module-level dependencies. diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 748c2df1e73c3..5f971d0872e63 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -1330,10 +1330,10 @@ synthesizeValueConstructorBody(AbstractFunctionDecl *afd, void *context) { // To keep DI happy, initialize stored properties before computed. auto parameters = constructor->getParameters(); - for (unsigned pass = 0; pass < 2; pass++) { + for (unsigned pass = 0; pass < 2; ++pass) { unsigned paramPos = 0; - for (unsigned i = 0, e = members.size(); i < e; i++) { + for (unsigned i = 0, e = members.size(); i < e; ++i) { auto var = members[i]; if (var->hasClangNode() && @@ -1341,7 +1341,7 @@ synthesizeValueConstructorBody(AbstractFunctionDecl *afd, void *context) { continue; if (var->hasStorage() == (pass != 0)) { - paramPos++; + ++paramPos; continue; } @@ -1369,7 +1369,7 @@ synthesizeValueConstructorBody(AbstractFunctionDecl *afd, void *context) { assign->setType(TupleType::getEmpty(ctx)); stmts.push_back(assign); - paramPos++; + ++paramPos; } } @@ -7928,7 +7928,7 @@ void ClangImporter::Implementation::startedImportingEntity() { ++NumTotalImportedEntities; // FIXME: (transitional) increment the redundant "always-on" counter. if (auto *Stats = SwiftContext.Stats) - Stats->getFrontendCounters().NumTotalClangImportedEntities++; + ++Stats->getFrontendCounters().NumTotalClangImportedEntities; } /// Look up associated type requirements in the conforming type. diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 9b7fa76b06db5..87c5518c3e1e3 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -2082,7 +2082,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( auto argNames = importedName.getDeclName().getArgumentNames(); unsigned nameIndex = 0; - for (size_t paramIndex = 0; paramIndex != params.size(); paramIndex++) { + for (size_t paramIndex = 0, e = params.size(); paramIndex != e; + ++paramIndex) { auto param = params[paramIndex]; auto paramTy = param->getType(); auto paramIsError = errorInfo && paramIndex == errorInfo->ErrorParameterIndex; diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 7963151dda780..977b2b268d726 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -392,6 +392,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Clang arguments used to create the Clang invocation. std::vector ClangArgs; + + /// Extra clang args specified via "-Xcc" + std::vector ExtraClangArgs; public: /// Mapping of already-imported declarations. llvm::DenseMap, Decl *> ImportedDecls; @@ -922,12 +925,12 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Retrieves the Swift wrapper for the given Clang module, creating /// it if necessary. - ClangModuleUnit *getWrapperForModule(const clang::Module *underlying); + ClangModuleUnit *getWrapperForModule(const clang::Module *underlying, + SourceLoc importLoc = SourceLoc()); /// Constructs a Swift module for the given Clang module. - ModuleDecl *finishLoadingClangModule(SourceLoc importLoc, - const clang::Module *clangModule, - bool preferOverlay); + ModuleDecl *finishLoadingClangModule(const clang::Module *clangModule, + SourceLoc importLoc); /// Call finishLoadingClangModule on each deferred import collected /// while scanning a bridging header or PCH. diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index f447c2cef583b..37aed75054988 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -373,7 +373,7 @@ void Node::removeChildAt(unsigned Pos) { for (unsigned i = Pos, n = Children.Number - 1; i != n; ++i) { Children.Nodes[i] = Children.Nodes[i + 1]; } - Children.Number--; + --Children.Number; break; default: assert(false && "cannot remove child"); @@ -582,13 +582,12 @@ NodePointer Demangler::demangleType(StringRef MangledName, } bool Demangler::parseAndPushNodes() { - int Idx = 0; - while (Pos < Text.size()) { + const auto textSize = Text.size(); + while (Pos < textSize) { NodePointer Node = demangleOperator(); if (!Node) return false; pushNode(Node); - Idx++; } return true; } @@ -1831,12 +1830,12 @@ NodePointer Demangler::demangleImplFunctionType() { type = addChild(type, Param); if (NodePointer Diff = demangleImplDifferentiability()) Param = addChild(Param, Diff); - NumTypesToAdd++; + ++NumTypesToAdd; } while (NodePointer Result = demangleImplResultConvention( Node::Kind::ImplResult)) { type = addChild(type, Result); - NumTypesToAdd++; + ++NumTypesToAdd; } while (nextIf('Y')) { NodePointer YieldResult = @@ -1844,7 +1843,7 @@ NodePointer Demangler::demangleImplFunctionType() { if (!YieldResult) return nullptr; type = addChild(type, YieldResult); - NumTypesToAdd++; + ++NumTypesToAdd; } if (nextIf('z')) { NodePointer ErrorResult = demangleImplResultConvention( @@ -1852,7 +1851,7 @@ NodePointer Demangler::demangleImplFunctionType() { if (!ErrorResult) return nullptr; type = addChild(type, ErrorResult); - NumTypesToAdd++; + ++NumTypesToAdd; } if (!nextIf('_')) return nullptr; diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 22d52337aae39..96c6b2cdd74e3 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -243,9 +243,15 @@ class NodePrinter { if (!Options.QualifyEntities) return false; - if (Context->getKind() == Node::Kind::Module && - Context->getText().startswith(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX)) { - return Options.DisplayDebuggerGeneratedModule; + if (Context->getKind() == Node::Kind::Module) { + if (Context->getText() == swift::STDLIB_NAME) + return Options.DisplayStdlibModule; + if (Context->getText() == swift::MANGLING_MODULE_OBJC) + return Options.DisplayObjCModule; + if (Context->getText() == Options.HidingCurrentModule) + return false; + if (Context->getText().startswith(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX)) + return Options.DisplayDebuggerGeneratedModule; } return true; } @@ -990,7 +996,7 @@ void NodePrinter::printSpecializationPrefix(NodePointer node, print(child); } } - argNum++; + ++argNum; break; } } @@ -1583,13 +1589,13 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { bool isSerialized = false; if (lastChild->getKind() == Node::Kind::IsSerialized) { isSerialized = true; - lastChildIndex--; + --lastChildIndex; lastChild = Node->getChild(lastChildIndex - 1); } if (lastChild->getKind() == Node::Kind::DependentGenericSignature) { print(lastChild); - lastChildIndex--; + --lastChildIndex; } Printer << "("; @@ -1880,7 +1886,7 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { NodePointer repr = Node->getChild(Idx); print(repr); Printer << " "; - Idx++; + ++Idx; } NodePointer type = Node->getChild(Idx)->getChild(0); printWithParens(type); @@ -1897,7 +1903,7 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { NodePointer repr = Node->getChild(Idx); print(repr); Printer << " "; - Idx++; + ++Idx; } NodePointer type = Node->getChild(Idx); @@ -1947,8 +1953,8 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { printChildren(type_list, " & "); Printer << " & "; } - if (Options.QualifyEntities) - Printer << "Swift."; + if (Options.QualifyEntities && Options.DisplayStdlibModule) + Printer << swift::STDLIB_NAME << "."; Printer << "AnyObject"; return nullptr; } diff --git a/lib/Demangling/OldDemangler.cpp b/lib/Demangling/OldDemangler.cpp index d9d9dd4a1c54c..e8961e130a8e7 100644 --- a/lib/Demangling/OldDemangler.cpp +++ b/lib/Demangling/OldDemangler.cpp @@ -839,7 +839,7 @@ class OldDemangler { if (demangleNatural(natural)) { if (!Mangled.nextIf('_')) return false; - natural++; + ++natural; return true; } return false; diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index 02e974a926ee0..67aa6ba5c1e40 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -1201,7 +1201,7 @@ void Remangler::mangleImplFunctionType(Node *node) { auto i = node->begin(), e = node->end(); if (i != e && (*i)->getKind() == Node::Kind::ImplConvention) { StringRef text = (*i)->getText(); - i++; + ++i; if (text == "@callee_unowned") { Buffer << 'd'; } else if (text == "@callee_guaranteed") { @@ -1224,7 +1224,7 @@ void Remangler::mangleImplFunctionType(Node *node) { Buffer << ((*i)->getKind() == Node::Kind::DependentGenericSignature ? 'G' : 'g'); mangleDependentGenericSignature((*i)); - i++; + ++i; } Buffer << '_'; for (; i != e && (*i)->getKind() == Node::Kind::ImplParameter; ++i) { diff --git a/lib/Demangling/Punycode.cpp b/lib/Demangling/Punycode.cpp index 1e065b55776fc..4339b8b20d0cc 100644 --- a/lib/Demangling/Punycode.cpp +++ b/lib/Demangling/Punycode.cpp @@ -127,7 +127,7 @@ bool Punycode::decodePunycode(StringRef InputPunycode, return true; // insert n into output at position i OutCodePoints.insert(OutCodePoints.begin() + i, n); - i++; + ++i; } return true; diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index f5a19356b5223..d30c52137244a 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -895,7 +895,7 @@ void Remangler::mangleDependentGenericLayoutRequirement(Node *node) { void Remangler::mangleDependentGenericSignature(Node *node) { size_t ParamCountEnd = 0; - for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; Idx++) { + for (size_t Idx = 0, Num = node->getNumChildren(); Idx < Num; ++Idx) { Node *Child = node->getChild(Idx); if (Child->getKind() == Node::Kind::DependentGenericParamCount) { ParamCountEnd = Idx + 1; diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 1718f0ba233a2..b4829ab4b402b 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -374,9 +374,9 @@ namespace driver { if (auto *Stats = Comp.getStatsReporter()) { auto &D = Stats->getDriverCounters(); if (Skipped) - D.NumDriverJobsSkipped++; + ++D.NumDriverJobsSkipped; else - D.NumDriverJobsRun++; + ++D.NumDriverJobsRun; } auto BlockedIter = BlockingCommands.find(Cmd); if (BlockedIter != BlockingCommands.end()) { diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 4b9428e9d3de0..d0be6bc80fd3a 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2041,7 +2041,7 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, InputIndex); AllLinkerInputs.push_back(BJA); } - InputIndex++; + ++InputIndex; } if (!OI.isMultiThreading()) { // No multi-threading: the compilation only produces a single output diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index d41a07c1485f6..232a69ac30487 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -290,8 +290,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, arguments.push_back("-enable-anonymous-context-mangled-names"); } - inputArgs.AddLastArg(arguments, options::OPT_disable_leaf_frame_pointer_elim); - // Pass through any subsystem flags. inputArgs.AddAllArgs(arguments, options::OPT_Xllvm); inputArgs.AddAllArgs(arguments, options::OPT_Xcc); diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 14f5ac00ec9cf..f5f28b1a4e793 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -83,6 +83,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.TrackSystemDeps |= Args.hasArg(OPT_track_system_dependencies); + Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules); + // Always track system dependencies when scanning dependencies. if (const Arg *ModeArg = Args.getLastArg(OPT_modes_Group)) { if (ModeArg->getOption().matches(OPT_scan_dependencies)) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 17f28871d3243..46bdf5c5f0d8d 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -802,6 +802,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, Opts.DisableOverlayModules |= Args.hasArg(OPT_emit_imported_modules); + Opts.ExtraArgsOnly |= Args.hasArg(OPT_extra_clang_options_only); + if (const Arg *A = Args.getLastArg(OPT_pch_output_dir)) { Opts.PrecompiledHeaderOutputDir = A->getValue(); Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation); @@ -863,6 +865,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, Opts.DisableModulesValidateSystemDependencies |= Args.hasArg(OPT_disable_modules_validate_system_headers); + for (auto A: Args.filtered(OPT_swift_module_file)) { + Opts.ExplicitSwiftModules.push_back(resolveSearchPath(A->getValue())); + } // Opts.RuntimeIncludePath is set by calls to // setRuntimeIncludePath() or setMainExecutablePath(). // Opts.RuntimeImportPath is set by calls to @@ -1528,9 +1533,6 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, getRuntimeCompatVersion(); } - if (Args.hasArg(OPT_disable_leaf_frame_pointer_elim)) - Opts.DisableFPElimLeaf = true; - return false; } diff --git a/lib/Frontend/DiagnosticVerifier.cpp b/lib/Frontend/DiagnosticVerifier.cpp index c1918dc613088..16dfe72379f90 100644 --- a/lib/Frontend/DiagnosticVerifier.cpp +++ b/lib/Frontend/DiagnosticVerifier.cpp @@ -688,7 +688,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) { /// ^ remove /// @endcode if (replStartLoc[-1] == ' ') { - replStartLoc--; + --replStartLoc; } } else { auto phrase = makeActualFixitsPhrase(FoundDiagnostic.FixIts); @@ -796,7 +796,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) { } if (I == CapturedDiagnostics.end()) { - expectedDiagIter++; + ++expectedDiagIter; continue; } @@ -877,7 +877,7 @@ DiagnosticVerifier::Result DiagnosticVerifier::verifyFile(unsigned BufferID) { auto CapturedDiagIter = CapturedDiagnostics.begin(); while (CapturedDiagIter != CapturedDiagnostics.end()) { if (CapturedDiagIter->FileName != BufferName) { - CapturedDiagIter++; + ++CapturedDiagIter; continue; } diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index aca792d419588..2f862316262a7 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -450,17 +450,27 @@ bool CompilerInstance::setUpModuleLoaders() { return true; } + // If implicit modules are disabled, we need to install an explicit module + // loader. + if (Invocation.getFrontendOptions().DisableImplicitModules) { + auto ESML = ExplicitSwiftModuleLoader::create( + *Context, + getDependencyTracker(), MLM, + Invocation.getSearchPathOptions().ExplicitSwiftModules, + IgnoreSourceInfoFile); + Context->addModuleLoader(std::move(ESML)); + } if (MLM != ModuleLoadingMode::OnlySerialized) { auto const &Clang = clangImporter->getClangInstance(); std::string ModuleCachePath = getModuleCachePathFromClang(Clang); auto &FEOpts = Invocation.getFrontendOptions(); StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath; + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); auto PIML = ModuleInterfaceLoader::create( *Context, ModuleCachePath, PrebuiltModuleCachePath, getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules, - FEOpts.RemarkOnRebuildFromModuleInterface, - IgnoreSourceInfoFile, - FEOpts.DisableInterfaceFileLock); + LoaderOpts, + IgnoreSourceInfoFile); Context->addModuleLoader(std::move(PIML)); } @@ -489,6 +499,12 @@ Optional CompilerInstance::setUpCodeCompletionBuffer() { return codeCompletionBufferID; } +SourceFile *CompilerInstance::getCodeCompletionFile() const { + auto *mod = getMainModule(); + auto &eval = mod->getASTContext().evaluator; + return evaluateOrDefault(eval, CodeCompletionFileRequest{mod}, nullptr); +} + static bool shouldTreatSingleInputAsMain(InputFileKind inputKind) { switch (inputKind) { case InputFileKind::Swift: @@ -707,6 +723,12 @@ ModuleDecl *CompilerInstance::getMainModule() const { return MainModule; } +void CompilerInstance::setMainModule(ModuleDecl *newMod) { + assert(newMod->isMainModule()); + MainModule = newMod; + Context->LoadedModules[newMod->getName()] = newMod; +} + void CompilerInstance::performParseOnly(bool EvaluateConditionals, bool CanDelayBodies) { const InputFileKind Kind = Invocation.getInputKind(); @@ -740,17 +762,6 @@ void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage, ModuleDecl *mainModule = getMainModule(); Context->LoadedModules[mainModule->getName()] = mainModule; - // If we aren't in a parse-only context, load the standard library. - if (LimitStage > SourceFile::Unprocessed && - Invocation.getImplicitStdlibKind() == ImplicitStdlibKind::Stdlib - && !loadStdlib()) { - // If we failed to load the stdlib, mark the main module as having - // "failed to load", as it will contain no files. - // FIXME: We need to better handle a missing stdlib. - mainModule->setFailedToLoad(); - return; - } - // Make sure the main file is the first file in the module, so do this now. if (MainBufferID != NO_SUCH_BUFFER) { auto *mainFile = createSourceFileForMainModule( @@ -813,23 +824,27 @@ void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage, finishTypeChecking(); } -bool CompilerInstance::loadStdlib() { +bool CompilerInstance::loadStdlibIfNeeded() { + // If we aren't expecting an implicit stdlib import, there's nothing to do. + if (getImplicitImportInfo().StdlibKind != ImplicitStdlibKind::Stdlib) + return false; + FrontendStatsTracer tracer(getStatsReporter(), "load-stdlib"); - ModuleDecl *M = Context->getStdlibModule(true); + ModuleDecl *M = Context->getStdlibModule(/*loadIfAbsent*/ true); if (!M) { Diagnostics.diagnose(SourceLoc(), diag::error_stdlib_not_found, Invocation.getTargetTriple()); - return false; + return true; } - // If we failed to load, we should have already diagnosed + // If we failed to load, we should have already diagnosed. if (M->failedToLoad()) { assert(Diagnostics.hadAnyError() && "Module failed to load but nothing was diagnosed?"); - return false; + return true; } - return true; + return false; } bool CompilerInstance::loadPartialModulesAndImplicitImports() { @@ -870,7 +885,7 @@ void CompilerInstance::forEachFileToTypeCheck( fn(*SF); } } else { - for (auto *SF : PrimarySourceFiles) { + for (auto *SF : getPrimarySourceFiles()) { fn(*SF); } } @@ -900,19 +915,12 @@ SourceFile *CompilerInstance::createSourceFileForMainModule( SourceFile *inputFile = new (*Context) SourceFile(*mainModule, fileKind, bufferID, Invocation.getLangOptions().CollectParsedToken, - Invocation.getLangOptions().BuildSyntaxTree, opts); + Invocation.getLangOptions().BuildSyntaxTree, opts, isPrimary); MainModule->addFile(*inputFile); if (isPrimary) { - PrimarySourceFiles.push_back(inputFile); inputFile->enableInterfaceHash(); } - - if (bufferID == SourceMgr.getCodeCompletionBufferID()) { - assert(!CodeCompletionFile && "Multiple code completion files?"); - CodeCompletionFile = inputFile; - } - return inputFile; } @@ -923,7 +931,6 @@ void CompilerInstance::freeASTContext() { SML = nullptr; MemoryBufferLoader = nullptr; PrimaryBufferIDs.clear(); - PrimarySourceFiles.clear(); } /// Perform "stable" optimizations that are invariant across compiler versions. diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 884c5fa9f47bf..5e573ceb6412b 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -339,23 +339,19 @@ class ModuleInterfaceLoaderImpl { const SourceLoc diagnosticLoc; DependencyTracker *const dependencyTracker; const ModuleLoadingMode loadMode; - const bool remarkOnRebuildFromInterface; - const bool disableInterfaceLock; + ModuleInterfaceLoaderOptions Opts; ModuleInterfaceLoaderImpl( ASTContext &ctx, StringRef modulePath, StringRef interfacePath, StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, - SourceLoc diagLoc, bool remarkOnRebuildFromInterface, - bool disableInterfaceLock, + SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts, DependencyTracker *dependencyTracker = nullptr, ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags), modulePath(modulePath), interfacePath(interfacePath), moduleName(moduleName), prebuiltCacheDir(prebuiltCacheDir), cacheDir(cacheDir), diagnosticLoc(diagLoc), - dependencyTracker(dependencyTracker), loadMode(loadMode), - remarkOnRebuildFromInterface(remarkOnRebuildFromInterface), - disableInterfaceLock(disableInterfaceLock) {} + dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts) {} /// Constructs the full path of the dependency \p dep by prepending the SDK /// path if necessary. @@ -828,20 +824,19 @@ class ModuleInterfaceLoaderImpl { } InterfaceSubContextDelegateImpl astDelegate(ctx.SourceMgr, ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts, + Opts, ctx.getClangModuleLoader(), /*buildModuleCacheDirIfAbsent*/true, cacheDir, prebuiltCacheDir, /*serializeDependencyHashes*/false, - trackSystemDependencies, - remarkOnRebuildFromInterface, - disableInterfaceLock); + trackSystemDependencies); // Set up a builder if we need to build the module. It'll also set up // the subinvocation we'll need to use to compute the cache paths. ModuleInterfaceBuilder builder( ctx.SourceMgr, ctx.Diags, astDelegate, interfacePath, moduleName, cacheDir, prebuiltCacheDir, - disableInterfaceLock, diagnosticLoc, + Opts.disableInterfaceLock, diagnosticLoc, dependencyTracker); // Compute the output path if we're loading or emitting a cached module. @@ -885,6 +880,10 @@ class ModuleInterfaceLoaderImpl { return std::move(module.moduleBuffer); } + // If implicit module is disabled, we are done. + if (Opts.disableImplicitSwiftModule) { + return std::make_error_code(std::errc::not_supported); + } std::unique_ptr moduleBuffer; @@ -904,7 +903,7 @@ class ModuleInterfaceLoaderImpl { if (builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true, &moduleBuffer, - remarkOnRebuildFromInterface ? remarkRebuild: + Opts.remarkOnRebuildFromInterface ? remarkRebuild: llvm::function_ref())) return std::make_error_code(std::errc::invalid_argument); @@ -964,7 +963,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( ModuleInterfaceLoaderImpl Impl( Ctx, ModPath, InPath, ModuleName, CacheDir, PrebuiltCacheDir, ModuleID.Loc, - RemarkOnRebuildFromInterface, DisableInterfaceFileLock, + Opts, dependencyTracker, llvm::is_contained(PreferInterfaceForModules, ModuleName) ? @@ -1000,22 +999,29 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( SourceManager &SourceMgr, DiagnosticEngine &Diags, const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts, + const ClangImporterOptions &ClangOpts, StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock) { + ModuleInterfaceLoaderOptions LoaderOpts) { InterfaceSubContextDelegateImpl astDelegate(SourceMgr, Diags, SearchPathOpts, LangOpts, + LoaderOpts, /*clangImporter*/nullptr, /*CreateCacheDirIfAbsent*/true, CacheDir, PrebuiltCacheDir, SerializeDependencyHashes, - TrackSystemDependencies, - RemarkOnRebuildFromInterface, - DisableInterfaceFileLock); + TrackSystemDependencies); + // At this point we don't have an ClangImporter instance because the instance + // is created later when we create a new ASTContext to build the interface. + // Thus, we have to add these extra clang flags manually here to ensure explict + // module building works. + for (auto &Arg: ClangOpts.ExtraArgs) { + astDelegate.addExtraClangArg(Arg); + } ModuleInterfaceBuilder builder(SourceMgr, Diags, astDelegate, InPath, ModuleName, CacheDir, PrebuiltCacheDir, - DisableInterfaceFileLock); + LoaderOpts.disableInterfaceLock); // FIXME: We really only want to serialize 'important' dependencies here, if // we want to ship the built swiftmodules to another machine. return builder.buildSwiftModule(OutPath, /*shouldSerializeDeps*/true, @@ -1158,19 +1164,24 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( return false; } +void InterfaceSubContextDelegateImpl::addExtraClangArg(StringRef arg) { + subInvocation.getClangImporterOptions().ExtraArgs.push_back(arg); + GenericArgs.push_back("-Xcc"); + GenericArgs.push_back(ArgSaver.save(arg)); +} + InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( SourceManager &SM, DiagnosticEngine &Diags, const SearchPathOptions &searchPathOpts, const LangOptions &langOpts, + ModuleInterfaceLoaderOptions LoaderOpts, ClangModuleLoader *clangImporter, bool buildModuleCacheDirIfAbsent, StringRef moduleCachePath, StringRef prebuiltCachePath, bool serializeDependencyHashes, - bool trackSystemDependencies, - bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock): SM(SM), Diags(Diags), ArgSaver(Allocator) { + bool trackSystemDependencies): SM(SM), Diags(Diags), ArgSaver(Allocator) { inheritOptionsForBuildingInterface(searchPathOpts, langOpts); // Configure front-end input. auto &SubFEOpts = subInvocation.getFrontendOptions(); @@ -1190,10 +1201,31 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( if (trackSystemDependencies) { GenericArgs.push_back("-track-system-dependencies"); } - // Respect the detailed-record preprocessor setting of the parent context. - // This, and the "raw" clang module format it implicitly enables, are - // required by sourcekitd. + if (LoaderOpts.disableImplicitSwiftModule) { + subInvocation.getFrontendOptions().DisableImplicitModules = true; + GenericArgs.push_back("-disable-implicit-swift-modules"); + } + subInvocation.getSearchPathOptions().ExplicitSwiftModules = + searchPathOpts.ExplicitSwiftModules; + // Dependencies scanner shouldn't know any explict Swift modules to use. + // Adding these argumnets may not be necessary. + // FIXME: remove it? + for (auto EM: searchPathOpts.ExplicitSwiftModules) { + GenericArgs.push_back("-swift-module-file"); + GenericArgs.push_back(ArgSaver.save(EM)); + } if (clangImporter) { + // We need to add these extra clang flags because explict module building + // related flags are all there: -fno-implicit-modules, -fmodule-map-file=, + // and -fmodule-file=. + // If we don't add these flags, the interface will be built with implicit + // PCMs. + for (auto arg: static_cast(clangImporter)->getExtraClangArgs()) { + addExtraClangArg(arg); + } + // Respect the detailed-record preprocessor setting of the parent context. + // This, and the "raw" clang module format it implicitly enables, are + // required by sourcekitd. auto &Opts = clangImporter->getClangInstance().getPreprocessorOpts(); if (Opts.DetailedRecord) { subInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true; @@ -1211,8 +1243,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( // Tell the subinvocation to remark on rebuilds from an interface if asked // to do so. frontendOpts.RemarkOnRebuildFromModuleInterface = - remarkOnRebuildFromInterface; - if (remarkOnRebuildFromInterface) { + LoaderOpts.remarkOnRebuildFromInterface; + if (LoaderOpts.remarkOnRebuildFromInterface) { GenericArgs.push_back("-Rmodule-interface-rebuild"); } @@ -1335,10 +1367,6 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN subInvocation.getFrontendOptions().InputsAndOutputs .setMainAndSupplementaryOutputs(outputFiles, ModuleOutputPaths); - // Add -o for building the module explicitly. - BuildArgs.push_back("-o"); - BuildArgs.push_back(outputPath); - SmallVector SubArgs; std::string CompilerVersion; // Extract compiler arguments from the interface file and use them to configure @@ -1373,3 +1401,81 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN // Run the action under the sub compiler instance. return action(info); } + +struct ExplicitSwiftModuleLoader::Implementation { + // Information about explicitly specified Swift module files. + struct ExplicitModuleInfo { + // Path of the module file. + StringRef path; + // Buffer of the module content. + std::unique_ptr moduleBuffer; + }; + llvm::StringMap ExplicitModuleMap; +}; + +ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader( + ASTContext &ctx, + DependencyTracker *tracker, + ModuleLoadingMode loadMode, + bool IgnoreSwiftSourceInfoFile): + SerializedModuleLoaderBase(ctx, tracker, loadMode, + IgnoreSwiftSourceInfoFile), + Impl(*new Implementation()) {} + +ExplicitSwiftModuleLoader::~ExplicitSwiftModuleLoader() { delete &Impl; } + +std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer) { + StringRef moduleName = ModuleID.Item.str(); + auto it = Impl.ExplicitModuleMap.find(moduleName); + // If no explicit module path is given matches the name, return with an + // error code. + if (it == Impl.ExplicitModuleMap.end()) { + return std::make_error_code(std::errc::not_supported); + } + // We found an explicit module matches the given name, give the buffer + // back to the caller side. + *ModuleBuffer = std::move(it->getValue().moduleBuffer); + return std::error_code(); +} + +void ExplicitSwiftModuleLoader::collectVisibleTopLevelModuleNames( + SmallVectorImpl &names) const { + for (auto &entry: Impl.ExplicitModuleMap) { + names.push_back(Ctx.getIdentifier(entry.getKey())); + } +} + +std::unique_ptr +ExplicitSwiftModuleLoader::create(ASTContext &ctx, + DependencyTracker *tracker, ModuleLoadingMode loadMode, + ArrayRef ExplicitModulePaths, + bool IgnoreSwiftSourceInfoFile) { + auto result = std::unique_ptr( + new ExplicitSwiftModuleLoader(ctx, tracker, loadMode, + IgnoreSwiftSourceInfoFile)); + auto &Impl = result->Impl; + for (auto path: ExplicitModulePaths) { + std::string name; + // Load the explicit module into a buffer and get its name. + std::unique_ptr buffer = getModuleName(ctx, path, name); + if (buffer) { + // Register this module for future loading. + auto &entry = Impl.ExplicitModuleMap[name]; + entry.path = path; + entry.moduleBuffer = std::move(buffer); + } else { + // We cannot read the module content, diagnose. + ctx.Diags.diagnose(SourceLoc(), + diag::error_opening_explicit_module_file, + path); + } + } + + return result; +} diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 2cab277dfddbd..f322da4198ae4 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -778,15 +778,16 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { assert(FEOpts.InputsAndOutputs.hasSingleInput()); StringRef InputPath = FEOpts.InputsAndOutputs.getFilenameOfFirstInput(); StringRef PrebuiltCachePath = FEOpts.PrebuiltModuleCachePath; + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); return ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( Instance.getSourceMgr(), Instance.getDiags(), Invocation.getSearchPathOptions(), Invocation.getLangOptions(), + Invocation.getClangImporterOptions(), Invocation.getClangModuleCachePath(), PrebuiltCachePath, Invocation.getModuleName(), InputPath, Invocation.getOutputFilename(), FEOpts.SerializeModuleInterfaceDependencyHashes, - FEOpts.TrackSystemDeps, FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock); + FEOpts.TrackSystemDeps, LoaderOpts); } static bool compileLLVMIR(CompilerInstance &Instance) { @@ -1250,6 +1251,17 @@ static bool performCompile(CompilerInstance &Instance, if (Invocation.getInputKind() == InputFileKind::LLVM) return compileLLVMIR(Instance); + // If we aren't in a parse-only context and expect an implicit stdlib import, + // load in the standard library. If we either fail to find it or encounter an + // error while loading it, bail early. Continuing the compilation will at best + // trigger a bunch of other errors due to the stdlib being missing, or at + // worst crash downstream as many call sites don't currently handle a missing + // stdlib. + if (!FrontendOptions::shouldActionOnlyParse(Action)) { + if (Instance.loadStdlibIfNeeded()) + return true; + } + if (FrontendOptions::shouldActionOnlyParse(Action)) { // Disable delayed parsing of type and function bodies when we've been // asked to dump the resulting AST. diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index 31ce01280bf81..f8974d96ea6f2 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -69,16 +69,16 @@ static std::vector resolveDirectDependencies( auto ModuleCachePath = getModuleCachePathFromClang(ctx .getClangModuleLoader()->getClangInstance()); auto &FEOpts = instance.getInvocation().getFrontendOptions(); + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts, + LoaderOpts, ctx.getClangModuleLoader(), /*buildModuleCacheDirIfAbsent*/false, ModuleCachePath, FEOpts.PrebuiltModuleCachePath, FEOpts.SerializeModuleInterfaceDependencyHashes, - FEOpts.TrackSystemDeps, - FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock); + FEOpts.TrackSystemDeps); // Find the dependencies of every module this module directly depends on. std::vector result; for (auto dependsOn : knownDependencies.getModuleDependencies()) { diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 63d59acd325a5..f05c3c8ffe83a 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -193,7 +193,7 @@ class ClangCommentExtractor : public ConstCommentVisitor return; auto &Parent = Parents.back(); for (auto CIT = std::find(Parent->child_begin(), Parent->child_end(), C) + 1; - CIT != Parent->child_end(); CIT++) { + CIT != Parent->child_end(); ++CIT) { if (auto TC = dyn_cast(*CIT)) { auto Text = TC->getText(); std::vector Subs; @@ -330,7 +330,7 @@ std::string swift::ide::removeCodeCompletionTokens( } if (C == '#' && Ptr <= End - 2 && Ptr[1] == '^') { do { - Ptr++; + ++Ptr; } while (Ptr < End && *Ptr != '#'); if (Ptr == End) break; @@ -455,7 +455,7 @@ void CodeCompletionString::print(raw_ostream &OS) const { } while (PrevNestingLevel > 0) { OS << "#}"; - PrevNestingLevel--; + --PrevNestingLevel; } } @@ -795,10 +795,10 @@ static ArrayRef> copyStringPairArray( void CodeCompletionResultBuilder::withNestedGroup( CodeCompletionString::Chunk::ChunkKind Kind, llvm::function_ref body) { - CurrentNestingLevel++; + ++CurrentNestingLevel; addSimpleChunk(Kind); body(); - CurrentNestingLevel--; + --CurrentNestingLevel; } void CodeCompletionResultBuilder::addChunkWithText( @@ -907,7 +907,7 @@ void CodeCompletionResultBuilder::addCallParameter(Identifier Name, bool isAutoClosure, bool useUnderscoreLabel, bool isLabeledTrailingClosure) { - CurrentNestingLevel++; + ++CurrentNestingLevel; using ChunkKind = CodeCompletionString::Chunk::ChunkKind; addSimpleChunk(ChunkKind::CallParameterBegin); @@ -1059,7 +1059,7 @@ void CodeCompletionResultBuilder::addCallParameter(Identifier Name, if (IsVarArg) addEllipsis(); - CurrentNestingLevel--; + --CurrentNestingLevel; } void CodeCompletionResultBuilder::addTypeAnnotation(Type T, PrintOptions PO, @@ -3640,7 +3640,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { Builder.addBaseName(IndexStr.str()); } addTypeAnnotation(Builder, TupleElt.getType()); - Index++; + ++Index; } return true; } @@ -4491,6 +4491,51 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { getAttributeDeclParamCompletions(DAK_Available, 0); } + void getSelfTypeCompletionInDeclContext(SourceLoc Loc, bool isForDeclResult) { + const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext(); + if (!typeDC) + return; + + // For protocols, there's a 'Self' generic parameter. + if (typeDC->getSelfProtocolDecl()) + return; + + Type selfType = + CurrDeclContext->mapTypeIntoContext(typeDC->getSelfInterfaceType()); + + if (typeDC->getSelfClassDecl()) { + // In classes, 'Self' can be used in result type of func, subscript and + // computed property, or inside function bodies. + bool canUseDynamicSelf = false; + if (isForDeclResult) { + canUseDynamicSelf = true; + } else { + const auto *checkDC = CurrDeclContext; + if (isa(checkDC)) + checkDC = checkDC->getParent(); + + if (const auto *AFD = checkDC->getInnermostMethodContext()) { + canUseDynamicSelf = Ctx.SourceMgr.rangeContainsTokenLoc( + AFD->getBodySourceRange(), Loc); + } + } + if (!canUseDynamicSelf) + return; + // 'Self' in class is a dynamic type. + selfType = DynamicSelfType::get(selfType, Ctx); + } else { + // In enums and structs, 'Self' is just an alias for the nominal type, + // and can be used anywhere. + } + + CodeCompletionResultBuilder Builder( + Sink, CodeCompletionResult::ResultKind::Keyword, + SemanticContextKind::CurrentNominal, expectedTypeContext); + Builder.addKeyword("Self"); + Builder.setKeywordKind(CodeCompletionKeywordKind::kw_Self); + addTypeAnnotation(Builder, selfType); + } + void getTypeCompletionsInDeclContext(SourceLoc Loc, bool ModuleQualifier = true) { Kind = LookupKind::TypeInDeclContext; @@ -5734,9 +5779,11 @@ void CodeCompletionCallbacksImpl::doneParsing() { CurDeclContext = DC; } - typeCheckContextUntil( + typeCheckContextAt( CurDeclContext, - CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); + ParsedExpr + ? ParsedExpr->getLoc() + : CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); // Add keywords even if type checking fails completely. addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); @@ -5783,6 +5830,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { auto DoPostfixExprBeginning = [&] (){ SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc(); Lookup.getValueCompletionsInDeclContext(Loc); + Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false); }; switch (Kind) { @@ -5933,8 +5981,10 @@ void CodeCompletionCallbacksImpl::doneParsing() { case CompletionKind::TypeDeclResultBeginning: case CompletionKind::TypeSimpleBeginning: { - Lookup.getTypeCompletionsInDeclContext( - P.Context.SourceMgr.getCodeCompletionLoc()); + auto Loc = Context.SourceMgr.getCodeCompletionLoc(); + Lookup.getTypeCompletionsInDeclContext(Loc); + Lookup.getSelfTypeCompletionInDeclContext( + Loc, Kind == CompletionKind::TypeDeclResultBeginning); break; } @@ -6311,7 +6361,7 @@ void PrintingCodeCompletionConsumer::handleResults( for (auto Result : Results) { if (!IncludeKeywords && Result->getKind() == CodeCompletionResult::Keyword) continue; - NumResults++; + ++NumResults; } if (NumResults == 0) return; diff --git a/lib/IDE/CodeCompletionResultPrinter.cpp b/lib/IDE/CodeCompletionResultPrinter.cpp index e74ab3a3d6e91..e5c9986ab1fde 100644 --- a/lib/IDE/CodeCompletionResultPrinter.cpp +++ b/lib/IDE/CodeCompletionResultPrinter.cpp @@ -143,7 +143,7 @@ class AnnotatingResultPrinter { if (i->is(ChunkKind::CallParameterTypeBegin)) { OS << ""; auto nestingLevel = i->getNestingLevel(); - i++; + ++i; for (; i != e; ++i) { if (i->endsPreviousNestedGroup(nestingLevel)) break; @@ -241,7 +241,7 @@ void swift::ide::printCodeCompletionResultTypeName(const CodeCompletionResult &R if (i->is(CodeCompletionString::Chunk::ChunkKind::TypeAnnotationBegin)) { auto nestingLevel = i->getNestingLevel(); - i++; + ++i; for (; i != e && !i->endsPreviousNestedGroup(nestingLevel); ++i) { if (i->hasText()) OS << i->getText(); diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 6f60d681e6d9a..7a00e4c627343 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -169,11 +169,10 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC, /// returns \c true. Returns \c true if any callback call returns \c true, \c /// false otherwise. static bool -forEachDependencyUntilTrue(CompilerInstance &CI, ModuleDecl *CurrentModule, - unsigned excludeBufferID, +forEachDependencyUntilTrue(CompilerInstance &CI, unsigned excludeBufferID, llvm::function_ref callback) { // Check files in the current module. - for (FileUnit *file : CurrentModule->getFiles()) { + for (FileUnit *file : CI.getMainModule()->getFiles()) { StringRef filename; if (auto SF = dyn_cast(file)) { if (SF->getBufferID() == excludeBufferID) @@ -203,12 +202,11 @@ forEachDependencyUntilTrue(CompilerInstance &CI, ModuleDecl *CurrentModule, /// Collect hash codes of the dependencies into \c Map. static void cacheDependencyHashIfNeeded(CompilerInstance &CI, - ModuleDecl *CurrentModule, unsigned excludeBufferID, llvm::StringMap &Map) { auto &FS = CI.getFileSystem(); forEachDependencyUntilTrue( - CI, CurrentModule, excludeBufferID, [&](StringRef filename) { + CI, excludeBufferID, [&](StringRef filename) { if (Map.count(filename)) return false; @@ -229,12 +227,12 @@ static void cacheDependencyHashIfNeeded(CompilerInstance &CI, /// Check if any dependent files are modified since \p timestamp. static bool areAnyDependentFilesInvalidated( - CompilerInstance &CI, ModuleDecl *CurrentModule, llvm::vfs::FileSystem &FS, + CompilerInstance &CI, llvm::vfs::FileSystem &FS, unsigned excludeBufferID, llvm::sys::TimePoint<> timestamp, llvm::StringMap &Map) { return forEachDependencyUntilTrue( - CI, CurrentModule, excludeBufferID, [&](StringRef filePath) { + CI, excludeBufferID, [&](StringRef filePath) { auto stat = FS.status(filePath); if (!stat) // Missing. @@ -291,7 +289,7 @@ bool CompletionInstance::performCachedOperationIfPossible( return false; auto &CI = *CachedCI; - auto *oldSF = CI.getCodeCompletionFile().get(); + auto *oldSF = CI.getCodeCompletionFile(); auto *oldState = oldSF->getDelayedParserState(); assert(oldState->hasCodeCompletionDelayedDeclState()); @@ -304,7 +302,7 @@ bool CompletionInstance::performCachedOperationIfPossible( if (shouldCheckDependencies()) { if (areAnyDependentFilesInvalidated( - CI, CurrentModule, *FileSystem, SM.getCodeCompletionBufferID(), + CI, *FileSystem, SM.getCodeCompletionBufferID(), DependencyCheckedTimestamp, InMemoryDependencyHash)) return false; DependencyCheckedTimestamp = std::chrono::system_clock::now(); @@ -441,22 +439,21 @@ bool CompletionInstance::performCachedOperationIfPossible( // Create a new module and a source file using the current AST context. auto &Ctx = oldM->getASTContext(); - auto *newM = - ModuleDecl::create(oldM->getName(), Ctx, oldM->getImplicitImportInfo()); + auto *newM = ModuleDecl::createMainModule(Ctx, oldM->getName(), + oldM->getImplicitImportInfo()); auto *newSF = new (Ctx) SourceFile(*newM, SourceFileKind::Main, newBufferID); newM->addFile(*newSF); newSF->enableInterfaceHash(); - // Tell the compiler instance we've replaced the code completion file. - CI.setCodeCompletionFile(newSF); + // Tell the compiler instance we've replaced the main module. + CI.setMainModule(newM); // Re-process the whole file (parsing will be lazily triggered). Still // re-use imported modules. performImportResolution(*newSF); bindExtensions(*newM); - CurrentModule = newM; traceDC = newM; #ifndef NDEBUG const auto *reparsedState = newSF->getDelayedParserState(); @@ -483,7 +480,7 @@ bool CompletionInstance::performCachedOperationIfPossible( } CachedReuseCount += 1; - cacheDependencyHashIfNeeded(CI, CurrentModule, SM.getCodeCompletionBufferID(), + cacheDependencyHashIfNeeded(CI, SM.getCodeCompletionBufferID(), InMemoryDependencyHash); return true; @@ -527,16 +524,16 @@ bool CompletionInstance::performNewOperation( } registerIDERequestFunctions(CI.getASTContext().evaluator); - CI.performParseAndResolveImportsOnly(); - - // If we didn't create a source file for completion, bail. This can happen - // if for example we fail to load the stdlib. - auto completionFile = CI.getCodeCompletionFile(); - if (!completionFile) + // If we're expecting a standard library, but there either isn't one, or it + // failed to load, let's bail early and hand back an empty completion + // result to avoid any downstream crashes. + if (CI.loadStdlibIfNeeded()) return true; + CI.performParseAndResolveImportsOnly(); + // If we didn't find a code completion token, bail. - auto *state = completionFile.get()->getDelayedParserState(); + auto *state = CI.getCodeCompletionFile()->getDelayedParserState(); if (!state->hasCodeCompletionDelayedDeclState()) return true; @@ -553,14 +550,13 @@ bool CompletionInstance::performNewOperation( void CompletionInstance::cacheCompilerInstance( std::unique_ptr CI, llvm::hash_code ArgsHash) { CachedCI = std::move(CI); - CurrentModule = CachedCI->getMainModule(); CachedArgHash = ArgsHash; auto now = std::chrono::system_clock::now(); DependencyCheckedTimestamp = now; CachedReuseCount = 0; InMemoryDependencyHash.clear(); cacheDependencyHashIfNeeded( - *CachedCI, CurrentModule, + *CachedCI, CachedCI->getASTContext().SourceMgr.getCodeCompletionBufferID(), InMemoryDependencyHash); } diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index 30c6600f53222..9a843b82f0cc0 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -67,9 +67,7 @@ void ConformingMethodListCallbacks::doneParsing() { if (!ParsedExpr) return; - typeCheckContextUntil( - CurDeclContext, - CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); + typeCheckContextAt(CurDeclContext, ParsedExpr->getLoc()); Type T = ParsedExpr->getType(); diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index a4d2914f3b4fd..d93d311f45493 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -38,7 +38,7 @@ using namespace swift; using namespace ide; //===----------------------------------------------------------------------===// -// typeCheckContextUntil(DeclContext, SourceLoc) +// typeCheckContextAt(DeclContext, SourceLoc) //===----------------------------------------------------------------------===// namespace { @@ -80,7 +80,7 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { auto &SM = DC->getASTContext().SourceMgr; auto bodyRange = AFD->getBodySourceRange(); if (SM.rangeContainsTokenLoc(bodyRange, Loc)) { - swift::typeCheckAbstractFunctionBodyUntil(AFD, Loc); + swift::typeCheckAbstractFunctionBodyAtLoc(AFD, Loc); } else { assert(bodyRange.isInvalid() && "The body should not be parsed if the " "completion happens in the signature"); @@ -100,27 +100,12 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { } } // anonymous namespace -void swift::ide::typeCheckContextUntil(DeclContext *DC, SourceLoc Loc) { +void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) { while (isa(DC)) DC = DC->getParent(); if (auto *TLCD = dyn_cast(DC)) { - // Typecheck all 'TopLevelCodeDecl's up to the target one. - // In theory, this is not needed, but it fails to resolve the type of - // 'guard'ed variable. e.g. - // - // guard value = something() else { fatalError() } - // - // Here, 'value' is '' unless we explicitly typecheck the - // 'guard' statement. - SourceFile *SF = DC->getParentSourceFile(); - for (auto *D : SF->getTopLevelDecls()) { - if (auto Code = dyn_cast(D)) { - typeCheckTopLevelCodeDecl(Code); - if (Code == TLCD) - break; - } - } + typeCheckTopLevelCodeDecl(TLCD); } else { typeCheckContextImpl(DC, Loc); } @@ -882,10 +867,10 @@ class ExprContextAnalyzer { break; } default: - if (auto *AFD = dyn_cast(D)) { - assert(isSingleExpressionBodyForCodeCompletion(AFD->getBody())); + if (auto *FD = dyn_cast(D)) { + assert(isSingleExpressionBodyForCodeCompletion(FD->getBody())); singleExpressionBody = true; - recordPossibleType(getReturnTypeFromContext(AFD)); + recordPossibleType(getReturnTypeFromContext(FD)); break; } llvm_unreachable("Unhandled decl kind."); @@ -1019,8 +1004,8 @@ class ExprContextAnalyzer { case DeclKind::PatternBinding: return true; default: - if (auto *AFD = dyn_cast(D)) - if (auto *body = AFD->getBody()) + if (auto *FD = dyn_cast(D)) + if (auto *body = FD->getBody()) return isSingleExpressionBodyForCodeCompletion(body); return false; } diff --git a/lib/IDE/ExprContextAnalysis.h b/lib/IDE/ExprContextAnalysis.h index 039d28c60643d..38c9443c46a1d 100644 --- a/lib/IDE/ExprContextAnalysis.h +++ b/lib/IDE/ExprContextAnalysis.h @@ -28,7 +28,7 @@ enum class SemanticContextKind; /// Type check parent contexts of the given decl context, and the body of the /// given context until \c Loc if the context is a function body. -void typeCheckContextUntil(DeclContext *DC, SourceLoc Loc); +void typeCheckContextAt(DeclContext *DC, SourceLoc Loc); /// From \p DC, find and returns the outer most expression which source range is /// exact the same as \p TargetRange. Returns \c nullptr if not found. diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index 7362ff7c79378..cf601d5b7d5b2 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -1475,7 +1475,7 @@ class FormatWalker : public ASTWalker { return; for (auto Invalid = Loc.isInvalid(); CurrentTokIt != TokenList.end() && (Invalid || SM.isBeforeInBuffer(CurrentTokIt->getLoc(), Loc)); - CurrentTokIt++) { + ++CurrentTokIt) { if (CurrentTokIt->getKind() == tok::comment) { CharSourceRange CommentRange = CurrentTokIt->getRange(); SourceLoc StartLineLoc = Lexer::getLocForStartOfLine( diff --git a/lib/IDE/IDERequests.cpp b/lib/IDE/IDERequests.cpp index 2fe2ec5931d93..6fc451ee53262 100644 --- a/lib/IDE/IDERequests.cpp +++ b/lib/IDE/IDERequests.cpp @@ -577,7 +577,7 @@ struct RangeResolver::Implementation { } DeclContext *getImmediateContext() { - for (auto It = ContextStack.rbegin(); It != ContextStack.rend(); It ++) { + for (auto It = ContextStack.rbegin(); It != ContextStack.rend(); ++It) { if (auto *DC = It->Parent.getAsDeclContext()) return DC; } @@ -647,7 +647,7 @@ struct RangeResolver::Implementation { while(StartIt != AllTokens.end()) { if (StartIt->getKind() != tok::comment) break; - StartIt ++; + ++StartIt; } // Erroneous case. @@ -740,7 +740,7 @@ struct RangeResolver::Implementation { for (auto N : Nodes) { if (Stmt *S = N.is() ? N.get() : nullptr) { if (S->getKind() == StmtKind::Case) - CaseCount++; + ++CaseCount; } } // If there are more than one case/default statements, there are more than diff --git a/lib/IDE/ModuleInterfacePrinting.cpp b/lib/IDE/ModuleInterfacePrinting.cpp index 8bccb61ed88cd..5777a0ac00b0f 100644 --- a/lib/IDE/ModuleInterfacePrinting.cpp +++ b/lib/IDE/ModuleInterfacePrinting.cpp @@ -595,7 +595,7 @@ void swift::ide::printModuleInterface( if (TargetClangMod) { // Assume all submodules are missing. for (auto It = TargetClangMod->submodule_begin(); - It != TargetClangMod->submodule_end(); It++) { + It != TargetClangMod->submodule_end(); ++It) { NoImportSubModules.insert(*It); } } diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index 34bad673dfc98..59ceb43d053d5 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -326,7 +326,7 @@ REPLCompletions::CookedResult REPLCompletions::getNextStem() { if (CookedResults.empty()) return {}; - CurrentCompletionIdx++; + ++CurrentCompletionIdx; if (CurrentCompletionIdx >= CookedResults.size()) CurrentCompletionIdx = 0; diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp index 069b325acded8..080cb1ef1330f 100644 --- a/lib/IDE/Refactoring.cpp +++ b/lib/IDE/Refactoring.cpp @@ -1959,7 +1959,7 @@ bool RefactoringActionConvertStringsConcatenationToInterpolation::performChange( return true; EditorConsumerInsertStream OS(EditConsumer, SM, RangeInfo.ContentRange); OS << "\""; - for (auto It = Expressions->begin(); It != Expressions->end(); It++) { + for (auto It = Expressions->begin(); It != Expressions->end(); ++It) { interpolatedExpressionForm(*It, SM, OS); } OS << "\""; @@ -3586,7 +3586,7 @@ static NumberLiteralExpr *getTrailingNumberLiteral(ResolvedCursorInfo Tok) { static std::string insertUnderscore(StringRef Text) { llvm::SmallString<64> Buffer; llvm::raw_svector_ostream OS(Buffer); - for (auto It = Text.begin(); It != Text.end(); It++) { + for (auto It = Text.begin(); It != Text.end(); ++It) { unsigned Distance = It - Text.begin(); if (Distance && !(Distance % 3)) { OS << '_'; diff --git a/lib/IDE/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp index b57a33811927c..f2dc3e165a072 100644 --- a/lib/IDE/SourceEntityWalker.cpp +++ b/lib/IDE/SourceEntityWalker.cpp @@ -511,6 +511,17 @@ std::pair SemaAnnotator::walkToExprPre(Expr *E) { return doSkipChildren(); } + } else if (auto DMRE = dyn_cast(E)) { + // Visit in source order. + if (!DMRE->getBase()->walk(*this)) + return stopTraversal; + if (!passReference(DMRE->getMember().getDecl(), DMRE->getType(), + DMRE->getNameLoc(), + ReferenceMetaData(SemaReferenceKind::DynamicMemberRef, + OpAccess))) + return stopTraversal; + // We already visited the children. + return doSkipChildren(); } return { true, E }; diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index 1791ba33a75b9..aa97eb458e3b0 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -1416,7 +1416,7 @@ bool ModelASTWalker::pushStructureNode(const SyntaxStructureNode &Node, const ASTNodeType& ASTNode) { SubStructureStack.emplace_back(Node, ASTNode); if (shouldTreatAsSingleToken(Node, SM)) - AvoidPassingSyntaxToken ++; + ++AvoidPassingSyntaxToken; if (!passTokenNodesUntil(Node.Range.getStart(), ExcludeNodeAtLocation).shouldContinue) @@ -1552,12 +1552,12 @@ static CharSourceRange sanitizeUnpairedParenthesis(CharSourceRange Range) { unsigned TrimLen = 0; for (char C : Text) { if (C == '(') { - Pairs ++; + ++Pairs; } else if (C == ')') { if (Pairs == 0) - TrimLen ++; + ++TrimLen; else - Pairs --; + --Pairs; } else { TrimLen = 0; } diff --git a/lib/IDE/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index 1bd6be37e8e5d..aacaa875d96b3 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -89,9 +89,7 @@ void ContextInfoCallbacks::doneParsing() { if (!ParsedExpr) return; - typeCheckContextUntil( - CurDeclContext, - CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); + typeCheckContextAt(CurDeclContext, ParsedExpr->getLoc()); ExprContextInfo Info(CurDeclContext, ParsedExpr); diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index 6d97ec8ff9f57..616a0e6e0678f 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -812,7 +812,7 @@ unsigned DeclNameViewer::commonPartsCount(DeclNameViewer &Other) const { unsigned Len = std::min(args().size(), Other.args().size()); for (unsigned I = 0; I < Len; ++ I) { if (args()[I] == Other.args()[I]) - Result ++; + ++Result; else return Result; } diff --git a/lib/IRGen/EnumPayload.cpp b/lib/IRGen/EnumPayload.cpp index 54a2bc46f9490..5c520553d9f27 100644 --- a/lib/IRGen/EnumPayload.cpp +++ b/lib/IRGen/EnumPayload.cpp @@ -446,7 +446,7 @@ EnumPayload::emitApplyOrMask(IRGenFunction &IGF, assert(count == mask.PayloadValues.size()); auto &DL = IGF.IGM.DataLayout; - for (unsigned i = 0; i < count; i++ ) { + for (unsigned i = 0; i < count; ++i) { auto payloadTy = getPayloadType(PayloadValues[i]); unsigned size = DL.getTypeSizeInBits(payloadTy); diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index c33d650f11239..d97c0dd3f8e29 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -545,15 +545,15 @@ if (Builtin.ID == BuiltinValueKind::id) { \ bool isWeak = false, isVolatile = false, isSingleThread = false; if (NextPart != Parts.end() && *NextPart == "weak") { isWeak = true; - NextPart++; + ++NextPart; } if (NextPart != Parts.end() && *NextPart == "volatile") { isVolatile = true; - NextPart++; + ++NextPart; } if (NextPart != Parts.end() && *NextPart == "singlethread") { isSingleThread = true; - NextPart++; + ++NextPart; } assert(NextPart == Parts.end() && "Mismatch with sema"); diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index e321478381b01..292c36e5ff718 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -447,7 +447,7 @@ void SignatureExpansion::expandCoroutineResult(bool forContinuation) { // Remove the last component and add it as an overflow type. overflowTypes.push_back(components.pop_back_val()); - numDirectComponents--; + --numDirectComponents; // Add a pointer to the end of components. components.push_back(IGM.Int8PtrTy); diff --git a/lib/IRGen/GenClangType.cpp b/lib/IRGen/GenClangType.cpp index 104f908cca0e0..bc788fab6904a 100644 --- a/lib/IRGen/GenClangType.cpp +++ b/lib/IRGen/GenClangType.cpp @@ -354,7 +354,7 @@ clang::CanQualType GenClangType::visitTupleType(CanTupleType type) { return getClangASTContext().VoidTy; CanType eltTy = type.getElementType(0); - for (unsigned i = 1; i < e; i++) { + for (unsigned i = 1; i < e; ++i) { assert(eltTy == type.getElementType(i) && "Only tuples where all element types are equal " "map to fixed-size arrays"); diff --git a/lib/IRGen/GenConstant.cpp b/lib/IRGen/GenConstant.cpp index 6855b0ccadf94..071d49f82603b 100644 --- a/lib/IRGen/GenConstant.cpp +++ b/lib/IRGen/GenConstant.cpp @@ -177,7 +177,7 @@ namespace { void insertPadding(SmallVectorImpl &Elements, llvm::StructType *sTy) { // fill in any gaps, which are the explicit padding that swiftc inserts. - for (unsigned i = 0, e = Elements.size(); i != e; i++) { + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { auto &elt = Elements[i]; if (elt == nullptr) { auto *eltTy = sTy->getElementType(i); @@ -199,7 +199,7 @@ llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst, // run over the Swift initializers, putting them into the struct as // appropriate. - for (unsigned i = 0, e = inst->getElements().size(); i != e; i++) { + for (unsigned i = 0, e = inst->getElements().size(); i != e; ++i) { auto operand = inst->getOperand(i); Optional index = nextIndex(IGM, type, i); if (index.hasValue()) { @@ -244,7 +244,7 @@ llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI, assert(NumElems == ClassLayout->getElements().size()); // Construct the object init value including tail allocated elements. - for (unsigned i = 0; i != NumElems; i++) { + for (unsigned i = 0; i != NumElems; ++i) { SILValue Val = OI->getAllElements()[i]; const ElementLayout &EL = ClassLayout->getElements()[i]; if (!EL.isEmpty()) { diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 290f1d24a3138..7e6710311b798 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -2829,7 +2829,7 @@ llvm::Constant *IRGenModule::getOrCreateGOTEquivalent(llvm::Constant *global, } if (auto *Stats = Context.Stats) - Stats->getFrontendCounters().NumGOTEntries++; + ++Stats->getFrontendCounters().NumGOTEntries; // Use the global as the initializer for an anonymous constant. LLVM can treat // this as equivalent to the global's GOT entry. @@ -3667,7 +3667,7 @@ IRGenModule::getAddrOfGenericTypeMetadataAccessFunction( size_t numGenericArgs = genericArgs.size(); if (numGenericArgs > NumDirectGenericTypeMetadataAccessFunctionArgs) { paramTypesArray[1] = Int8PtrPtrTy; - numParams++; + ++numParams; } else { for (size_t i : indices(genericArgs)) paramTypesArray[i + 1] = genericArgs[i]; diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index 96f516f4c3b6a..dad7aaf4a0381 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -1387,7 +1387,7 @@ namespace { assert(ElementsWithPayload.size() >= 1); if (PayloadSchema) { PayloadSchema.forEachType(IGM, [&](llvm::Type *t){ - PayloadElementCount++; + ++PayloadElementCount; PayloadBitCount += IGM.DataLayout.getTypeSizeInBits(t); }); } else { @@ -2059,7 +2059,7 @@ namespace { auto nextCase = [&]() -> EnumElementDecl* { assert(elti != eltEnd); Element elt = *elti; - elti++; + ++elti; return elt.decl; }; @@ -6010,7 +6010,7 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) { TC.IGM.getResilienceExpansionForLayout(theEnum); for (auto elt : theEnum->getAllElements()) { - numElements++; + ++numElements; if (!elt->hasAssociatedValues()) { elementsWithNoPayload.push_back({elt, nullptr, nullptr}); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index cebd2a5caa886..45fce96be67e4 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1165,7 +1165,7 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM, if (!isABIIgnoredParameterWithoutStorage(IGM, subIGF, substType, origParamI)) break; - origParamI++; + ++origParamI; } if (origParamI < origType->getParameters().size()) { diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 76772801697cf..41128f62b8620 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -688,7 +688,7 @@ static unsigned getClassFieldIndex(ClassDecl *classDecl, VarDecl *property) { for (auto *other : superDecl->getStoredProperties()) { if (other == property) return index; - index++; + ++index; } } diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index b3205dfe2c6b1..927f329420c77 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -180,7 +180,7 @@ static void emitMetadataCompletionFunction(IRGenModule &IGM, IGM.getAddrOfTypeMetadataCompletionFunction(typeDecl, ForDefinition); f->setAttributes(IGM.constructInitialAttributes()); f->setDoesNotThrow(); - IGM.setHasFramePointer(f, false); + IGM.setHasNoFramePointer(f); IRGenFunction IGF(IGM, f); @@ -2270,7 +2270,7 @@ namespace { IGM.getAddrOfTypeMetadataInstantiationFunction(Target, ForDefinition); f->setAttributes(IGM.constructInitialAttributes()); f->setDoesNotThrow(); - IGM.setHasFramePointer(f, false); + IGM.setHasNoFramePointer(f); IRGenFunction IGF(IGM, f); diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp index 25d2635b1c195..a6a328f273aa4 100644 --- a/lib/IRGen/GenOpaque.cpp +++ b/lib/IRGen/GenOpaque.cpp @@ -407,7 +407,7 @@ static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, unsigned i = unsigned(index); if (i > unsigned(ValueWitness::Flags)) { if (IGF.IGM.getPointerSize() == Size(8)) { - i--; // one pointer width skips both flags and xiCount + --i; // one pointer width skips both flags and xiCount } else if (IGF.IGM.getPointerSize() == Size(4)) { // no adjustment required } else { diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index f3947efa47588..21a400c8f3213 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -449,7 +449,7 @@ static void countStatsPostIRGen(UnifiedStatsReporter &Stats, C.NumIRComdatSymbols += Module.getComdatSymbolTable().size(); for (auto const &Func : Module) { for (auto const &BB : Func) { - C.NumIRBasicBlocks++; + ++C.NumIRBasicBlocks; C.NumIRInsts += BB.size(); } } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 306ae4e3697b1..87f3207b6ef09 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -90,26 +90,11 @@ static llvm::PointerType *createStructPointerType(IRGenModule &IGM, return createStructType(IGM, name, types)->getPointerTo(DefaultAS); }; -static clang::CodeGenOptions::FramePointerKind -shouldUseFramePointer(const IRGenOptions &Opts, const llvm::Triple &triple) { - if (Opts.DisableFPElim) { - // General frame pointer elimination is disabled. - // Should we at least eliminate in leaf functions? - // Currently we only do that on arm64 (this matches the behavior of clang). - return Opts.DisableFPElimLeaf - ? clang::CodeGenOptions::FramePointerKind::All - : triple.isAArch64() - ? clang::CodeGenOptions::FramePointerKind::NonLeaf - : clang::CodeGenOptions::FramePointerKind::All; - } - - return clang::CodeGenOptions::FramePointerKind::None; -} - -static clang::CodeGenerator * -createClangCodeGenerator(ASTContext &Context, llvm::LLVMContext &LLVMContext, - const IRGenOptions &Opts, StringRef ModuleName, - StringRef PD, const llvm::Triple &triple) { +static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, + llvm::LLVMContext &LLVMContext, + const IRGenOptions &Opts, + StringRef ModuleName, + StringRef PD) { auto Loader = Context.getClangModuleLoader(); auto *Importer = static_cast(&*Loader); assert(Importer && "No clang module loader!"); @@ -117,7 +102,7 @@ createClangCodeGenerator(ASTContext &Context, llvm::LLVMContext &LLVMContext, auto &CGO = Importer->getClangCodeGenOpts(); CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0; - CGO.setFramePointer(shouldUseFramePointer(Opts, triple)); + CGO.DiscardValueNames = !Opts.shouldProvideValueNames(); switch (Opts.DebugInfoLevel) { case IRGenDebugInfoLevel::None: @@ -207,17 +192,17 @@ static void sanityCheckStdlib(IRGenModule &IGM) { IRGenModule::IRGenModule(IRGenerator &irgen, std::unique_ptr &&target, - SourceFile *SF, StringRef ModuleName, - StringRef OutputFilename, + SourceFile *SF, + StringRef ModuleName, StringRef OutputFilename, StringRef MainInputFilenameForDebugInfo, StringRef PrivateDiscriminator) - : LLVMContext(new llvm::LLVMContext()), IRGen(irgen), - Context(irgen.SIL.getASTContext()), + : LLVMContext(new llvm::LLVMContext()), + IRGen(irgen), Context(irgen.SIL.getASTContext()), // The LLVMContext (and the IGM itself) will get deleted by the IGMDeleter // as long as the IGM is registered with the IRGenerator. - ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext, irgen.Opts, - ModuleName, PrivateDiscriminator, - irgen.getEffectiveClangTriple())), + ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext, + irgen.Opts, + ModuleName, PrivateDiscriminator)), Module(*ClangCodeGen->GetModule()), DataLayout(irgen.getClangDataLayout()), Triple(irgen.getEffectiveClangTriple()), TargetMachine(std::move(target)), @@ -999,28 +984,13 @@ bool swift::irgen::shouldRemoveTargetFeature(StringRef feature) { return feature == "+thumb-mode"; } -void IRGenModule::setHasFramePointer(llvm::AttrBuilder &Attrs, - bool HasFramePointer) { - if (!HasFramePointer) { - Attrs.addAttribute("frame-pointer", "none"); - return; - } - if (IRGen.Opts.DisableFPElimLeaf) { - Attrs.addAttribute("frame-pointer", "all"); - return; - } - - // We omit frame pointers for leaf functions only for arm64 for now (matching - // clang's behavior). - auto framePointer = - IRGen.getEffectiveClangTriple().isAArch64() ? "non-leaf" : "all"; - Attrs.addAttribute("frame-pointer", framePointer); +void IRGenModule::setHasNoFramePointer(llvm::AttrBuilder &Attrs) { + Attrs.addAttribute("frame-pointer", "none"); } -void IRGenModule::setHasFramePointer(llvm::Function *F, - bool HasFramePointer) { +void IRGenModule::setHasNoFramePointer(llvm::Function *F) { llvm::AttrBuilder b; - setHasFramePointer(b, HasFramePointer); + setHasNoFramePointer(b); F->addAttributes(llvm::AttributeList::FunctionIndex, b); } @@ -1030,10 +1000,6 @@ void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs, // Add the default attributes for the Clang configuration. clang::CodeGen::addDefaultFunctionDefinitionAttributes(getClangCGM(), Attrs); - // Add frame pointer attributes. - // FIXME: why are we doing this? - setHasFramePointer(Attrs, IRGen.Opts.DisableFPElim); - // Add/remove MinSize based on the appropriate setting. if (FuncOptMode == OptimizationMode::NotSet) FuncOptMode = IRGen.Opts.OptMode; diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 17df8cb9dafa2..2eb6292c99b0c 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -1313,8 +1313,8 @@ private: \ void constructInitialFnAttributes(llvm::AttrBuilder &Attrs, OptimizationMode FuncOptMode = OptimizationMode::NotSet); - void setHasFramePointer(llvm::AttrBuilder &Attrs, bool HasFP); - void setHasFramePointer(llvm::Function *F, bool HasFP); + void setHasNoFramePointer(llvm::AttrBuilder &Attrs); + void setHasNoFramePointer(llvm::Function *F); llvm::AttributeList constructInitialAttributes(); void emitProtocolDecl(ProtocolDecl *D); diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index ea3fd56973801..e096798cee1c6 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -1624,7 +1624,7 @@ void LoadableStorageAllocation::allocateForArg(SILValue value) { SILInstruction *FirstNonAllocStack = &*BBIter; while (isa(FirstNonAllocStack) && BBIter != pass.F->begin()->end()) { - BBIter++; + ++BBIter; FirstNonAllocStack = &*BBIter; } SILBuilderWithScope allocBuilder(&*pass.F->begin()->begin(), diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp index 95ddfc0361528..274f3e6c616a4 100644 --- a/lib/IRGen/MetadataLayout.cpp +++ b/lib/IRGen/MetadataLayout.cpp @@ -317,7 +317,7 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl) void addGenericWitnessTable(GenericRequirement requirement, ClassDecl *forClass) { if (forClass == Target) { - Layout.NumImmediateMembers++; + ++Layout.NumImmediateMembers; } super::addGenericWitnessTable(requirement, forClass); } @@ -325,14 +325,14 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl) void addGenericArgument(GenericRequirement requirement, ClassDecl *forClass) { if (forClass == Target) { - Layout.NumImmediateMembers++; + ++Layout.NumImmediateMembers; } super::addGenericArgument(requirement, forClass); } void addMethod(SILDeclRef fn) { if (fn.getDecl()->getDeclContext() == Target) { - Layout.NumImmediateMembers++; + ++Layout.NumImmediateMembers; Layout.MethodInfos.try_emplace(fn, getNextOffset()); } super::addMethod(fn); @@ -346,7 +346,7 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl) void addFieldOffset(VarDecl *field) { if (field->getDeclContext() == Target) { - Layout.NumImmediateMembers++; + ++Layout.NumImmediateMembers; Layout.FieldOffsets.try_emplace(field, getNextOffset()); } super::addFieldOffset(field); diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index ef6e5ab9dad33..1ffa24555c328 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -1684,7 +1684,7 @@ void irgen::emitCacheAccessFunction(IRGenModule &IGM, accessor->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoInline); // Accessor functions don't need frame pointers. - IGM.setHasFramePointer(accessor, false); + IGM.setHasNoFramePointer(accessor); // This function is logically 'readnone': the caller does not need // to reason about any side effects or stores it might perform. @@ -2094,8 +2094,8 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction( thunkFn->setCallingConv(IGM.SwiftCC); thunkFn->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoInline); - IGM.setHasFramePointer(thunkFn, false); - + IGM.setHasNoFramePointer(thunkFn); + [&IGM, thunkFn]{ IRGenFunction subIGF(IGM, thunkFn); @@ -2631,7 +2631,7 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type, instantiationFn->setDoesNotThrow(); instantiationFn->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoInline); - IGM.setHasFramePointer(instantiationFn, false); + IGM.setHasNoFramePointer(instantiationFn); [&IGM, instantiationFn, request]{ IRGenFunction subIGF(IGM, instantiationFn); diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index 66f11250ab5a5..77701453230dd 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -223,7 +223,7 @@ bool StructLayoutBuilder::addField(ElementLayout &elt, if (eltTI.isKnownEmpty(ResilienceExpansion::Maximal)) { addEmptyElement(elt); // If the element type is empty, it adds nothing. - NextNonFixedOffsetIndex++; + ++NextNonFixedOffsetIndex; return false; } // TODO: consider using different layout rules. @@ -238,7 +238,7 @@ bool StructLayoutBuilder::addField(ElementLayout &elt, } else { addNonFixedSizeElement(elt); } - NextNonFixedOffsetIndex++; + ++NextNonFixedOffsetIndex; return true; } diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp index 8cc4d3997b8a0..d441ade35075f 100644 --- a/lib/Index/IndexRecord.cpp +++ b/lib/Index/IndexRecord.cpp @@ -416,14 +416,16 @@ static void addModuleDependencies(ArrayRef imports, StringRef moduleName = mod->getNameStr(); bool withoutUnitName = true; if (FU->getKind() == FileUnitKind::ClangModule) { - withoutUnitName = false; auto clangModUnit = cast(LFU); - if (auto clangMod = clangModUnit->getUnderlyingClangModule()) { - moduleName = clangMod->getTopLevelModuleName(); - // FIXME: clang's -Rremarks do not seem to go through Swift's - // diagnostic emitter. - clang::index::emitIndexDataForModuleFile(clangMod, - clangCI, unitWriter); + if (!clangModUnit->isSystemModule() || indexSystemModules) { + withoutUnitName = false; + if (auto clangMod = clangModUnit->getUnderlyingClangModule()) { + moduleName = clangMod->getTopLevelModuleName(); + // FIXME: clang's -Rremarks do not seem to go through Swift's + // diagnostic emitter. + clang::index::emitIndexDataForModuleFile(clangMod, + clangCI, unitWriter); + } } } else { // Serialized AST file. diff --git a/lib/LLVMPasses/LLVMARCContract.cpp b/lib/LLVMPasses/LLVMARCContract.cpp index f39a61dc440e8..c2328cb73ecb4 100644 --- a/lib/LLVMPasses/LLVMARCContract.cpp +++ b/lib/LLVMPasses/LLVMARCContract.cpp @@ -115,10 +115,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { // then delete them. for (auto *Inst : RetainList) { Inst->eraseFromParent(); - NumRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumRetainReleasesEliminatedByMergingIntoRetainReleaseN; } RetainList.clear(); @@ -140,10 +140,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { // Remove all old release instructions. for (auto *Inst : ReleaseList) { Inst->eraseFromParent(); - NumRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumRetainReleasesEliminatedByMergingIntoRetainReleaseN; } ReleaseList.clear(); @@ -166,10 +166,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { // then delete them. for (auto *Inst : UnknownObjectRetainList) { Inst->eraseFromParent(); - NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN; } UnknownObjectRetainList.clear(); @@ -193,10 +193,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { // Remove all old release instructions. for (auto *Inst : UnknownObjectReleaseList) { Inst->eraseFromParent(); - NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumUnknownObjectRetainReleasesEliminatedByMergingIntoRetainReleaseN; } UnknownObjectReleaseList.clear(); @@ -226,10 +226,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { B.setInsertPoint(Inst); Inst->replaceAllUsesWith(B.maybeCast(I, Inst->getType())); Inst->eraseFromParent(); - NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN; } BridgeRetainList.clear(); @@ -252,10 +252,10 @@ performRRNOptimization(DenseMap &PtrToLocalStateMap) { // Remove all old release instructions. for (auto *Inst : BridgeReleaseList) { Inst->eraseFromParent(); - NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN++; + ++NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN; } - NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN--; + --NumBridgeRetainReleasesEliminatedByMergingIntoRetainReleaseN; } BridgeReleaseList.clear(); } diff --git a/lib/LLVMPasses/LLVMInlineTree.cpp b/lib/LLVMPasses/LLVMInlineTree.cpp index 5fc584c9fd5a7..678470d5e0b95 100644 --- a/lib/LLVMPasses/LLVMInlineTree.cpp +++ b/lib/LLVMPasses/LLVMInlineTree.cpp @@ -215,7 +215,7 @@ void InlineTree::buildTree(Function *F) { LLVM_DEBUG(dbgs() << I << '\n'); - totalNumberOfInstructions++; + ++totalNumberOfInstructions; SmallVector InlineChain; // Scan the chain of inlined scopes. @@ -239,15 +239,15 @@ void InlineTree::buildTree(Function *F) { Nd = rootNode; LLVM_DEBUG(dbgs() << ", root\n"); } - Nd->numTotalInsts++; + ++Nd->numTotalInsts; PrevDL = DL; } if (!Nd) { Nd = rootNode; - Nd->numTotalInsts++; + ++Nd->numTotalInsts; } - Nd->numSelfInsts++; + ++Nd->numSelfInsts; } } } @@ -319,7 +319,7 @@ void InlineTree::print(raw_ostream &os) { S.instanceOverhead; S.selfInstOverhead = Nd->numSelfInsts - Nd->numSelfInsts / S.instanceOverhead; - S.instanceOverhead--; + --S.instanceOverhead; } } else { S.totalInstOverhead += Nd->numTotalInsts; diff --git a/lib/Markup/AST.cpp b/lib/Markup/AST.cpp index 8ac6b741af04f..b4b3bec013557 100644 --- a/lib/Markup/AST.cpp +++ b/lib/Markup/AST.cpp @@ -263,7 +263,7 @@ void swift::markup::printInlinesUnder(const MarkupASTNode *Node, bool PrintDecorators) { auto printChildren = [](const ArrayRef Children, llvm::raw_ostream &OS) { - for (auto Child = Children.begin(); Child != Children.end(); Child++) + for (auto Child = Children.begin(); Child != Children.end(); ++Child) swift::markup::printInlinesUnder(*Child, OS); }; @@ -366,7 +366,7 @@ void swift::markup::dump(const MarkupASTNode *Node, llvm::raw_ostream &OS, auto dumpChildren = [](const ArrayRef Children, llvm::raw_ostream &OS, unsigned indent) { OS << '\n'; - for (auto Child = Children.begin(); Child != Children.end(); Child++) { + for (auto Child = Children.begin(); Child != Children.end(); ++Child) { swift::markup::dump(*Child, OS, indent + 1); if (Child != Children.end() - 1) OS << '\n'; diff --git a/lib/Markup/LineList.cpp b/lib/Markup/LineList.cpp index fce78f8fcd565..804c14b2f15ab 100644 --- a/lib/Markup/LineList.cpp +++ b/lib/Markup/LineList.cpp @@ -46,7 +46,7 @@ size_t swift::markup::measureIndentation(StringRef Text) { size_t Col = 0; for (size_t i = 0, e = Text.size(); i != e; ++i) { if (Text[i] == ' ' || Text[i] == '\v' || Text[i] == '\f') { - Col++; + ++Col; continue; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6af22bee14e21..09010264d323f 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -351,7 +351,7 @@ ParserResult Parser::parseExtendedAvailabilitySpecList( auto ArgumentLoc = Tok.getLoc(); AnyAnnotations = true; StringRef ArgumentKindStr = Tok.getText(); - ParamIndex++; + ++ParamIndex; enum { IsMessage, IsRenamed, @@ -3276,13 +3276,13 @@ static unsigned skipUntilMatchingRBrace(Parser &P, HasPoundDirective |= P.Tok.isAny(tok::pound_sourceLocation, tok::pound_line, tok::pound_if, tok::pound_else, tok::pound_endif, tok::pound_elseif); if (P.consumeIf(tok::l_brace)) { - OpenBraces++; + ++OpenBraces; continue; } if (OpenBraces == 1 && P.Tok.is(tok::r_brace)) break; if (P.consumeIf(tok::r_brace)) { - OpenBraces--; + --OpenBraces; continue; } P.consumeToken(); @@ -4422,10 +4422,18 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi, return Result; } -bool Parser::parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, - SourceLoc PosBeforeLB, - Diag<> ErrorDiag, +bool Parser::parseMemberDeclList(SourceLoc &LBLoc, SourceLoc &RBLoc, + Diag<> LBraceDiag, Diag<> RBraceDiag, IterableDeclContext *IDC) { + if (parseToken(tok::l_brace, LBLoc, LBraceDiag)) { + LBLoc = RBLoc = PreviousLoc; + + // Cache the empty result to prevent delayed parsing. + Context.evaluator.cacheOutput( + ParseMembersRequest{IDC}, FingerprintAndMembers{None, {}}); + return true; + } + bool HasOperatorDeclarations; bool HasNestedClassDeclarations; @@ -4444,7 +4452,7 @@ bool Parser::parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, bool hadError = false; ParseDeclOptions Options = getMemberParseDeclOptions(IDC); auto membersAndHash = - parseDeclList(LBLoc, RBLoc, ErrorDiag, Options, IDC, hadError); + parseDeclList(LBLoc, RBLoc, RBraceDiag, Options, IDC, hadError); IDC->setMaybeHasOperatorDeclarations(); IDC->setMaybeHasNestedClassDeclarations(); Context.evaluator.cacheOutput( @@ -4503,7 +4511,7 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag, // Increase counter. if (auto *stat = Context.Stats) { - stat->getFrontendCounters().NumIterableDeclContextParsed ++; + ++stat->getFrontendCounters().NumIterableDeclContextParsed; } // If we found the closing brace, then the caller should not care if there // were errors while parsing inner decls, because we recovered. @@ -4614,16 +4622,12 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) { SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - auto PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_extension)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - status.setIsParseError(); - } else { + { ContextChange CC(*this, ext); Scope S(this, ScopeKind::Extension); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_extension, diag::expected_rbrace_extension, ext)) status.setIsParseError(); @@ -5248,7 +5252,7 @@ bool Parser::skipBracedBlock() { HasOperatorDeclarations, HasNestedClassDeclarations); if (consumeIf(tok::r_brace)) - OpenBraces--; + --OpenBraces; return OpenBraces != 0; } @@ -6376,7 +6380,7 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) { setLocalDiscriminatorToParamList(AFD->getParameters()); if (auto *Stats = Context.Stats) - Stats->getFrontendCounters().NumFunctionsParsed++; + ++Stats->getFrontendCounters().NumFunctionsParsed; // In implicit getter, if a CC token is the first token after '{', it might // be a start of an accessor block. Perform special completion for that. @@ -6576,15 +6580,11 @@ ParserResult Parser::parseDeclEnum(ParseDeclOptions Flags, SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { Scope S(this, ScopeKind::EnumBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_enum, diag::expected_rbrace_enum, ED)) Status.setIsParseError(); @@ -6862,16 +6862,12 @@ ParserResult Parser::parseDeclStruct(ParseDeclOptions Flags, // Make the entities of the struct as a code block. SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { // Parse the body. Scope S(this, ScopeKind::StructBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_struct, diag::expected_rbrace_struct, SD)) Status.setIsParseError(); @@ -6978,16 +6974,12 @@ ParserResult Parser::parseDeclClass(ParseDeclOptions Flags, SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - auto PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { // Parse the body. Scope S(this, ScopeKind::ClassBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_class, diag::expected_rbrace_class, CD)) Status.setIsParseError(); @@ -7079,14 +7071,10 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) { SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBraceLoc; SourceLoc RBraceLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBraceLoc, diag::expected_lbrace_protocol)) { - LBraceLoc = PreviousLoc; - RBraceLoc = LBraceLoc; - Status.setIsParseError(); - } else { + { // Parse the members. - if (parseMemberDeclList(LBraceLoc, RBraceLoc, PosBeforeLB, + if (parseMemberDeclList(LBraceLoc, RBraceLoc, + diag::expected_lbrace_protocol, diag::expected_rbrace_protocol, Proto)) Status.setIsParseError(); diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index 5a552a69dd7c7..c1631d2de3c4a 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -443,7 +443,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc, if (Tok.getLoc() == StartLoc) { // If we took a default argument index for this parameter, but didn't add // one, then give it back. - if (defaultArgs) defaultArgs->NextIndex--; + if (defaultArgs) --defaultArgs->NextIndex; return status; } diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index fd89e9d9d8d54..4e58d38f021bf 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -613,7 +613,7 @@ AbstractionPattern::getFunctionParamType(unsigned index) const { if (!errorInfo.isErrorParameterReplacedWithVoid()) { if (paramIndex >= errorParamIndex) { - paramIndex++; + ++paramIndex; } } } diff --git a/lib/SIL/IR/SILArgument.cpp b/lib/SIL/IR/SILArgument.cpp index 799398edc6ca2..1d447fbd00976 100644 --- a/lib/SIL/IR/SILArgument.cpp +++ b/lib/SIL/IR/SILArgument.cpp @@ -169,6 +169,28 @@ bool SILPhiArgument::getIncomingPhiOperands( return true; } +bool SILPhiArgument::visitIncomingPhiOperands( + function_ref visitor) const { + if (!isPhiArgument()) + return false; + + const auto *parentBlock = getParent(); + assert(!parentBlock->pred_empty()); + + unsigned argIndex = getIndex(); + for (auto *predBlock : getParent()->getPredecessorBlocks()) { + Operand *incomingOperand = + getIncomingPhiOperandForPred(parentBlock, predBlock, argIndex); + assert(incomingOperand); + + // Call the visitor, bailing if the callee signals error. + if (!visitor(incomingOperand)) { + return false; + } + } + return true; +} + bool SILPhiArgument::getIncomingPhiValues( SmallVectorImpl> &returnedPredBBAndPhiValuePairs) const { diff --git a/lib/SIL/IR/SILBasicBlock.cpp b/lib/SIL/IR/SILBasicBlock.cpp index e352a97924f79..f5b7ea53ca9e9 100644 --- a/lib/SIL/IR/SILBasicBlock.cpp +++ b/lib/SIL/IR/SILBasicBlock.cpp @@ -76,7 +76,7 @@ int SILBasicBlock::getDebugID() const { for (const SILBasicBlock &B : *getParent()) { if (&B == this) return idx; - idx++; + ++idx; } llvm_unreachable("block not in function's block list"); } diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 0af0f064e60a2..6989994303775 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -814,7 +814,12 @@ bool SILDeclRef::requiresNewVTableEntry() const { if (derivativeFunctionIdentifier) if (derivativeFunctionRequiresNewVTableEntry(*this)) return true; - if (cast(getDecl())->needsNewVTableEntry()) + if (!hasDecl()) + return false; + auto fnDecl = dyn_cast(getDecl()); + if (!fnDecl) + return false; + if (fnDecl->needsNewVTableEntry()) return true; return false; } diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 9efed4201ceb7..ed3a450a1a96f 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -1604,7 +1604,7 @@ class DestructureInputs { // Assume the error parameter doesn't have interesting lowering. Inputs.push_back(SILParameterInfo(foreignErrorTy, ParameterConvention::Direct_Unowned)); - NextOrigParamIndex++; + ++NextOrigParamIndex; return true; } @@ -3302,7 +3302,7 @@ static CanType copyOptionalityFromDerivedToBase(TypeConverter &tc, auto derivedParams = derivedFunc.getParams(); auto baseParams = baseFunc.getParams(); assert(derivedParams.size() == baseParams.size()); - for (unsigned i = 0, e = derivedParams.size(); i < e; i++) { + for (unsigned i = 0, e = derivedParams.size(); i < e; ++i) { assert(derivedParams[i].getParameterFlags() == baseParams[i].getParameterFlags()); diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index dd9c3b93b1110..4feafae6df321 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -3127,6 +3127,9 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { switch (entry.TheKind) { case SILVTable::Entry::Kind::Normal: break; + case SILVTable::Entry::Kind::NormalNonOverridden: + OS << " [nonoverridden]"; + break; case SILVTable::Entry::Kind::Inherited: OS << " [inherited]"; break; @@ -3569,7 +3572,7 @@ ID SILPrintContext::getID(const SILNode *node) { // If there are no results, make sure we don't reuse that ID. auto results = I.getResults(); if (results.empty()) { - idx++; + ++idx; continue; } diff --git a/lib/SIL/IR/SILWitnessTable.cpp b/lib/SIL/IR/SILWitnessTable.cpp index 581cd9a16fac5..b6be229f53e41 100644 --- a/lib/SIL/IR/SILWitnessTable.cpp +++ b/lib/SIL/IR/SILWitnessTable.cpp @@ -193,7 +193,7 @@ bool SILWitnessTable::enumerateWitnessTableConditionalConformances( if (fn(conformanceIndex, req.getFirstType()->getCanonicalType(), proto)) return true; - conformanceIndex++; + ++conformanceIndex; } } return false; diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 94521a73a4d69..43cd5899e96aa 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -1308,14 +1308,14 @@ bool SILParser::parseSILDottedPathWithoutPound(ValueDecl *&Decl, values.clear(); VD = lookupMember(P, ModuleType::get(Mod), FullName[1], Locs[1], values, FullName.size() == 2/*ExpectMultipleResults*/); - for (unsigned I = 2, E = FullName.size(); I < E; I++) { + for (unsigned I = 2, E = FullName.size(); I < E; ++I) { values.clear(); VD = lookupMember(P, VD->getInterfaceType(), FullName[I], Locs[I], values, I == FullName.size() - 1/*ExpectMultipleResults*/); } } else { VD = Res.get(); - for (unsigned I = 1, E = FullName.size(); I < E; I++) { + for (unsigned I = 1, E = FullName.size(); I < E; ++I) { values.clear(); VD = lookupMember(P, VD->getInterfaceType(), FullName[I], Locs[I], values, I == FullName.size() - 1/*ExpectMultipleResults*/); @@ -2115,7 +2115,7 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Member, bool FnTypeRequired) { // Pick the ValueDecl that has the right type. ValueDecl *TheDecl = nullptr; auto declTy = Ty.getType()->getCanonicalType(); - for (unsigned I = 0, E = values.size(); I < E; I++) { + for (unsigned I = 0, E = values.size(); I < E; ++I) { auto *decl = values[I]; auto lookupTy = @@ -6090,6 +6090,9 @@ bool SILParserState::parseSILVTable(Parser &P) { } else if (P.Tok.getText() == "inherited") { P.consumeToken(); Kind = SILVTable::Entry::Kind::Inherited; + } else if (P.Tok.getText() == "nonoverridden") { + P.consumeToken(); + Kind = SILVTable::Entry::Kind::NormalNonOverridden; } else { P.diagnose(P.Tok.getLoc(), diag::sil_vtable_bad_entry_kind); return true; diff --git a/lib/SIL/Utils/DynamicCasts.cpp b/lib/SIL/Utils/DynamicCasts.cpp index d6cfef83222a2..fcdbd25fd0268 100644 --- a/lib/SIL/Utils/DynamicCasts.cpp +++ b/lib/SIL/Utils/DynamicCasts.cpp @@ -25,7 +25,7 @@ static unsigned getAnyMetatypeDepth(CanType type) { unsigned depth = 0; while (auto metatype = dyn_cast(type)) { type = metatype.getInstanceType(); - depth++; + ++depth; } return depth; } @@ -719,7 +719,7 @@ swift::classifyDynamicCast(ModuleDecl *M, static unsigned getOptionalDepth(CanType type) { unsigned depth = 0; while (CanType objectType = type.getOptionalObjectType()) { - depth++; + ++depth; type = objectType; } return depth; diff --git a/lib/SIL/Utils/OwnershipUtils.cpp b/lib/SIL/Utils/OwnershipUtils.cpp index 8ccc42453f021..836895a103a9c 100644 --- a/lib/SIL/Utils/OwnershipUtils.cpp +++ b/lib/SIL/Utils/OwnershipUtils.cpp @@ -485,6 +485,9 @@ void OwnedValueIntroducerKind::print(llvm::raw_ostream &os) const { case OwnedValueIntroducerKind::Phi: os << "Phi"; return; + case OwnedValueIntroducerKind::Struct: + os << "Struct"; + return; case OwnedValueIntroducerKind::FunctionArgument: os << "FunctionArgument"; return; diff --git a/lib/SIL/Utils/Projection.cpp b/lib/SIL/Utils/Projection.cpp index 849e5ebcd95a9..c54ab49ec5b0f 100644 --- a/lib/SIL/Utils/Projection.cpp +++ b/lib/SIL/Utils/Projection.cpp @@ -428,8 +428,8 @@ ProjectionPath::hasNonEmptySymmetricDifference(const ProjectionPath &RHS) const{ } // Continue if we are accessing the same field. - LHSIter++; - RHSIter++; + ++LHSIter; + ++RHSIter; } // All path elements are the same. The symmetric difference is empty. @@ -442,12 +442,12 @@ ProjectionPath::hasNonEmptySymmetricDifference(const ProjectionPath &RHS) const{ for (unsigned li = i, e = size(); li != e; ++li) { if (LHSIter->isAliasingCast()) return false; - LHSIter++; + ++LHSIter; } for (unsigned ri = i, e = RHS.size(); ri != e; ++ri) { if (RHSIter->isAliasingCast()) return false; - RHSIter++; + ++RHSIter; } // If we don't have any casts in our symmetric difference (i.e. only typed @@ -493,8 +493,8 @@ ProjectionPath::computeSubSeqRelation(const ProjectionPath &RHS) const { return SubSeqRelation_t::Unknown; // Otherwise increment reverse iterators. - LHSIter++; - RHSIter++; + ++LHSIter; + ++RHSIter; } // Ok, we now know that one of the paths is a subsequence of the other. If @@ -533,7 +533,7 @@ ProjectionPath::removePrefix(const ProjectionPath &Path, // First make sure that the prefix matches. Optional P = ProjectionPath(Path.BaseType); - for (unsigned i = 0; i < PrefixSize; i++) { + for (unsigned i = 0; i < PrefixSize; ++i) { if (Path.Path[i] != Prefix.Path[i]) { P.reset(); return P; diff --git a/lib/SIL/Verifier/LoadBorrowInvalidationChecker.cpp b/lib/SIL/Verifier/LoadBorrowInvalidationChecker.cpp index 6aa28ced2c1d5..1b414791e15c0 100644 --- a/lib/SIL/Verifier/LoadBorrowInvalidationChecker.cpp +++ b/lib/SIL/Verifier/LoadBorrowInvalidationChecker.cpp @@ -247,6 +247,13 @@ constructValuesForKey(SILValue initialValue, continue; } + // We consider address_to_pointer to be an escape from our system. The + // frontend must protect the uses of the load_borrow as appropriate in other + // ways (for instance by using a mark_dependence). + if (isa(user)) { + continue; + } + if (auto *yi = dyn_cast(user)) { auto info = yi->getYieldInfoForOperand(*op); if (info.isIndirectInGuaranteed()) { diff --git a/lib/SIL/Verifier/MemoryLifetime.cpp b/lib/SIL/Verifier/MemoryLifetime.cpp index e7cb283cb5eed..0ee60934e8265 100644 --- a/lib/SIL/Verifier/MemoryLifetime.cpp +++ b/lib/SIL/Verifier/MemoryLifetime.cpp @@ -238,7 +238,7 @@ void MemoryLocations::dump() const { << ", #f=" << loc.numFieldsNotCoveredBySubfields << ", #ntf=" << loc.numNonTrivialFieldsNotCovered << ": " << loc.representativeValue; - idx++; + ++idx; } } diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index fdcd178603e18..ca14212c91eb3 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -546,6 +546,7 @@ struct ImmutableAddressUseVerifier { case SILInstructionKind::FixLifetimeInst: case SILInstructionKind::KeyPathInst: case SILInstructionKind::SwitchEnumAddrInst: + case SILInstructionKind::SelectEnumAddrInst: break; case SILInstructionKind::AddressToPointerInst: // We assume that the user is attempting to do something unsafe since we @@ -3569,7 +3570,7 @@ class SILVerifier : public SILVerifierBase { fromCanTy = fromMetaty.getInstanceType(); toCanTy = toMetaty.getInstanceType(); - MetatyLevel++; + ++MetatyLevel; } if (isExact) { @@ -5360,8 +5361,22 @@ void SILProperty::verify(const SILModule &M) const { void SILVTable::verify(const SILModule &M) const { if (!verificationEnabled(M)) return; - - for (auto &entry : getEntries()) { + + // Compare against the base class vtable if there is one. + const SILVTable *superVTable = nullptr; + auto superclass = getClass()->getSuperclassDecl(); + if (superclass) { + for (auto &vt : M.getVTables()) { + if (vt.getClass() == superclass) { + superVTable = &vt; + break; + } + } + } + + for (unsigned i : indices(getEntries())) { + auto &entry = getEntries()[i]; + // All vtable entries must be decls in a class context. assert(entry.Method.hasDecl() && "vtable entry is not a decl"); auto baseInfo = @@ -5403,6 +5418,55 @@ void SILVTable::verify(const SILModule &M) const { "vtable entry for " + baseName + " must be ABI-compatible", *entry.Implementation); } + + // Validate the entry against its superclass vtable. + if (!superclass) { + // Root methods should not have inherited or overridden entries. + bool validKind; + switch (entry.TheKind) { + case Entry::Normal: + case Entry::NormalNonOverridden: + validKind = true; + break; + + case Entry::Inherited: + case Entry::Override: + validKind = false; + break; + } + assert(validKind && "vtable entry in root class must not be inherited or override"); + } else if (superVTable) { + // Validate the entry against the matching entry from the superclass + // vtable. + + const Entry *superEntry = nullptr; + for (auto &se : superVTable->getEntries()) { + if (se.Method.getOverriddenVTableEntry() == entry.Method.getOverriddenVTableEntry()) { + superEntry = &se; + break; + } + } + + switch (entry.TheKind) { + case Entry::Normal: + case Entry::NormalNonOverridden: + assert(!superEntry && "non-root vtable entry must be inherited or override"); + break; + + case Entry::Inherited: + break; + + case Entry::Override: + if (!superEntry) + break; + + // The superclass entry must not prohibit overrides. + assert(superEntry->TheKind != Entry::NormalNonOverridden + && "vtable entry overrides an entry that claims to have no overrides"); + // TODO: Check the root vtable entry for the method too. + break; + } + } } } @@ -5531,7 +5595,7 @@ void SILModule::verify() const { << entry.Implementation->getName() << "not in cache!\n"; assert(false && "triggering standard assertion failure routine"); } - EntriesSZ++; + ++EntriesSZ; } } assert(EntriesSZ == VTableEntryCache.size() && diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 6a29f111034f5..e80d4f8da4d5e 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -3361,7 +3361,7 @@ struct ParamLowering { } if (foreignError) - count++; + ++count; if (foreignSelf.isImportAsMember()) { // Claim only the self parameter. diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index e5214379747f9..6f1c92ea9f26c 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1709,7 +1709,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { if (foreignError && foreignArgIndex == foreignError->getErrorParameterIndex()) { args.push_back(ManagedValue()); - foreignArgIndex++; + ++foreignArgIndex; } }; @@ -1759,7 +1759,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { // Leave space for `self` to be filled in later. if (foreignArgIndex == memberStatus.getSelfIndex()) { args.push_back({}); - foreignArgIndex++; + ++foreignArgIndex; } // Use the `self` space we skipped earlier if it's time. diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp index 21fcd0dc9cc9f..bf0e64a90cc79 100644 --- a/lib/SILGen/SILGenBuilder.cpp +++ b/lib/SILGen/SILGenBuilder.cpp @@ -774,6 +774,13 @@ ReturnInst *SILGenBuilder::createReturn(SILLocation loc, return createReturn(loc, returnValue.forward(SGF)); } +ReturnInst * +SILGenBuilder::createReturn(SILLocation loc, SILValue returnValue, + AssertingManualScope &&functionLevelScope) { + std::move(functionLevelScope).pop(); + return createReturn(loc, returnValue); +} + ManagedValue SILGenBuilder::createTuple(SILLocation loc, SILType type, ArrayRef elements) { // Handle the empty tuple case. diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h index cce1589276537..b5b6c3567d213 100644 --- a/lib/SILGen/SILGenBuilder.h +++ b/lib/SILGen/SILGenBuilder.h @@ -34,6 +34,7 @@ namespace Lowering { class SILGenFunction; class SGFContext; +class AssertingManualScope; /// A subclass of SILBuilder that wraps APIs to vend ManagedValues. /// APIs only vend ManagedValues. @@ -362,6 +363,9 @@ class SILGenBuilder : public SILBuilder { using SILBuilder::createReturn; ReturnInst *createReturn(SILLocation Loc, ManagedValue ReturnValue); + ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue, + AssertingManualScope &&functionLevelScope); + using SILBuilder::emitDestructureValueOperation; /// Perform either a tuple or struct destructure and then pass its components /// as managed value one by one with an index to the closure. diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 6e1a94e9a2eff..83ad4870154aa 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -152,6 +152,10 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, ConstructorDecl *ctor) { RegularLocation Loc(ctor); Loc.markAutoGenerated(); + + AssertingManualScope functionLevelScope(SGF.Cleanups, + CleanupLocation::get(Loc)); + // FIXME: Handle 'self' along with the other arguments. auto *paramList = ctor->getParameters(); auto *selfDecl = ctor->getImplicitSelfDecl(); @@ -238,8 +242,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, SGF.emitExprInto(field->getParentInitializer(), init.get()); } } + SGF.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc), - SGF.emitEmptyTuple(Loc)); + SGF.emitEmptyTuple(Loc), std::move(functionLevelScope)); return; } @@ -287,7 +292,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, SILValue selfValue = SGF.B.createStruct(Loc, selfTy, eltValues); SGF.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc), - selfValue); + selfValue, std::move(functionLevelScope)); return; } diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index 65f779eca8339..ecacd2536ca7d 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -168,14 +168,14 @@ static unsigned getNumSpecializationsRecursive(const Pattern *p, unsigned n) { // isa and enum-element patterns are refutable, at least in theory. case PatternKind::Is: { auto isa = cast(p); - n++; + ++n; if (auto sub = isa->getSubPattern()) return getNumSpecializationsRecursive(sub, n); return n; } case PatternKind::EnumElement: { auto en = cast(p); - n++; + ++n; if (en->hasSubPattern()) n = getNumSpecializationsRecursive(en->getSubPattern(), n); return n; @@ -565,7 +565,7 @@ class ClauseRow { // AlwaysRefutable before decrementing because we only ever test // this value against zero. if (isDirectlyRefutablePattern(Columns[column])) - NumRemainingSpecializations--; + --NumRemainingSpecializations; if (newColumns.size() == 1) { Columns[column] = newColumns[0]; diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 3134c36c7305a..e0d71dc6bb708 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -3801,7 +3801,7 @@ ManagedValue SILGenFunction::getThunkedAutoDiffLinearMap( } // Convert direct result to indirect result. // Increment thunk argument iterator; reabstraction handled later. - toArgIter++; + ++toArgIter; } // Reabstract parameters. diff --git a/lib/SILGen/Scope.h b/lib/SILGen/Scope.h index 28f880cbe4aef..4eef14b3b9a41 100644 --- a/lib/SILGen/Scope.h +++ b/lib/SILGen/Scope.h @@ -47,8 +47,23 @@ class LLVM_LIBRARY_VISIBILITY Scope { Scope(const Scope &other) = delete; Scope &operator=(const Scope &other) = delete; - Scope(Scope &&other) = delete; - Scope &operator=(Scope &&other) = delete; // implementable if needed + Scope(Scope &&other) + : cleanups(other.cleanups), depth(other.depth), + savedInnermostScope(other.savedInnermostScope), loc(other.loc) { + // Invalidate other. + other.depth = CleanupsDepth::invalid(); + } + + Scope &operator=(Scope &&other) { + depth = other.depth; + savedInnermostScope = other.savedInnermostScope; + loc = other.loc; + + // Invalidate other. + other.depth = CleanupsDepth::invalid(); + + return *this; + } explicit Scope(SILGenFunction &SGF, SILLocation loc) : Scope(SGF.Cleanups, CleanupLocation::get(loc)) {} @@ -83,6 +98,30 @@ class LLVM_LIBRARY_VISIBILITY Scope { void popImpl(); }; +/// A scope that must be manually popped by the using code. If not +/// popped, the destructor asserts. +class LLVM_LIBRARY_VISIBILITY AssertingManualScope { + Scope scope; + +public: + explicit AssertingManualScope(CleanupManager &cleanups, CleanupLocation loc) + : scope(cleanups, loc) {} + + AssertingManualScope(AssertingManualScope &&other) + : scope(std::move(other.scope)) {} + + AssertingManualScope &operator=(AssertingManualScope &&other) { + scope = std::move(other.scope); + return *this; + } + + ~AssertingManualScope() { + assert(!scope.isValid() && "Unpopped manual scope?!"); + } + + void pop() && { scope.pop(); } +}; + /// A FullExpr is a RAII object recording that a full-expression has /// been entered. A full-expression is essentially a very small scope /// for the temporaries in an expression, with the added complexity diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index cbe9cd0db4448..cbb9309eff547 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -2488,7 +2488,7 @@ void EscapeAnalysis::recompute(FunctionInfo *Initial) { } } } - Iteration++; + ++Iteration; } while (NeedAnotherIteration); for (FunctionInfo *FInfo : BottomUpOrder) { diff --git a/lib/SILOptimizer/Analysis/FunctionOrder.cpp b/lib/SILOptimizer/Analysis/FunctionOrder.cpp index 03cc277a0dcc5..e0bf1a17ef177 100644 --- a/lib/SILOptimizer/Analysis/FunctionOrder.cpp +++ b/lib/SILOptimizer/Analysis/FunctionOrder.cpp @@ -74,7 +74,3 @@ void BottomUpFunctionOrder::DFS(SILFunction *Start) { } } -void BottomUpFunctionOrder::FindSCCs(SILModule &M) { - for (auto &F : M) - DFS(&F); -} diff --git a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp index c7be441ba87d5..86d91eb494161 100644 --- a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp +++ b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp @@ -86,7 +86,7 @@ SILValue InstSimplifier::visitStructInst(StructInst *SI) { return SILValue(); // Check that all of the operands are extracts of the correct kind. - for (unsigned i = 0, e = SI->getNumOperands(); i < e; i++) { + for (unsigned i = 0, e = SI->getNumOperands(); i < e; ++i) { auto *Ex = dyn_cast(SI->getOperand(i)); // Must be an extract. if (!Ex) @@ -121,7 +121,7 @@ SILValue InstSimplifier::visitTupleInst(TupleInst *TI) { return SILValue(); // Check that all of the operands are extracts of the correct kind. - for (unsigned i = 0, e = TI->getNumOperands(); i < e; i++) { + for (unsigned i = 0, e = TI->getNumOperands(); i < e; ++i) { auto *Ex = dyn_cast(TI->getOperand(i)); // Must be an extract. if (!Ex) diff --git a/lib/SILOptimizer/Differentiation/JVPEmitter.cpp b/lib/SILOptimizer/Differentiation/JVPEmitter.cpp index 4f1c422825a63..f37c67a3a7a1f 100644 --- a/lib/SILOptimizer/Differentiation/JVPEmitter.cpp +++ b/lib/SILOptimizer/Differentiation/JVPEmitter.cpp @@ -983,7 +983,7 @@ void JVPEmitter::prepareForDifferentialGeneration() { for (auto index : range(diffParamArgs.size())) { auto *diffArg = diffParamArgs[index]; auto *origArg = origParamArgs[*diffParamsIt]; - diffParamsIt++; + ++diffParamsIt; if (diffArg->getType().isAddress()) { setTangentBuffer(origEntry, origArg, diffArg); } else { diff --git a/lib/SILOptimizer/Differentiation/Thunk.cpp b/lib/SILOptimizer/Differentiation/Thunk.cpp index 4a387a182e92d..e0b66c4be29f4 100644 --- a/lib/SILOptimizer/Differentiation/Thunk.cpp +++ b/lib/SILOptimizer/Differentiation/Thunk.cpp @@ -330,7 +330,7 @@ SILFunction *getOrCreateReabstractionThunk(SILOptFunctionBuilder &fb, } // Convert direct result to indirect result. // Increment thunk argument iterator; reabstraction handled later. - toArgIter++; + ++toArgIter; } // Reabstract parameters. @@ -562,7 +562,7 @@ getOrCreateSubsetParametersThunkForLinearMap( unsigned indexInBitVec = 0; for (auto index : actualIndices.parameters->getIndices()) { actualParamIndicesMap[index] = indexInBitVec; - indexInBitVec++; + ++indexInBitVec; } } auto mapOriginalParameterIndex = [&](unsigned index) -> unsigned { @@ -622,7 +622,7 @@ getOrCreateSubsetParametersThunkForLinearMap( continue; auto resultInfo = linearMapType->getResults()[pullbackResultIndex]; assert(pullbackResultIndex < linearMapType->getNumResults()); - pullbackResultIndex++; + ++pullbackResultIndex; // Skip pullback direct results. Only indirect results are relevant as // arguments. if (resultInfo.isFormalDirect()) diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index be18e74779b45..0296ea0bb0c51 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -376,7 +376,6 @@ ExistentialTransform::createExistentialSpecializedFunctionType() { /// Finally the ExtInfo. auto ExtInfo = FTy->getExtInfo(); ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin); - auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrInvalid(); /// Return the new signature. return SILFunctionType::get( @@ -384,7 +383,7 @@ ExistentialTransform::createExistentialSpecializedFunctionType() { FTy->getCalleeConvention(), InterfaceParams, FTy->getYields(), FTy->getResults(), InterfaceErrorResult, SubstitutionMap(), SubstitutionMap(), - Ctx, witnessMethodConformance); + Ctx); } /// Create the Thunk Body with always_inline attribute. diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index 97a444b0e0d28..05ab7bcaf6f10 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -340,7 +340,7 @@ static void rewriteApplyInst(const CallSiteDescriptor &CSDesc, for (auto Arg : AI.getArguments()) { if (Index != CSDesc.getClosureIndex()) NewArgs.push_back(Arg); - Index++; + ++Index; } // ... and appending the captured arguments. We also insert retains here at @@ -982,7 +982,7 @@ void SILClosureSpecializerTransform::run() { LLVM_DEBUG(llvm::dbgs() << " Visiting: " << *Closure); if (!tryDeleteDeadClosure(Closure)) { LLVM_DEBUG(llvm::dbgs() << " Failed to delete closure!\n"); - NumPropagatedClosuresNotEliminated++; + ++NumPropagatedClosuresNotEliminated; continue; } diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index b1b2a25960fc1..15c65d2d70f36 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -616,7 +616,7 @@ class DeadFunctionElimination : FunctionLivenessComputation { auto &WitnessTables = Module->getWitnessTableList(); for (auto WI = WitnessTables.begin(), EI = WitnessTables.end(); WI != EI;) { SILWitnessTable *WT = &*WI; - WI++; + ++WI; WT->clearMethods_if([this, &changedTable] (const SILWitnessTable::MethodWitness &MW) -> bool { if (!isAlive(MW.Witness)) { @@ -634,7 +634,7 @@ class DeadFunctionElimination : FunctionLivenessComputation { EI = DefaultWitnessTables.end(); WI != EI;) { SILDefaultWitnessTable *WT = &*WI; - WI++; + ++WI; WT->clearMethods_if([this, &changedTable](SILFunction *MW) -> bool { if (!MW) return false; @@ -691,7 +691,7 @@ class DeadFunctionElimination : FunctionLivenessComputation { LLVM_DEBUG(llvm::dbgs() << " erase dead function " << F->getName() << "\n"); - NumDeadFunc++; + ++NumDeadFunc; DFEPass->notifyWillDeleteFunction(F); Module->eraseFunction(F); } diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index 365fcd50e6199..4c5178eba7f3d 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -270,7 +270,7 @@ void SILGlobalOpt::collectOnceCall(BuiltinInst *BI) { // an addressor, we set count to 2 to disable optimizing the initializer. InitializerCount[Callee] = 2; else - InitializerCount[Callee]++; + ++InitializerCount[Callee]; } static bool isPotentialStore(SILInstruction *inst) { diff --git a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp index b0b6dc0ecd162..e70e9ca8c9f0b 100644 --- a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp @@ -466,7 +466,7 @@ void GlobalPropertyOpt::replacePropertyCalls() { AI->replaceAllUsesWith(TrueStruct); semCall.removeCall(); - NumPropertiesReplaced++; + ++NumPropertiesReplaced; } } } diff --git a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp index 2f2adfe656bae..b734d134cf29e 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -174,7 +174,7 @@ class ArrayPropertiesAnalysis { if (!canHoistArrayPropsInst(ArrayPropsInst)) return false; - LoopInstCount++; + ++LoopInstCount; FoundHoistable = true; } } diff --git a/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp b/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp index 56715e2bbc743..a1da1e09b6e9f 100644 --- a/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp +++ b/lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp @@ -446,7 +446,7 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall, // than needed as the unrolled code have many branches (due to try applies) // all of which joins later into a single path eventually. SmallVector elementCopies; - for (uint64_t i = 0; i < arrayInfo.getNumElements(); i++) { + for (uint64_t i = 0; i < arrayInfo.getNumElements(); ++i) { StoreInst *elementStore = arrayInfo.getElementStore(i); // Insert the copy just before the store of the element into the array. SILValue copy = SILBuilderWithScope(elementStore) @@ -516,7 +516,7 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall, // it is `normalBB`. (The normal target is captured by `nextNormalBB`.) // Jump to a new error block: err_i in the error case. Note that all // error blocks jump to the error target of the original forEach call. - for (uint64_t num = arrayInfo.getNumElements(); num > 0; num--) { + for (uint64_t num = arrayInfo.getNumElements(); num > 0; --num) { SILValue elementCopy = elementCopies[num - 1]; SILBasicBlock *currentBB = num > 1 ? normalTargetGenerator(nextNormalBB) : forEachCall->getParentBlock(); @@ -604,14 +604,14 @@ class ForEachLoopUnroller : public SILFunctionTransform { SILInstruction *inst = &*instIter; ApplyInst *apply = dyn_cast(inst); if (!apply) { - instIter++; + ++instIter; continue; } // Note that the following operation may delete a forEach call but // would not delete this apply instruction, which is an array // initializer. Therefore, the iterator should be valid here. changed |= tryUnrollForEachCallsOverArrayLiteral(apply, deleter); - instIter++; + ++instIter; } } diff --git a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp index 03113c78db51e..ea9521f061b2f 100644 --- a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp +++ b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp @@ -198,7 +198,7 @@ static void rewriteNewLoopEntryCheckBlock( auto &inst = *instIter; updateSSAForUseOfInst(updater, insertedPhis, valueMap, header, entryCheckBlock, &inst); - instIter++; + ++instIter; } } diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp index dd95d46977c98..093cb4482e6b1 100644 --- a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp +++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp @@ -402,7 +402,7 @@ static bool tryRewriteToPartialApplyStack( // instruction from the memoized map. auto saveDeleteInst = [&](SILInstruction *i) { if (&*advanceIfDelete == i) - advanceIfDelete++; + ++advanceIfDelete; memoized.erase(i); i->eraseFromParent(); }; diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index b83872daea424..4c884da10b911 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -68,7 +68,7 @@ static unsigned getElementCountRec(TypeExpansionContext context, if (CanTupleType TT = T.getAs()) { assert(!IsSelfOfNonDelegatingInitializer && "self never has tuple type"); unsigned NumElements = 0; - for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) + for (unsigned i = 0, e = TT->getNumElements(); i < e; ++i) NumElements += getElementCountRec(context, Module, T.getTupleElementType(i), false); return NumElements; @@ -162,7 +162,7 @@ static SILType getElementTypeRec(TypeExpansionContext context, // If this is a tuple type, walk into it. if (CanTupleType TT = T.getAs()) { assert(!IsSelfOfNonDelegatingInitializer && "self never has tuple type"); - for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { + for (unsigned i = 0, e = TT->getNumElements(); i < e; ++i) { auto FieldType = T.getTupleElementType(i); unsigned NumFieldElements = getElementCountRec(context, Module, FieldType, false); @@ -230,7 +230,7 @@ SILValue DIMemoryObjectInfo::emitElementAddressForDestroy( // Figure out which field we're walking into. unsigned FieldNo = 0; - for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { + for (unsigned i = 0, e = TT->getNumElements(); i < e; ++i) { auto EltTy = PointeeType.getTupleElementType(i); unsigned NumSubElt = getElementCountRec( TypeExpansionContext(B.getFunction()), Module, EltTy, false); @@ -320,7 +320,7 @@ static void getPathStringToElementRec(TypeExpansionContext context, } unsigned FieldNo = 0; - for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { + for (unsigned i = 0, e = TT->getNumElements(); i < e; ++i) { auto Field = TT->getElement(i); SILType FieldTy = T.getTupleElementType(i); unsigned NumFieldElements = getElementCountRec(context, Module, FieldTy, false); @@ -1128,7 +1128,7 @@ void ElementUseCollector::collectClassSelfUses() { // function. Ignore it. if (auto *Arg = dyn_cast(SI->getSrc())) { if (Arg->getParent() == TheMemory.getParentBlock()) { - StoresOfArgumentToSelf++; + ++StoresOfArgumentToSelf; continue; } } @@ -1633,7 +1633,7 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() { // function. Ignore it. if (auto *Arg = dyn_cast(SI->getSrc())) { if (Arg->getParent() == uninitMemory->getParent()) { - StoresOfArgumentToSelf++; + ++StoresOfArgumentToSelf; continue; } } diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 65e5513dc1d7e..ab7a60c936c07 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -2238,7 +2238,7 @@ SILValue LifetimeChecker::handleConditionalInitAssign() { // We might need an extra bit to check if self was consumed. if (HasConditionalSelfInitialized) - NumMemoryElements++; + ++NumMemoryElements; // Create the control variable as the first instruction in the function (so // that it is easy to destroy the stack location. @@ -2404,7 +2404,7 @@ handleConditionalDestroys(SILValue ControlVariableAddr) { // We might need an extra bit to check if self was consumed. if (HasConditionalSelfInitialized) - NumMemoryElements++; + ++NumMemoryElements; // Utilities. diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp index 4fc4f36435d0f..b5b24f9581bd5 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp @@ -154,17 +154,17 @@ class SubAccessInfo { } if (BAI->getAccessKind() == SILAccessKind::Read) - Reads++; + ++Reads; else - NonReads++; + ++NonReads; } /// Decrement the count for given access. void endAccess(EndAccessInst *EAI) { if (EAI->getBeginAccess()->getAccessKind() == SILAccessKind::Read) - Reads--; + --Reads; else - NonReads--; + --NonReads; // If all open accesses are now ended, forget the location of the // first access. diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp index 0d75c687a1ef2..e1ca3bc186428 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp @@ -181,7 +181,7 @@ static void propagateBasicBlockArgs(SILBasicBlock &BB) { // We were able to fold, so all users should use the new folded value. Arg->replaceAllUsesWith(Args[Idx]); - NumBasicBlockArgsPropagated++; + ++NumBasicBlockArgsPropagated; } // Remove args from the block. @@ -277,7 +277,7 @@ static bool constantFoldEnumTerminator(SILBasicBlock &BB, LLVM_DEBUG(llvm::dbgs() << "Folding terminator: " << *SUI); recursivelyDeleteTriviallyDeadInstructions(SUI, true); - NumTerminatorsFolded++; + ++NumTerminatorsFolded; return true; } @@ -352,7 +352,7 @@ static bool constantFoldEnumAddrTerminator( LLVM_DEBUG(llvm::dbgs() << "Folding terminator: " << *SUI); recursivelyDeleteTriviallyDeadInstructions(SUI, true); - NumTerminatorsFolded++; + ++NumTerminatorsFolded; return true; } @@ -528,7 +528,7 @@ static bool constantFoldTerminator(SILBasicBlock &BB, CondIsTrue = true; } recursivelyDeleteTriviallyDeadInstructions(TI, true); - NumInstructionsRemoved++; + ++NumInstructionsRemoved; // Produce an unreachable code warning for this basic block if it // contains user code (only if we are not within an inlined function or a @@ -552,7 +552,7 @@ static bool constantFoldTerminator(SILBasicBlock &BB, UnreachableInfo{UnreachableKind::FoldedBranch, Loc, CondIsTrue})); } - NumTerminatorsFolded++; + ++NumTerminatorsFolded; return true; } } @@ -611,7 +611,7 @@ static bool constantFoldTerminator(SILBasicBlock &BB, SILBuilderWithScope B(&BB, TI); B.createBranch(TI->getLoc(), TheSuccessorBlock); recursivelyDeleteTriviallyDeadInstructions(TI, true); - NumTerminatorsFolded++; + ++NumTerminatorsFolded; return true; } @@ -777,7 +777,7 @@ static bool simplifyBlocksWithCallsToNoReturn(SILBasicBlock &BB, // noreturn function and therefore dead. setOutsideBlockUsesToUndef(CurrentInst); - NumInstructionsRemoved++; + ++NumInstructionsRemoved; continue; } @@ -975,7 +975,7 @@ static bool removeUnreachableBlocks(SILFunction &F, SILModule &M, // Drop references to other blocks. recursivelyDeleteTriviallyDeadInstructions(BB->getTerminator(), true); - NumInstructionsRemoved++; + ++NumInstructionsRemoved; } // Delete dead instructions and everything that could become dead after @@ -992,7 +992,7 @@ static bool removeUnreachableBlocks(SILFunction &F, SILModule &M, for (auto I = F.begin(), E = F.end(); I != E;) if (!Reachable.count(&*I)) { I = F.getBlocks().erase(I); - NumBlocksRemoved++; + ++NumBlocksRemoved; } else ++I; diff --git a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp index 087b6c093112a..c543b72f8f79a 100644 --- a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp +++ b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp @@ -594,7 +594,7 @@ static SILValue emitCodeForConstantArray(ArrayRef elements, // element. elementTypeLowering.emitStore(builder, loc, elementSIL, currentStorageAddr, StoreOwnershipQualifier::Init); - elementIndex++; + ++elementIndex; } return arraySIL; } diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 369ad70e03d88..10072818e3476 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -491,8 +491,9 @@ runFunctionPasses(unsigned FromTransIdx, unsigned ToTransIdx) { return; BasicCalleeAnalysis *BCA = getAnalysis(); - BottomUpFunctionOrder BottomUpOrder(*Mod, BCA); - auto BottomUpFunctions = BottomUpOrder.getFunctions(); + BottomUpFunctionOrder BottomUpOrder(BCA); + BottomUpOrder.computeBottomUpOrder(Mod); + auto BottomUpFunctions = BottomUpOrder.getBottomUpOrder(); assert(FunctionWorklist.empty() && "Expected empty function worklist!"); @@ -545,6 +546,47 @@ runFunctionPasses(unsigned FromTransIdx, unsigned ToTransIdx) { ++Entry.PipelineIdx; } clearRestartPipeline(); + + if (TailIdx == (FunctionWorklist.size() - 1)) { + // No new functions to process + continue; + } + + // Compute the bottom up order of the new functions and the callees in it + BottomUpFunctionOrder SubBottomUpOrder(BCA); + // Initialize BottomUpFunctionOrder with new functions + for (auto It = FunctionWorklist.begin() + TailIdx + 1; + It != FunctionWorklist.end(); It++) { + SubBottomUpOrder.computeBottomUpOrder(It->F); + } + auto NewFunctionsBottomUp = SubBottomUpOrder.getBottomUpOrder(); + SmallPtrSet NewBottomUpSet(NewFunctionsBottomUp.begin(), + NewFunctionsBottomUp.end()); + + // Remove all the functions in the new bottom up order from FunctionWorklist + llvm::DenseMap FunctionsToReorder; + auto RemoveFn = [&FunctionsToReorder, + &NewBottomUpSet](WorklistEntry Entry) { + if (NewBottomUpSet.find(Entry.F) == NewBottomUpSet.end()) { + return false; + } + FunctionsToReorder.insert(std::make_pair(Entry.F, Entry)); + return true; + }; + std::remove_if(FunctionWorklist.begin(), FunctionWorklist.end(), RemoveFn); + FunctionWorklist.erase((FunctionWorklist.begin() + FunctionWorklist.size() - + FunctionsToReorder.size()), + FunctionWorklist.end()); + + // Add back the functions in the new bottom up order to the FunctionWorklist + for (auto it = NewFunctionsBottomUp.rbegin(); + it != NewFunctionsBottomUp.rend(); it++) { + auto Entry = FunctionsToReorder.find(*it); + if (Entry == FunctionsToReorder.end()) { + continue; + } + FunctionWorklist.push_back((*Entry).second); + } } } @@ -875,7 +917,7 @@ namespace { child_iterator &operator++() { baseIter++; return *this; } child_iterator operator++(int) { auto tmp = *this; - baseIter++; + ++baseIter; return tmp; } Node *operator*() const { return baseIter->Child; } diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp index 28817b8f20fa0..92f0958f82b98 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp @@ -229,7 +229,7 @@ bool SILCombiner::runOnFunction(SILFunction &F) { // Perform iterations until we do not make any changes. while (doOneIteration(F, Iteration)) { Changed = true; - Iteration++; + ++Iteration; } if (invalidatedStackNesting) { diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index 6dfeffba7d1bc..67090d1886a97 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -658,7 +658,8 @@ void SILCombiner::buildConcreteOpenedExistentialInfos( llvm::SmallDenseMap &COEIs, SILBuilderContext &BuilderCtx, SILOpenedArchetypesTracker &OpenedArchetypesTracker) { - for (unsigned ArgIdx = 0; ArgIdx < Apply.getNumArguments(); ArgIdx++) { + for (unsigned ArgIdx = 0, e = Apply.getNumArguments(); ArgIdx < e; + ++ArgIdx) { auto ArgASTType = Apply.getArgument(ArgIdx)->getType().getASTType(); if (!ArgASTType->hasArchetype()) continue; @@ -770,7 +771,7 @@ bool SILCombiner::canReplaceArg(FullApplySite Apply, // This bailout check is also needed for non-Self arguments [including Self]. unsigned NumApplyArgs = Apply.getNumArguments(); - for (unsigned Idx = 0; Idx < NumApplyArgs; Idx++) { + for (unsigned Idx = 0; Idx < NumApplyArgs; ++Idx) { if (Idx == ArgIdx) continue; if (Apply.getArgument(Idx)->getType().getASTType().findIf( @@ -1416,7 +1417,7 @@ isTryApplyResultNotUsed(UserListTy &AcceptedUses, TryApplyInst *TAI) { "mismatching number of arguments for the same destination block"); // Check if both blocks pass the same arguments to the common destination. - for (unsigned Idx = 0, End = NormalBr->getNumArgs(); Idx < End; Idx++) { + for (unsigned Idx = 0, End = NormalBr->getNumArgs(); Idx < End; ++Idx) { if (NormalBr->getArg(Idx) != ErrorBr->getArg(Idx)) return false; } diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index 2d79a39f6d9eb..2001a208d78a5 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -222,7 +222,7 @@ SILInstruction *SILCombiner::visitSelectEnumAddrInst(SelectEnumAddrInst *SEAI) { if (elementDecl.isNonNull()) { // Construct a new instruction by copying all the case entries. SmallVector, 4> CaseValues; - for (int idx = 0, numIdcs = SEAI->getNumCases(); idx < numIdcs; idx++) { + for (int idx = 0, numIdcs = SEAI->getNumCases(); idx < numIdcs; ++idx) { CaseValues.push_back(SEAI->getCase(idx)); } // Add the default-entry of the original instruction as case-entry. @@ -1581,9 +1581,9 @@ SILInstruction *SILCombiner::visitCondBranchInst(CondBranchInst *CBI) { if (isa(Pair.second)) { bool isFalse = match(Pair.second, Zero); if (!isFalse) { - TrueBBCases++; + ++TrueBBCases; } else { - FalseBBCases++; + ++FalseBBCases; } continue; } @@ -1602,9 +1602,9 @@ SILInstruction *SILCombiner::visitCondBranchInst(CondBranchInst *CBI) { unsigned NumFalseBBCases = 0; if (DefaultBB == CBI->getFalseBB()) - NumFalseBBCases++; + ++NumFalseBBCases; else - NumTrueBBCases++; + ++NumTrueBBCases; // We can now convert cond_br(select_enum) into switch_enum. SmallVector, 8> Cases; @@ -1619,11 +1619,11 @@ SILInstruction *SILCombiner::visitCondBranchInst(CondBranchInst *CBI) { bool isFalse = match(Pair.second, Zero); if (!isFalse && DefaultBB != CBI->getTrueBB()) { Cases.push_back(std::make_pair(Pair.first, CBI->getTrueBB())); - NumTrueBBCases++; + ++NumTrueBBCases; } if (isFalse && DefaultBB != CBI->getFalseBB()) { Cases.push_back(std::make_pair(Pair.first, CBI->getFalseBB())); - NumFalseBBCases++; + ++NumFalseBBCases; } } @@ -1649,7 +1649,7 @@ SILInstruction *SILCombiner::visitSelectEnumInst(SelectEnumInst *SEI) { if (elementDecl.isNonNull()) { // Construct a new instruction by copying all the case entries. SmallVector, 4> CaseValues; - for (int idx = 0, numIdcs = SEI->getNumCases(); idx < numIdcs; idx++) { + for (int idx = 0, numIdcs = SEI->getNumCases(); idx < numIdcs; ++idx) { CaseValues.push_back(SEI->getCase(idx)); } // Add the default-entry of the original instruction as case-entry. diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp index 376b1765c4123..af2cef2882e4a 100644 --- a/lib/SILOptimizer/Transforms/CSE.cpp +++ b/lib/SILOptimizer/Transforms/CSE.cpp @@ -1154,7 +1154,7 @@ static bool tryToCSEOpenExtCall(OpenExistentialAddrInst *From, ToAI->isNonThrowing()); FromAI->replaceAllUsesWith(NAI); FromAI->eraseFromParent(); - NumOpenExtRemoved++; + ++NumOpenExtRemoved; return true; } @@ -1195,10 +1195,10 @@ static bool CSExistentialInstructions(SILFunctionArgument *Arg, // Try to CSE the users of the current open_existential_addr instruction with // one of the other open_existential_addr that dominate it. int NumOpenInstr = Opens.size(); - for (int i = 0; i < NumOpenInstr; i++) { + for (int i = 0; i < NumOpenInstr; ++i) { // Try to find a better dominating 'open' for the i-th instruction. OpenExistentialAddrInst *SomeOpen = TopDominator[i]; - for (int j = 0; j < NumOpenInstr; j++) { + for (int j = 0; j < NumOpenInstr; ++j) { if (i == j || TopDominator[i] == TopDominator[j]) continue; @@ -1221,13 +1221,13 @@ static bool CSExistentialInstructions(SILFunctionArgument *Arg, // because we'll be adding new users and we need to make sure that we can // find the original users. llvm::SmallVector OriginalAW; - for (int i=0; i < NumOpenInstr; i++) { + for (int i=0; i < NumOpenInstr; ++i) { OriginalAW.push_back(getOpenExistentialUsers(TopDominator[i])); } // Perform the CSE for the open_existential_addr instruction and their // dominating instruction. - for (int i=0; i < NumOpenInstr; i++) { + for (int i=0; i < NumOpenInstr; ++i) { if (Opens[i] != TopDominator[i]) Changed |= tryToCSEOpenExtCall(Opens[i], TopDominator[i], OriginalAW[i], DA); diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp index 0eca4b14568be..9737b457831a4 100644 --- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp @@ -489,7 +489,7 @@ bool DCE::removeDead(SILFunction &F) { for (auto I = BB.begin(), E = BB.end(); I != E; ) { auto *Inst = &*I; - I++; + ++I; if (LiveValues.count(Inst) || isa(Inst)) continue; diff --git a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp index 3deef3a7afe1c..2da566a30041f 100644 --- a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp +++ b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp @@ -66,7 +66,7 @@ bool ObjectOutliner::run(SILFunction *F) { while (Iter != BB.end()) { SILInstruction *I = &*Iter; - Iter++; + ++Iter; if (auto *ARI = dyn_cast(I)) { unsigned GarbageSize = ToRemove.size(); diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp index 61a5467cbc8e0..fbf76e306f85d 100644 --- a/lib/SILOptimizer/Transforms/Outliner.cpp +++ b/lib/SILOptimizer/Transforms/Outliner.cpp @@ -1010,7 +1010,7 @@ ObjCMethodCall::outline(SILModule &M) { // Otherwise, use the original type convention. Args.push_back(Arg); } - OrigSigIdx++; + ++OrigSigIdx; } OutlinedCall = Builder.createApply(Loc, FunRef, SubstitutionMap(), Args); if (!BridgedCall->use_empty() && !BridgedReturn) @@ -1059,7 +1059,7 @@ ObjCMethodCall::outline(SILModule &M) { BridgedCall->setArgument(OrigSigIdx, FunArg); LastArg = FunArg; } - OrigSigIdx++; + ++OrigSigIdx; } // Set the method lookup's target. @@ -1173,7 +1173,7 @@ CanSILFunctionType ObjCMethodCall::getOutlinedFunctionType(SILModule &M) { // Otherwise, use the original type convention. Parameters.push_back(ParamInfo); } - OrigSigIdx++; + ++OrigSigIdx; } auto ExtInfo = SILFunctionType::ExtInfo( diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp index a5acb3643a512..f018f3a695b58 100644 --- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp +++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp @@ -881,7 +881,7 @@ void SILPerformanceInliner::collectAppliesToInline( for (auto AI : InitialCandidates) { SILFunction *Callee = AI.getReferencedFunctionOrNull(); assert(Callee && "apply_inst does not have a direct callee anymore"); - CalleeCount[Callee]++; + ++CalleeCount[Callee]; } // Now copy each candidate callee that has a small enough number of @@ -948,7 +948,7 @@ bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller) { // will assert, so we are safe making this assumption. SILInliner::inlineFullApply(AI, SILInliner::InlineKind::PerformanceInline, FuncBuilder); - NumFunctionsInlined++; + ++NumFunctionsInlined; } // The inliner splits blocks at call sites. Re-merge trivial branches to // reestablish a canonical CFG. diff --git a/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp b/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp index 63615c2c5cc6c..69fa9f615aa9f 100644 --- a/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp +++ b/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp @@ -114,7 +114,7 @@ class RedundantOverflowCheckRemovalPass : public SILFunctionTransform { for (auto *CF : ToRemove) { CF->eraseFromParent(); - NumCondFailRemoved++; + ++NumCondFailRemoved; } ToRemove.clear(); return true; @@ -136,7 +136,7 @@ class RedundantOverflowCheckRemovalPass : public SILFunctionTransform { // For each block in a Reverse Post Order scan: for (auto &BB : ReversePostOrder) { // For each instruction: - for (auto Inst = BB->begin(), End = BB->end(); Inst != End; Inst++) { + for (auto Inst = BB->begin(), End = BB->end(); Inst != End; ++Inst) { // Use branch information for eliminating condfails. if (auto *CBI = dyn_cast(Inst)) registerBranchFormula(CBI); diff --git a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp index 3642e337053fc..e284b0b9745c7 100644 --- a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp @@ -166,7 +166,7 @@ bool ReleaseDevirtualizer::createDeallocCall(SILType AllocType, B.createApply(ReleaseInst->getLoc(), MI, AllocSubMap, {object}); - NumReleasesDevirtualized++; + ++NumReleasesDevirtualized; ReleaseInst->eraseFromParent(); return true; } diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp index 4d1bfa160e287..95e0704ae8fa0 100644 --- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp +++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp @@ -1044,7 +1044,7 @@ SILInstruction *findIdenticalInBlock(SILBasicBlock *BB, SILInstruction *Iden, if (InstToSink == BB->begin()) return nullptr; - SkipBudget--; + --SkipBudget; InstToSink = std::prev(InstToSink); LLVM_DEBUG(llvm::dbgs() << "Continuing scan. Next inst: " << *InstToSink); } @@ -1384,7 +1384,7 @@ static bool sinkCodeFromPredecessors(EnumCaseDataflowContext &Context, for (auto P : BB->getPredecessorBlocks()) { if (auto *BI = dyn_cast(P->getTerminator())) { auto Args = BI->getArgs(); - for (size_t idx = 0, size = Args.size(); idx < size; idx++) { + for (size_t idx = 0, size = Args.size(); idx < size; ++idx) { valueToArgIdxMap[{Args[idx], P}] = idx; } } @@ -1431,7 +1431,7 @@ static bool sinkCodeFromPredecessors(EnumCaseDataflowContext &Context, // Replace operand values (which are passed to the successor block) // with corresponding block arguments. for (size_t idx = 0, numOps = InstToSink->getNumOperands(); - idx < numOps; idx++) { + idx < numOps; ++idx) { ValueInBlock OpInFirstPred(InstToSink->getOperand(idx), FirstPred); assert(valueToArgIdxMap.count(OpInFirstPred) != 0); int argIdx = valueToArgIdxMap[OpInFirstPred]; @@ -1445,7 +1445,7 @@ static bool sinkCodeFromPredecessors(EnumCaseDataflowContext &Context, Context.blotValue(Result); } I->eraseFromParent(); - NumSunk++; + ++NumSunk; } // Restart the scan. @@ -1468,7 +1468,7 @@ static bool sinkCodeFromPredecessors(EnumCaseDataflowContext &Context, return Changed; } - SkipBudget--; + --SkipBudget; InstToSink = std::prev(InstToSink); LLVM_DEBUG(llvm::dbgs() << "Continuing scan. Next inst: " << *InstToSink); } @@ -1530,7 +1530,7 @@ static bool tryToSinkRefCountAcrossSwitch(SwitchEnumInst *Switch, } RV->eraseFromParent(); - NumSunk++; + ++NumSunk; return true; } @@ -1616,7 +1616,7 @@ static bool tryToSinkRefCountAcrossSelectEnum(CondBranchInst *CondBr, } I->eraseFromParent(); - NumSunk++; + ++NumSunk; return true; } diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 51a4493a7da0d..f1d224c485d32 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -417,7 +417,7 @@ StackAllocationPromoter::promoteAllocationInBlock(SILBasicBlock *BB) { LLVM_DEBUG(llvm::dbgs() << "*** Promoting load: " << *Load); replaceLoad(Load, RunningVal, ASI); - NumInstRemoved++; + ++NumInstRemoved; } else if (Load->getOperand() == ASI) { // If we don't know the content of the AllocStack then the loaded // value *is* the new value; @@ -438,7 +438,7 @@ StackAllocationPromoter::promoteAllocationInBlock(SILBasicBlock *BB) { // If we met a store before this one, delete it. if (LastStore) { - NumInstRemoved++; + ++NumInstRemoved; LLVM_DEBUG(llvm::dbgs() << "*** Removing redundant store: " << *LastStore); LastStore->eraseFromParent(); @@ -504,7 +504,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) { RunningVal = SILUndef::get(ASI->getElementType(), *ASI->getFunction()); } replaceLoad(cast(Inst), RunningVal, ASI); - NumInstRemoved++; + ++NumInstRemoved; continue; } @@ -514,7 +514,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) { if (SI->getDest() == ASI) { RunningVal = SI->getSrc(); Inst->eraseFromParent(); - NumInstRemoved++; + ++NumInstRemoved; continue; } } @@ -561,7 +561,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) { if (!I->use_empty()) break; Node = I->getOperand(0); I->eraseFromParent(); - NumInstRemoved++; + ++NumInstRemoved; } } } @@ -648,7 +648,7 @@ void StackAllocationPromoter::fixBranchesAndUses(BlockSet &PhiBlocks) { SmallVector collectedLoads; for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E;) { auto *Inst = UI->getUser(); - UI++; + ++UI; bool removedUser = false; collectedLoads.clear(); @@ -668,7 +668,7 @@ void StackAllocationPromoter::fixBranchesAndUses(BlockSet &PhiBlocks) { // Replace the load with the definition that we found. replaceLoad(LI, Def, ASI); removedUser = true; - NumInstRemoved++; + ++NumInstRemoved; } if (removedUser) @@ -683,7 +683,7 @@ void StackAllocationPromoter::fixBranchesAndUses(BlockSet &PhiBlocks) { // Replace DebugValueAddr with DebugValue. SILValue Def = getLiveInValue(PhiBlocks, BB); promoteDebugValueAddr(DVAI, Def, B); - NumInstRemoved++; + ++NumInstRemoved; continue; } @@ -870,12 +870,12 @@ void StackAllocationPromoter::run() { bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){ LLVM_DEBUG(llvm::dbgs() << "*** Memory to register looking at: " << *alloc); - NumAllocStackFound++; + ++NumAllocStackFound; // Don't handle captured AllocStacks. bool inSingleBlock = false; if (isCaptured(alloc, inSingleBlock)) { - NumAllocStackCaptured++; + ++NumAllocStackCaptured; return false; } @@ -942,7 +942,7 @@ bool MemoryToRegisters::run() { if (promoted) { if (ASI->use_empty()) ASI->eraseFromParent(); - NumInstRemoved++; + ++NumInstRemoved; Changed = true; } } diff --git a/lib/SILOptimizer/Transforms/SILSROA.cpp b/lib/SILOptimizer/Transforms/SILSROA.cpp index dcfb8d6803e78..fbcc7ccca62c0 100644 --- a/lib/SILOptimizer/Transforms/SILSROA.cpp +++ b/lib/SILOptimizer/Transforms/SILSROA.cpp @@ -169,7 +169,7 @@ bool SROAMemoryUseAnalyzer::analyze() { LLVM_DEBUG(llvm::dbgs() << " Found a load of the projection.\n"); Loads.push_back(LI); for (auto useIter = LI->use_begin(), End = LI->use_end(); - !hasBenefit && useIter != End; useIter++) { + !hasBenefit && useIter != End; ++useIter) { hasBenefit = (isa(useIter->get()) || isa(useIter->get())); } diff --git a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index c0901db5b29f3..8b22cc85b36af 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -41,13 +41,125 @@ STATISTIC(NumEliminatedInsts, "number of removed instructions"); STATISTIC(NumLoadCopyConvertedToLoadBorrow, "number of load_copy converted to load_borrow"); +//===----------------------------------------------------------------------===// +// Ownership Phi Operand +//===----------------------------------------------------------------------===// + +namespace { + +/// The operand of a "phi" in the induced ownership graph of a def-use graph. +/// +/// Some examples: br, struct, tuple. +class OwnershipPhiOperand { +public: + enum Kind { + Branch, + Struct, + }; + +private: + Operand *op; + + OwnershipPhiOperand(Operand *op) : op(op) {} + +public: + static Optional get(const Operand *op) { + switch (op->getUser()->getKind()) { + case SILInstructionKind::BranchInst: + case SILInstructionKind::StructInst: + return {{const_cast(op)}}; + default: + return None; + } + } + + Kind getKind() const { + switch (op->getUser()->getKind()) { + case SILInstructionKind::BranchInst: + return Kind::Branch; + case SILInstructionKind::StructInst: + return Kind::Struct; + default: + llvm_unreachable("unhandled case?!"); + } + } + + Operand *getOperand() const { return op; } + SILValue getValue() const { return op->get(); } + SILType getType() const { return op->get()->getType(); } + + unsigned getOperandNumber() const { return op->getOperandNumber(); } + + void markUndef() & { + op->set(SILUndef::get(getType(), *op->getUser()->getFunction())); + } + + SILInstruction *getInst() const { return op->getUser(); } + + /// Return true if this phi consumes a borrow. + /// + /// If so, we may need to insert an extra begin_borrow to balance the +1 when + /// converting owned ownership phis to guaranteed ownership phis. + bool isGuaranteedConsuming() const { + switch (getKind()) { + case Kind::Branch: + return true; + case Kind::Struct: + return false; + } + } + + bool operator<(const OwnershipPhiOperand &other) const { + return op < other.op; + } + + bool operator==(const OwnershipPhiOperand &other) const { + return op == other.op; + } + + bool visitResults(function_ref visitor) const { + switch (getKind()) { + case Kind::Struct: + return visitor(cast(getInst())); + case Kind::Branch: { + auto *br = cast(getInst()); + unsigned opNum = getOperandNumber(); + return llvm::all_of( + br->getSuccessorBlocks(), [&](SILBasicBlock *succBlock) { + return visitor(succBlock->getSILPhiArguments()[opNum]); + }); + } + } + } +}; + +} // end anonymous namespace + //===----------------------------------------------------------------------===// // Live Range Modeling //===----------------------------------------------------------------------===// namespace { -class LiveRange { +/// This class represents an "extended live range" of an owned value. Such a +/// representation includes: +/// +/// 1. The owned introducing value. +/// 2. Any forwarding instructions that consume the introduced value +/// (transitively) and then propagate a new owned value. +/// 3. Transitive destroys on the forwarding instructions/destroys on the owned +/// introducing value. +/// 4. Any unknown consuming uses that are not understood by this code. +/// +/// This allows for this to be used to convert such a set of uses from using +/// owned ownership to using guaranteed ownership by converting the +/// destroy_value -> end_borrow and "flipping" the ownership of individual +/// forwarding instructions. +/// +/// NOTE: We do not look through "phi nodes" in the ownership graph (e.x.: real +/// phi arguments, struct, tuple). Instead we represent those as nodes in a +/// larger phi ownership web, connected via individual OwnershipLiveRange. +class OwnershipLiveRange { /// The value that we are computing the LiveRange for. Expected to be an owned /// introducer and not to be forwarding. OwnedValueIntroducer introducer; @@ -71,9 +183,18 @@ class LiveRange { ArrayRef destroyingUses; /// A list of forwarding instructions that forward owned ownership, but that - /// are also able to be converted to guaranteed ownership. If we are able to - /// eliminate this LiveRange due to it being from a guaranteed value, we must - /// flip the ownership of all of these instructions to guaranteed from owned. + /// are also able to be converted to guaranteed ownership. + /// + /// If we are able to eliminate this LiveRange due to it being from a + /// guaranteed value, we must flip the ownership of all of these instructions + /// to guaranteed from owned. + /// + /// NOTE: Normally only destroying or consuming uses end the live range. We + /// copy these transitive uses as well into the consumingUses array since + /// transitive uses can extend a live range up to an unreachable block without + /// ultimately being consuming. In such a situation if we did not also store + /// this into consuming uses, we would not be able to ascertain just using the + /// "consumingUses" array the true lifetime of the OwnershipLiveRange. /// /// Corresponds to isOwnershipForwardingInst(...). ArrayRef ownershipForwardingUses; @@ -84,9 +205,9 @@ class LiveRange { ArrayRef unknownConsumingUses; public: - LiveRange(SILValue value); - LiveRange(const LiveRange &) = delete; - LiveRange &operator=(const LiveRange &) = delete; + OwnershipLiveRange(SILValue value); + OwnershipLiveRange(const OwnershipLiveRange &) = delete; + OwnershipLiveRange &operator=(const OwnershipLiveRange &) = delete; enum class HasConsumingUse_t { No = 0, @@ -162,9 +283,10 @@ class LiveRange { /// A consuming operation that in order: /// - /// 1. Converts the phi argument to be guaranteed. + /// 1. Converts the phi argument to be guaranteed via setOwnership. /// - /// 2. Inserts end_borrows at the relevant destroy_values. + /// 2. If this consumes a borrow, insert end_borrows at the relevant + /// destroy_values. /// /// 3. Deletes all destroy_values. /// @@ -176,11 +298,9 @@ class LiveRange { /// /// NOTE: This routine leaves inserting begin_borrows for the incoming values /// to the caller since those are not part of the LiveRange itself. - /// - /// NOTE: Asserts that value is a phi argument. - void convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, - ValueLifetimeAnalysis::Frontier &scratch, - InstModCallbacks callbacks) &&; + void convertJoinedLiveRangePhiToGuaranteed( + DeadEndBlocks &deadEndBlocks, ValueLifetimeAnalysis::Frontier &scratch, + InstModCallbacks callbacks) &&; /// Given a new guaranteed value, insert end_borrow for the newGuaranteedValue /// at all of our destroy_values in prepration for converting from owned to @@ -194,7 +314,7 @@ class LiveRange { } // end anonymous namespace -struct LiveRange::OperandToUser { +struct OwnershipLiveRange::OperandToUser { OperandToUser() {} SILInstruction *operator()(const Operand *use) const { @@ -203,11 +323,12 @@ struct LiveRange::OperandToUser { } }; -LiveRange::DestroyingInstsRange LiveRange::getDestroyingInsts() const { +OwnershipLiveRange::DestroyingInstsRange +OwnershipLiveRange::getDestroyingInsts() const { return DestroyingInstsRange(getDestroyingUses(), OperandToUser()); } -LiveRange::LiveRange(SILValue value) +OwnershipLiveRange::OwnershipLiveRange(SILValue value) : introducer(*OwnedValueIntroducer::get(value)), destroyingUses(), ownershipForwardingUses(), unknownConsumingUses() { assert(introducer.value.getOwnershipKind() == ValueOwnershipKind::Owned); @@ -324,7 +445,7 @@ LiveRange::LiveRange(SILValue value) unknownConsumingUses = cUseArrayRef.take_back(tmpUnknownConsumingUses.size()); } -void LiveRange::insertEndBorrowsAtDestroys( +void OwnershipLiveRange::insertEndBorrowsAtDestroys( SILValue newGuaranteedValue, DeadEndBlocks &deadEndBlocks, ValueLifetimeAnalysis::Frontier &scratch) { assert(scratch.empty() && "Expected scratch to be initially empty?!"); @@ -377,7 +498,7 @@ void LiveRange::insertEndBorrowsAtDestroys( } } -void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { +void OwnershipLiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { while (!ownershipForwardingUses.empty()) { auto *i = ownershipForwardingUses.back()->getUser(); ownershipForwardingUses = ownershipForwardingUses.drop_back(); @@ -437,8 +558,8 @@ void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { } } -void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue, - InstModCallbacks callbacks) && { +void OwnershipLiveRange::convertToGuaranteedAndRAUW( + SILValue newGuaranteedValue, InstModCallbacks callbacks) && { auto *value = cast(introducer.value); while (!destroyingUses.empty()) { auto *d = destroyingUses.back(); @@ -455,17 +576,46 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue, std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } -void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, - ValueLifetimeAnalysis::Frontier &scratch, - InstModCallbacks callbacks) && { - // First convert the phi argument to be guaranteed. - auto *phiArg = cast(introducer.value); - phiArg->setOwnershipKind(ValueOwnershipKind::Guaranteed); +// TODO: If this is useful, move onto OwnedValueIntroducer itself? +static SILValue convertIntroducerToGuaranteed(OwnedValueIntroducer introducer) { + switch (introducer.kind) { + case OwnedValueIntroducerKind::Phi: { + auto *phiArg = cast(introducer.value); + phiArg->setOwnershipKind(ValueOwnershipKind::Guaranteed); + return phiArg; + } + case OwnedValueIntroducerKind::Struct: { + auto *si = cast(introducer.value); + si->setOwnershipKind(ValueOwnershipKind::Guaranteed); + return si; + } + case OwnedValueIntroducerKind::Copy: + case OwnedValueIntroducerKind::LoadCopy: + case OwnedValueIntroducerKind::Apply: + case OwnedValueIntroducerKind::BeginApply: + case OwnedValueIntroducerKind::TryApply: + case OwnedValueIntroducerKind::LoadTake: + case OwnedValueIntroducerKind::FunctionArgument: + case OwnedValueIntroducerKind::PartialApplyInit: + case OwnedValueIntroducerKind::AllocBoxInit: + case OwnedValueIntroducerKind::AllocRefInit: + return SILValue(); + } +} + +void OwnershipLiveRange::convertJoinedLiveRangePhiToGuaranteed( + DeadEndBlocks &deadEndBlocks, ValueLifetimeAnalysis::Frontier &scratch, + InstModCallbacks callbacks) && { - // Then insert end_borrows at each of our destroys. We have to convert the phi - // to guaranteed first since otherwise, the ownership check when we create the - // end_borrows will trigger. - insertEndBorrowsAtDestroys(phiArg, deadEndBlocks, scratch); + // First convert the phi value itself to be guaranteed. + SILValue phiValue = convertIntroducerToGuaranteed(introducer); + + // Then insert end_borrows at each of our destroys if we are consuming. We + // have to convert the phi to guaranteed first since otherwise, the ownership + // check when we create the end_borrows will trigger. + if (introducer.hasConsumingGuaranteedOperands()) { + insertEndBorrowsAtDestroys(phiValue, deadEndBlocks, scratch); + } // Then eliminate all of the destroys... while (!destroyingUses.empty()) { @@ -481,8 +631,8 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } -LiveRange::HasConsumingUse_t -LiveRange::hasUnknownConsumingUse(bool assumingAtFixPoint) const { +OwnershipLiveRange::HasConsumingUse_t +OwnershipLiveRange::hasUnknownConsumingUse(bool assumingAtFixPoint) const { // First do a quick check if we have /any/ unknown consuming // uses. If we do not have any, return false early. if (unknownConsumingUses.empty()) { @@ -506,7 +656,7 @@ LiveRange::hasUnknownConsumingUse(bool assumingAtFixPoint) const { // Make sure our single unknown consuming use is a branch inst. If not, bail, // this is a /real/ unknown consuming use. - if (!isa(op->getUser())) { + if (!OwnershipPhiOperand::get(op)) { return HasConsumingUse_t::Yes; } @@ -853,7 +1003,7 @@ struct SemanticARCOptVisitor FORWARDING_TERM(Branch) #undef FORWARDING_TERM - bool isWrittenTo(LoadInst *li, const LiveRange &lr); + bool isWrittenTo(LoadInst *li, const OwnershipLiveRange &lr); bool processWorklist(); bool optimize(); @@ -872,10 +1022,10 @@ VerifyAfterTransform("sil-semantic-arc-opts-verify-after-transform", static bool canEliminatePhi( SemanticARCOptVisitor::FrozenMultiMapRange optimizableIntroducerRange, - ArrayRef incomingValueOperandList, + ArrayRef incomingValueOperandList, SmallVectorImpl &ownedValueIntroducerAccumulator) { - for (Operand *incomingValueOperand : incomingValueOperandList) { - SILValue incomingValue = incomingValueOperand->get(); + for (auto incomingValueOperand : incomingValueOperandList) { + SILValue incomingValue = incomingValueOperand.getValue(); // Before we do anything, see if we have an incoming value with trivial // ownership. This can occur in the case where we are working with enums due @@ -890,7 +1040,8 @@ static bool canEliminatePhi( // NOTE: If this linear search is too slow, we can change the multimap to // sort the mapped to list by pointer instead of insertion order. In such a // case, we could then bisect. - if (llvm::find(optimizableIntroducerRange, incomingValueOperand) == + if (llvm::find(optimizableIntroducerRange, + incomingValueOperand.getOperand()) == optimizableIntroducerRange.end()) { return false; } @@ -934,9 +1085,30 @@ static bool canEliminatePhi( } static bool getIncomingJoinedLiveRangeOperands( - SILValue joinedLiveRange, SmallVectorImpl &resultingOperands) { + SILValue joinedLiveRange, + SmallVectorImpl &resultingOperands) { if (auto *phi = dyn_cast(joinedLiveRange)) { - return phi->getIncomingPhiOperands(resultingOperands); + return phi->visitIncomingPhiOperands([&](Operand *op) { + if (auto phiOp = OwnershipPhiOperand::get(op)) { + resultingOperands.push_back(*phiOp); + return true; + } + return false; + }); + } + + if (auto *svi = dyn_cast(joinedLiveRange)) { + return llvm::all_of(svi->getAllOperands(), [&](const Operand &op) { + // skip type dependent operands. + if (op.isTypeDependent()) + return true; + + auto phiOp = OwnershipPhiOperand::get(&op); + if (!phiOp) + return false; + resultingOperands.push_back(*phiOp); + return true; + }); } llvm_unreachable("Unhandled joined live range?!"); @@ -951,7 +1123,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() { SWIFT_DEFER { joinedOwnedIntroducerToConsumedOperands.reset(); }; // Now for each phi argument that we have in our multi-map... - SmallVector incomingValueOperandList; + SmallVector incomingValueOperandList; SmallVector ownedValueIntroducers; for (auto pair : joinedOwnedIntroducerToConsumedOperands.getRange()) { SWIFT_DEFER { @@ -963,7 +1135,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() { // only handle cases now where the result does not have any additional // ownershipPhi uses. SILValue joinedIntroducer = pair.first; - LiveRange joinedLiveRange(joinedIntroducer); + OwnershipLiveRange joinedLiveRange(joinedIntroducer); if (bool(joinedLiveRange.hasUnknownConsumingUse())) { continue; } @@ -993,11 +1165,9 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() { // through the list of incomingValueOperandList and stash the value/set the // operand's stored value to undef. We will hook them back up later. SmallVector originalIncomingValues; - for (Operand *incomingValueOperand : incomingValueOperandList) { - originalIncomingValues.push_back(incomingValueOperand->get()); - SILType type = incomingValueOperand->get()->getType(); - auto *undef = SILUndef::get(type, F); - incomingValueOperand->set(undef); + for (auto &incomingValueOperand : incomingValueOperandList) { + originalIncomingValues.push_back(incomingValueOperand.getValue()); + incomingValueOperand.markUndef(); } // Then go through all of our owned value introducers, compute their live @@ -1014,7 +1184,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() { SmallVector, 8> incomingValueUpdates; for (auto introducer : ownedValueIntroducers) { SILValue v = introducer.value; - LiveRange lr(v); + OwnershipLiveRange lr(v); // For now, we only handle copy_value for simplicity. // @@ -1050,25 +1220,25 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() { // Then convert the phi's live range to be guaranteed. std::move(joinedLiveRange) - .convertArgToGuaranteed(getDeadEndBlocks(), lifetimeFrontier, - getCallbacks()); - - // Now insert a begin_borrow along the incoming value edges and We have to - // do this after converting the incoming values to be guaranteed since - // SILBuilder checks simple ownership invariants (namely that def/use line - // up) when creating instructions. + .convertJoinedLiveRangePhiToGuaranteed( + getDeadEndBlocks(), lifetimeFrontier, getCallbacks()); + + // Now if our phi operand consumes/forwards its guaranteed input, insert a + // begin_borrow along the incoming value edges. We have to do this after + // converting the incoming values to be guaranteed to avoid tripping + // SILBuilder checks around simple ownership invariants (namely that def/use + // line up) when creating instructions. assert(incomingValueOperandList.size() == originalIncomingValues.size()); while (!incomingValueOperandList.empty()) { - auto *incomingValueOperand = incomingValueOperandList.pop_back_val(); + auto incomingValueOperand = incomingValueOperandList.pop_back_val(); SILValue originalValue = originalIncomingValues.pop_back_val(); - - auto *br = cast(incomingValueOperand->getUser()); - if (originalValue.getOwnershipKind() != ValueOwnershipKind::None) { + if (incomingValueOperand.isGuaranteedConsuming() && + originalValue.getOwnershipKind() != ValueOwnershipKind::None) { auto loc = RegularLocation::getAutoGeneratedLocation(); - SILBuilderWithScope builder(br); + SILBuilderWithScope builder(incomingValueOperand.getInst()); originalValue = builder.createBeginBorrow(loc, originalValue); } - incomingValueOperand->set(originalValue); + incomingValueOperand.getOperand()->set(originalValue); } madeChange = true; @@ -1267,10 +1437,11 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst // be some consuming use that we either do not understand is /actually/ // forwarding or a user that truly represents a necessary consume of the value // (e.x. storing into memory). - LiveRange lr(cvi); + OwnershipLiveRange lr(cvi); auto hasUnknownConsumingUseState = lr.hasUnknownConsumingUse(assumingAtFixedPoint); - if (hasUnknownConsumingUseState == LiveRange::HasConsumingUse_t::Yes) { + if (hasUnknownConsumingUseState == + OwnershipLiveRange::HasConsumingUse_t::Yes) { return false; } @@ -1375,24 +1546,21 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst // within the guaranteed value scope. So we /could/ optimize it. Now check if // we were truly dead or if we are dead if we can eliminate phi arg uses. If // we need to handle the phi arg uses, we bail. After we reach a fixed point, - // we will try to eliminate this value then. + // we will try to eliminate this value then if we can find a complete set of + // all incoming values to our phi argument. if (hasUnknownConsumingUseState == - LiveRange::HasConsumingUse_t::YesButAllPhiArgs) { - auto *op = lr.getSingleUnknownConsumingUse(); - assert(op); - unsigned opNum = op->getOperandNumber(); - auto *br = cast(op->getUser()); + OwnershipLiveRange::HasConsumingUse_t::YesButAllPhiArgs) { + auto opPhi = *OwnershipPhiOperand::get(lr.getSingleUnknownConsumingUse()); SmallVector scratchSpace; SmallPtrSet visitedBlocks; - for (auto *succBlock : br->getSuccessorBlocks()) { + bool canOptimizePhi = opPhi.visitResults([&](SILValue value) { SWIFT_DEFER { scratchSpace.clear(); visitedBlocks.clear(); }; - auto *arg = succBlock->getSILPhiArguments()[opNum]; - LiveRange phiArgLR(arg); + OwnershipLiveRange phiArgLR(value); if (bool(phiArgLR.hasUnknownConsumingUse())) { return false; } @@ -1404,11 +1572,16 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst })) { return false; } - } - for (auto *succBlock : br->getSuccessorBlocks()) { - auto *arg = succBlock->getSILPhiArguments()[opNum]; - joinedOwnedIntroducerToConsumedOperands.insert(arg, op); + return true; + }); + + if (canOptimizePhi) { + opPhi.visitResults([&](SILValue value) { + joinedOwnedIntroducerToConsumedOperands.insert(value, + opPhi.getOperand()); + return true; + }); } return false; @@ -1663,7 +1836,7 @@ class StorageGuaranteesLoadVisitor SemanticARCOptVisitor &ARCOpt; // The live range of the original load. - const LiveRange &liveRange; + const OwnershipLiveRange &liveRange; // The current address being visited. SILValue currentAddress; @@ -1672,7 +1845,7 @@ class StorageGuaranteesLoadVisitor public: StorageGuaranteesLoadVisitor(SemanticARCOptVisitor &arcOpt, LoadInst *load, - const LiveRange &liveRange) + const OwnershipLiveRange &liveRange) : ARCOpt(arcOpt), liveRange(liveRange), currentAddress(load->getOperand()) {} @@ -1920,7 +2093,8 @@ class StorageGuaranteesLoadVisitor } // namespace -bool SemanticARCOptVisitor::isWrittenTo(LoadInst *load, const LiveRange &lr) { +bool SemanticARCOptVisitor::isWrittenTo(LoadInst *load, + const OwnershipLiveRange &lr) { StorageGuaranteesLoadVisitor visitor(*this, load, lr); return visitor.doIt(); } @@ -1938,7 +2112,7 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) { // FIXME: We should consider if it is worth promoting a load [copy] // -> load_borrow if we can put a copy_value on a cold path and thus // eliminate RR traffic on a hot path. - LiveRange lr(li); + OwnershipLiveRange lr(li); if (bool(lr.hasUnknownConsumingUse())) return false; diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index 46887a58e5b69..b2de748e580db 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -1053,7 +1053,7 @@ static bool onlyHasTerminatorAndDebugInsts(SILBasicBlock *BB) { while (&*Iter != Terminator) { if (!(&*Iter)->isDebugInstruction()) return false; - Iter++; + ++Iter; } return true; } @@ -2664,7 +2664,7 @@ bool SimplifyCFG::canonicalizeSwitchEnums() { // Construct a new instruction by copying all the case entries. SmallVector, 4> CaseBBs; - for (int idx = 0, numIdcs = SWI->getNumCases(); idx < numIdcs; idx++) { + for (int idx = 0, numIdcs = SWI->getNumCases(); idx < numIdcs; ++idx) { CaseBBs.push_back(SWI->getCase(idx)); } // Add the default-entry of the original instruction as case-entry. @@ -3346,7 +3346,7 @@ static bool simplifySwitchEnumToSelectEnum(SILBasicBlock *BB, unsigned ArgNum, unsigned ElemCount = 0; for (auto E : Enum->getAllElements()) { if (E) - ElemCount++; + ++ElemCount; } // Check if all possible cases are covered. diff --git a/lib/SILOptimizer/Transforms/Sink.cpp b/lib/SILOptimizer/Transforms/Sink.cpp index b9b7342c9f75f..65ef7d69011a1 100644 --- a/lib/SILOptimizer/Transforms/Sink.cpp +++ b/lib/SILOptimizer/Transforms/Sink.cpp @@ -112,7 +112,7 @@ class CodeSinkingPass : public SILFunctionTransform { } II->moveBefore(&*Dest->begin()); - NumInstrSunk++; + ++NumInstrSunk; return true; } @@ -136,7 +136,7 @@ class CodeSinkingPass : public SILFunctionTransform { // Skip empty blocks. if (Inst == Begin) continue; // Point to the first real instruction. - Inst--; + --Inst; while (true) { if (Inst == Begin) { diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp index 1991379ee6481..ecd0e7db862ff 100644 --- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp @@ -226,7 +226,7 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI, } // Update the stats. - NumTargetsPredicted++; + ++NumTargetsPredicted; // Devirtualize the apply instruction on the identical path. auto NewInst = @@ -502,7 +502,7 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA, // FIXME: Add support for generic subclasses. if (S->isGenericContext()) { - NotHandledSubsNum++; + ++NotHandledSubsNum; continue; } @@ -517,7 +517,7 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA, // Pass the metatype of the subclass. auto NewAI = speculateMonomorphicTarget(AI, ClassOrMetatypeType, S, LastCCBI); if (!NewAI) { - NotHandledSubsNum++; + ++NotHandledSubsNum; continue; } AI = NewAI; diff --git a/lib/SILOptimizer/Transforms/StackPromotion.cpp b/lib/SILOptimizer/Transforms/StackPromotion.cpp index a7579edc39094..e1436f9d7714b 100644 --- a/lib/SILOptimizer/Transforms/StackPromotion.cpp +++ b/lib/SILOptimizer/Transforms/StackPromotion.cpp @@ -140,7 +140,7 @@ bool StackPromotion::tryPromoteAlloc(AllocRefInst *ARI, EscapeAnalysis *EA, LLVM_DEBUG(llvm::dbgs() << " uses don't post-dom allocation -> don't promote"); return false; } - NumStackPromoted++; + ++NumStackPromoted; // We set the [stack] attribute in the alloc_ref. ARI->setStackAllocatable(); diff --git a/lib/SILOptimizer/Transforms/TempRValueElimination.cpp b/lib/SILOptimizer/Transforms/TempRValueElimination.cpp index 9a9a07df54083..5a8cf979bcc48 100644 --- a/lib/SILOptimizer/Transforms/TempRValueElimination.cpp +++ b/lib/SILOptimizer/Transforms/TempRValueElimination.cpp @@ -352,7 +352,7 @@ bool TempRValueOptPass::checkNoSourceModification( SILInstruction *inst = &*iter; if (useInsts.count(inst)) - numLoadsFound++; + ++numLoadsFound; // If this is the last use of the temp we are ok. After this point, // modifications to the source don't matter anymore. diff --git a/lib/SILOptimizer/UtilityPasses/FunctionOrderPrinter.cpp b/lib/SILOptimizer/UtilityPasses/FunctionOrderPrinter.cpp index 59bd0b43a8fa7..da66869263cac 100644 --- a/lib/SILOptimizer/UtilityPasses/FunctionOrderPrinter.cpp +++ b/lib/SILOptimizer/UtilityPasses/FunctionOrderPrinter.cpp @@ -35,8 +35,8 @@ class FunctionOrderPrinterPass : public SILModuleTransform { /// The entry point to the transformation. void run() override { BCA = getAnalysis(); - auto &M = *getModule(); - BottomUpFunctionOrder Orderer(M, BCA); + BottomUpFunctionOrder Orderer(BCA); + Orderer.computeBottomUpOrder(getModule()); llvm::outs() << "Bottom up function order:\n"; auto SCCs = Orderer.getSCCs(); diff --git a/lib/SILOptimizer/UtilityPasses/InstCount.cpp b/lib/SILOptimizer/UtilityPasses/InstCount.cpp index c38c4c4a87c78..bad7bf8a9056f 100644 --- a/lib/SILOptimizer/UtilityPasses/InstCount.cpp +++ b/lib/SILOptimizer/UtilityPasses/InstCount.cpp @@ -67,7 +67,7 @@ struct InstCountVisitor : SILInstructionVisitor { unsigned BlockCount = 0; void visitSILBasicBlock(SILBasicBlock *BB) { - BlockCount++; + ++BlockCount; SILInstructionVisitor::visitSILBasicBlock(BB); } @@ -104,14 +104,14 @@ class InstCount : public SILFunctionTransform { if (F->isDefinition()) { TotalExternalFuncInsts += V.InstCount; TotalExternalFuncBlocks += V.BlockCount; - TotalExternalFuncDefs++; + ++TotalExternalFuncDefs; } else { - TotalExternalFuncDecls++; + ++TotalExternalFuncDecls; } } else { TotalInsts += V.InstCount; TotalBlocks += V.BlockCount; - TotalFuncs++; + ++TotalFuncs; } switch (F->getLinkage()) { diff --git a/lib/SILOptimizer/UtilityPasses/SILDebugInfoGenerator.cpp b/lib/SILOptimizer/UtilityPasses/SILDebugInfoGenerator.cpp index 8847f87deba6c..5bdce88065e83 100644 --- a/lib/SILOptimizer/UtilityPasses/SILDebugInfoGenerator.cpp +++ b/lib/SILOptimizer/UtilityPasses/SILDebugInfoGenerator.cpp @@ -51,7 +51,7 @@ class SILDebugInfoGenerator : public SILModuleTransform { uint64_t Pos = 0; void write_impl(const char *Ptr, size_t Size) override { - for (size_t Idx = 0; Idx < Size; Idx++) { + for (size_t Idx = 0; Idx < Size; ++Idx) { char c = Ptr[Idx]; if (c == '\n') ++LineNum; diff --git a/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp b/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp index 97c03c862937d..aa94c8055de80 100644 --- a/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp +++ b/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp @@ -156,7 +156,7 @@ static bool canDuplicateBlock(SILBasicBlock *BB) { void CheckedCastBrJumpThreading::classifyPredecessor( SILBasicBlock *Pred, bool SuccessDominates, bool FailureDominates) { if (SuccessDominates == FailureDominates) { - numUnknownPreds++; + ++numUnknownPreds; return; } if (SuccessDominates) { @@ -414,8 +414,8 @@ areEquivalentConditionsAlongSomePaths(CheckedCastBranchInst *DomCCBI, IncomingValue, DomBB, DomCondition, DT); if (ReachingValue == SILValue()) { - numUnknownPreds++; - idx++; + ++numUnknownPreds; + ++idx; continue; } @@ -435,7 +435,7 @@ areEquivalentConditionsAlongSomePaths(CheckedCastBranchInst *DomCCBI, classifyPredecessor( PredBB, SuccessDominates, FailureDominates); - idx++; + ++idx; } } else { // ArgBB is the entry block. Check that conditions are the equivalent in this diff --git a/lib/SILOptimizer/Utils/ConstExpr.cpp b/lib/SILOptimizer/Utils/ConstExpr.cpp index 01a36e1f8907f..60db9517dd647 100644 --- a/lib/SILOptimizer/Utils/ConstExpr.cpp +++ b/lib/SILOptimizer/Utils/ConstExpr.cpp @@ -852,7 +852,7 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, switch (callee) { case WellKnownFunction::AssertionFailure: { SmallString<4> message; - for (unsigned i = 0; i < apply->getNumArguments(); i++) { + for (unsigned i = 0, e = apply->getNumArguments(); i < e; ++i) { SILValue argument = apply->getArgument(i); SymbolicValue argValue = getConstantValue(argument); Optional stringOpt = diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 88c1f6681573b..a11584530c6fc 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -810,7 +810,7 @@ swift::devirtualizeClassMethod(FullApplySite applySite, *applySite.getInstruction()) << "Devirtualized call to class method " << NV("Method", f); }); - NumClassDevirt++; + ++NumClassDevirt; return {newAI, changedCFG}; } @@ -1045,7 +1045,7 @@ devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f, *applySite.getInstruction()) << "Devirtualized call to " << NV("Method", f); }); - NumWitnessDevirt++; + ++NumWitnessDevirt; return {newApplySite, changedCFG}; } diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index 88cd53e7c33bc..fd0a3fa40a3cb 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -84,7 +84,7 @@ static std::pair getTypeDepthAndWidth(Type t) { auto StoredProperties = NTD->getStoredProperties(); Width += StoredProperties.size(); } - Depth++; + ++Depth; unsigned MaxTypeDepth = 0; auto GenericArgs = BGT->getGenericArgs(); for (auto Ty : GenericArgs) { @@ -101,7 +101,7 @@ static std::pair getTypeDepthAndWidth(Type t) { if (auto *TupleTy = t->getAs()) { Width += TupleTy->getNumElements(); - Depth++; + ++Depth; unsigned MaxTypeDepth = 0; auto ElementTypes = TupleTy->getElementTypes(); for (auto Ty : ElementTypes) { @@ -117,7 +117,7 @@ static std::pair getTypeDepthAndWidth(Type t) { } if (auto *FnTy = t->getAs()) { - Depth++; + ++Depth; unsigned MaxTypeDepth = 0; auto Params = FnTy->getParameters(); Width += Params.size(); @@ -156,7 +156,7 @@ static std::pair getTypeDepthAndWidth(Type t) { } if (auto *FnTy = t->getAs()) { - Depth++; + ++Depth; unsigned MaxTypeDepth = 0; auto Params = FnTy->getParams(); Width += Params.size(); @@ -345,7 +345,7 @@ static bool createsInfiniteSpecializationLoop(ApplySite Apply) { // contain small specialization cycles. if (numAcceptedCycles == 0) return true; - numAcceptedCycles--; + --numAcceptedCycles; } } @@ -441,7 +441,7 @@ bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee, << IndentDebug(4) << "Cannot specialize because the generic type is too deep"; }); - NumPreventedTooComplexGenericSpecializations++; + ++NumPreventedTooComplexGenericSpecializations; return false; } } @@ -525,7 +525,7 @@ bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee, llvm::errs() << "Detected and prevented an infinite " "generic specialization loop for callee: " << Callee->getName() << '\n'; - NumPreventedGenericSpecializationLoops++; + ++NumPreventedGenericSpecializationLoops; return false; } diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 46ff29ceffe3b..334cb559e142d 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -212,7 +212,7 @@ unsigned swift::getNumInOutArguments(FullApplySite applySite) { switch (ParamConvention) { case ParameterConvention::Indirect_Inout: case ParameterConvention::Indirect_InoutAliasable: { - numInOutArguments++; + ++numInOutArguments; break; default: break; @@ -641,7 +641,7 @@ void swift::eraseUsesOfInstruction(SILInstruction *inst, CallbackTy callback) { void swift::collectUsesOfValue(SILValue v, llvm::SmallPtrSetImpl &insts) { - for (auto ui = v->use_begin(), E = v->use_end(); ui != E; ui++) { + for (auto ui = v->use_begin(), E = v->use_end(); ui != E; ++ui) { auto *user = ui->getUser(); // Instruction has been processed. if (!insts.insert(user).second) @@ -927,7 +927,7 @@ swift::castValueToABICompatibleType(SILBuilder *builder, SILLocation loc, if (auto srcTupleTy = srcTy.getAs()) { SmallVector expectedTuple; bool changedCFG = false; - for (unsigned i = 0, e = srcTupleTy->getNumElements(); i < e; i++) { + for (unsigned i = 0, e = srcTupleTy->getNumElements(); i < e; ++i) { SILValue element = builder->createTupleExtract(loc, value, i); // Cast the value if necessary. bool neededCFGChange; @@ -966,7 +966,7 @@ swift::castValueToABICompatibleType(SILBuilder *builder, SILLocation loc, ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *abi, unsigned index) { SILBasicBlock::iterator iter(abi); - iter++; + ++iter; assert(iter != abi->getParent()->end() && "alloc_box cannot be the last instruction of a block"); SILInstruction *nextInst = &*iter; diff --git a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp index d9185096e4bd3..4e6d8a114eae2 100644 --- a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp +++ b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp @@ -141,7 +141,7 @@ class StatsOnlyInstructionsOpt { unsigned index = getIndexForKind(kind); if (!ShouldComputeInstCounts[index]) { ShouldComputeInstCounts[index] = true; - NumInstCounts++; + ++NumInstCounts; } } } diff --git a/lib/SILOptimizer/Utils/ValueLifetime.cpp b/lib/SILOptimizer/Utils/ValueLifetime.cpp index 62e17b97a9189..5fc8b0228b62b 100644 --- a/lib/SILOptimizer/Utils/ValueLifetime.cpp +++ b/lib/SILOptimizer/Utils/ValueLifetime.cpp @@ -33,14 +33,14 @@ void ValueLifetimeAnalysis::propagateLiveness() { // A user in the defBB could potentially be located before the defValue. if (userBlock == defBB) - numUsersBeforeDef++; + ++numUsersBeforeDef; } // Don't count any users in the defBB which are actually located _after_ // the defValue. auto instIter = defValue->getIterator(); while (numUsersBeforeDef > 0 && ++instIter != defBB->end()) { if (userSet.count(&*instIter)) - numUsersBeforeDef--; + --numUsersBeforeDef; } // Initialize the hasUsersBeforeDef field. diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 9b2bc350e03b3..b7ae0510c49c6 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -400,7 +400,7 @@ class BuilderClosureVisitor unsigned &numPayloads, bool &isOptional) { // The 'then' clause contributes a payload. - numPayloads++; + ++numPayloads; // If there's an 'else' clause, it contributes payloads: if (auto elseStmt = ifStmt->getElseStmt()) { @@ -410,7 +410,7 @@ class BuilderClosureVisitor isOptional); // Otherwise it's just the one. } else { - numPayloads++; + ++numPayloads; } // If not, the chain result is at least optional. @@ -1701,6 +1701,13 @@ class PreCheckFunctionBuilderApplication : public ASTWalker { FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval, AnyFunctionRef fn) const { + // We don't want to do the precheck if it will already have happened in + // the enclosing expression. + bool skipPrecheck = false; + if (auto closure = dyn_cast_or_null( + fn.getAbstractClosureExpr())) + skipPrecheck = shouldTypeCheckInEnclosingExpression(closure); + return PreCheckFunctionBuilderApplication(fn, false).run(); } diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 78232a90851c2..ec5fb98be762d 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -628,7 +628,7 @@ namespace { // equal to its parent expression's base. Expr *prev = ExprStack.back(); - for (argCount = 1; argCount < maxArgCount && argCount < e; argCount++) { + for (argCount = 1; argCount < maxArgCount && argCount < e; ++argCount) { Expr *result = ExprStack[e - argCount - 1]; Expr *base = getBaseExpr(result); if (base != prev) @@ -5293,7 +5293,7 @@ static unsigned getOptionalEvaluationDepth(Expr *expr, Expr *target) { // If we see an optional evaluation, the depth goes up. if (auto optEval = dyn_cast(expr)) { - depth++; + ++depth; expr = optEval->getSubExpr(); // We have to handle any other expressions that can be introduced by @@ -5787,9 +5787,9 @@ static bool applyTypeToClosureExpr(ConstraintSystem &cs, if (auto CE = dyn_cast(expr)) { cs.setType(CE, toType); - // If this is not a single-expression closure, write the type into the - // ClosureExpr directly here, since the visitor won't. - if (!CE->hasSingleExpressionBody()) + // If this closure isn't type-checked in its enclosing expression, write + // theg type into the ClosureExpr directly here, since the visitor won't. + if (!shouldTypeCheckInEnclosingExpression(CE)) CE->setType(toType); return true; @@ -7063,7 +7063,7 @@ ExprRewriter::buildDynamicCallable(ApplyExpr *apply, SelectedOverload selected, conformance.getTypeWitnessByName(argumentType, ctx.Id_Value); SmallVector names; SmallVector dictElements; - for (unsigned i = 0, n = arg->getNumElements(); i < n; i++) { + for (unsigned i = 0, n = arg->getNumElements(); i < n; ++i) { Expr *labelExpr = new (ctx) StringLiteralExpr(arg->getElementName(i).get(), arg->getElementNameLoc(i), diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index 592fca0024441..7aafe866c370b 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -331,18 +331,23 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution( fn.setBody(newBody, /*isSingleExpression=*/false); if (closure) { closure->setAppliedFunctionBuilder(); + closure->setTypeCheckedInEnclosingContext(); solution.setExprTypes(closure); } return SolutionApplicationToFunctionResult::Success; + } + assert(closure && "Can only get here with a closure at the moment"); - // If there is a single-expression body, transform that body now. - if (fn.hasSingleExpressionBody()) { + // If this closure is checked as part of the enclosing expression, handle + // that now. + if (shouldTypeCheckInEnclosingExpression(closure)) { ClosureConstraintApplication application( solution, closure, closureFnType->getResult(), rewriteTarget); application.visit(fn.getBody()); + closure->setTypeCheckedInEnclosingContext(); return SolutionApplicationToFunctionResult::Success; } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index b704deb84fa24..83357e9d8efcf 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -166,12 +166,6 @@ bool FailureDiagnostic::conformsToKnownProtocol( return constraints::conformsToKnownProtocol(cs, type, protocol); } -Type FailureDiagnostic::isRawRepresentable(Type type, - KnownProtocolKind protocol) const { - auto &cs = getConstraintSystem(); - return constraints::isRawRepresentable(cs, type, protocol); -} - Type RequirementFailure::getOwnerType() const { auto anchor = getRawAnchor(); @@ -651,7 +645,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { break; // Disregard optional payload element to look at its source. - toDrop++; + ++toDrop; } path = path.drop_back(toDrop); @@ -1103,7 +1097,7 @@ class VarDeclMultipleReferencesChecker : public ASTWalker { std::pair walkToExprPre(Expr *E) { if (auto *DRE = dyn_cast(E)) { if (DRE->getDecl() == varDecl) - count++; + ++count; } return { true, E }; } @@ -2297,12 +2291,6 @@ void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const { if (trySequenceSubsequenceFixIts(diagnostic)) return; - if (tryRawRepresentableFixIts( - diagnostic, KnownProtocolKind::ExpressibleByIntegerLiteral) || - tryRawRepresentableFixIts(diagnostic, - KnownProtocolKind::ExpressibleByStringLiteral)) - return; - if (tryIntegerCastFixIts(diagnostic)) return; @@ -2532,130 +2520,6 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const { return true; } -bool ContextualFailure::tryRawRepresentableFixIts( - InFlightDiagnostic &diagnostic, - KnownProtocolKind rawRepresentableProtocol) const { - auto anchor = getAnchor(); - auto fromType = getFromType(); - auto toType = getToType(); - - // The following fixes apply for optional destination types as well. - bool toTypeIsOptional = !toType->getOptionalObjectType().isNull(); - toType = toType->lookThroughAllOptionalTypes(); - - Type fromTypeUnwrapped = fromType->getOptionalObjectType(); - bool fromTypeIsOptional = !fromTypeUnwrapped.isNull(); - if (fromTypeIsOptional) - fromType = fromTypeUnwrapped; - - auto fixIt = [&](StringRef convWrapBefore, StringRef convWrapAfter, - const Expr *expr) { - SourceRange exprRange = expr->getSourceRange(); - if (fromTypeIsOptional && toTypeIsOptional) { - // Use optional's map function to convert conditionally, like so: - // expr.map{ T(rawValue: $0) } - bool needsParens = !expr->canAppendPostfixExpression(); - std::string mapCodeFix; - if (needsParens) { - diagnostic.fixItInsert(exprRange.Start, "("); - mapCodeFix += ")"; - } - mapCodeFix += ".map { "; - mapCodeFix += convWrapBefore; - mapCodeFix += "$0"; - mapCodeFix += convWrapAfter; - mapCodeFix += " }"; - diagnostic.fixItInsertAfter(exprRange.End, mapCodeFix); - } else if (!fromTypeIsOptional) { - diagnostic.fixItInsert(exprRange.Start, convWrapBefore); - diagnostic.fixItInsertAfter(exprRange.End, convWrapAfter); - } else { - SmallString<16> fixItBefore(convWrapBefore); - SmallString<16> fixItAfter; - - if (!expr->canAppendPostfixExpression(true)) { - fixItBefore += "("; - fixItAfter = ")"; - } - - fixItAfter += "!" + convWrapAfter.str(); - - diagnostic.flush(); - emitDiagnostic(diag::construct_raw_representable_from_unwrapped_value, - toType, fromType) - .highlight(exprRange) - .fixItInsert(exprRange.Start, fixItBefore) - .fixItInsertAfter(exprRange.End, fixItAfter); - } - }; - - if (conformsToKnownProtocol(fromType, rawRepresentableProtocol)) { - if (conformsToKnownProtocol(fromType, KnownProtocolKind::OptionSet) && - isExpr(anchor) && - castToExpr(anchor)->getDigitsText() == "0") { - diagnostic.fixItReplace(::getSourceRange(anchor), "[]"); - return true; - } - if (auto rawTy = isRawRepresentable(toType, rawRepresentableProtocol)) { - // Produce before/after strings like 'Result(rawValue: RawType())' - // or just 'Result(rawValue: )'. - std::string convWrapBefore = toType.getString(); - convWrapBefore += "(rawValue: "; - std::string convWrapAfter = ")"; - if (!isExpr(anchor) && - !TypeChecker::isConvertibleTo(fromType, rawTy, getDC())) { - // Only try to insert a converting construction if the protocol is a - // literal protocol and not some other known protocol. - switch (rawRepresentableProtocol) { -#define EXPRESSIBLE_BY_LITERAL_PROTOCOL_WITH_NAME(name, _, __, ___) \ - case KnownProtocolKind::name: \ - break; -#define PROTOCOL_WITH_NAME(name, _) \ - case KnownProtocolKind::name: \ - return false; -#include "swift/AST/KnownProtocols.def" - } - convWrapBefore += rawTy->getString(); - convWrapBefore += "("; - convWrapAfter += ")"; - } - - if (auto *E = getAsExpr(anchor)) - fixIt(convWrapBefore, convWrapAfter, E); - return true; - } - } - - if (auto rawTy = isRawRepresentable(fromType, rawRepresentableProtocol)) { - if (conformsToKnownProtocol(toType, rawRepresentableProtocol)) { - std::string convWrapBefore; - std::string convWrapAfter = ".rawValue"; - if (!TypeChecker::isConvertibleTo(rawTy, toType, getDC())) { - // Only try to insert a converting construction if the protocol is a - // literal protocol and not some other known protocol. - switch (rawRepresentableProtocol) { -#define EXPRESSIBLE_BY_LITERAL_PROTOCOL_WITH_NAME(name, _, __, ___) \ - case KnownProtocolKind::name: \ - break; -#define PROTOCOL_WITH_NAME(name, _) \ - case KnownProtocolKind::name: \ - return false; -#include "swift/AST/KnownProtocols.def" - } - convWrapBefore += toType->getString(); - convWrapBefore += "("; - convWrapAfter += ")"; - } - - if (auto *E = getAsExpr(anchor)) - fixIt(convWrapBefore, convWrapAfter, E); - return true; - } - } - - return false; -} - bool ContextualFailure::tryIntegerCastFixIts( InFlightDiagnostic &diagnostic) const { auto fromType = getFromType(); @@ -6389,3 +6253,136 @@ bool UnableToInferKeyPathRootFailure::diagnoseAsError() { .fixItInsertAfter(keyPathExpr->getStartLoc(), "<#Root#>"); return true; } + +Optional> +AbstractRawRepresentableFailure::getDiagnostic() const { + auto *locator = getLocator(); + + if (locator->isForContextualType()) { + return diag::cannot_convert_initializer_value; + } else if (locator->isForAssignment()) { + return diag::cannot_convert_assign; + } else if (locator->isLastElement()) { + return diag::cannot_convert_argument_value; + } + + return None; +} + +bool AbstractRawRepresentableFailure::diagnoseAsError() { + auto message = getDiagnostic(); + if (!message) + return false; + + auto diagnostic = emitDiagnostic(*message, getFromType(), getToType()); + fixIt(diagnostic); + return true; +} + +bool AbstractRawRepresentableFailure::diagnoseAsNote() { + auto *locator = getLocator(); + + Optional diagnostic; + if (locator->isForContextualType()) { + auto overload = getCalleeOverloadChoiceIfAvailable(locator); + if (!overload) + return false; + + if (auto *decl = overload->choice.getDeclOrNull()) { + diagnostic.emplace(emitDiagnosticAt( + decl, diag::cannot_convert_candidate_result_to_contextual_type, + decl->getName(), ExpectedType, RawReprType)); + } + } else if (auto argConv = + locator->getLastElementAs()) { + diagnostic.emplace( + emitDiagnostic(diag::candidate_has_invalid_argument_at_position, + RawReprType, argConv->getParamIdx(), /*inOut=*/false)); + } + + if (diagnostic) { + fixIt(*diagnostic); + return true; + } + + return false; +} + +void MissingRawRepresentableInitFailure::fixIt( + InFlightDiagnostic &diagnostic) const { + if (auto *E = getAsExpr(getAnchor())) { + auto range = E->getSourceRange(); + auto rawReprObjType = RawReprType->getOptionalObjectType(); + auto valueObjType = ExpectedType->getOptionalObjectType(); + + if (rawReprObjType && valueObjType) { + std::string mapCodeFix; + + // Check whether expression has been be wrapped in parens first. + if (!E->canAppendPostfixExpression()) { + diagnostic.fixItInsert(range.Start, "("); + mapCodeFix += ")"; + } + + mapCodeFix += ".map { "; + mapCodeFix += rawReprObjType->getString(); + mapCodeFix += "(rawValue: $0) }"; + + diagnostic.fixItInsertAfter(range.End, mapCodeFix); + } else if (rawReprObjType) { + diagnostic + .fixItInsert(range.Start, rawReprObjType->getString() + "(rawValue: ") + .fixItInsertAfter(range.End, ")"); + } else if (valueObjType) { + diagnostic.flush(); + + std::string fixItBefore = RawReprType->getString() + "(rawValue: "; + std::string fixItAfter; + + if (!E->canAppendPostfixExpression(true)) { + fixItBefore += "("; + fixItAfter += ")"; + } + + fixItAfter += "!) ?? <#default value#>"; + + emitDiagnostic(diag::construct_raw_representable_from_unwrapped_value, + RawReprType, valueObjType) + .highlight(range) + .fixItInsert(range.Start, fixItBefore) + .fixItInsertAfter(range.End, fixItAfter); + } else { + diagnostic + .fixItInsert(range.Start, RawReprType->getString() + "(rawValue: ") + .fixItInsertAfter(range.End, ") ?? <#default value#>"); + } + } +} + +void MissingRawValueFailure::fixIt(InFlightDiagnostic &diagnostic) const { + auto *E = getAsExpr(getAnchor()); + if (!E) + return; + + std::string fix; + + auto range = E->getSourceRange(); + if (!E->canAppendPostfixExpression()) { + diagnostic.fixItInsert(range.Start, "("); + fix += ")"; + } + + // If raw representable is an optional we need to map its raw value out + // out first and then, if destination is not optional, allow to specify + // default value. + if (RawReprType->getOptionalObjectType()) { + fix += "?.rawValue"; + + if (!ExpectedType->getOptionalObjectType()) + fix += " ?? <#default value#>"; + } else { + fix += ".rawValue"; + } + + diagnostic.fixItInsertAfter(range.End, fix); +} diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 72670b9f3fd4e..be251b6da89e6 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -219,7 +219,6 @@ class FailureDiagnostic { } bool conformsToKnownProtocol(Type type, KnownProtocolKind protocol) const; - Type isRawRepresentable(Type type, KnownProtocolKind protocol) const; }; /// Base class for all of the diagnostics related to generic requirement @@ -621,23 +620,6 @@ class ContextualFailure : public FailureDiagnostic { /// Attempt to attach any relevant fix-its to already produced diagnostic. void tryFixIts(InFlightDiagnostic &diagnostic) const; - /// Attempts to add fix-its for these two mistakes: - /// - /// - Passing an integer where a type conforming to RawRepresentable is - /// expected, by wrapping the expression in a call to the contextual - /// type's initializer - /// - /// - Passing a type conforming to RawRepresentable where an integer is - /// expected, by wrapping the expression in a call to the rawValue - /// accessor - /// - /// - Return true on the fixit is added, false otherwise. - /// - /// This helps migration with SDK changes. - bool - tryRawRepresentableFixIts(InFlightDiagnostic &diagnostic, - KnownProtocolKind rawRepresentablePrococol) const; - /// Attempts to add fix-its for these two mistakes: /// /// - Passing an integer with the right type but which is getting wrapped with @@ -2102,6 +2084,85 @@ class UnableToInferKeyPathRootFailure final : public FailureDiagnostic { bool diagnoseAsError() override; }; +class AbstractRawRepresentableFailure : public FailureDiagnostic { +protected: + Type RawReprType; + Type ExpectedType; + + AbstractRawRepresentableFailure(const Solution &solution, Type rawReprType, + Type expectedType, ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), + RawReprType(resolveType(rawReprType)), + ExpectedType(resolveType(expectedType)) {} + +public: + virtual Type getFromType() const = 0; + virtual Type getToType() const = 0; + + bool diagnoseAsError() override; + bool diagnoseAsNote() override; + +protected: + Optional> getDiagnostic() const; + + virtual void fixIt(InFlightDiagnostic &diagnostic) const = 0; +}; + +/// Diagnose an attempt to initialize raw representable type or convert to it +/// a value of some other type that matches its `RawValue` type. +/// +/// ```swift +/// enum E : Int { +/// case a, b, c +/// } +/// +/// let _: E = 0 +/// ``` +/// +/// `0` has to be wrapped into `E(rawValue: 0)` and either defaulted via `??` or +/// force unwrapped to constitute a valid binding. +class MissingRawRepresentableInitFailure final + : public AbstractRawRepresentableFailure { +public: + MissingRawRepresentableInitFailure(const Solution &solution, Type rawReprType, + Type expectedType, + ConstraintLocator *locator) + : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, + locator) {} + + Type getFromType() const override { return ExpectedType; } + Type getToType() const override { return RawReprType; } + +protected: + void fixIt(InFlightDiagnostic &diagnostic) const override; +}; + +/// Diagnose an attempt to pass raw representable type where its raw value +/// is expected instead. +/// +/// ```swift +/// enum E : Int { +/// case one = 1 +/// } +/// +/// let _: Int = E.one +/// ``` +/// +/// `E.one` has to use `.rawValue` to match `Int` expected by pattern binding. +class MissingRawValueFailure final : public AbstractRawRepresentableFailure { +public: + MissingRawValueFailure(const Solution &solution, Type rawReprType, + Type expectedType, ConstraintLocator *locator) + : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, + locator) {} + + Type getFromType() const override { return RawReprType; } + Type getToType() const override { return ExpectedType; } + +private: + void fixIt(InFlightDiagnostic &diagnostic) const override; +}; + } // end namespace constraints } // end namespace swift diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 7e68315383a1f..ab31071816944 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1087,28 +1087,6 @@ AllowInOutConversion *AllowInOutConversion::create(ConstraintSystem &cs, AllowInOutConversion(cs, argType, paramType, locator); } -/// Check whether given `value` type is indeed a the same type as a `RawValue` -/// type of a given raw representable type. -static bool isValueOfRawRepresentable(ConstraintSystem &cs, - Type rawRepresentableType, - Type valueType) { - auto rawType = isRawRepresentable(cs, rawRepresentableType); - if (!rawType) - return false; - - KnownProtocolKind protocols[] = { - KnownProtocolKind::ExpressibleByStringLiteral, - KnownProtocolKind::ExpressibleByIntegerLiteral}; - - for (auto protocol : protocols) { - if (conformsToKnownProtocol(cs, valueType, protocol) && - valueType->isEqual(rawType)) - return true; - } - - return false; -} - ExpandArrayIntoVarargs * ExpandArrayIntoVarargs::attempt(ConstraintSystem &cs, Type argType, Type paramType, @@ -1144,32 +1122,32 @@ bool ExpandArrayIntoVarargs::diagnose(const Solution &solution, return failure.diagnose(asNote); } -ExplicitlyConstructRawRepresentable * -ExplicitlyConstructRawRepresentable::attempt(ConstraintSystem &cs, Type argType, - Type paramType, - ConstraintLocatorBuilder locator) { - auto rawRepresentableType = paramType->lookThroughAllOptionalTypes(); - auto valueType = argType->lookThroughAllOptionalTypes(); - - if (isValueOfRawRepresentable(cs, rawRepresentableType, valueType)) - return new (cs.getAllocator()) ExplicitlyConstructRawRepresentable( - cs, valueType, rawRepresentableType, cs.getConstraintLocator(locator)); - - return nullptr; +bool ExplicitlyConstructRawRepresentable::diagnose(const Solution &solution, + bool asNote) const { + MissingRawRepresentableInitFailure failure(solution, RawReprType, + ExpectedType, getLocator()); + return failure.diagnose(asNote); } -UseValueTypeOfRawRepresentative * -UseValueTypeOfRawRepresentative::attempt(ConstraintSystem &cs, Type argType, - Type paramType, - ConstraintLocatorBuilder locator) { - auto rawRepresentableType = argType->lookThroughAllOptionalTypes(); - auto valueType = paramType->lookThroughAllOptionalTypes(); +ExplicitlyConstructRawRepresentable * +ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, + Type rawReprType, Type expectedType, + ConstraintLocator *locator) { + return new (cs.getAllocator()) ExplicitlyConstructRawRepresentable( + cs, rawReprType, expectedType, locator); +} - if (isValueOfRawRepresentable(cs, rawRepresentableType, valueType)) - return new (cs.getAllocator()) UseValueTypeOfRawRepresentative( - cs, rawRepresentableType, valueType, cs.getConstraintLocator(locator)); +bool UseRawValue::diagnose(const Solution &solution, bool asNote) const { + MissingRawValueFailure failure(solution, RawReprType, ExpectedType, + getLocator()); + return failure.diagnose(asNote); +} - return nullptr; +UseRawValue *UseRawValue::create(ConstraintSystem &cs, Type rawReprType, + Type expectedType, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + UseRawValue(cs, rawReprType, expectedType, locator); } unsigned AllowArgumentMismatch::getParamIdx() const { diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index ad3b45633bc70..093e8b96dea9d 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -213,9 +213,10 @@ enum class FixKind : uint8_t { /// via forming `Foo(rawValue:)` instead of using its `RawValue` directly. ExplicitlyConstructRawRepresentable, - /// Use raw value type associated with raw representative accessible + /// Use raw value type associated with raw representable, accessible /// using `.rawValue` member. - UseValueTypeOfRawRepresentative, + UseRawValue, + /// If an array was passed to a variadic argument, give a specific diagnostic /// and offer to drop the brackets if it's a literal. ExpandArrayIntoVarargs, @@ -264,7 +265,7 @@ enum class FixKind : uint8_t { /// Allow key path to be bound to a function type with more than 1 argument AllowMultiArgFuncKeyPathMismatch, - + /// Specify key path root type when it cannot be infered from context. SpecifyKeyPathRootType, @@ -1594,37 +1595,47 @@ class ExpandArrayIntoVarargs final : public AllowArgumentMismatch { ConstraintLocatorBuilder locator); }; -class ExplicitlyConstructRawRepresentable final : public AllowArgumentMismatch { - ExplicitlyConstructRawRepresentable(ConstraintSystem &cs, Type argType, - Type paramType, +class ExplicitlyConstructRawRepresentable final : public ConstraintFix { + Type RawReprType; + Type ExpectedType; + + ExplicitlyConstructRawRepresentable(ConstraintSystem &cs, Type rawReprType, + Type expectedType, ConstraintLocator *locator) - : AllowArgumentMismatch(cs, FixKind::ExplicitlyConstructRawRepresentable, - argType, paramType, locator) {} + : ConstraintFix(cs, FixKind::ExplicitlyConstructRawRepresentable, + locator), + RawReprType(rawReprType), ExpectedType(expectedType) {} public: std::string getName() const override { return "explicitly construct a raw representable type"; } + bool diagnose(const Solution &solution, bool asNote = false) const override; + static ExplicitlyConstructRawRepresentable * - attempt(ConstraintSystem &cs, Type argType, Type paramType, - ConstraintLocatorBuilder locator); + create(ConstraintSystem &cs, Type rawTypeRepr, Type expectedType, + ConstraintLocator *locator); }; -class UseValueTypeOfRawRepresentative final : public AllowArgumentMismatch { - UseValueTypeOfRawRepresentative(ConstraintSystem &cs, Type argType, - Type paramType, ConstraintLocator *locator) - : AllowArgumentMismatch(cs, FixKind::UseValueTypeOfRawRepresentative, - argType, paramType, locator) {} +class UseRawValue final : public ConstraintFix { + Type RawReprType; + Type ExpectedType; + + UseRawValue(ConstraintSystem &cs, Type rawReprType, Type expectedType, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::UseRawValue, locator), + RawReprType(rawReprType), ExpectedType(expectedType) {} public: std::string getName() const override { return "use `.rawValue` of a raw representable type"; } - static UseValueTypeOfRawRepresentative * - attempt(ConstraintSystem &cs, Type argType, Type paramType, - ConstraintLocatorBuilder locator); + bool diagnose(const Solution &solution, bool asNote = false) const override; + + static UseRawValue *create(ConstraintSystem &cs, Type rawReprType, + Type expectedType, ConstraintLocator *locator); }; /// Replace a coercion ('as') with a forced checked cast ('as!'). diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 3fabb0505b120..86cacf5c8afbf 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -670,7 +670,7 @@ namespace { assert(!AFD->hasImplicitSelfDecl()); for (auto param : *AFD->getParameters()) { if (!param->isDefaultArgument()) - nNoDefault++; + ++nNoDefault; } } else { nNoDefault = nOperands; @@ -2248,7 +2248,8 @@ namespace { // as potential hole right away. resultTy = CS.createTypeVariable( resultLoc, - closure->hasSingleExpressionBody() ? 0 : TVO_CanBindToHole); + shouldTypeCheckInEnclosingExpression(closure) + ? 0 : TVO_CanBindToHole); } } @@ -2544,7 +2545,17 @@ namespace { ConstraintKind::CheckedCast, subPatternType, castType, locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); - return setType(subPatternType); + // Allow `is` pattern to infer type from context which is then going + // to be propaged down to its sub-pattern via conversion. This enables + // correct handling of patterns like `_ as Foo` where `_` would + // get a type of `Foo` but `is` pattern enclosing it could still be + // inferred from enclosing context. + auto isType = CS.createTypeVariable(CS.getConstraintLocator(pattern), + TVO_CanBindToNoEscape); + CS.addConstraint( + ConstraintKind::Conversion, subPatternType, isType, + locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); + return setType(isType); } case PatternKind::Bool: diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index f3a146f9ba32a..85aecf8352a9d 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3135,6 +3135,60 @@ bool ConstraintSystem::repairFailures( return false; }; + // Check whether given `value` type matches a `RawValue` type of + // a given raw representable type. + auto isValueOfRawRepresentable = [&](Type valueType, + Type rawReprType) -> bool { + // diagnostic is going to suggest failable initializer anyway. + if (auto objType = rawReprType->getOptionalObjectType()) + rawReprType = objType; + + // If value is optional diagnostic would suggest using `Optional.map` in + // combination with `(rawValue: ...)` initializer. + if (auto objType = valueType->getOptionalObjectType()) + valueType = objType; + + if (rawReprType->isTypeVariableOrMember()) + return false; + + auto rawValue = isRawRepresentable(*this, rawReprType); + if (!rawValue) + return false; + + auto result = matchTypes(valueType, rawValue, ConstraintKind::Conversion, + TMF_ApplyingFix, locator); + return !result.isFailure(); + }; + + // Check whether given `rawReprType` does indeed conform to `RawRepresentable` + // and if so check that given `expectedType` matches its `RawValue` type. If + // that condition holds add a tailored fix which is going to suggest to + // explicitly construct a raw representable type from a given value type. + auto repairByConstructingRawRepresentableType = + [&](Type expectedType, Type rawReprType) -> bool { + if (!isValueOfRawRepresentable(expectedType, rawReprType)) + return false; + + conversionsOrFixes.push_back(ExplicitlyConstructRawRepresentable::create( + *this, rawReprType, expectedType, getConstraintLocator(locator))); + return true; + }; + + // Check whether given `rawReprType` does indeed conform to `RawRepresentable` + // and if so check that given `expectedType` matches its `RawValue` type. If + // that condition holds add a tailored fix which is going to suggest to + // use `.rawValue` associated with given raw representable type to match + // given expected type. + auto repairByUsingRawValueOfRawRepresentableType = + [&](Type rawReprType, Type expectedType) -> bool { + if (!isValueOfRawRepresentable(expectedType, rawReprType)) + return false; + + conversionsOrFixes.push_back(UseRawValue::create( + *this, rawReprType, expectedType, getConstraintLocator(locator))); + return true; + }; + auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) { return llvm::any_of(conversionsOrFixes, [kind](const RestrictionOrFix correction) { @@ -3351,6 +3405,13 @@ bool ConstraintSystem::repairFailures( conversionsOrFixes, locator)) return true; + // `rhs` - is an assignment destination and `lhs` is its source. + if (repairByConstructingRawRepresentableType(lhs, rhs)) + return true; + + if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) + return true; + // Let's try to match source and destination types one more // time to see whether they line up, if they do - the problem is // related to immutability, otherwise it's a type mismatch. @@ -3583,18 +3644,6 @@ bool ConstraintSystem::repairFailures( break; } - if (auto *fix = ExplicitlyConstructRawRepresentable::attempt( - *this, lhs, rhs, locator)) { - conversionsOrFixes.push_back(fix); - break; - } - - if (auto *fix = UseValueTypeOfRawRepresentative::attempt(*this, lhs, rhs, - locator)) { - conversionsOrFixes.push_back(fix); - break; - } - // If parameter is a collection but argument is not, let's try // to try and match collection element type to the argument to // produce better diagnostics e.g.: @@ -3624,6 +3673,13 @@ bool ConstraintSystem::repairFailures( if (lhs->hasHole() || rhs->hasHole()) return true; + // `lhs` - is an argument and `rhs` is a parameter type. + if (repairByConstructingRawRepresentableType(lhs, rhs)) + break; + + if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) + break; + if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; @@ -3842,6 +3898,9 @@ bool ConstraintSystem::repairFailures( break; } + if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) + break; + if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; @@ -3854,6 +3913,10 @@ bool ConstraintSystem::repairFailures( })) break; + // `lhs` - is an result type and `rhs` is a contextual type. + if (repairByConstructingRawRepresentableType(lhs, rhs)) + break; + conversionsOrFixes.push_back(IgnoreContextualType::create( *this, lhs, rhs, getConstraintLocator(locator))); break; @@ -7157,14 +7220,13 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, } } - bool hasReturn = hasExplicitResult(closure); + // If this closure should be type-checked as part of this expression, + // generate constraints for it now. auto &ctx = getASTContext(); - // If this is a multi-statement closure its body doesn't participate - // in type-checking. - if (closure->hasSingleExpressionBody()) { + if (shouldTypeCheckInEnclosingExpression(closure)) { if (generateConstraints(closure, closureType->getResult())) return false; - } else if (!hasReturn) { + } else if (!hasExplicitResult(closure)) { // If this closure has an empty body and no explicit result type // let's bind result type to `Void` since that's the only type empty body // can produce. Otherwise, if (multi-statement) closure doesn't have @@ -9509,7 +9571,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::UsePropertyWrapper: case FixKind::UseWrappedValue: case FixKind::ExpandArrayIntoVarargs: - case FixKind::UseValueTypeOfRawRepresentative: + case FixKind::UseRawValue: case FixKind::ExplicitlyConstructRawRepresentable: case FixKind::SpecifyBaseTypeForContextualMember: case FixKind::CoerceToCheckedCast: diff --git a/lib/Sema/ConstantnessSemaDiagnostics.cpp b/lib/Sema/ConstantnessSemaDiagnostics.cpp index cd60bcff27ef2..c918be5b6536b 100644 --- a/lib/Sema/ConstantnessSemaDiagnostics.cpp +++ b/lib/Sema/ConstantnessSemaDiagnostics.cpp @@ -316,7 +316,7 @@ static void diagnoseConstantArgumentRequirementOfCall(const CallExpr *callExpr, // Collect argument indices that are required to be constants. SmallVector constantArgumentIndices; auto paramList = callee->getParameters(); - for (unsigned i = 0; i < paramList->size(); i++) { + for (unsigned i = 0; i < paramList->size(); ++i) { ParamDecl *param = paramList->get(i); if (isParamRequiredToBeConstant(callee, param)) constantArgumentIndices.push_back(i); diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp index 3148bef79e5b9..7037e3b9c32c7 100644 --- a/lib/Sema/ConstraintGraph.cpp +++ b/lib/Sema/ConstraintGraph.cpp @@ -883,8 +883,8 @@ namespace { } if (ctx.Stats) { - ctx.Stats->getFrontendCounters() - .NumCyclicOneWayComponentsCollapsed++; + ++ctx.Stats->getFrontendCounters() + .NumCyclicOneWayComponentsCollapsed; } contractedCycle = true; @@ -1188,8 +1188,8 @@ void ConstraintGraph::incrementConstraintsPerContractionCounter() { SWIFT_FUNC_STAT; auto &context = CS.getASTContext(); if (auto *Stats = context.Stats) { - Stats->getFrontendCounters() - .NumConstraintsConsideredForEdgeContraction++; + ++Stats->getFrontendCounters() + .NumConstraintsConsideredForEdgeContraction; } } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 9e112c9aab259..d0ba3ca4a16d9 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -88,15 +88,15 @@ ConstraintSystem::~ConstraintSystem() { } void ConstraintSystem::incrementScopeCounter() { - CountScopes++; + ++CountScopes; // FIXME: (transitional) increment the redundant "always-on" counter. if (auto *Stats = getASTContext().Stats) - Stats->getFrontendCounters().NumConstraintScopes++; + ++Stats->getFrontendCounters().NumConstraintScopes; } void ConstraintSystem::incrementLeafScopes() { if (auto *Stats = getASTContext().Stats) - Stats->getFrontendCounters().NumLeafScopes++; + ++Stats->getFrontendCounters().NumLeafScopes; } bool ConstraintSystem::hasFreeTypeVariables() { @@ -600,12 +600,12 @@ static void extendDepthMap( std::pair walkToExprPre(Expr *E) override { DepthMap[E] = {Depth, Parent.getAsExpr()}; - Depth++; + ++Depth; return { true, E }; } Expr *walkToExprPost(Expr *E) override { - Depth--; + --Depth; return E; } }; @@ -1912,7 +1912,7 @@ isInvalidPartialApplication(ConstraintSystem &cs, // application level already. unsigned level = 0; if (!baseTy->is()) - level++; + ++level; if (auto *call = dyn_cast_or_null(cs.getParentExpr(UDE))) { level += 1; @@ -3192,7 +3192,7 @@ static void extendPreorderIndexMap( std::pair walkToExprPre(Expr *E) override { IndexMap[E] = Index; - Index++; + ++Index; return { true, E }; } }; diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 60cf395ea1fda..1883272bb23c4 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -5487,6 +5487,12 @@ BraceStmt *applyFunctionBuilderTransform( constraints::SolutionApplicationTarget)> rewriteTarget); +/// Determine whether the given closure expression should be type-checked +/// within the context of its enclosing expression. Otherwise, it will be +/// separately type-checked once its enclosing expression has determined all +/// of the parameter and result types without looking at the body. +bool shouldTypeCheckInEnclosingExpression(ClosureExpr *expr); + } // end namespace swift #endif // LLVM_SWIFT_SEMA_CONSTRAINT_SYSTEM_H diff --git a/lib/Sema/DerivedConformanceComparable.cpp b/lib/Sema/DerivedConformanceComparable.cpp index 176cc6247486c..b43bc32ba7234 100644 --- a/lib/Sema/DerivedConformanceComparable.cpp +++ b/lib/Sema/DerivedConformanceComparable.cpp @@ -131,7 +131,7 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v // the same case, binding variables for the left- and right-hand associated // values. for (auto elt : enumDecl->getAllElements()) { - elementCount++; + ++elementCount; // .(let l0, let l1, ...) SmallVector lhsPayloadVars; @@ -182,7 +182,7 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v // breaking out early if any pair is unequal. (same as Equatable synthesis.) // the else statement performs the lexicographic comparison. SmallVector statementsInCase; - for (size_t varIdx = 0; varIdx < lhsPayloadVars.size(); varIdx++) { + for (size_t varIdx = 0; varIdx < lhsPayloadVars.size(); ++varIdx) { auto lhsVar = lhsPayloadVars[varIdx]; auto lhsExpr = new (C) DeclRefExpr(lhsVar, DeclNameLoc(), /*implicit*/true); diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index eca9d63ff55e0..c55e9117207ae 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -253,7 +253,7 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl, // the same case, binding variables for the left- and right-hand associated // values. for (auto elt : enumDecl->getAllElements()) { - elementCount++; + ++elementCount; // .(let l0, let l1, ...) SmallVector lhsPayloadVars; @@ -305,7 +305,7 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl, // constructing long lists of autoclosure-wrapped conditions connected by // &&, which the type checker has more difficulty processing.) SmallVector statementsInCase; - for (size_t varIdx = 0; varIdx < lhsPayloadVars.size(); varIdx++) { + for (size_t varIdx = 0; varIdx < lhsPayloadVars.size(); ++varIdx) { auto lhsVar = lhsPayloadVars[varIdx]; auto lhsExpr = new (C) DeclRefExpr(lhsVar, DeclNameLoc(), /*implicit*/true); diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index e2d98db6b4750..1a5498e649014 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -354,7 +354,7 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) { CaseLabelItem(litPat), SourceLoc(), SourceLoc(), body, /*case body var decls*/ None)); - Idx++; + ++Idx; } auto anyPat = AnyPattern::createImplicit(C); diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index fe886389cd1a8..2ec7aacd2a964 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -1062,7 +1062,7 @@ void ImportResolver::findCrossImports( << "'\n"); if (ctx.Stats) - ctx.Stats->getFrontendCounters().NumCrossImportsChecked++; + ++ctx.Stats->getFrontendCounters().NumCrossImportsChecked; // Find modules we need to import. SmallVector names; @@ -1078,7 +1078,7 @@ void ImportResolver::findCrossImports( I.importLoc); if (ctx.Stats && !names.empty()) - ctx.Stats->getFrontendCounters().NumCrossImportsFound++; + ++ctx.Stats->getFrontendCounters().NumCrossImportsFound; // Add import statements. for (auto &name : names) { diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index 57c7c2ec1a1bb..a31a423af41b6 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -864,7 +864,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { if (DeclAndReason.D != Decls[index]) continue; - index++; + ++index; auto *const VD = DeclAndReason.D; const auto Reason = DeclAndReason.Reason; diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 8d5b52db5b505..de1584df14f7f 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -86,7 +86,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, bool walkToDeclPre(Decl *D) override { if (auto *closure = dyn_cast(D->getDeclContext())) - return closure->hasAppliedFunctionBuilder(); + return closure->wasTypeCheckedInEnclosingContext(); return false; } @@ -189,14 +189,14 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, // Otherwise, try to drill down through member calls for the purposes // of argument-matching code below. } else if (auto selfApply = dyn_cast(base)) { - uncurryLevel++; + ++uncurryLevel; base = selfApply->getSemanticFn(); if (auto calleeDRE = dyn_cast(base)) callee = calleeDRE->getDeclRef(); // Otherwise, check for a dynamic member. } else if (auto dynamicMRE = dyn_cast(base)) { - uncurryLevel++; + ++uncurryLevel; callee = dynamicMRE->getMember(); } @@ -1459,7 +1459,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E, // Don't walk into nested decls. bool walkToDeclPre(Decl *D) override { if (auto *closure = dyn_cast(D->getDeclContext())) - return closure->hasAppliedFunctionBuilder(); + return closure->wasTypeCheckedInEnclosingContext(); return false; } @@ -3978,7 +3978,7 @@ static void diagnoseUnintendedOptionalBehavior(const Expr *E, } SmallString<4> forceUnwrapString; - for (size_t i = 0; i < optionalityDifference; i++) + for (size_t i = 0; i < optionalityDifference; ++i) forceUnwrapString += "!"; Ctx.Diags.diagnose(subExpr->getLoc(), diag::force_optional_to_any) diff --git a/lib/Sema/PCMacro.cpp b/lib/Sema/PCMacro.cpp index 18e42143bec48..5d6075ef5b031 100644 --- a/lib/Sema/PCMacro.cpp +++ b/lib/Sema/PCMacro.cpp @@ -497,7 +497,7 @@ class Instrumenter : InstrumenterBase { buildPatternAndVariable(Expr *InitExpr) { SmallString<16> NameBuf; (Twine("pctmp") + Twine(TmpNameIndex)).toVector(NameBuf); - TmpNameIndex++; + ++TmpNameIndex; Expr *MaybeLoadInitExpr = nullptr; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 11638181661cf..934521b90670b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3868,7 +3868,7 @@ getTransposeOriginalFunctionType(AnyFunctionType *transposeFnType, Type selfType; if (isCurried && wrtSelf) { selfType = transposeResultTypes.front().getType(); - transposeResultTypesIndex++; + ++transposeResultTypesIndex; } else if (isCurried) { selfType = transposeFnType->getParams().front().getPlainType(); } diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 3e85ef471206e..3cc7d89b10253 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -524,7 +524,7 @@ class TypeRefinementContextBuilder : private ASTWalker { Context, Query, LastElement, CurrentTRC, NewConstraint); pushContext(TRC, ParentTy()); - NestedCount++; + ++NestedCount; } @@ -1128,7 +1128,8 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange, [](ASTNode Node, ASTWalker::ParentTy Parent) { if (Expr *ParentExpr = Parent.getAsExpr()) { auto *ParentClosure = dyn_cast(ParentExpr); - if (!ParentClosure || !ParentClosure->hasSingleExpressionBody()) { + if (!ParentClosure || + !ParentClosure->wasTypeCheckedInEnclosingContext()) { return false; } } else if (auto *ParentStmt = Parent.getAsStmt()) { @@ -1834,7 +1835,7 @@ static void fixItAvailableAttrRename(InFlightDiagnostic &diag, ++I; // Two or more arguments: Insert empty labels after the first one. - variadicArgsNum--; + --variadicArgsNum; I = argumentLabelIDs.insert(I, variadicArgsNum, Identifier()); I += variadicArgsNum; } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 8d3a82dbe8251..845ec35715ddb 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1320,9 +1320,8 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) { if (hadParameterError) return false; - // If the closure has a multi-statement body, we don't walk into it - // here. - if (!closure->hasSingleExpressionBody()) + // If we won't be checking the body of the closure, don't walk into it here. + if (!shouldTypeCheckInEnclosingExpression(closure)) return false; // Update the current DeclContext to be the closure we're about to @@ -2355,23 +2354,23 @@ bool TypeChecker::typeCheckBinding( if (!initializer->getType()) initializer->setType(ErrorType::get(Context)); - // If the type of the pattern is inferred, assign error types to the pattern - // and its variables, to prevent it from being referenced by the constraint - // system. + // Assign error types to the pattern and its variables, to prevent it from + // being referenced by the constraint system. if (patternType->hasUnresolvedType() || patternType->hasUnboundGenericType()) { pattern->setType(ErrorType::get(Context)); - pattern->forEachVariable([&](VarDecl *var) { - // Don't change the type of a variable that we've been able to - // compute a type for. - if (var->hasInterfaceType() && - !var->getType()->hasUnboundGenericType() && - !var->isInvalid()) - return; - - var->setInvalid(); - }); } + + pattern->forEachVariable([&](VarDecl *var) { + // Don't change the type of a variable that we've been able to + // compute a type for. + if (var->hasInterfaceType() && + !var->getType()->hasUnboundGenericType() && + !var->isInvalid()) + return; + + var->setInvalid(); + }); return true; } @@ -2492,11 +2491,12 @@ bool TypeChecker::typeCheckCondition(Expr *&expr, DeclContext *dc) { return !resultTy; } -bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, - Diag<> diagnosticForAlwaysTrue) { +bool TypeChecker::typeCheckConditionForStatement(LabeledConditionalStmt *stmt, + DeclContext *dc) { auto &Context = dc->getASTContext(); bool hadError = false; bool hadAnyFalsable = false; + auto cond = stmt->getCond(); for (auto &elt : cond) { if (elt.getKind() == StmtConditionElement::CK_Availability) { hadAnyFalsable = true; @@ -2504,6 +2504,7 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, } if (auto E = elt.getBooleanOrNull()) { + assert(!E->getType() && "the bool condition is already type checked"); hadError |= typeCheckCondition(E, dc); elt.setBoolean(E); hadAnyFalsable = true; @@ -2528,8 +2529,10 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, }; // Resolve the pattern. + assert(!elt.getPattern()->hasType() && + "the pattern binding condition is already type checked"); auto *pattern = TypeChecker::resolvePattern(elt.getPattern(), dc, - /*isStmtCondition*/true); + /*isStmtCondition*/ true); if (!pattern) { typeCheckPatternFailed(); continue; @@ -2554,13 +2557,28 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, hadAnyFalsable |= pattern->isRefutablePattern(); } - // If the binding is not refutable, and there *is* an else, reject it as // unreachable. if (!hadAnyFalsable && !hadError) { auto &diags = dc->getASTContext().Diags; - diags.diagnose(cond[0].getStartLoc(), diagnosticForAlwaysTrue); + Diag<> msg = diag::invalid_diagnostic; + switch (stmt->getKind()) { + case StmtKind::If: + msg = diag::if_always_true; + break; + case StmtKind::While: + msg = diag::while_always_true; + break; + case StmtKind::Guard: + msg = diag::guard_always_succeeds; + break; + default: + llvm_unreachable("unknown LabeledConditionalStmt kind"); + } + diags.diagnose(cond[0].getStartLoc(), msg); } + + stmt->setCond(cond); return false; } @@ -4039,3 +4057,7 @@ HasDynamicCallableAttributeRequest::evaluate(Evaluator &evaluator, return type->hasDynamicCallableAttribute(); }); } + +bool swift::shouldTypeCheckInEnclosingExpression(ClosureExpr *expr) { + return expr->hasSingleExpressionBody(); +} diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 146b59ee3117f..6529f0ca38818 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -764,7 +764,7 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator, ++NumLazyRequirementSignaturesLoaded; // FIXME: (transitional) increment the redundant "always-on" counter. if (ctx.Stats) - ctx.Stats->getFrontendCounters().NumLazyRequirementSignaturesLoaded++; + ++ctx.Stats->getFrontendCounters().NumLazyRequirementSignaturesLoaded; auto contextData = static_cast( ctx.getOrCreateLazyContextData(proto, nullptr)); @@ -830,6 +830,10 @@ NeedsNewVTableEntryRequest::evaluate(Evaluator &evaluator, if (!isa(dc)) return true; + // Destructors always use a fixed vtable entry. + if (isa(decl)) + return false; + assert(isa(decl) || isa(decl)); // Final members are always be called directly. @@ -2360,23 +2364,33 @@ NamingPatternRequest::evaluate(Evaluator &evaluator, VarDecl *VD) const { if (!namingPattern) { auto *canVD = VD->getCanonicalVarDecl(); namingPattern = canVD->NamingPattern; + } + if (!namingPattern) { + // Try type checking parent conditional statement. + if (auto parentStmt = VD->getParentPatternStmt()) { + if (auto LCS = dyn_cast(parentStmt)) { + TypeChecker::typeCheckConditionForStatement(LCS, VD->getDeclContext()); + namingPattern = VD->NamingPattern; + } + } + } + + if (!namingPattern) { // HACK: If no other diagnostic applies, emit a generic diagnostic about // a variable being unbound. We can't do better than this at the // moment because TypeCheckPattern does not reliably invalidate parts of // the pattern AST on failure. // // Once that's through, this will only fire during circular validation. - if (!namingPattern) { - if (VD->hasInterfaceType() && - !VD->isInvalid() && !VD->getParentPattern()->isImplicit()) { - VD->diagnose(diag::variable_bound_by_no_pattern, VD->getName()); - } - - VD->getParentPattern()->setType(ErrorType::get(Context)); - setBoundVarsTypeError(VD->getParentPattern(), Context); - return nullptr; + if (VD->hasInterfaceType() && + !VD->isInvalid() && !VD->getParentPattern()->isImplicit()) { + VD->diagnose(diag::variable_bound_by_no_pattern, VD->getName()); } + + VD->getParentPattern()->setType(ErrorType::get(Context)); + setBoundVarsTypeError(VD->getParentPattern(), Context); + return nullptr; } if (!namingPattern->hasType()) { diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 303624d42cc10..47a6568ff5a08 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -241,7 +241,7 @@ static bool isParamListRepresentableInObjC(const AbstractFunctionDecl *AFD, bool Diagnose = shouldDiagnoseObjCReason(Reason, ctx); bool IsObjC = true; unsigned NumParams = PL->size(); - for (unsigned ParamIndex = 0; ParamIndex != NumParams; ParamIndex++) { + for (unsigned ParamIndex = 0; ParamIndex != NumParams; ++ParamIndex) { auto param = PL->get(ParamIndex); // Swift Varargs are not representable in Objective-C. @@ -734,7 +734,7 @@ bool swift::isRepresentableInObjC( // 'initFoo'. if (auto *CD = dyn_cast(AFD)) if (CD->isObjCZeroParameterWithLongSelector()) - errorParameterIndex--; + --errorParameterIndex; while (errorParameterIndex > 0) { // Skip over trailing closures. diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 2240e7b762046..912161abf0f84 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1290,7 +1290,7 @@ class DeclChecker : public DeclVisitor { void visit(Decl *decl) { if (auto *Stats = getASTContext().Stats) - Stats->getFrontendCounters().NumDeclsTypechecked++; + ++Stats->getFrontendCounters().NumDeclsTypechecked; FrontendStatsTracer StatsTracer(getASTContext().Stats, "typecheck-decl", decl); diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index f79cf4b4d8113..ff7efa8af8ecb 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -301,7 +301,7 @@ static bool isEscapingAutoclosureArgument(const ConstructorDecl *init, Optional parameterIndex = None; auto params = init->getParameters(); - for (size_t i = 0; i < params->size(); i++) { + for (size_t i = 0; i < params->size(); ++i) { if (params->get(i)->getArgumentName() == argumentLabel) { parameterIndex = i; break; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 2eb55f5da0b62..b3b7a9dc8a89c 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1525,7 +1525,7 @@ isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req) { void MultiConformanceChecker::checkAllConformances() { bool anyInvalid = false; - for (unsigned I = 0, N = AllConformances.size(); I < N; I ++) { + for (unsigned I = 0, N = AllConformances.size(); I < N; ++I) { auto *conformance = AllConformances[I]; // Check this conformance and emit fixits if this is the last one in the pool. checkIndividualConformance(conformance, I == N - 1); @@ -1553,7 +1553,7 @@ void MultiConformanceChecker::checkAllConformances() { // Otherwise, backtrack to the last checker that has missing witnesses // and diagnose missing witnesses from there. for (auto It = AllUsedCheckers.rbegin(); It != AllUsedCheckers.rend(); - It ++) { + ++It) { if (!It->getLocalMissingWitness().empty()) { It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly); } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 6bd303691dbb2..696646b17ae28 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -140,10 +140,10 @@ namespace { } } - // If the closure has a single expression body or has had a function - // builder applied to it, we need to walk into it with a new sequence. + // If the closure was type checked within its enclosing context, + // we need to walk into it with a new sequence. // Otherwise, it'll have been separately type-checked. - if (CE->hasSingleExpressionBody() || CE->hasAppliedFunctionBuilder()) + if (CE->wasTypeCheckedInEnclosingContext()) CE->getBody()->walk(ContextualizeClosures(CE)); TypeChecker::computeCaptures(CE); @@ -318,7 +318,7 @@ class StmtChecker : public StmtVisitor { CaseStmt /*nullable*/ *FallthroughDest = nullptr; FallthroughStmt /*nullable*/ *PreviousFallthrough = nullptr; - SourceLoc EndTypeCheckLoc; + SourceLoc TargetTypeCheckLoc; /// Used to distinguish the first BraceStmt that starts a TopLevelCodeDecl. bool IsBraceStmtFromTopLevelDecl; @@ -501,7 +501,7 @@ class StmtChecker : public StmtVisitor { TypeCheckExprOptions options = {}; - if (EndTypeCheckLoc.isValid()) { + if (TargetTypeCheckLoc.isValid()) { assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) && "Diagnosing and AllowUnresolvedTypeVariables don't seem to mix"); options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables; @@ -625,9 +625,7 @@ class StmtChecker : public StmtVisitor { } Stmt *visitIfStmt(IfStmt *IS) { - StmtCondition C = IS->getCond(); - TypeChecker::typeCheckStmtCondition(C, DC, diag::if_always_true); - IS->setCond(C); + TypeChecker::typeCheckConditionForStatement(IS, DC); AddLabeledStmt ifNest(*this, IS); @@ -644,10 +642,8 @@ class StmtChecker : public StmtVisitor { } Stmt *visitGuardStmt(GuardStmt *GS) { - StmtCondition C = GS->getCond(); - TypeChecker::typeCheckStmtCondition(C, DC, diag::guard_always_succeeds); - GS->setCond(C); - + TypeChecker::typeCheckConditionForStatement(GS, DC); + AddLabeledStmt ifNest(*this, GS); Stmt *S = GS->getBody(); @@ -665,9 +661,7 @@ class StmtChecker : public StmtVisitor { } Stmt *visitWhileStmt(WhileStmt *WS) { - StmtCondition C = WS->getCond(); - TypeChecker::typeCheckStmtCondition(C, DC, diag::while_always_true); - WS->setCond(C); + TypeChecker::typeCheckConditionForStatement(WS, DC); AddLabeledStmt loopNest(*this, WS); Stmt *S = WS->getBody(); @@ -1563,12 +1557,19 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) { } for (auto &elem : BS->getElements()) { - if (auto *SubExpr = elem.dyn_cast()) { - SourceLoc Loc = SubExpr->getStartLoc(); - if (EndTypeCheckLoc.isValid() && - (Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc))) + if (TargetTypeCheckLoc.isValid()) { + if (SM.isBeforeInBuffer(TargetTypeCheckLoc, elem.getStartLoc())) break; + // NOTE: We need to check the character loc here because the target loc + // can be inside the last token of the node. i.e. string interpolation. + SourceLoc endLoc = Lexer::getLocForEndOfToken(SM, elem.getEndLoc()); + if (endLoc == TargetTypeCheckLoc || + SM.isBeforeInBuffer(endLoc, TargetTypeCheckLoc)) + continue; + } + + if (auto *SubExpr = elem.dyn_cast()) { // Type check the expression. TypeCheckExprOptions options = TypeCheckExprFlags::IsExprStmt; bool isDiscarded = (!getASTContext().LangOpts.Playground && @@ -1576,7 +1577,7 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) { if (isDiscarded) options |= TypeCheckExprFlags::IsDiscarded; - if (EndTypeCheckLoc.isValid()) { + if (TargetTypeCheckLoc.isValid()) { assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) && "Diagnosing and AllowUnresolvedTypeVariables don't seem to mix"); options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables; @@ -1607,22 +1608,12 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) { } if (auto *SubStmt = elem.dyn_cast()) { - SourceLoc Loc = SubStmt->getStartLoc(); - if (EndTypeCheckLoc.isValid() && - (Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc))) - break; - typeCheckStmt(SubStmt); elem = SubStmt; continue; } Decl *SubDecl = elem.get(); - SourceLoc Loc = SubDecl->getStartLoc(); - if (EndTypeCheckLoc.isValid() && - (Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc))) - break; - TypeChecker::typeCheckDecl(SubDecl); } @@ -1644,7 +1635,8 @@ static Type getFunctionBuilderType(FuncDecl *FD) { } bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) { - auto res = TypeChecker::typeCheckAbstractFunctionBodyUntil(AFD, SourceLoc()); + auto res = evaluateOrDefault(AFD->getASTContext().evaluator, + TypeCheckFunctionBodyRequest{AFD}, true); TypeChecker::checkFunctionErrorHandling(AFD); TypeChecker::computeCaptures(AFD); return res; @@ -1843,10 +1835,41 @@ static void checkClassConstructorBody(ClassDecl *classDecl, } } +bool TypeCheckFunctionBodyAtLocRequest::evaluate(Evaluator &evaluator, + AbstractFunctionDecl *AFD, + SourceLoc Loc) const { + ASTContext &ctx = AFD->getASTContext(); + + BraceStmt *body = AFD->getBody(); + if (!body || AFD->isBodyTypeChecked()) + return false; + + // Function builder doesn't support partial type checking. + if (auto *func = dyn_cast(AFD)) { + if (Type builderType = getFunctionBuilderType(func)) { + auto optBody = + TypeChecker::applyFunctionBuilderBodyTransform(func, builderType); + if (!optBody || !*optBody) + return true; + // Wire up the function body now. + AFD->setBody(*optBody, AbstractFunctionDecl::BodyKind::TypeChecked); + return false; + } + } + + if (ctx.LangOpts.EnableASTScopeLookup) + ASTScope::expandFunctionBody(AFD); + + StmtChecker SC(AFD); + SC.TargetTypeCheckLoc = Loc; + bool hadError = SC.typeCheckBody(body); + AFD->setBody(body, AbstractFunctionDecl::BodyKind::TypeChecked); + return hadError; +} + bool -TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator, - AbstractFunctionDecl *AFD, - SourceLoc endTypeCheckLoc) const { +TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, + AbstractFunctionDecl *AFD) const { ASTContext &ctx = AFD->getASTContext(); Optional timer; @@ -1903,7 +1926,6 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator, bool hadError = false; if (!alreadyTypeChecked) { StmtChecker SC(AFD); - SC.EndTypeCheckLoc = endTypeCheckLoc; hadError = SC.typeCheckBody(body); } @@ -1934,20 +1956,12 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator, AFD->setBody(body, AbstractFunctionDecl::BodyKind::TypeChecked); // If nothing went wrong yet, perform extra checking. - if (!hadError && endTypeCheckLoc.isInvalid()) + if (!hadError) performAbstractFuncDeclDiagnostics(AFD); return hadError; } -bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc) { - return evaluateOrDefault( - AFD->getASTContext().evaluator, - TypeCheckFunctionBodyUntilRequest{AFD, EndTypeCheckLoc}, - true); -} - bool TypeChecker::typeCheckClosureBody(ClosureExpr *closure) { checkParameterAttributes(closure->getParameters()); diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index c5c195b581eca..adc999956ed4e 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -1821,7 +1821,7 @@ synthesizeAccessorBody(AbstractFunctionDecl *fn, void *) { auto &ctx = accessor->getASTContext(); if (ctx.Stats) - ctx.Stats->getFrontendCounters().NumAccessorBodiesSynthesized++; + ++ctx.Stats->getFrontendCounters().NumAccessorBodiesSynthesized; switch (accessor->getAccessorKind()) { case AccessorKind::Get: @@ -1850,7 +1850,7 @@ static void finishImplicitAccessor(AccessorDecl *accessor, accessor->setImplicit(); if (ctx.Stats) - ctx.Stats->getFrontendCounters().NumAccessorsSynthesized++; + ++ctx.Stats->getFrontendCounters().NumAccessorsSynthesized; if (doesAccessorHaveBody(accessor)) accessor->setBodySynthesizer(&synthesizeAccessorBody); diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp index dd5e04c6a590d..7b574e2562ef9 100644 --- a/lib/Sema/TypeCheckSwitchStmt.cpp +++ b/lib/Sema/TypeCheckSwitchStmt.cpp @@ -710,7 +710,7 @@ namespace { if (args != argEnd) { labelSpaces.push_back( std::pair(*args, param)); - args++; + ++args; } else labelSpaces.push_back( std::pair(Identifier(), param)); @@ -1336,7 +1336,7 @@ namespace { for (size_t rowIdx = 0, colIdx = 0; rowIdx < matrix.size(); ++rowIdx) { if (rowIdx != 0 && (rowIdx % stride) == 0) { - colIdx++; + ++colIdx; } matrix[rowIdx].push_back(columnVect[colIdx]); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 9bc5d3f264acd..8c6753d888d95 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -902,7 +902,7 @@ Type TypeChecker::applyUnboundGenericArguments( // Realize the types of the generic arguments and add them to the // substitution map. - for (unsigned i = 0, e = genericArgs.size(); i < e; i++) { + for (unsigned i = 0, e = genericArgs.size(); i < e; ++i) { auto origTy = genericSig->getInnermostGenericParams()[i]; auto substTy = genericArgs[i]; @@ -1694,7 +1694,7 @@ bool TypeChecker::validateType(TypeLoc &Loc, TypeResolution resolution) { return Loc.isError(); if (auto *Stats = resolution.getASTContext().Stats) - Stats->getFrontendCounters().NumTypesValidated++; + ++Stats->getFrontendCounters().NumTypesValidated; auto type = resolution.resolveType(Loc.getTypeRepr()); Loc.setType(type); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index faf691e6fa501..230adc8ca4e47 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -540,11 +540,13 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { return !resultTy; } -bool swift::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc) { +bool swift::typeCheckAbstractFunctionBodyAtLoc(AbstractFunctionDecl *AFD, + SourceLoc TargetLoc) { auto &Ctx = AFD->getASTContext(); DiagnosticSuppression suppression(Ctx.Diags); - return !TypeChecker::typeCheckAbstractFunctionBodyUntil(AFD, EndTypeCheckLoc); + return !evaluateOrDefault(Ctx.evaluator, + TypeCheckFunctionBodyAtLocRequest{AFD, TargetLoc}, + true); } bool swift::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index cbae4220752e6..c3bd2d9384d70 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -547,8 +547,6 @@ bool typesSatisfyConstraint(Type t1, Type t2, bool openArchetypes, /// of the function, set the result type of the expression to that sugar type. Expr *substituteInputSugarTypeForResult(ApplyExpr *E); -bool typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc); bool typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD); /// Try to apply the function builder transform of the given builder type @@ -756,15 +754,14 @@ void checkSwitchExhaustiveness(const SwitchStmt *stmt, const DeclContext *DC, /// \returns true if an error occurred, false otherwise. bool typeCheckCondition(Expr *&expr, DeclContext *dc); -/// Type check the given 'if' or 'while' statement condition, which -/// either converts an expression to a logic value or bind variables to the -/// contents of an Optional. +/// Type check the given 'if', 'while', or 'guard' statement condition. /// -/// \param cond The condition to type-check, which will be modified in place. +/// \param stmt The conditional statement to type-check, which will be modified +/// in place. /// /// \returns true if an error occurred, false otherwise. -bool typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, - Diag<> diagnosticForAlwaysTrue); +bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt, + DeclContext *dc); /// Determine the semantics of a checked cast operation. /// diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ed348fb28b46d..028919584dfd6 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -478,7 +478,7 @@ ModuleFile::readConformanceChecked(llvm::BitstreamCursor &Cursor, assert(next.Kind == llvm::BitstreamEntry::Record); if (auto *Stats = getContext().Stats) - Stats->getFrontendCounters().NumConformancesDeserialized++; + ++Stats->getFrontendCounters().NumConformancesDeserialized; unsigned kind = fatalIfUnexpected(Cursor.readRecord(next.ID, scratch)); switch (kind) { @@ -4510,7 +4510,7 @@ DeclDeserializer::getDeclCheckedImpl( } if (auto s = ctx.Stats) - s->getFrontendCounters().NumDeclsDeserialized++; + ++s->getFrontendCounters().NumDeclsDeserialized; // FIXME: @_dynamicReplacement(for:) includes a reference to another decl, // usually in the same type, and that can result in this decl being @@ -5637,7 +5637,7 @@ Expected ModuleFile::getTypeChecked(TypeID TID) { Expected TypeDeserializer::getTypeCheckedImpl() { if (auto s = ctx.Stats) - s->getFrontendCounters().NumTypesDeserialized++; + ++s->getFrontendCounters().NumTypesDeserialized; llvm::BitstreamEntry entry = MF.fatalIfUnexpected(MF.DeclTypeCursor.advance()); diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 5fbd28c55672b..a930d24d3d0b7 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -79,6 +79,8 @@ static Optional fromStableVTableEntryKind(unsigned value) { switch (value) { case SIL_VTABLE_ENTRY_NORMAL: return SILVTable::Entry::Kind::Normal; + case SIL_VTABLE_ENTRY_NORMAL_NON_OVERRIDDEN: + return SILVTable::Entry::Kind::NormalNonOverridden; case SIL_VTABLE_ENTRY_INHERITED: return SILVTable::Entry::Kind::Inherited; case SIL_VTABLE_ENTRY_OVERRIDE: return SILVTable::Entry::Kind::Override; default: return None; @@ -739,7 +741,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, return fn; } - NumDeserializedFunc++; + ++NumDeserializedFunc; assert(!(fn->getGenericEnvironment() && !fn->empty()) && "function already has context generic params?!"); @@ -1457,7 +1459,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, assert(substConventions.getNumSILArguments() == ListOfValues.size() && "Argument number mismatch in ApplyInst."); SmallVector Args; - for (unsigned I = 0, E = ListOfValues.size(); I < E; I++) + for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) Args.push_back(getLocalValue(ListOfValues[I], substConventions.getSILArgumentType( I, Builder.getTypeExpansionContext()))); @@ -1494,7 +1496,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, assert(substConventions.getNumSILArguments() == ListOfValues.size() && "Argument number mismatch in ApplyInst."); SmallVector Args; - for (unsigned I = 0, E = ListOfValues.size(); I < E; I++) + for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) Args.push_back(getLocalValue(ListOfValues[I], substConventions.getSILArgumentType( I, Builder.getTypeExpansionContext()))); @@ -1527,7 +1529,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SILValue FnVal = getLocalValue(ValID, FnTy); SmallVector Args; unsigned unappliedArgs = numArgs - ListOfValues.size(); - for (unsigned I = 0, E = ListOfValues.size(); I < E; I++) + for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) Args.push_back(getLocalValue( ListOfValues[I], fnConv.getSILArgumentType(I + unappliedArgs, @@ -2084,7 +2086,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, TupleType *TT = Ty->castTo(); assert(TT && "Type of a TupleInst should be TupleType"); SmallVector OpList; - for (unsigned I = 0, E = ListOfValues.size(); I < E; I++) { + for (unsigned I = 0, E = ListOfValues.size(); I < E; ++I) { Type EltTy = TT->getElement(I).getType(); OpList.push_back( getLocalValue(ListOfValues[I], @@ -3081,7 +3083,7 @@ void SILDeserializer::getAllVTables() { if (!VTableList) return; - for (unsigned I = 0, E = VTables.size(); I < E; I++) + for (unsigned I = 0, E = VTables.size(); I < E; ++I) readVTable(I+1); } @@ -3361,7 +3363,7 @@ llvm::Expected void SILDeserializer::getAllWitnessTables() { if (!WitnessTableList) return; - for (unsigned I = 0, E = WitnessTables.size(); I < E; I++) { + for (unsigned I = 0, E = WitnessTables.size(); I < E; ++I) { auto maybeTable = readWitnessTableChecked(I + 1, nullptr); if (!maybeTable) { if (maybeTable.errorIsA()) { @@ -3500,7 +3502,7 @@ readDefaultWitnessTable(DeclID WId, SILDefaultWitnessTable *existingWt) { void SILDeserializer::getAllDefaultWitnessTables() { if (!DefaultWitnessTableList) return; - for (unsigned I = 0, E = DefaultWitnessTables.size(); I < E; I++) + for (unsigned I = 0, E = DefaultWitnessTables.size(); I < E; ++I) readDefaultWitnessTable(I + 1, nullptr); } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index dd26ab5e44062..524c264c0406f 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -2190,6 +2190,30 @@ TypeDecl *ModuleFile::lookupLocalType(StringRef MangledName) { return cast(getDecl(*iter)); } +std::unique_ptr +ModuleFile::getModuleName(ASTContext &Ctx, StringRef modulePath, + std::string &Name) { + // Open the module file + auto &fs = *Ctx.SourceMgr.getFileSystem(); + auto moduleBuf = fs.getBufferForFile(modulePath); + if (!moduleBuf) + return nullptr; + + // Load the module file without validation. + std::unique_ptr loadedModuleFile; + ExtendedValidationInfo ExtInfo; + bool isFramework = false; + serialization::ValidationInfo loadInfo = + ModuleFile::load(modulePath.str(), + std::move(moduleBuf.get()), + nullptr, + nullptr, + /*isFramework*/isFramework, loadedModuleFile, + &ExtInfo); + Name = loadedModuleFile->Name; + return std::move(loadedModuleFile->ModuleInputBuffer); +} + OpaqueTypeDecl *ModuleFile::lookupOpaqueResultType(StringRef MangledName) { PrettyStackTraceModuleFile stackEntry(*this); diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index 0b239c86cbbcc..9f233aa1f89dc 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -106,6 +106,10 @@ class ModuleFile StringRef MiscVersion; public: + static std::unique_ptr getModuleName(ASTContext &Ctx, + StringRef modulePath, + std::string &Name); + /// Represents another module that has been imported as a dependency. class Dependency { public: diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 09f53e1658124..c5ac6129a8889 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 557; // COW instructions +const uint16_t SWIFTMODULE_VERSION_MINOR = 558; // SILVTable entry kind for non-overridden entries /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index a0e0ab5a41937..154e50886fb63 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -51,6 +51,7 @@ using SILLinkageField = BCFixed<4>; enum SILVTableEntryKindEncoding : uint8_t { SIL_VTABLE_ENTRY_NORMAL, + SIL_VTABLE_ENTRY_NORMAL_NON_OVERRIDDEN, SIL_VTABLE_ENTRY_INHERITED, SIL_VTABLE_ENTRY_OVERRIDE, }; diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 0ba068798906f..5c2da231e1263 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -73,6 +73,8 @@ static unsigned toStableSILLinkage(SILLinkage linkage) { static unsigned toStableVTableEntryKind(SILVTable::Entry::Kind kind) { switch (kind) { case SILVTable::Entry::Kind::Normal: return SIL_VTABLE_ENTRY_NORMAL; + case SILVTable::Entry::Kind::NormalNonOverridden: + return SIL_VTABLE_ENTRY_NORMAL_NON_OVERRIDDEN; case SILVTable::Entry::Kind::Inherited: return SIL_VTABLE_ENTRY_INHERITED; case SILVTable::Entry::Kind::Override: return SIL_VTABLE_ENTRY_OVERRIDE; } diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index e8ce91f5936ae..6a8c3be82b06b 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -275,6 +275,12 @@ std::error_code SerializedModuleLoaderBase::openModuleDocFileIfPresent( return std::error_code(); } +std::unique_ptr +SerializedModuleLoaderBase::getModuleName(ASTContext &Ctx, StringRef modulePath, + std::string &Name) { + return ModuleFile::getModuleName(Ctx, modulePath, Name); +} + std::error_code SerializedModuleLoaderBase::openModuleSourceInfoFileIfPresent( AccessPathElem ModuleID, diff --git a/lib/SymbolGraphGen/AvailabilityMixin.cpp b/lib/SymbolGraphGen/AvailabilityMixin.cpp new file mode 100644 index 0000000000000..3ac0ecaba3d05 --- /dev/null +++ b/lib/SymbolGraphGen/AvailabilityMixin.cpp @@ -0,0 +1,187 @@ +//===--- AvailabilityMixin.cpp - Symbol Graph Symbol Availability ---------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "AvailabilityMixin.h" +#include "JSON.h" + +using namespace swift; +using namespace symbolgraphgen; + +namespace { +StringRef getDomain(const AvailableAttr &AvAttr) { + switch (AvAttr.getPlatformAgnosticAvailability()) { + // SPM- and Swift-specific availability. + case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific: + return { "SwiftPM" }; + case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific: + case PlatformAgnosticAvailabilityKind::UnavailableInSwift: + return { "Swift" }; + // Although these are in the agnostic kinds, they are actually a signal + // that there is either platform-specific or completely platform-agnostic. + // They'll be handled below. + case PlatformAgnosticAvailabilityKind::Deprecated: + case PlatformAgnosticAvailabilityKind::Unavailable: + case PlatformAgnosticAvailabilityKind::None: + break; + } + + // Platform-specific availability. + switch (AvAttr.Platform) { + case swift::PlatformKind::iOS: + return { "iOS" }; + case swift::PlatformKind::macCatalyst: + return { "macCatalyst" }; + case swift::PlatformKind::OSX: + return { "macOS" }; + case swift::PlatformKind::tvOS: + return { "tvOS" }; + case swift::PlatformKind::watchOS: + return { "watchOS" }; + case swift::PlatformKind::iOSApplicationExtension: + return { "iOSAppExtension" }; + case swift::PlatformKind::macCatalystApplicationExtension: + return { "macCatalystAppExtension" }; + case swift::PlatformKind::OSXApplicationExtension: + return { "macOSAppExtension" }; + case swift::PlatformKind::tvOSApplicationExtension: + return { "tvOSAppExtension" }; + case swift::PlatformKind::watchOSApplicationExtension: + return { "watchOSAppExtension" }; + case swift::PlatformKind::none: + return { "*" }; + } + llvm_unreachable("invalid platform kind"); +} +} // end anonymous namespace + +Availability::Availability(const AvailableAttr &AvAttr) + : Domain(getDomain(AvAttr)), + Introduced(AvAttr.Introduced), + Deprecated(AvAttr.Deprecated), + Obsoleted(AvAttr.Obsoleted), + Message(AvAttr.Message), + Renamed(AvAttr.Rename), + IsUnconditionallyDeprecated(AvAttr.isUnconditionallyDeprecated()) { + assert(!Domain.empty()); +} + +void +Availability::updateFromDuplicate(const Availability &Other) { + assert(Domain == Other.Domain); + + // The highest `introduced` version always wins + // regardless of the order in which they appeared in the source. + if (!Introduced) { + Introduced = Other.Introduced; + } else if (Other.Introduced && *Other.Introduced > *Introduced) { + Introduced = Other.Introduced; + } + + // The `deprecated` version that appears last in the source always wins, + // allowing even to erase a previous deprecated. + Deprecated = Other.Deprecated; + + // Same for `deprecated` with no version. + IsUnconditionallyDeprecated = Other.IsUnconditionallyDeprecated; + + // Same for `obsoleted`. + Obsoleted = Other.Obsoleted; + + // The `message` that appears last in the source always wins. + Message = Other.Message; + + // Same for `renamed`. + Renamed = Other.Renamed; +} + +void +Availability::updateFromParent(const Availability &Parent) { + assert(Domain == Parent.Domain); + + // Allow filling, but never replace a child's existing `introduced` + // availability because it can never be less available than the parent anyway. + // + // e.g. you cannot write this: + // @available(macos, introduced: 10.15) + // struct S { + // @available(macos, introduced: 10.14) + // func foo() {} + // } + // + // So the child's `introduced` availability will always + // be >= the parent's. + if (!Introduced) { + Introduced = Parent.Introduced; + } + + // Allow filling from the parent. + // For replacement, we will consider a parent's + // earlier deprecation to supercede a child's later deprecation. + if (!Deprecated) { + Deprecated = Parent.Deprecated; + } else if (Parent.Deprecated && *Parent.Deprecated < *Deprecated) { + Deprecated = Parent.Deprecated; + } + + // The above regarding `deprecated` also will apply to `obsoleted`. + if (!Obsoleted) { + Obsoleted = Parent.Obsoleted; + } else if (Parent.Obsoleted && *Parent.Obsoleted < *Obsoleted) { + Obsoleted = Parent.Obsoleted; + } + + // Never replace or fill a child's `message` with a parent's because + // there may be context at the parent that doesn't apply at the child, + // i.e. it might not always make sense. + + // Never replace or fill a child's `renamed` field because it + // doesn't make sense. Just because a parent is renamed doesn't + // mean its child is renamed to the same thing. + + // If a parent is unconditionally deprecated, then so are all + // of its children. + IsUnconditionallyDeprecated |= Parent.IsUnconditionallyDeprecated; +} + +void Availability::serialize(llvm::json::OStream &OS) const { + OS.object([&](){ + OS.attribute("domain", Domain); + if (Introduced) { + AttributeRAII IntroducedAttribute("introduced", OS); + symbolgraphgen::serialize(*Introduced, OS); + } + if (Deprecated) { + AttributeRAII DeprecatedAttribute("deprecated", OS); + symbolgraphgen::serialize(*Deprecated, OS); + } + if (Obsoleted) { + AttributeRAII ObsoletedAttribute("obsoleted", OS); + symbolgraphgen::serialize(*Obsoleted, OS); + } + if (!Message.empty()) { + OS.attribute("message", Message); + } + if (!Renamed.empty()) { + OS.attribute("renamed", Renamed); + } + if (IsUnconditionallyDeprecated) { + OS.attribute("isUnconditionallyDeprecated", true); + } + }); // end availability object +} + +bool Availability::empty() const { + return !Introduced.hasValue() && + !Deprecated.hasValue() && + !Obsoleted.hasValue() && + !IsUnconditionallyDeprecated; +} diff --git a/lib/SymbolGraphGen/AvailabilityMixin.h b/lib/SymbolGraphGen/AvailabilityMixin.h new file mode 100644 index 0000000000000..34fc2bc34b2c2 --- /dev/null +++ b/lib/SymbolGraphGen/AvailabilityMixin.h @@ -0,0 +1,78 @@ +//===--- AvailabilityMixin.h - Symbol Graph Symbol Availability -----------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_SYMBOLGRAPHGEN_AVAILABILITYMIXIN_H +#define SWIFT_SYMBOLGRAPHGEN_AVAILABILITYMIXIN_H + +#include "swift/AST/Attr.h" +#include "swift/AST/Module.h" +#include "swift/Basic/LLVM.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/VersionTuple.h" + +namespace swift { +namespace symbolgraphgen { + +/// A mixin representing a symbol's effective availability in its module. +struct Availability { + /// The domain to which the availability applies, such as + /// an operating system or Swift itself. + StringRef Domain; + + /// The domain version at which a symbol was introduced if defined. + Optional Introduced; + + /// The domain version at which a symbol was deprecated if defined. + Optional Deprecated; + + /// The domain version at which a symbol was obsoleted if defined. + Optional Obsoleted; + + /// An optional message regarding a symbol's availability. + StringRef Message; + + /// The informal spelling of a new replacement symbol if defined. + StringRef Renamed; + + /// If \c true, is unconditionally deprecated in this \c Domain. + bool IsUnconditionallyDeprecated; + + Availability(const AvailableAttr &AvAttr); + + /// Update this availability from a duplicate @available + /// attribute with the same platform on the same declaration. + /// + /// e.g. + /// @available(macOS, deprecated: 10.15) + /// @available(macOS, deprecated: 10.12) + /// func foo() {} + /// + /// Updates the first availability using the second's information. + void updateFromDuplicate(const Availability &Other); + + /// Update this availability from a parent context's availability. + void updateFromParent(const Availability &Parent); + + /// Returns true if this availability item doesn't have + /// any introduced version, deprecated version, obsoleted version, + /// or uncondtional deprecation status. + /// + /// \note \c message and \c renamed are not considered. + bool empty() const; + + void serialize(llvm::json::OStream &OS) const; +}; + +} // end namespace symbolgraphgen +} // end namespace swift + +#endif // SWIFT_SYMBOLGRAPHGEN_AVAILABILITYMIXIN_H diff --git a/lib/SymbolGraphGen/CMakeLists.txt b/lib/SymbolGraphGen/CMakeLists.txt index 64f34c90254b7..57159b83dc59b 100644 --- a/lib/SymbolGraphGen/CMakeLists.txt +++ b/lib/SymbolGraphGen/CMakeLists.txt @@ -1,4 +1,5 @@ add_swift_host_library(swiftSymbolGraphGen STATIC + AvailabilityMixin.cpp DeclarationFragmentPrinter.cpp Edge.cpp JSON.cpp diff --git a/lib/SymbolGraphGen/Symbol.cpp b/lib/SymbolGraphGen/Symbol.cpp index 2e4c12fc3766f..94d3c5bdb2801 100644 --- a/lib/SymbolGraphGen/Symbol.cpp +++ b/lib/SymbolGraphGen/Symbol.cpp @@ -16,6 +16,7 @@ #include "swift/AST/ParameterList.h" #include "swift/AST/USRGeneration.h" #include "swift/Basic/SourceManager.h" +#include "AvailabilityMixin.h" #include "JSON.h" #include "Symbol.h" #include "SymbolGraph.h" @@ -325,98 +326,89 @@ void Symbol::serializeLocationMixin(llvm::json::OStream &OS) const { }); } -llvm::Optional -Symbol::getDomain(PlatformAgnosticAvailabilityKind AgnosticKind, - PlatformKind Kind) const { - switch (AgnosticKind) { - // SPM- and Swift-specific availability. - case PlatformAgnosticAvailabilityKind::PackageDescriptionVersionSpecific: - return { "SwiftPM" }; - case PlatformAgnosticAvailabilityKind::SwiftVersionSpecific: - case PlatformAgnosticAvailabilityKind::UnavailableInSwift: - return { "Swift" }; - // Although these are in the agnostic kinds, they are actually a signal - // that there is either platform-specific or completely platform-agnostic. - // They'll be handled below. - case PlatformAgnosticAvailabilityKind::Deprecated: - case PlatformAgnosticAvailabilityKind::Unavailable: - case PlatformAgnosticAvailabilityKind::None: - break; +namespace { +/// Get the availabilities for each domain on a declaration without walking +/// up the parent hierarchy. +/// +/// \param D The declaration whose availabilities the method will collect. +/// \param Availabilities The domain -> availability map that will be updated. +/// \param IsParent If \c true\c, will update or fill availabilities for a given +/// domain with different "inheriting" rules rather than filling from +/// duplicate \c \@available attributes on the same declaration. +void getAvailabilities(const Decl *D, + llvm::StringMap &Availabilities, + bool IsParent) { + // DeclAttributes is a linked list in reverse order from where they + // appeared in the source. Let's re-reverse them. + SmallVector AvAttrs; + for (const auto *Attr : D->getAttrs()) { + if (const auto *AvAttr = dyn_cast(Attr)) { + AvAttrs.push_back(AvAttr); + } } + std::reverse(AvAttrs.begin(), AvAttrs.end()); - // Platform-specific availability. - switch (Kind) { - case swift::PlatformKind::iOS: - return { "iOS" }; - case swift::PlatformKind::macCatalyst: - return { "macCatalyst" }; - case swift::PlatformKind::OSX: - return { "macOS" }; - case swift::PlatformKind::tvOS: - return { "tvOS" }; - case swift::PlatformKind::watchOS: - return { "watchOS" }; - case swift::PlatformKind::iOSApplicationExtension: - return { "iOSAppExtension" }; - case swift::PlatformKind::macCatalystApplicationExtension: - return { "macCatalystAppExtension" }; - case swift::PlatformKind::OSXApplicationExtension: - return { "macOSAppExtension" }; - case swift::PlatformKind::tvOSApplicationExtension: - return { "tvOSAppExtension" }; - case swift::PlatformKind::watchOSApplicationExtension: - return { "watchOSAppExtension" }; - // Platform-agnostic availability, such as "unconditionally deprecated" - // or "unconditionally obsoleted". - case swift::PlatformKind::none: - return None; + // Now go through them in source order. + for (auto *AvAttr : AvAttrs) { + Availability NewAvailability(*AvAttr); + if (NewAvailability.empty()) { + continue; + } + auto ExistingAvailability = Availabilities.find(NewAvailability.Domain); + if (ExistingAvailability != Availabilities.end()) { + // There are different rules for filling in missing components + // or replacing existing components from a parent's @available + // attribute compared to duplicate @available attributes on the + // same declaration. + // See the respective methods below for an explanation for the + // replacement/filling rules. + if (IsParent) { + ExistingAvailability->getValue().updateFromParent(NewAvailability); + } else { + ExistingAvailability->getValue().updateFromDuplicate(NewAvailability); + } + } else { + // There are no availabilities for this domain yet, so either + // inherit the parent's in its entirety or set it from this declaration. + Availabilities.insert(std::make_pair(NewAvailability.Domain, + NewAvailability)); + } } - llvm_unreachable("invalid platform kind"); } -void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const { - SmallVector Availabilities; - for (const auto *Attr : VD->getAttrs()) { - if (const auto *AvAttr = dyn_cast(Attr)) { - Availabilities.push_back(AvAttr); +/// Get the availabilities of a declaration, considering all of its +/// parent context's except for the module. +void getInheritedAvailabilities(const Decl *D, +llvm::StringMap &Availabilities) { + getAvailabilities(D, Availabilities, /*IsParent*/false); + + auto CurrentContext = D->getDeclContext(); + while (CurrentContext) { + if (const auto *Parent = CurrentContext->getAsDecl()) { + if (isa(Parent)) { + return; + } + getAvailabilities(Parent, Availabilities, /*IsParent*/true); } + CurrentContext = CurrentContext->getParent(); } +} + +} // end anonymous namespace + +void Symbol::serializeAvailabilityMixin(llvm::json::OStream &OS) const { + llvm::StringMap Availabilities; + getInheritedAvailabilities(VD, Availabilities); + if (Availabilities.empty()) { return; } - OS.attributeArray("availability", [&](){ - for (const auto *AvAttr : Availabilities) { - OS.object([&](){ - auto Domain = getDomain(AvAttr->getPlatformAgnosticAvailability(), - AvAttr->Platform); - if (Domain) { - OS.attribute("domain", *Domain); - } - if (AvAttr->Introduced) { - AttributeRAII Introduced("introduced", OS); - symbolgraphgen::serialize(*AvAttr->Introduced, OS); - } - if (AvAttr->Deprecated) { - AttributeRAII Deprecated("deprecated", OS); - symbolgraphgen::serialize(*AvAttr->Deprecated, OS); - } - if (AvAttr->Obsoleted) { - AttributeRAII Obsoleted("obsoleted", OS); - symbolgraphgen::serialize(*AvAttr->Obsoleted, OS); - } - if (!AvAttr->Message.empty()) { - OS.attribute("message", AvAttr->Message); - } - if (!AvAttr->Rename.empty()) { - OS.attribute("renamed", AvAttr->Rename); - } - if (AvAttr->isUnconditionallyDeprecated()) { - OS.attribute("isUnconditionallyDeprecated", true); - } - }); // end availability object + OS.attributeArray("availability", [&]{ + for (const auto &Availability : Availabilities) { + Availability.getValue().serialize(OS); } - }); // end availability: [] + }); } void Symbol::serialize(llvm::json::OStream &OS) const { diff --git a/lib/SymbolGraphGen/Symbol.h b/lib/SymbolGraphGen/Symbol.h index 4e5987e5b0274..2be6765157b8c 100644 --- a/lib/SymbolGraphGen/Symbol.h +++ b/lib/SymbolGraphGen/Symbol.h @@ -21,7 +21,7 @@ namespace swift { namespace symbolgraphgen { -struct AvailabilityDomain; +struct Availability; struct SymbolGraphASTWalker; struct SymbolGraph; @@ -68,10 +68,6 @@ class Symbol { void serializeLocationMixin(llvm::json::OStream &OS) const; - llvm::Optional - getDomain(PlatformAgnosticAvailabilityKind AgnosticKind, - PlatformKind Kind) const; - void serializeAvailabilityMixin(llvm::json::OStream &OS) const; public: diff --git a/lib/SymbolGraphGen/SymbolGraph.cpp b/lib/SymbolGraphGen/SymbolGraph.cpp index 991fb7db23a8f..44aee2e537f49 100644 --- a/lib/SymbolGraphGen/SymbolGraph.cpp +++ b/lib/SymbolGraphGen/SymbolGraph.cpp @@ -60,7 +60,7 @@ PrintOptions SymbolGraph::getDeclarationFragmentsPrintOptions() const { Opts.PrintUserInaccessibleAttrs = false; Opts.SkipPrivateStdlibDecls = true; Opts.SkipUnderscoredStdlibProtocols = true; - Opts.PrintGenericRequirements = false; + Opts.PrintGenericRequirements = true; Opts.ExclusiveAttrList.clear(); @@ -90,6 +90,7 @@ SymbolGraph::getSubHeadingDeclarationFragmentsPrintOptions() const { Options.PrintDefaultArgumentValue = false; Options.PrintEmptyArgumentNames = false; Options.PrintOverrideKeyword = false; + Options.PrintGenericRequirements = false; return Options; } diff --git a/lib/Syntax/SyntaxData.cpp b/lib/Syntax/SyntaxData.cpp index 7861f41aee51e..440a9a076fc3d 100644 --- a/lib/Syntax/SyntaxData.cpp +++ b/lib/Syntax/SyntaxData.cpp @@ -57,7 +57,7 @@ void SyntaxData::dump() const { dump(llvm::errs()); } RC SyntaxData::getPreviousNode() const { if (size_t N = getIndexInParent()) { if (hasParent()) { - for (size_t I = N - 1; ; I--) { + for (size_t I = N - 1; ; --I) { if (auto C = getParent()->getChild(I)) { if (C->getRaw()->isPresent() && C->getFirstToken()) return C; @@ -73,7 +73,7 @@ RC SyntaxData::getPreviousNode() const { RC SyntaxData::getNextNode() const { if (hasParent()) { for (size_t I = getIndexInParent() + 1, N = Parent->getNumChildren(); - I != N; I++) { + I != N; ++I) { if (auto C = getParent()->getChild(I)) { if (C->getRaw()->isPresent() && C->getFirstToken()) return C; diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index d44ec419cde63..5ffd59ec41290 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -623,7 +623,7 @@ void TBDGenVisitor::visitDefaultArguments(ValueDecl *VD, ParameterList *PL) { for (auto *param : *PL) { if (param->isDefaultArgument()) addSymbol(SILDeclRef::getDefaultArgGenerator(VD, index)); - index++; + ++index; } } diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 05123d1d8e127..6feafeddbc345 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -2,6 +2,20 @@ include(AddSwift) include(SwiftSource) +function(is_darwin_based_sdk sdk_name out_var) + if ("${sdk_name}" STREQUAL "OSX" OR + "${sdk_name}" STREQUAL "IOS" OR + "${sdk_name}" STREQUAL "IOS_SIMULATOR" OR + "${sdk_name}" STREQUAL "TVOS" OR + "${sdk_name}" STREQUAL "TVOS_SIMULATOR" OR + "${sdk_name}" STREQUAL "WATCHOS" OR + "${sdk_name}" STREQUAL "WATCHOS_SIMULATOR") + set(${out_var} TRUE PARENT_SCOPE) + else() + set(${out_var} FALSE PARENT_SCOPE) + endif() +endfunction() + function(add_dependencies_multiple_targets) cmake_parse_arguments( ADMT # prefix @@ -351,6 +365,8 @@ function(_add_target_variant_link_flags) list(APPEND link_libraries "pthread" "dl") elseif("${LFLAGS_SDK}" STREQUAL "FREEBSD") list(APPEND link_libraries "pthread") + elseif("${LFLAGS_SDK}" STREQUAL "OPENBSD") + list(APPEND link_libraries "pthread") elseif("${LFLAGS_SDK}" STREQUAL "CYGWIN") # No extra libraries required. elseif("${LFLAGS_SDK}" STREQUAL "WINDOWS") diff --git a/stdlib/include/llvm-c/DataTypes.h b/stdlib/include/llvm-c/DataTypes.h deleted file mode 100644 index 0f27ba81865e0..0000000000000 --- a/stdlib/include/llvm-c/DataTypes.h +++ /dev/null @@ -1,84 +0,0 @@ -/*===-- include/llvm-c/DataTypes.h - Define fixed size types ------*- C -*-===*\ -|* *| -|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| -|* Exceptions. *| -|* See https://llvm.org/LICENSE.txt for license information. *| -|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This file contains definitions to figure out the size of _HOST_ data types.*| -|* This file is important because different host OS's define different macros,*| -|* which makes portability tough. This file exports the following *| -|* definitions: *| -|* *| -|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| -|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| -|* *| -|* No library is required when using these functions. *| -|* *| -|*===----------------------------------------------------------------------===*/ - -/* Please leave this file C-compatible. */ - -#ifndef LLVM_C_DATATYPES_H -#define LLVM_C_DATATYPES_H - -#include -#include - -#ifndef _MSC_VER - -#if !defined(UINT32_MAX) -# error "The standard header is not C++11 compliant. Must #define "\ - "__STDC_LIMIT_MACROS before #including llvm-c/DataTypes.h" -#endif - -#if !defined(UINT32_C) -# error "The standard header is not C++11 compliant. Must #define "\ - "__STDC_CONSTANT_MACROS before #including llvm-c/DataTypes.h" -#endif - -/* Note that includes , if this is a C99 system. */ -#include - -#ifdef _AIX -// GCC is strict about defining large constants: they must have LL modifier. -#undef INT64_MAX -#undef INT64_MIN -#endif - -#else /* _MSC_VER */ -#ifdef __cplusplus -#include -#include -#else -#include -#include -#endif -#include - -#if defined(_WIN64) -typedef signed __int64 ssize_t; -#else -typedef signed int ssize_t; -#endif /* _WIN64 */ - -#endif /* _MSC_VER */ - -/* Set defaults for constants which we cannot find. */ -#if !defined(INT64_MAX) -# define INT64_MAX 9223372036854775807LL -#endif -#if !defined(INT64_MIN) -# define INT64_MIN ((-INT64_MAX)-1) -#endif -#if !defined(UINT64_MAX) -# define UINT64_MAX 0xffffffffffffffffULL -#endif - -#ifndef HUGE_VALF -#define HUGE_VALF (float)HUGE_VAL -#endif - -#endif /* LLVM_C_DATATYPES_H */ diff --git a/stdlib/include/llvm/ADT/Hashing.h b/stdlib/include/llvm/ADT/Hashing.h index 3cc288bc73b91..7418fd0161bc7 100644 --- a/stdlib/include/llvm/ADT/Hashing.h +++ b/stdlib/include/llvm/ADT/Hashing.h @@ -44,13 +44,13 @@ #ifndef LLVM_ADT_HASHING_H #define LLVM_ADT_HASHING_H -#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/type_traits.h" #include #include #include +#include #include #include diff --git a/stdlib/include/llvm/Support/Atomic.h b/stdlib/include/llvm/Support/Atomic.h index 1c531931c7495..cee4b4d254f0e 100644 --- a/stdlib/include/llvm/Support/Atomic.h +++ b/stdlib/include/llvm/Support/Atomic.h @@ -17,7 +17,7 @@ #ifndef LLVM_SUPPORT_ATOMIC_H #define LLVM_SUPPORT_ATOMIC_H -#include "llvm/Support/DataTypes.h" +#include // Windows will at times define MemoryFence. #ifdef MemoryFence diff --git a/stdlib/include/llvm/Support/DataTypes.h b/stdlib/include/llvm/Support/DataTypes.h deleted file mode 100644 index a3fcc82531b71..0000000000000 --- a/stdlib/include/llvm/Support/DataTypes.h +++ /dev/null @@ -1,16 +0,0 @@ -//===-- llvm/Support/DataTypes.h - Define fixed size types ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Due to layering constraints (Support depends on llvm-c) this is a thin -// wrapper around the implementation that lives in llvm-c, though most clients -// can/should think of this as being provided by Support for simplicity (not -// many clients are aware of their dependency on llvm-c). -// -//===----------------------------------------------------------------------===// - -#include "llvm-c/DataTypes.h" diff --git a/stdlib/include/llvm/Support/PointerLikeTypeTraits.h b/stdlib/include/llvm/Support/PointerLikeTypeTraits.h index e6683ab0fc27c..e1ca42dc6fcd5 100644 --- a/stdlib/include/llvm/Support/PointerLikeTypeTraits.h +++ b/stdlib/include/llvm/Support/PointerLikeTypeTraits.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H -#include "llvm/Support/DataTypes.h" #include +#include #include inline namespace __swift { inline namespace __runtime { diff --git a/stdlib/public/Darwin/os/format.m b/stdlib/public/Darwin/os/format.m index 5ef8a790ddd79..460e336e3eb63 100644 --- a/stdlib/public/Darwin/os/format.m +++ b/stdlib/public/Darwin/os/format.m @@ -46,11 +46,11 @@ break; } - for (bool done = false; !done; percent++) { + for (bool done = false; !done; ++percent) { switch (ch = percent[0]) { /* type of types or other */ - case 'l': type++; break; // longer - case 'h': type--; break; // shorter + case 'l': ++type; break; // longer + case 'h': --type; break; // shorter case 'z': type = T_SIZE; break; case 'j': type = T_INTMAX; break; case 't': type = T_PTRDIFF; break; @@ -62,16 +62,16 @@ if (percent[1] != '.') { break; } - percent++; + ++percent; // FALLTHROUGH case '.': // precision if ((percent[1]) == '*') { prect = T_C_DYNAMIC; - percent++; + ++percent; } else { while (isdigit(percent[1])) { precision = 10 * precision + (percent[1] - '0'); - percent++; + ++percent; } if (precision > 1024) precision = 1024; prect = T_C_STATIC; @@ -86,7 +86,7 @@ break; case '{': // annotated symbols - for (const char *curr2 = percent + 1; (ch = (*curr2)) != 0; curr2++) { + for (const char *curr2 = percent + 1; (ch = (*curr2)) != 0; ++curr2) { if (ch == '}') { if (strncmp(percent + 1, "private", MIN(curr2 - percent - 1, 7)) == 0) { hdr.hdr_flags |= OSLF_HDR_FLAG_HAS_PRIVATE; @@ -121,7 +121,7 @@ precision = va_arg(args, int); \ } \ _os_log_encode_arg(ob, &cmd, &precision); \ - hdr.hdr_cmd_cnt++; \ + ++hdr.hdr_cmd_cnt; \ prect = T_C_NONE; \ } \ } while (0) @@ -148,7 +148,7 @@ cmd.cmd_flags = flags; \ cmd.cmd_size = sizeof(__var); \ _os_log_encode_arg(ob, &cmd, &__var); \ - hdr.hdr_cmd_cnt++; \ + ++hdr.hdr_cmd_cnt; \ } while (0) #define encode_smallint(ty, flags) \ @@ -157,7 +157,7 @@ cmd.cmd_flags = flags; \ cmd.cmd_size = sizeof(__var); \ _os_log_encode_arg(ob, &cmd, &__var); \ - hdr.hdr_cmd_cnt++; \ + ++hdr.hdr_cmd_cnt; \ } while (0) #define encode(ty, flags) \ @@ -166,7 +166,7 @@ cmd.cmd_flags = flags; \ cmd.cmd_size = sizeof(__var); \ _os_log_encode_arg(ob, &cmd, &__var); \ - hdr.hdr_cmd_cnt++; \ + ++hdr.hdr_cmd_cnt; \ } while (0) /* fixed types */ @@ -276,7 +276,7 @@ cmd.cmd_size = sizeof(int); cmd.cmd_flags = flags; _os_log_encode_arg(ob, &cmd, &saved_errno); - hdr.hdr_cmd_cnt++; + ++hdr.hdr_cmd_cnt; done = true; break; diff --git a/stdlib/public/Darwin/os/os_trace_blob.h b/stdlib/public/Darwin/os/os_trace_blob.h index ad7bc8b09a365..386f983df7d14 100644 --- a/stdlib/public/Darwin/os/os_trace_blob.h +++ b/stdlib/public/Darwin/os/os_trace_blob.h @@ -135,7 +135,7 @@ static inline void os_trace_blob_rtrim(os_trace_blob_t ob) { uint32_t len = ob->ob_len; - while (len > 0 && isspace(ob->ob_s[len - 1])) len--; + while (len > 0 && isspace(ob->ob_s[len - 1])) --len; _os_trace_blob_setlen(ob, len); } diff --git a/stdlib/public/Differentiation/ArrayDifferentiation.swift b/stdlib/public/Differentiation/ArrayDifferentiation.swift index fbaef9c34fe80..a4b1149a20f56 100644 --- a/stdlib/public/Differentiation/ArrayDifferentiation.swift +++ b/stdlib/public/Differentiation/ArrayDifferentiation.swift @@ -30,7 +30,7 @@ extension Array.DifferentiableView: Differentiable where Element: Differentiable { /// The viewed array. public var base: [Element] { - get { return _base } + get { _base } _modify { yield &_base } } @@ -58,9 +58,10 @@ where Element: Differentiable { public mutating func move(along direction: TangentVector) { precondition( - base.count == direction.base.count, - "cannot move Array.DifferentiableView with count \(base.count) along " - + "direction with different count \(direction.base.count)") + base.count == direction.base.count, """ + Count mismatch: \(base.count) ('self') and \(direction.base.count) \ + ('direction') + """) for i in base.indices { base[i].move(along: direction.base[i]) } @@ -106,17 +107,15 @@ where Element: AdditiveArithmetic & Differentiable { lhs: Array.DifferentiableView, rhs: Array.DifferentiableView ) -> Array.DifferentiableView { - precondition( - lhs.base.count == 0 || rhs.base.count == 0 - || lhs.base.count == rhs.base.count, - "cannot add Array.DifferentiableViews with different counts: " - + "\(lhs.base.count) and \(rhs.base.count)") if lhs.base.count == 0 { return rhs } if rhs.base.count == 0 { return lhs } + precondition( + lhs.base.count == rhs.base.count, + "Count mismatch: \(lhs.base.count) and \(rhs.base.count)") return Array.DifferentiableView(zip(lhs.base, rhs.base).map(+)) } @@ -124,17 +123,15 @@ where Element: AdditiveArithmetic & Differentiable { lhs: Array.DifferentiableView, rhs: Array.DifferentiableView ) -> Array.DifferentiableView { - precondition( - lhs.base.count == 0 || rhs.base.count == 0 - || lhs.base.count == rhs.base.count, - "cannot subtract Array.DifferentiableViews with different counts: " - + "\(lhs.base.count) and \(rhs.base.count)") if lhs.base.count == 0 { return rhs } if rhs.base.count == 0 { return lhs } + precondition( + lhs.base.count == rhs.base.count, + "Count mismatch: \(lhs.base.count) and \(rhs.base.count)") return Array.DifferentiableView(zip(lhs.base, rhs.base).map(-)) } @@ -202,10 +199,10 @@ extension Array where Element: Differentiable { ) { func pullback(_ v: TangentVector) -> (TangentVector, TangentVector) { precondition( - v.base.count == lhs.count + rhs.count, - "+ should receive gradient with count equal to sum of operand " - + "counts, but counts are: gradient \(v.base.count), " - + "lhs \(lhs.count), rhs \(rhs.count)") + v.base.count == lhs.count + rhs.count, """ + Tangent vector with invalid count; expected to equal the sum of \ + operand counts \(lhs.count) and \(rhs.count) + """) return ( TangentVector([Element.TangentVector](v.base[0..getParent())) return false; - for (unsigned i = 0, e = O->getGenericParams().size(); i < e; i++) { + for (unsigned i = 0, e = O->getGenericParams().size(); i < e; ++i) { if (!deriveSubstitutions(Subs, O->getGenericParams()[i], S->getGenericParams()[i])) @@ -1138,7 +1138,7 @@ bool TypeRef::deriveSubstitutions(GenericArgumentMap &Subs, if (O->getElements().size() != S->getElements().size()) return false; - for (unsigned i = 0, e = O->getElements().size(); i < e; i++) { + for (unsigned i = 0, e = O->getElements().size(); i < e; ++i) { if (!deriveSubstitutions(Subs, O->getElements()[i], S->getElements()[i])) diff --git a/stdlib/public/core/EitherSequence.swift b/stdlib/public/core/EitherSequence.swift index 36dc7b2744564..ad84251320884 100644 --- a/stdlib/public/core/EitherSequence.swift +++ b/stdlib/public/core/EitherSequence.swift @@ -173,9 +173,9 @@ internal typealias _EitherRandomAccessCollection< extension _EitherRandomAccessCollection: RandomAccessCollection { } extension _Either { - init( + init( _ collection: C - ) where Right == AnyCollection, C.Element == T { + ) where Right == AnyCollection { self = .right(AnyCollection(collection)) } } diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift index f92818baa5f21..d7276880dbb54 100644 --- a/stdlib/public/core/Result.swift +++ b/stdlib/public/core/Result.swift @@ -89,6 +89,25 @@ public enum Result { /// Returns a new result, mapping any success value using the given /// transformation and unwrapping the produced result. /// + /// Use this method to avoid a nested result when your transformation + /// produces another `Result` type. + /// + /// In this example, note the difference in the result of using `map` and + /// `flatMap` with a transformation that returns an result type. + /// + /// func getNextInteger() -> Result { + /// .success(4) + /// } + /// func getNextAfterInteger(_ n: Int) -> Result { + /// .success(n + 1) + /// } + /// + /// let result = getNextInteger().map({ getNextAfterInteger($0) }) + /// // result == .success(.success(5)) + /// + /// let result = getNextInteger().flatMap({ getNextAfterInteger($0) }) + /// // result == .success(5) + /// /// - Parameter transform: A closure that takes the success value of the /// instance. /// - Returns: A `Result` instance with the result of evaluating `transform` diff --git a/stdlib/public/core/UnicodeScalarProperties.swift b/stdlib/public/core/UnicodeScalarProperties.swift index c08e41cacea91..d0c39c2efee3b 100644 --- a/stdlib/public/core/UnicodeScalarProperties.swift +++ b/stdlib/public/core/UnicodeScalarProperties.swift @@ -692,15 +692,14 @@ extension Unicode.Scalar.Properties { /// all current case mappings. In the event more space is needed, it will be /// allocated on the heap. internal func _applyMapping(_ u_strTo: _U_StrToX) -> String { - // TODO(String performance): Stack buffer first and then detect real count - let count = 64 - var array = Array(repeating: 0, count: count) - let len: Int = array.withUnsafeMutableBufferPointer { bufPtr in + // Allocate 16 code units on the stack. + var fixedArray = _FixedArray16(allZeros: ()) + let count: Int = fixedArray.withUnsafeMutableBufferPointer { buf in return _scalar.withUTF16CodeUnits { utf16 in var err = __swift_stdlib_U_ZERO_ERROR let correctSize = u_strTo( - bufPtr.baseAddress._unsafelyUnwrappedUnchecked, - Int32(bufPtr.count), + buf.baseAddress._unsafelyUnwrappedUnchecked, + Int32(buf.count), utf16.baseAddress._unsafelyUnwrappedUnchecked, Int32(utf16.count), "", @@ -708,13 +707,36 @@ extension Unicode.Scalar.Properties { guard err.isSuccess else { fatalError("Unexpected error case-converting Unicode scalar.") } - // TODO: _internalInvariant(count == correctSize, "inconsistent ICU behavior") return Int(correctSize) } } - // TODO: replace `len` with `count` - return array[..(unsafeUninitializedCapacity: count) { + buf, initializedCount in + _scalar.withUTF16CodeUnits { utf16 in + var err = __swift_stdlib_U_ZERO_ERROR + let correctSize = u_strTo( + buf.baseAddress._unsafelyUnwrappedUnchecked, + Int32(buf.count), + utf16.baseAddress._unsafelyUnwrappedUnchecked, + Int32(utf16.count), + "", + &err) + guard err.isSuccess else { + fatalError("Unexpected error case-converting Unicode scalar.") + } + _internalInvariant(count == correctSize, "inconsistent ICU behavior") + initializedCount = count + } + } + return array.withUnsafeBufferPointer { + String._uncheckedFromUTF16($0) } } diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index c73961205828d..db829a67538b7 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -34,6 +34,7 @@ set(swift_runtime_sources CygwinPort.cpp Demangle.cpp Enum.cpp + EnvironmentVariables.cpp ErrorObjectCommon.cpp ErrorObjectConstants.cpp ErrorObjectNative.cpp diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index 0e820890d5882..f5bf92357f35b 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -19,6 +19,7 @@ #include "swift/Strings.h" #include +#include #if SWIFT_OBJC_INTEROP #include diff --git a/stdlib/public/runtime/EnvironmentVariables.cpp b/stdlib/public/runtime/EnvironmentVariables.cpp new file mode 100644 index 0000000000000..dfaf099d8a16f --- /dev/null +++ b/stdlib/public/runtime/EnvironmentVariables.cpp @@ -0,0 +1,190 @@ +//===--- EnvironmentVariables.h - Debug variables. --------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Debug behavior conditionally enabled using environment variables. +// +//===----------------------------------------------------------------------===// + +#include "swift/Runtime/Debug.h" +#include "swift/Runtime/EnvironmentVariables.h" + +#include + +using namespace swift; + +namespace { + +// Require all environment variable names to start with SWIFT_ +static constexpr bool hasSwiftPrefix(const char *str) { + const char prefix[] = "SWIFT_"; + for (unsigned i = 0; i < sizeof(prefix) - 1; i++) + if (str[i] != prefix[i]) + return false; + return true; +} +#define VARIABLE(name, type, defaultValue, help) \ + static_assert(hasSwiftPrefix(#name), "Names must start with SWIFT"); +#include "EnvironmentVariables.def" + +// Value parsers. Add new functions named parse_ to accommodate more +// debug variable types. +static bool parse_bool(const char *name, const char *value, bool defaultValue) { + if (!value) + return defaultValue; + switch (value[0]) { + case 'Y': + case 'y': + case 'T': + case 't': + case '1': + return true; + case 'N': + case 'n': + case 'F': + case 'f': + case '0': + return false; + default: + swift::warning(RuntimeErrorFlagNone, + "Warning: cannot parse value %s=%s, defaulting to %s.\n", + name, value, defaultValue ? "true" : "false"); + return defaultValue; + } +} + +static uint8_t parse_uint8_t(const char *name, + const char *value, + uint8_t defaultValue) { + if (!value) + return defaultValue; + char *end; + long n = strtol(value, &end, 0); + if (*end != '\0') { + swift::warning(RuntimeErrorFlagNone, + "Warning: cannot parse value %s=%s, defaulting to %u.\n", + name, value, defaultValue); + return defaultValue; + } + + if (n < 0) { + swift::warning(RuntimeErrorFlagNone, + "Warning: %s=%s out of bounds, clamping to 0.\n", + name, value); + return 0; + } + if (n > UINT8_MAX) { + swift::warning(RuntimeErrorFlagNone, + "Warning: %s=%s out of bounds, clamping to %d.\n", + name, value, UINT8_MAX); + return UINT8_MAX; + } + + return n; +} + +// Print a list of all the environment variables. Lazy initialization makes +// this a bit odd, but the use of these variables in the metadata system means +// it's almost certain to run early. +// +// The "extra" parameter is printed after the header and before the list of +// variables. +void printHelp(const char *extra) { + swift::warning(RuntimeErrorFlagNone, "Swift runtime debugging:\n"); + if (extra) + swift::warning(RuntimeErrorFlagNone, "%s\n", extra); +#define VARIABLE(name, type, defaultValue, help) \ + swift::warning(RuntimeErrorFlagNone, "%7s %s [default: %s] - %s\n", \ + #type, #name, #defaultValue, help); +#include "EnvironmentVariables.def" + swift::warning(RuntimeErrorFlagNone, "SWIFT_DEBUG_HELP=YES - Print this help."); +} + +} // end anonymous namespace + +// Define backing variables. +#define VARIABLE(name, type, defaultValue, help) \ + type swift::runtime::environment::name ## _variable = defaultValue; +#include "EnvironmentVariables.def" + +// Initialization code. +OnceToken_t swift::runtime::environment::initializeToken; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) +extern "C" char **environ; +#define ENVIRON environ +#elif defined(_WIN32) +extern "C" char **_environ; +#define ENVIRON _environ +#endif + +#ifdef ENVIRON +void swift::runtime::environment::initialize(void *context) { + // On platforms where we have an environment variable array available, scan it + // directly. This optimizes for the common case where no variables are set, + // since we only need to perform one scan to set all variables. It also allows + // us to detect some spelling mistakes by warning on unknown SWIFT_ variables. + + bool SWIFT_DEBUG_HELP_variable = false; + for (char **var = ENVIRON; *var; var++) { + // Immediately skip anything without a SWIFT_ prefix. + if (strncmp(*var, "SWIFT_", 6) != 0) + continue; + + bool foundVariable = false; + // Check each defined variable in turn, plus SWIFT_DEBUG_HELP. Variables are + // parsed by functions named parse_ above. An unknown type will + // produce an error that parse_ doesn't exist. Add new parsers + // above. +#define VARIABLE(name, type, defaultValue, help) \ + if (strncmp(*var, #name "=", strlen(#name "=")) == 0) { \ + name ## _variable = \ + parse_ ## type(#name, *var + strlen(#name "="), defaultValue); \ + foundVariable = true; \ + } + // SWIFT_DEBUG_HELP is not in the variables list. Parse it like the other + // variables. + VARIABLE(SWIFT_DEBUG_HELP, bool, false, ) +#include "EnvironmentVariables.def" + + // Flag unknown SWIFT_DEBUG_ variables to catch misspellings. We don't flag + // all unknown SWIFT_ variables, because there are a bunch of other SWIFT_ + // variables used for other purposes, such as SWIFT_SOURCE_ROOT and + // SWIFT_INSTALL_DIR, and we don't want to warn for all of those. + const char *swiftDebugPrefix = "SWIFT_DEBUG_"; + if (!foundVariable && + strncmp(*var, swiftDebugPrefix, strlen(swiftDebugPrefix)) == 0) { + const char *equals = strchr(*var, '='); + if (!equals) + equals = *var + strlen(*var); + swift::warning(RuntimeErrorFlagNone, + "Warning: unknown environment variable %.*s\n", + (int)(equals - *var), *var); + } + } + + if (SWIFT_DEBUG_HELP_variable) + printHelp(nullptr); +} +#else +void swift::runtime::environment::initialize(void *context) { + // Emit a getenv call for each variable. This is less efficient but works + // everywhere. +#define VARIABLE(name, type, defaultValue, help) \ + name ## _variable = parse_ ## type(#name, getenv(#name), defaultValue); +#include "EnvironmentVariables.def" + + // Print help if requested. + if (parse_bool("SWIFT_DEBUG_HELP", getenv("SWIFT_DEBUG_HELP"), false)) + printHelp("Using getenv to read variables. Unknown SWIFT_DEBUG_ variables " + "will not be flagged."); +} +#endif diff --git a/stdlib/public/runtime/EnvironmentVariables.def b/stdlib/public/runtime/EnvironmentVariables.def new file mode 100644 index 0000000000000..093c43f04f6fe --- /dev/null +++ b/stdlib/public/runtime/EnvironmentVariables.def @@ -0,0 +1,40 @@ +//===--- EnvironmentVariables.def - Debug variables. ------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines x-macros used for metaprogramming with the set of +// environment variables used for configuring or enabling debug features in the +// runtime. +// +//===----------------------------------------------------------------------===// + +// #define VARIABLE(name, type, defaultValue, help) + +#ifndef VARIABLE +#error "Must define VARIABLE to include EnvironmentVariables.def" +#endif + +VARIABLE(SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION, bool, false, + "Enable additional metadata allocation tracking for swift-inspect to " + "use.") + +VARIABLE(SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT, uint8_t, 2, + "Print warnings when using implicit @objc entrypoints. Set to " + "desired reporting level, 0-3.") + +VARIABLE(SWIFT_DETERMINISTIC_HASHING, bool, false, + "Disable randomized hash seeding.") + +VARIABLE(SWIFT_ENABLE_MANGLED_NAME_VERIFICATION, bool, false, + "Enable verification that metadata can roundtrip through a mangled " + "name each time metadata is instantiated.") + +#undef VARIABLE diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp index aa6993d29284f..4d8d0d23eea7b 100644 --- a/stdlib/public/runtime/Exclusivity.cpp +++ b/stdlib/public/runtime/Exclusivity.cpp @@ -30,6 +30,7 @@ #include "swift/Runtime/Debug.h" #include "swift/Runtime/Metadata.h" #include +#include #include // Pick a return-address strategy diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index fbafd97872c12..3bbc55b13f1ed 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -21,6 +21,7 @@ #include "swift/Demangling/Demangler.h" #include "swift/ABI/TypeIdentity.h" #include "swift/Runtime/Casting.h" +#include "swift/Runtime/EnvironmentVariables.h" #include "swift/Runtime/ExistentialContainer.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Mutex.h" @@ -113,15 +114,14 @@ Metadata *TargetSingletonMetadataInitialization::allocate( // Such a template will fail the `isTypeMetadata` test and we'll think that it // isn't Swift metadata but a plain old ObjC class instead. if (metadata->getKind() == MetadataKind::Class) { - auto *classMetadata = static_cast(metadata); -#if SWIFT_OBJC_INTEROP - classMetadata->setAsTypeMetadata(); -#endif auto *fullMetadata = asFullMetadata(metadata); // Begin by initializing the value witness table; everything else is // initialized by swift_initClassMetadata(). #if SWIFT_OBJC_INTEROP + auto *classMetadata = static_cast(metadata); + classMetadata->setAsTypeMetadata(); + fullMetadata->ValueWitnesses = (classMetadata->Flags & ClassFlags::UsesSwiftRefcounting) ? &VALUE_WITNESS_SYM(Bo) @@ -2281,7 +2281,7 @@ static uint32_t getLog2AlignmentFromMask(size_t alignMask) { uint32_t log2 = 0; while ((1 << log2) != (alignMask + 1)) - log2++; + ++log2; return log2; } @@ -4163,7 +4163,7 @@ template <> SWIFT_USED void Metadata::dump() const { auto genericCount = contextDescriptor->getFullGenericContextHeader().Base.getNumArguments(); auto *args = getGenericArgs(); printf("Generic Args: %u: [", genericCount); - for (uint32_t i = 0; i < genericCount; i++) { + for (uint32_t i = 0; i < genericCount; ++i) { if (i > 0) printf(", "); printf("%p", args[i]); @@ -5505,21 +5505,21 @@ bool swift::_swift_debug_metadataAllocationIterationEnabled = false; const void * const swift::_swift_debug_allocationPoolPointer = &AllocationPool; static void checkAllocatorDebugEnvironmentVariable(void *context) { - const char *value = - getenv("SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION"); - if (value && (value[0] == '1' || value[0] == 'y' || value[0] == 'Y')) { - _swift_debug_metadataAllocationIterationEnabled = true; - // Write a PoolTrailer to the end of InitialAllocationPool and shrink - // the pool accordingly. - auto poolCopy = AllocationPool.load(std::memory_order_relaxed); - assert(poolCopy.Begin == InitialAllocationPool.Pool); - size_t newPoolSize = InitialPoolSize - sizeof(PoolTrailer); - PoolTrailer trailer = { nullptr, newPoolSize }; - memcpy(InitialAllocationPool.Pool + newPoolSize, &trailer, - sizeof(trailer)); - poolCopy.Remaining = newPoolSize; - AllocationPool.store(poolCopy, std::memory_order_relaxed); - } + _swift_debug_metadataAllocationIterationEnabled + = runtime::environment::SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION(); + if (!_swift_debug_metadataAllocationIterationEnabled) + return; + + // Write a PoolTrailer to the end of InitialAllocationPool and shrink + // the pool accordingly. + auto poolCopy = AllocationPool.load(std::memory_order_relaxed); + assert(poolCopy.Begin == InitialAllocationPool.Pool); + size_t newPoolSize = InitialPoolSize - sizeof(PoolTrailer); + PoolTrailer trailer = { nullptr, newPoolSize }; + memcpy(InitialAllocationPool.Pool + newPoolSize, &trailer, + sizeof(trailer)); + poolCopy.Remaining = newPoolSize; + AllocationPool.store(poolCopy, std::memory_order_relaxed); } void *MetadataAllocator::Allocate(size_t size, size_t alignment) { @@ -5655,10 +5655,8 @@ void swift::verifyMangledNameRoundtrip(const Metadata *metadata) { // variable lets us easily turn on verification to find and fix these // bugs. Remove this and leave it permanently on once everything works // with it enabled. - bool verificationEnabled = - SWIFT_LAZY_CONSTANT((bool)getenv("SWIFT_ENABLE_MANGLED_NAME_VERIFICATION")); - - if (!verificationEnabled) return; + if (!swift::runtime::environment::SWIFT_ENABLE_MANGLED_NAME_VERIFICATION()) + return; Demangle::StackAllocatedDemangler<1024> Dem; auto node = _swift_buildDemanglingForMetadata(metadata, Dem); diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 32f737d0a39b6..10bcd6b7903c6 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -576,7 +576,7 @@ swift_conformsToSwiftProtocolImpl(const Metadata * const type, } // Really scan conformance records. - for (size_t i = startIndex; i < endIndex; i++) { + for (size_t i = startIndex; i < endIndex; ++i) { auto §ion = snapshot.Start[i]; // Eagerly pull records for nondependent witnesses into our cache. for (const auto &record : section) { diff --git a/stdlib/public/runtime/SwiftDtoa.cpp b/stdlib/public/runtime/SwiftDtoa.cpp index f24ac932cb140..edde4f1368d0a 100644 --- a/stdlib/public/runtime/SwiftDtoa.cpp +++ b/stdlib/public/runtime/SwiftDtoa.cpp @@ -1426,7 +1426,7 @@ size_t swift_format_exponential(char *dest, size_t length, exponent -= 1; if (digit_count > 1) { *p++ = '.'; - for (int i = 1; i < digit_count; i++) { + for (int i = 1; i < digit_count; ++i) { *p++ = digits[i] + '0'; } } @@ -1520,7 +1520,7 @@ size_t swift_format_decimal(char *dest, size_t length, *p++ = digits[i] + '0'; } } else if (exponent < digit_count) { - for (int i = 0; i < digit_count; i++) { + for (int i = 0; i < digit_count; ++i) { if (exponent == 0) { *p++ = '.'; } @@ -1528,7 +1528,7 @@ size_t swift_format_decimal(char *dest, size_t length, exponent -= 1; } } else { - for (int i = 0; i < digit_count; i++) { + for (int i = 0; i < digit_count; ++i) { *p++ = digits[i] + '0'; exponent -= 1; } diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm index 34e87a9b1e99f..af7489d33cb11 100644 --- a/stdlib/public/runtime/SwiftObject.mm +++ b/stdlib/public/runtime/SwiftObject.mm @@ -26,6 +26,7 @@ #include "llvm/ADT/StringRef.h" #include "swift/Basic/Lazy.h" #include "swift/Runtime/Casting.h" +#include "swift/Runtime/EnvironmentVariables.h" #include "swift/Runtime/Heap.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Metadata.h" @@ -42,6 +43,7 @@ #if SWIFT_OBJC_INTEROP #include #endif +#include #include #include #include @@ -1478,22 +1480,9 @@ void swift_objc_swift3ImplicitObjCEntrypoint(id self, SEL selector, // if possible. // 3: Complain about uses of implicit @objc entrypoints, then abort(). // - // The actual reportLevel is stored as the above values +1, so that - // 0 indicates we have not yet checked. It's fine to race through here. - // // The default, if SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT is not set, is 2. - static int storedReportLevel = 0; - if (storedReportLevel == 0) { - auto reportLevelStr = getenv("SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT"); - if (reportLevelStr && - reportLevelStr[0] >= '0' && reportLevelStr[0] <= '3' && - reportLevelStr[1] == 0) - storedReportLevel = (reportLevelStr[0] - '0') + 1; - else - storedReportLevel = 3; - } - - int reportLevel = storedReportLevel - 1; + uint8_t reportLevel = + runtime::environment::SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT(); if (reportLevel < 1) return; // Report the error. diff --git a/stdlib/public/stubs/CommandLine.cpp b/stdlib/public/stubs/CommandLine.cpp index cf371e5ababe4..4c236c03f69cf 100644 --- a/stdlib/public/stubs/CommandLine.cpp +++ b/stdlib/public/stubs/CommandLine.cpp @@ -174,7 +174,7 @@ char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) { char *argPtr = nullptr; // or use ARG_MAX? 8192 is used in LLDB though.. int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, getpid() }; size_t argPtrSize = 0; - for (int i = 0; i < 3 && !argPtr; i++) { // give up after 3 tries + for (int i = 0; i < 3 && !argPtr; ++i) { // give up after 3 tries if (sysctl(mib, 4, nullptr, &argPtrSize, nullptr, 0) != -1) { argPtr = (char *)malloc(argPtrSize); if (sysctl(mib, 4, argPtr, &argPtrSize, nullptr, 0) == -1) { diff --git a/stdlib/public/stubs/GlobalObjects.cpp b/stdlib/public/stubs/GlobalObjects.cpp index 201169a195287..8167fde149f79 100644 --- a/stdlib/public/stubs/GlobalObjects.cpp +++ b/stdlib/public/stubs/GlobalObjects.cpp @@ -20,6 +20,7 @@ #include "../SwiftShims/Random.h" #include "swift/Runtime/Metadata.h" #include "swift/Runtime/Debug.h" +#include "swift/Runtime/EnvironmentVariables.h" #include namespace swift { @@ -113,8 +114,7 @@ static swift::_SwiftHashingParameters initializeHashingParameters() { // results are repeatable, e.g., in certain test environments. (Note that // even if the seed override is enabled, hash values aren't guaranteed to // remain stable across even minor stdlib releases.) - auto determinism = getenv("SWIFT_DETERMINISTIC_HASHING"); - if (determinism && 0 == strcmp(determinism, "1")) { + if (swift::runtime::environment::SWIFT_DETERMINISTIC_HASHING()) { return { 0, 0, true }; } __swift_uint64_t seed0 = 0, seed1 = 0; diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index c94c21aac151e..0cdb3d39804ff 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -363,7 +363,7 @@ swift::swift_stdlib_readLine_stdin(unsigned char **LinePtr) { static bool swift_stringIsSignalingNaN(const char *nptr) { if (nptr[0] == '+' || nptr[0] == '-') { - nptr++; + ++nptr; } return strcasecmp(nptr, "snan") == 0; diff --git a/stdlib/toolchain/Compatibility50/ProtocolConformance.cpp b/stdlib/toolchain/Compatibility50/ProtocolConformance.cpp index 059b5f7999cee..a48e801a5a43a 100644 --- a/stdlib/toolchain/Compatibility50/ProtocolConformance.cpp +++ b/stdlib/toolchain/Compatibility50/ProtocolConformance.cpp @@ -66,7 +66,7 @@ static void addImageCallback(const mach_header *mh, intptr_t vmaddr_slide) { auto recordsEnd = reinterpret_cast (section + size); - for (auto record = recordsBegin; record != recordsEnd; record++) { + for (auto record = recordsBegin; record != recordsEnd; ++record) { auto descriptor = record->get(); if (auto typePtr = descriptor->_getTypeDescriptorLocation()) { if (*typePtr == nullptr) diff --git a/stdlib/toolchain/Compatibility51/Concurrent.h b/stdlib/toolchain/Compatibility51/Concurrent.h index c34ceb7854aff..bf0eb623a6274 100644 --- a/stdlib/toolchain/Compatibility51/Concurrent.h +++ b/stdlib/toolchain/Compatibility51/Concurrent.h @@ -353,7 +353,7 @@ template struct ConcurrentReadableArray { } void deallocate() { - for (size_t i = 0; i < Count; i++) { + for (size_t i = 0; i < Count; ++i) { data()[i].~ElemTy(); } free(this); diff --git a/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp b/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp index 68483306e4ee9..4f22fd2bfda2d 100644 --- a/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp +++ b/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp @@ -647,7 +647,7 @@ swift::swift51override_conformsToSwiftProtocol(const Metadata * const type, } // Really scan conformance records. - for (size_t i = startIndex; i < endIndex; i++) { + for (size_t i = startIndex; i < endIndex; ++i) { auto §ion = snapshot.Start[i]; // Eagerly pull records for nondependent witnesses into our cache. for (const auto &record : section) { diff --git a/test/Constraints/argument_matching.swift b/test/Constraints/argument_matching.swift index febabc64f094d..f316c06dab41a 100644 --- a/test/Constraints/argument_matching.swift +++ b/test/Constraints/argument_matching.swift @@ -690,8 +690,120 @@ func testUnlabeledParameterBindingPosition() { do { func f(_ aa: Int) {} + f(1) // ok + + f(xx: 1) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + f(0, 1) // expected-error@-1:10 {{extra argument in call}} + + f(xx: 1, 2) + // expected-error@-1:14 {{extra argument in call}} + + f(1, xx: 2) + // expected-error@-1:14 {{extra argument 'xx' in call}} + + f(xx: 1, yy: 2) + // expected-error@-1:18 {{extra argument 'yy' in call}} + } + + do { + func f(aa: Int) { } + + f(1) + // expected-error@-1:7 {{missing argument label 'aa:' in call}} + + f(aa: 1) // ok + + f(xx: 1) + // expected-error@-1 {{incorrect argument label in call (have 'xx:', expected 'aa:')}} + } + + do { + func f(_ aa: Int, _ bb: Int) { } + // expected-note@-1 3 {{'f' declared here}} + + f(1) + // expected-error@-1:8 {{missing argument for parameter #2 in call}} + + f(xx: 1) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + // expected-error@-2:12 {{missing argument for parameter #2 in call}} + + f(1, 2) // ok + + f(1, xx: 2) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + + f(xx: 1, 2) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + + f(xx: 1, yy: 2) + // expected-error@-1 {{extraneous argument labels 'xx:yy:' in call}} + + f(xx: 1, 2, 3) + // expected-error@-1:17 {{extra argument in call}} + + f(1, xx: 2, 3) + // expected-error@-1:17 {{extra argument in call}} + + f(1, 2, xx: 3) + // expected-error@-1:17 {{extra argument 'xx' in call}} + + f(xx: 1, yy: 2, 3) + // expected-error@-1:21 {{extra argument in call}} + + f(xx: 1, yy: 2, 3, 4) + // expected-error@-1:6 {{extra arguments at positions #3, #4 in call}} + } + + do { + func f(_ aa: Int = 0, _ bb: Int) { } + // expected-note@-1 {{'f' declared here}} + + f(1) + // expected-error@-1:8 {{missing argument for parameter #2 in call}} + + f(1, 2) // ok + } + + do { + func f(_ aa: Int, bb: Int) { } + // expected-note@-1 3 {{'f(_:bb:)' declared here}} + + f(1) + // expected-error@-1:8 {{missing argument for parameter 'bb' in call}} + + f(1, 2) + // expected-error@-1 {{missing argument label 'bb:' in call}} + + f(1, bb: 2) // ok + + f(xx: 1, 2) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:', expected '_:bb:')}} + + f(xx: 1, bb: 2) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + + f(bb: 1, 2, 3) + // expected-error@-1:17 {{extra argument in call}} + + f(1, bb: 2, 3) + // expected-error@-1:17 {{extra argument in call}} + + f(1, 2, bb: 3) + // expected-error@-1:10 {{extra argument in call}} + + f(xx: 1, 2, 3) + // expected-error@-1:17 {{extra argument in call}} + + f(1, xx: 2, 3) + // expected-error@-1:6 {{extra arguments at positions #2, #3 in call}} + // expected-error@-2:8 {{missing argument for parameter 'bb' in call}} + + f(1, 2, xx: 3) + // expected-error@-1:17 {{extra argument 'xx' in call}} } do { @@ -699,7 +811,7 @@ func testUnlabeledParameterBindingPosition() { func f(aa: Int, _ bb: Int) { } f(1) - // expected-error@-1 {{missing argument for parameter 'aa' in call}} + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} f(0, 1) // expected-error@-1:6 {{missing argument label 'aa:' in call}} @@ -719,15 +831,88 @@ func testUnlabeledParameterBindingPosition() { // expected-error@-1:17 {{extra argument 'xx' in call}} f(xx: 91, 1, 92) - // expected-error@-1 {{extra arguments at positions #2, #3 in call}} - // expected-error@-2 {{missing argument for parameter 'aa' in call}} + // expected-error@-1:6 {{extra arguments at positions #2, #3 in call}} + // expected-error@-2:7 {{missing argument for parameter 'aa' in call}} + + f(1, xx: 2, 3) + // expected-error@-1:6 {{extra arguments at positions #2, #3 in call}} + // expected-error@-2:7 {{missing argument for parameter 'aa' in call}} + + f(1, 2, xx: 3) + // expected-error@-1:17 {{extra argument 'xx' in call}} + } + + do { + func f(_ aa: Int, _ bb: Int = 82, _ cc: Int) { } + // expected-note@-1 {{'f' declared here}} + + f(1, 2) + // expected-error@-1:11 {{missing argument for parameter #3 in call}} + + f(1, 2, 3) // ok + } + + do { + func f(_ aa: Int, _ bb: Int, cc: Int) { } + + f(1, 2, cc: 3) // ok + + f(1, 2, xx: 3) + // expected-error@-1 {{incorrect argument label in call (have '_:_:xx:', expected '_:_:cc:')}} + + f(1, cc: 2, 3) + // expected-error@-1 {{unnamed argument #3 must precede argument 'cc'}} + + f(1, xx: 2, 3) + // expected-error@-1 {{incorrect argument labels in call (have '_:xx:_:', expected '_:_:cc:')}} + + f(cc: 1, 2, 3) + // expected-error@-1 {{incorrect argument labels in call (have 'cc:_:_:', expected '_:_:cc:')}} + + f(xx: 1, 2, 3) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:_:', expected '_:_:cc:')}} + + f(xx: 1, yy: 2, 3) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:yy:_:', expected '_:_:cc:')}} + + f(xx: 1, 2, yy: 3) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:yy:', expected '_:_:cc:')}} + + f(1, xx: 2, yy: 3) + // expected-error@-1 {{incorrect argument labels in call (have '_:xx:yy:', expected '_:_:cc:')}} } do { func f(_ aa: Int, bb: Int, _ cc: Int) { } + // expected-note@-1 4 {{'f(_:bb:_:)' declared here}} + + f(1) + // expected-error@-1:7 {{missing arguments for parameters 'bb', #3 in call}} + + f(1, 2) + // expected-error@-1:8 {{missing argument for parameter 'bb' in call}} + + f(1, 2, 3) + // expected-error@-1 {{missing argument label 'bb:' in call}} + + f(1, 2, bb: 3) + // expected-error@-1 {{argument 'bb' must precede unnamed argument #2}} + + f(1, bb: 2, 3) // ok f(bb: 1, 0, 2) // expected-error@-1 {{unnamed argument #3 must precede argument 'bb'}} + + f(xx: 1, 2, 3) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:_:', expected '_:bb:_:')}} + + f(1, xx: 2, 3) + // expected-error@-1:17 {{extra argument in call}} + // expected-error@-2:8 {{missing argument for parameter 'bb' in call}} + + f(1, 2, xx: 3) + // expected-error@-1:8 {{missing argument for parameter 'bb' in call}} + // expected-error@-2:17 {{extra argument 'xx' in call}} } do { @@ -741,7 +926,7 @@ func testUnlabeledParameterBindingPosition() { func f(_ aa: Int, bb: Int, _ cc: Int...) { } f(bb: 1, 2, 3, 4) - // expected-error@-1 {{missing argument for parameter #1 in call}} + // expected-error@-1:7 {{missing argument for parameter #1 in call}} } do { @@ -754,8 +939,51 @@ func testUnlabeledParameterBindingPosition() { // expected-note@+1 *{{'f(aa:_:_:)' declared here}} func f(aa: Int, _ bb: Int, _ cc: Int) {} + f(1) + // expected-error@-1:7 {{missing arguments for parameters 'aa', #3 in call}} + f(0, 1) // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + + f(1, 2, 3) + // expected-error@-1:6 {{missing argument label 'aa:' in call}} + + f(1, aa: 2, 3) + // expected-error@-1:10 {{argument 'aa' must precede unnamed argument #1}} + + f(1, xx: 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:17 {{extra argument in call}} + + f(aa: 1, 2, 3) // ok + + f(xx: 1, 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:17 {{extra argument in call}} + + f(xx: 1, 2, yy: 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:21 {{extra argument 'yy' in call}} + + f(xx: 1, yy: 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:21 {{extra argument in call}} + + f(1, xx: 2, yy: 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:21 {{extra argument 'yy' in call}} + + f(1, 2, 3, 4) + // expected-error@-1:16 {{extra argument in call}} + + f(1, aa: 2, 3, 4) + // expected-error@-1:20 {{extra argument in call}} + + f(1, aa: 2, 3, xx: 4) + // expected-error@-1:24 {{extra argument 'xx' in call}} + + f(1, aa: 2, xx: 3, 4) + // expected-error@-1:24 {{extra argument in call}} } do { @@ -776,6 +1004,34 @@ func testUnlabeledParameterBindingPosition() { f(0, bb: 1, 2) // expected-error@-1:6 {{missing argument label 'aa:' in call}} + + f(xx: 1, 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:17 {{extra argument in call}} + + f(1, xx: 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:17 {{extra argument in call}} + + f(1, 2, xx: 3) + // expected-error@-1:8 {{missing argument for parameter 'bb' in call}} + // expected-error@-2:17 {{extra argument 'xx' in call}} + } + + do { + func f(aa: Int, bb: Int, cc: Int) { } + + f(1, aa: 2, bb: 3) + // expected-error@-1 {{incorrect argument labels in call (have '_:aa:bb:', expected 'aa:bb:cc:')}} + + f(1, bb: 2, aa: 3) + // expected-error@-1 {{incorrect argument labels in call (have '_:bb:aa:', expected 'aa:bb:cc:')}} + + f(aa: 1, 2, bb: 3) + // expected-error@-1 {{incorrect argument labels in call (have 'aa:_:bb:', expected 'aa:bb:cc:')}} + + f(aa: 1, bb: 2, 3) + // expected-error@-1 {{missing argument label 'cc:' in call}} } do { @@ -788,6 +1044,130 @@ func testUnlabeledParameterBindingPosition() { func f(_ aa: Int, _ bb: Int = 81, cc: Int = 82, _ dd: Int) {} f(0, cc: 2, 3) // ok + + f(cc: 1, 2, 3, 4) + // expected-error@-1 {{unnamed argument #3 must precede argument 'cc'}} + } + + do { + func f(_ aa: Int, _ bb: Int, cc: Int, dd: Int) { } + // expected-note@-1 6 {{'f(_:_:cc:dd:)' declared here}} + + f(1, xx: 2) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + // expected-error@-2:6 {{missing arguments for parameters 'cc', 'dd' in call}} + + f(xx: 1, 2) + // expected-error@-1:6 {{missing arguments for parameters 'cc', 'dd' in call}} + // expected-error@-2 {{extraneous argument label 'xx:' in call}} + + f(1, xx: 2, cc: 3) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + // expected-error@-2:22 {{missing argument for parameter 'dd' in call}} + + f(1, xx: 2, dd: 3) + // expected-error@-1 {{incorrect argument labels in call (have '_:xx:dd:', expected '_:_:cc:dd:')}} + // expected-error@-2:15 {{missing argument for parameter 'cc' in call}} + + f(xx: 1, 2, cc: 3) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + // expected-error@-2:22 {{missing argument for parameter 'dd' in call}} + + f(xx: 1, 2, dd: 3) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:dd:', expected '_:_:cc:dd:')}} + // expected-error@-2:15 {{missing argument for parameter 'cc' in call}} + + f(1, xx: 2, cc: 3, dd: 4) + // expected-error@-1:6 {{extraneous argument label 'xx:' in call}} + + f(xx: 1, 2, cc: 3, dd: 4) + // expected-error@-1:6 {{extraneous argument label 'xx:' in call}} + } + + do { + func f(_ aa: Int, bb: Int = 82, _ cc: Int, _ dd: Int) { } + + f(1, bb: 2, 3, 4) // ok + + f(1, 2, bb: 3, 4) + // expected-error@-1 {{argument 'bb' must precede unnamed argument #2}} + } + + do { + func f(aa: Int, _ bb: Int, cc: Int, _ dd: Int) { } + // expected-note@-1 3 {{'f(aa:_:cc:_:)' declared here}} + + f(1) + // expected-error@-1:7 {{missing arguments for parameters 'aa', 'cc', #4 in call}} + + f(1, 2) + // expected-error@-1:6 {{missing arguments for parameters 'aa', 'cc' in call}} + + f(1, 2, 3) + // expected-error@-1 {{missing argument labels 'aa:cc:' in call}} + // expected-error@-2:11 {{missing argument for parameter 'cc' in call}} + + f(1, 2, 3, 4) + // expected-error@-1:6 {{missing argument labels 'aa:cc:' in call}} + + f(1, 2, 3, 4, 5) + // expected-error@-1:19 {{extra argument in call}} + } + + do { + func f(aa: Int, bb: Int, _ cc: Int, _ dd: Int) { } + // expected-note@-1 6 {{'f(aa:bb:_:_:)' declared here}} + + f(1, xx: 2) + // expected-error@-1:6 {{missing arguments for parameters 'aa', 'bb' in call}} + // expected-error@-2 {{incorrect argument labels in call (have '_:xx:', expected 'aa:bb:_:_:')}} + + f(xx: 1, 2) + // expected-error@-1 {{incorrect argument labels in call (have 'xx:_:', expected 'aa:bb:_:_:')}} + // expected-error@-2:6 {{missing arguments for parameters 'aa', 'bb' in call}} + + f(bb: 1, 2, xx: 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + + f(bb: 1, xx: 2, 3) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + + f(aa: 1, 2, xx: 3) + // expected-error@-1:12 {{missing argument for parameter 'bb' in call}} + + f(aa: 1, xx: 2, 3) + // expected-error@-1 {{incorrect argument label in call (have 'aa:xx:_:', expected 'aa:bb:_:_:')}} + // expected-error@-2:12 {{missing argument for parameter 'bb' in call}} + + f(aa: 1, bb: 2, 3, xx: 4) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + + f(aa: 1, bb: 2, xx: 3, 4) + // expected-error@-1 {{extraneous argument label 'xx:' in call}} + } + + do { + func f(_ aa: Int, bb: Int, _ cc: Int, dd: Int, _ ee: Int) { } + + f(1, bb: 2, 3, 4, dd: 5) + // expected-error@-1:23 {{argument 'dd' must precede unnamed argument #4}} + + f(1, dd: 2, 3, 4, bb: 5) + // expected-error@-1 {{incorrect argument labels in call (have '_:dd:_:_:bb:', expected '_:bb:_:dd:_:')}} + + f(1, bb: 2, 3, dd: 4, 5) // ok + + f(1, dd: 2, 3, bb: 4, 5) + // expected-error@-1 {{incorrect argument labels in call (have '_:dd:_:bb:_:', expected '_:bb:_:dd:_:')}} + + f(1, 2, bb: 3, 4, dd: 5, 6) + // expected-error@-1:30 {{extra argument in call}} + + f(1, bb: 2, 3, 4, dd: 5, 6) + // expected-error@-1:30 {{extra argument in call}} + + f(1, dd: 2, 3, 4, bb: 5, 6) + // expected-error@-1:30 {{extra argument in call}} } } diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index f184629fa37f4..a3a2de3f5ee24 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -478,3 +478,20 @@ func rdar_60048356() { } } } + +// rdar://problem/63510989 - valid pattern doesn't type-check +func rdar63510989() { + enum Value : P { + func p() {} + } + + enum E { + case foo(P?) + } + + func test(e: E) { + if case .foo(_ as Value) = e {} // Ok + if case .foo(let v as Value) = e {} // Ok + // expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}} + } +} diff --git a/test/DebugInfo/ASTPrinter-imported-names.swift b/test/DebugInfo/ASTPrinter-imported-names.swift new file mode 100644 index 0000000000000..18929674e4cae --- /dev/null +++ b/test/DebugInfo/ASTPrinter-imported-names.swift @@ -0,0 +1,12 @@ +// REQUIRES: executable_test +// REQUIRES: objc_interop +// RUN: %empty-directory(%t) +// RUN: echo '$sSo3FooVD' > %t/list +// RUN: %target-build-swift -emit-executable %s -g -o %t/a.out -I %S/Inputs \ +// RUN: -module-name ASTPrinter -emit-module +// RUN: %lldb-moduleimport-test -qualify-types \ +// RUN: -type-from-mangled=%t/list %t/a.out | %FileCheck %s +// This name should come out fully qualified. +// CHECK: ClangModule.Foo +import ClangModule +let foo = Foo() diff --git a/test/DebugInfo/curry_thunk.swift b/test/DebugInfo/curry_thunk.swift index 3197a6a78ac17..aed9a2a48dfbd 100644 --- a/test/DebugInfo/curry_thunk.swift +++ b/test/DebugInfo/curry_thunk.swift @@ -4,5 +4,5 @@ public func testCurryThunk() -> [HTTPMethod] { return ["asdf"].map(HTTPMethod.init) } -// CHECK: [[FILE:![0-9]+]] = !DIFile(filename: "{{.*}}/curry_thunk.swift", directory: "{{.*}}") +// CHECK: [[FILE:![0-9]+]] = !DIFile(filename: "{{.*[/\\]}}curry_thunk.swift", directory: "{{.*}}") // CHECK: {{![0-9]+}} = !DILocalVariable(name: "rawValue", arg: 1, scope: {{![0-9]+}}, file: {{![0-9]+}}, type: {{![0-9]+}}, flags: DIFlagArtificial) diff --git a/test/DebugInfo/inlined-generics-basic.swift b/test/DebugInfo/inlined-generics-basic.swift index 93f13e5d05955..5dddba06245a5 100644 --- a/test/DebugInfo/inlined-generics-basic.swift +++ b/test/DebugInfo/inlined-generics-basic.swift @@ -91,9 +91,9 @@ public class C { // IR-LABEL: ret void // IR: ![[BOOL:[0-9]+]] = !DICompositeType({{.*}}name: "Bool" -// IR: ![[LET_BOOL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[BOOL]]) // IR: ![[INT:[0-9]+]] = !DICompositeType({{.*}}name: "Int" // IR: ![[LET_INT:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[INT]]) +// IR: ![[LET_BOOL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[BOOL]]) // IR: ![[TAU_0_0:[0-9]+]] = {{.*}}DW_TAG_structure_type, name: "$sxD", // IR: ![[LET_TAU_0_0:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[TAU_0_0]]) // IR: ![[TAU_1_0:[0-9]+]] = {{.*}}DW_TAG_structure_type, name: "$sqd__D", diff --git a/test/Demangle/demangle-special-options.test b/test/Demangle/demangle-special-options.test new file mode 100644 index 0000000000000..87c54ca483780 --- /dev/null +++ b/test/Demangle/demangle-special-options.test @@ -0,0 +1,12 @@ +RUN: swift-demangle -display-stdlib-module=true sSi | %FileCheck %s --check-prefix=SWIFT-INT +SWIFT-INT: {{ Swift.Int$}} +RUN: swift-demangle -display-stdlib-module=false sSi | %FileCheck %s --check-prefix=INT +INT: {{ Int$}} + +RUN: swift-demangle -display-objc-module=true sSo6CGRectVD | %FileCheck %s --check-prefix=OBJC-CGRECT +OBJC-CGRECT: {{ __C.CGRect$}} +RUN: swift-demangle -display-objc-module=false sSo6CGRectVD | %FileCheck %s --check-prefix=CGRECT +CGRECT: {{ CGRect$}} + +RUN: swift-demangle -hiding-module=foo _TtC3foo3bar | %FileCheck %s --check-prefix=BAR +BAR: {{ bar$}} diff --git a/test/Demangle/lit.local.cfg b/test/Demangle/lit.local.cfg new file mode 100644 index 0000000000000..a8d933b5bdcfd --- /dev/null +++ b/test/Demangle/lit.local.cfg @@ -0,0 +1,2 @@ +# suffixes: A list of file extensions to treat as test files. +config.suffixes.add('.test') diff --git a/test/IDE/complete_skipbody.swift b/test/IDE/complete_skipbody.swift new file mode 100644 index 0000000000000..9b9d3f61e13b2 --- /dev/null +++ b/test/IDE/complete_skipbody.swift @@ -0,0 +1,63 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token FUNCTIONBODY -debug-forbid-typecheck-prefix FORBIDDEN | %FileCheck %s +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token TOPLEVEL -debug-forbid-typecheck-prefix FORBIDDEN | %FileCheck %s + +struct FORBIDDEN_Struct { + func FORBIDDEN_method() -> Int? { 1 } +} + +struct MyStruct { + var x: Int { 1 } + var y: Int { 1 } +} + +let globalUnrelated = FORBIDDEN_Struct(); + +guard let globalValueOpt = MyStruct() as MyStruct?? else { + let localUnrelated = FORBIDDEN_Struct(); + fatalError() +} + +func test(valueOptOpt: MyStruct??) { + + let FORBIDDEN_localVar = 1 + let unrelated = FORBIDDEN_Struct() + + let valueOpt = valueOptOpt! + + guard let a = unrelated.FORBIDDEN_method() else { + return + } + + guard let value = valueOpt else { + let FORBIDDEN_localVar2 = 1 + return + } + + if (value.x == 1) { + let unrelated2 = FORBIDDEN_Struct() + switch value.x { + case let x where x < 2: + let unrelated3 = FORBIDDEN_Struct() + if x == value.#^FUNCTIONBODY^# {} + default: + break + } + } +} + +let globalValue = globalValueOpt! + +let FORBIDDEN_globalVar = 1 + +switch glovalValue.x { +case let x where x < 2: + if x == globalValue.#^TOPLEVEL^# {} +default: + break +} + +// CHECK: Begin completions, 3 items +// CHECK-DAG: Keyword[self]/CurrNominal: self[#MyStruct#]; name=self +// CHECK-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; name=x +// CHECK-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; name=y +// CHECK: End completions diff --git a/test/IDE/complete_sself.swift b/test/IDE/complete_sself.swift new file mode 100644 index 0000000000000..93b7f6da4bea7 --- /dev/null +++ b/test/IDE/complete_sself.swift @@ -0,0 +1,223 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_EXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_BODY_TYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_VARBODY_EXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBAL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=NOSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VAR_TYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_BODY_TYPE | %FileCheck %s --check-prefix=GENERICPARAM +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=GENERICPARAM + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VAR_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_EXPR | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_BODY_TYPE | %FileCheck %s --check-prefix=STATICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STRUCTEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=STATICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_FUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_PARAMTYPE | %FileCheck %s --check-prefix=NOSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_SUBSCRIPT_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VAR_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_BODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASSEXT_VARBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF + +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDBODY_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_PARAMTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_DEFAULTEXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDFUNC_RESULTTYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_TYPEALIAS_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_EXPR | %FileCheck %s --check-prefix=DYNAMICSELF +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLASS_NESTEDTYPE_TYPE | %FileCheck %s --check-prefix=DYNAMICSELF + +// NOSELF: Begin completions +// NOSELF-NOT: name=Self +// NOSELF: End completions + +// GENERICPARAM: Begin completions +// GENERICPARAM: Decl[GenericTypeParam]/Local: Self[#Self#]; + +// STATICSELF: Begin completions +// STATICSELF: Keyword[Self]/CurrNominal: Self[#S#]; + +// DYNAMICSELF: Begin completions +// DYNAMICSELF: Keyword[Self]/CurrNominal: Self[#Self#]; + +func freeFunc() { + #^GLOBAL_BODY_EXPR^# + let _: #^GLOBAL_BODY_TYPE^# +} +var freeVar: String { + "\(#^GLOBAL_VARBODY_EXPR^#)" +} +func freeFunc(x: #^GLOBAL_FUNC_PARAMTYPE^#) {} +func freeFunc(x: Int = #^GLOBAL_FUNC_DEFAULTEXPR^#) {} +func freeFunc(x: Int) -> #^GLOBAL_FUNC_RESULTTYPE^# {} + +var x: ^#GLOBAL_VAR_TYPE^# + +func sync() {} + +protocol P { + func protoMeth(x: #^PROTOCOL_FUNC_PARAMTYPE^#) + func protoMeth(x: Int) -> #^PROTOCOL_FUNC_RESULTTYPE^# + + subscript(x: #^PROTOCOL_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^PROTOCOL_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^PROTOCOL_VAR_TYPE^# +} +extension P { + func method(x: #^PROTOEXT_FUNC_PARAMTYPE^#) { } + func method(x: Int = #^PROTOEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^PROTOEXT_FUNC_RESULTTYPE^# { } + + subscript(x: #^PROTOEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { } + subscript(y: Int) -> #^PROTOEXT_SUBSCRIPT_RESULTTYPE^# { } + + var x: #^PROTOEXT_VAR_TYPE^# { } + + func bodyTest() { + #^PROTOEXT_BODY_EXPR^# + let _: #^PROTOEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^PROTOEXT_VARBODY_EXPR^#)" + } +} + +struct S { + func method(x: #^STRUCT_FUNC_PARAMTYPE^#) + func method(x: Int = #^STRUCT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^STRUCT_FUNC_RESULTTYPE^# + + subscript(x: #^STRUCT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^STRUCT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^STRUCT_VAR_TYPE^# + + func bodyTest() { + #^STRUCT_BODY_EXPR^# + let _: #^STRUCT_BODY_TYPE^# + } + var varTest: String { + "\(#^STRUCT_VARBODY_EXPR^#)" + } +} +extension S { + func method(x: #^STRUCTEXT_FUNC_PARAMTYPE^#) + func method(x: Int = #^STRUCTEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^STRUCTEXT_FUNC_RESULTTYPE^# + + subscript(x: #^STRUCTEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^STRUCTEXT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^STRUCTEXT_VAR_TYPE^# + + func bodyTest() { + #^STRUCTEXT_BODY_EXPR^# + let _: #^STRUCTEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^STRUCTEXT_VARBODY_EXPR^#)" + } +} + +class C { + func method(x: #^CLASS_FUNC_PARAMTYPE^#) + func method(x: Int = #^CLASS_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^CLASS_FUNC_RESULTTYPE^# + + subscript(x: #^CLASS_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^CLASS_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^CLASS_VAR_TYPE^# + + func bodyTest() { + #^CLASS_BODY_EXPR^# + let _: #^CLASS_BODY_TYPE^# + } + var varTest: String { + "\(#^CLASS_VARBODY_EXPR^#)" + } +} +class CC {} +extension CC { + func method(x: #^CLASSEXT_FUNC_PARAMTYPE^#) + func method(x: Int = #^CLASSEXT_FUNC_DEFAULTEXPR^#) { } + func method(x: Int) -> #^CLASSEXT_FUNC_RESULTTYPE^# + + subscript(x: #^CLASSEXT_SUBSCRIPT_PARAMTYPE^#) -> Int { get } + subscript(y: Int) -> #^CLASSEXT_SUBSCRIPT_RESULTTYPE^# { get } + + var x: #^CLASSEXT_VAR_TYPE^# + + func bodyTest() { + #^CLASSEXT_BODY_EXPR^# + let _: #^CLASSEXT_BODY_TYPE^# + } + var varTest: String { + "\(#^CLASSEXT_VARBODY_EXPR^#)" + } +} + +class CCC { + func bodyTest() { + func inner() { + #^CLASS_NESTEDBODY_EXPR^# + let _: #^CLASS_NESTEDBODY_TYPE^# + } + + func inner(x: #^CLASS_NESTEDFUNC_PARAMTYPE^#) {} + func inner(y: Int = #^CLASS_NESTEDFUNC_DEFAULTEXPR^#) {} + func inner() -> #^CLASS_NESTEDFUNC_RESULTTYPE^# {} + + typealias A = #^CLASS_TYPEALIAS_TYPE^# + } + class Inner { + func method() { + #^CLASS_NESTEDTYPE_EXPR^# + let _: #^CLASS_NESTEDTYPE_TYPE^# + } + } +} diff --git a/test/IRGen/c_globals.swift b/test/IRGen/c_globals.swift index 489167a65207f..f19f9f4a8d566 100644 --- a/test/IRGen/c_globals.swift +++ b/test/IRGen/c_globals.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-cpu +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECK -check-prefix CHECK-%target-cpu-%target-abi import c_layout @@ -31,23 +31,37 @@ public func testCaptureGlobal() { }) // CHECK: {{^}$}} } -// CHECK-i386-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-i386-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-i386-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-i386-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-i386-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-i386-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" -// CHECK-x86_64-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-x86_64-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-x86_64-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-x86_64-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-x86_64-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="none"{{.*}} +// CHECK-x86_64-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="none" {{.*}}"target-cpu" -// CHECK-armv7-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-armv7-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" -// CHECK-armv7s-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-armv7s-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7s-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7s-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7s-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7s-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" -// CHECK-armv7k-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-armv7k-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7k-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7k-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-armv7k-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} +// CHECK-armv7k-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" -// CHECK-arm64-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} -// CHECK-arm64-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" -// CHECK-arm64e-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} -// CHECK-arm64e-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64e-SYSV-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64e-SYSV-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" +// CHECK-arm64e-WIN-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} +// CHECK-arm64e-WIN-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="non-leaf" {{.*}}"target-cpu" diff --git a/test/IRGen/framepointer.sil b/test/IRGen/framepointer.sil index ab1d393011a36..62062ec2eef11 100644 --- a/test/IRGen/framepointer.sil +++ b/test/IRGen/framepointer.sil @@ -1,6 +1,8 @@ -// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK -// RUN: %target-swift-frontend -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL +// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s -check-prefix CHECK --check-prefix=CHECK-%target-abi +// RUN: %target-swift-frontend -primary-file %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s -check-prefix CHECK-ALL --check-prefix=CHECK-%target-abi-ALL // RUN: %target-swift-frontend -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM --check-prefix=CHECKASM-%target-os-%target-cpu +// RUN: %target-swift-frontend -primary-file %s -emit-ir -Xcc -momit-leaf-frame-pointer | %FileCheck %s -check-prefix LEAF --check-prefix=LEAF-%target-abi +// RUN: %target-swift-frontend -primary-file %s -emit-ir -Xcc -fomit-frame-pointer | %FileCheck %s --check-prefix=NOFP // REQUIRES: CPU=x86_64 @@ -31,7 +33,8 @@ entry(%i : $Int32): // CHECK: ret i32 %1 // CHECK: } -// CHECK: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" +// CHECK-SYSV: attributes [[ATTR]] = { {{.*}}"frame-pointer"="all" +// CHECK-WIN: attributes [[ATTR]] = { {{.*}}"frame-pointer"="none" // CHECK-ALL: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { // CHECK-ALL: entry: @@ -44,7 +47,35 @@ entry(%i : $Int32): // CHECK-ALL: ret i32 %1 // CHECK-ALL: } -// CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" +// CHECK-SYSV-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" +// CHECK-WIN-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="none" + +// LEAF: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// LEAF: entry: +// LEAF: ret i32 %0 +// LEAF: } + +// LEAF: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// LEAF: entry: +// LEAF: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// LEAF: ret i32 %1 +// LEAF: } + +// LEAF-SYSV: attributes [[ATTR]] = {{{.*}}"frame-pointer"="non-leaf" +// LEAF-WIN: attributes [[ATTR]] = {{{.*}}"frame-pointer"="none" + +// NOFP: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// NOFP: entry: +// NOFP: ret i32 %0 +// NOFP: } + +// NOFP: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// NOFP: entry: +// NOFP: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// NOFP: ret i32 %1 +// NOFP: } + +// NOFP: attributes [[ATTR]] = {{{.*}}"frame-pointer"="none" // Silence other os-archs. // CHECKASM: {{.*}} diff --git a/test/IRGen/framepointer_arm64.sil b/test/IRGen/framepointer_arm64.sil index 2ab1c7e888535..0f99f4dd7a8ad 100644 --- a/test/IRGen/framepointer_arm64.sil +++ b/test/IRGen/framepointer_arm64.sil @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK -// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir -Xcc -mno-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL // RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM -// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S -no-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECKASM-ALL +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECKASM-ALL // REQUIRES: CODEGENERATOR=AArch64 // REQUIRES: OS=ios diff --git a/test/Index/Store/ignore-system-clang-modules.swift b/test/Index/Store/ignore-system-clang-modules.swift new file mode 100644 index 0000000000000..7147488165fdf --- /dev/null +++ b/test/Index/Store/ignore-system-clang-modules.swift @@ -0,0 +1,35 @@ +// RUN: %empty-directory(%t) + +// Make a basic clang framework to import +// +// RUN: %empty-directory(%t/MySystemFramework.framework/Headers) +// RUN: %empty-directory(%t/MySystemFramework.framework/Modules) +// RUN: echo 'void someSystemFunc(int arg);' > %t/MySystemFramework.framework/Headers/MySystemFramework.h +// RUN: echo 'framework module MySystemFramework { umbrella header "MySystemFramework.h" export * }' > %t/MySystemFramework.framework/Modules/module.modulemap + +import MySystemFramework +someSystemFunc(2) + +// Index this file with and without ignoring system frameworks +// +// RUN: %target-swiftc_driver -index-store-path %t/idx1 -o %t/file.o -Fsystem %t -typecheck %s +// RUN: %target-swiftc_driver -index-store-path %t/idx2 -o %t/file.o -index-ignore-system-modules -Fsystem %t -typecheck %s +// RUN: c-index-test core -print-unit %t/idx1 | %FileCheck --check-prefixes=ALLOWSYSTEM,BOTH %s +// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck --check-prefixes=IGNORESYSTEM,BOTH %s + +// We should always get a dependency on the system framework in the unit for this file's module. +// +// BOTH: DEPEND START +// BOTH: Unit | system | MySystemFramework | +// BOTH: DEPEND END + +// We should get a unit for the system framework if not ignoring them. +// +// ALLOWSYSTEM: provider: clang +// ALLOWSYSTEM-NEXT: is-system: 1 +// ALLOWSYSTEM-NEXT: is-module: 1 +// ALLOWSYSTEM-NEXT: module-name: MySystemFramework + +// But shouldn't if we are. +// +// IGNORESYSTEM-NOT: module-name: MySystemFramework diff --git a/test/Index/index_keypath_member_lookup.swift b/test/Index/index_keypath_member_lookup.swift index 78ce511d319e8..247bd1a1feabf 100644 --- a/test/Index/index_keypath_member_lookup.swift +++ b/test/Index/index_keypath_member_lookup.swift @@ -137,3 +137,24 @@ func testExplicit(r: Lens, a: Lens<[Int]>) { // CHECK: [[EA_LINE]]:8 | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB_USR]] | Ref,Read,RelCont | rel: 1 // CHECK: [[EA_LINE]]:26 | instance-property/subscript/Swift | subscript(_:) | s:SayxSicip | Ref,Read,RelCont | rel: 1 } + +// Don't crash: rdar63558609 +// +@dynamicMemberLookup +protocol Foo { + var prop: Bar {get} + // CHECK: [[@LINE-1]]:7 | instance-property/Swift | prop | [[PROP_USR:.*]] | Def,RelChild | rel: 1 +} +struct Bar { + let enabled = false +} +extension Foo { + subscript(dynamicMember keyPath: KeyPath) -> T { + // CHECK: [[@LINE-1]]:3 | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB2_USR:.*]] | Def,RelChild | rel: 1 + // CHECK: [[@LINE-2]]:60 | instance-method/acc-get/Swift | getter:subscript(dynamicMember:) | {{.*}} | Def,Dyn,RelChild,RelAcc | rel: 1 + // CHECK-NEXT: RelChild,RelAcc | instance-property/subscript/Swift | subscript(dynamicMember:) | [[SUB2_USR]] + + prop[keyPath: keyPath] + // CHECK: [[@LINE-1]]:5 | instance-property/Swift | prop | [[PROP_USR]] | Ref,Read,RelCont | rel: 1 + } +} diff --git a/test/Index/index_objc_dynamic_refs.swift b/test/Index/index_objc_dynamic_refs.swift new file mode 100644 index 0000000000000..c42805b38b5fc --- /dev/null +++ b/test/Index/index_objc_dynamic_refs.swift @@ -0,0 +1,26 @@ +// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s +// REQUIRES: objc_interop + +import Foundation + +@objc protocol AProtocol { + @objc optional func dynamicMethod() + // CHECK: [[@LINE-1]]:25 | instance-method/Swift | dynamicMethod() | [[DynamicMethod_USR:.*]] | Def + @objc optional var property: String { get } + // CHECK: [[@LINE-1]]:24 | instance-property/Swift | property | [[DynamicProperty_USR:.*]] | Def +} + +class AClass { + + weak var objcDelegate: AProtocol? + // CHECK: [[@LINE-1]]:14 | instance-property/Swift | objcDelegate | [[Delegate_USR:.*]] | Def + + func doSomething() { + objcDelegate?.dynamicMethod?() + // CHECK: [[@LINE-1]]:9 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + // CHECK: [[@LINE-2]]:23 | instance-method/Swift | dynamicMethod() | [[DynamicMethod_USR]] | Ref + _ = objcDelegate?.property + // CHECK: [[@LINE-1]]:13 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + // CHECK: [[@LINE-2]]:27 | instance-property/Swift | property | [[DynamicProperty_USR]] | Ref + } +} diff --git a/test/Interop/Cxx/operators/Inputs/module.modulemap b/test/Interop/Cxx/operators/Inputs/module.modulemap index 3fad5697d2a02..2cc3fa14cd834 100644 --- a/test/Interop/Cxx/operators/Inputs/module.modulemap +++ b/test/Interop/Cxx/operators/Inputs/module.modulemap @@ -1,3 +1,7 @@ module NonMemberInline { header "non-member-inline.h" } + +module NonMemberOutOfLine { + header "non-member-out-of-line.h" +} diff --git a/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp b/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp new file mode 100644 index 0000000000000..d6bccca7e7be0 --- /dev/null +++ b/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp @@ -0,0 +1,5 @@ +#include "non-member-out-of-line.h" + +IntBox operator+(IntBox lhs, IntBox rhs) { + return IntBox{.value = lhs.value + rhs.value}; +} diff --git a/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h b/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h new file mode 100644 index 0000000000000..a0466d812d8c5 --- /dev/null +++ b/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h @@ -0,0 +1,10 @@ +#ifndef TEST_INTEROP_CXX_OPERATORS_INPUTS_NON_MEMBER_OUT_OF_LINE_H +#define TEST_INTEROP_CXX_OPERATORS_INPUTS_NON_MEMBER_OUT_OF_LINE_H + +struct IntBox { + int value; +}; + +IntBox operator+(IntBox lhs, IntBox rhs); + +#endif diff --git a/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift b/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift new file mode 100644 index 0000000000000..456520b248e0a --- /dev/null +++ b/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift @@ -0,0 +1,8 @@ +// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import NonMemberOutOfLine + +public func add(_ lhs: IntBox, _ rhs: IntBox) -> IntBox { lhs + rhs } + +// CHECK: call {{i32|i64}} [[NAME:@(_Zpl6IntBoxS_|"\?\?H@YA\?AUIntBox@@U0@0@Z")]]({{i32|\[1 x i32\]|i64}} %{{[0-9]+}}, {{i32|\[1 x i32\]|i64}} %{{[0-9]+}}) +// CHECK: declare {{(dso_local )?}}{{i32|i64}} [[NAME]]({{i32|\[1 x i32\]|i64}}, {{i32|\[1 x i32\]|i64}}) diff --git a/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift b/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift new file mode 100644 index 0000000000000..302efa7cf8a1d --- /dev/null +++ b/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift @@ -0,0 +1,10 @@ +// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import NonMemberOutOfLine + +public func add(_ lhs: IntBox, _ rhs: IntBox) -> IntBox { lhs + rhs } + +// CHECK: [[COUNTER:%.*]] = function_ref [[NAME:@(_Zpl6IntBoxS_|\?\?H@YA\?AUIntBox@@U0@0@Z)]] : $@convention(c) (IntBox, IntBox) -> IntBox +// CHECK: apply [[COUNTER]](%0, %1) : $@convention(c) (IntBox, IntBox) -> IntBox + +// CHECK: sil [serializable] [clang "+"] [[NAME]] : $@convention(c) (IntBox, IntBox) -> IntBox diff --git a/test/Interop/Cxx/operators/non-member-out-of-line.swift b/test/Interop/Cxx/operators/non-member-out-of-line.swift new file mode 100644 index 0000000000000..55a4fc8506650 --- /dev/null +++ b/test/Interop/Cxx/operators/non-member-out-of-line.swift @@ -0,0 +1,23 @@ +// RUN: %empty-directory(%t) +// RUN: %target-clang -c %S/Inputs/non-member-out-of-line.cpp -I %S/Inputs -o %t/non-member-out-of-line.o -std=c++17 +// RUN: %target-build-swift %s -I %S/Inputs -o %t/non-member-out-of-line %t/non-member-out-of-line.o -Xfrontend -enable-cxx-interop +// RUN: %target-codesign %t/non-member-out-of-line +// RUN: %target-run %t/non-member-out-of-line +// +// REQUIRES: executable_test + +import NonMemberOutOfLine +import StdlibUnittest + +var OperatorsTestSuite = TestSuite("Operators") + +OperatorsTestSuite.test("plus") { + let lhs = IntBox(value: 42) + let rhs = IntBox(value: 23) + + let result = lhs + rhs + + expectEqual(65, result.value) +} + +runAllTests() diff --git a/test/Migrator/rdar31892850.swift b/test/Migrator/rdar31892850.swift index e910a0ecf9ea1..b8c861cc0a772 100644 --- a/test/Migrator/rdar31892850.swift +++ b/test/Migrator/rdar31892850.swift @@ -21,6 +21,6 @@ func foo() { // CHECK: { // CHECK: "file": "{{.*}}rdar31892850.swift", // CHECK: "offset": 329, -// CHECK: "text": ")" +// CHECK: "text": ") ?? <#default value#>" // CHECK: } // CHECK:] diff --git a/test/Misc/stats_dir_profiler.swift b/test/Misc/stats_dir_profiler.swift index 87b86d005e199..2fb630e9345f1 100644 --- a/test/Misc/stats_dir_profiler.swift +++ b/test/Misc/stats_dir_profiler.swift @@ -7,7 +7,7 @@ // RUN: %FileCheck -check-prefix=ENTITIES -input-file %t/stats-entities/*.dir/Time.User.entities %s // EVENTS: {{perform-sema;.*;typecheck-decl.* [0-9]+}} -// ENTITIES: {{perform-sema;.*;TypeCheckFunctionBodyUntilRequest bar\(\);typecheck-stmt.* [0-9]+}} +// ENTITIES: {{perform-sema;.*;TypeCheckFunctionBodyRequest bar\(\);typecheck-stmt.* [0-9]+}} public func foo() { print("hello") diff --git a/test/Runtime/environment_variables.swift b/test/Runtime/environment_variables.swift new file mode 100644 index 0000000000000..8f772339d3011 --- /dev/null +++ b/test/Runtime/environment_variables.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -o %t/main +// RUN: %target-codesign %t/main +// RUN: env %env-SWIFT_DEBUG_HELP=YES %env-SWIFT_DEBUG_SOME_UNKNOWN_VARIABLE=42 %env-SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION=YES %env-SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT=abc %env-SWIFT_DETERMINISTIC_HASHING=whatever %env-SWIFT_ENABLE_MANGLED_NAME_VERIFICATION=YES %target-run %t/main 2>&1 | %FileCheck %s --dump-input fail + +// CHECK-DAG: {{Warning: unknown environment variable SWIFT_DEBUG_SOME_UNKNOWN_VARIABLE|Using getenv to read variables. Unknown variables will not be flagged.}} +// CHECK-DAG: Warning: cannot parse value SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT=abc, defaulting to 2. +// CHECK-DAG: Warning: cannot parse value SWIFT_DETERMINISTIC_HASHING=whatever, defaulting to false. +// CHECK-DAG: Swift runtime debugging: +// CHECK-DAG: bool SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION [default: false] - Enable additional metadata allocation tracking for swift-inspect to use. +// CHECK-DAG: uint8_t SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT [default: 2] - Print warnings when using implicit @objc entrypoints. Set to desired reporting level, 0-3. +// CHECK-DAG: bool SWIFT_DETERMINISTIC_HASHING [default: false] - Disable randomized hash seeding. +// CHECK-DAG: bool SWIFT_ENABLE_MANGLED_NAME_VERIFICATION [default: false] - Enable verification that metadata can roundtrip through a mangled name each time metadata is instantiated. + +print("Hello, world") +// CHECK: Hello, world diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil index ccc691560c6b8..b144a203448b2 100644 --- a/test/SIL/Parser/basic.sil +++ b/test/SIL/Parser/basic.sil @@ -1688,11 +1688,22 @@ bb0: return %1 : $() } +class Foo2: Foo {} + // CHECK-LABEL: sil_vtable Foo { -// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter -// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter [override] +// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [nonoverridden] +// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter // CHECK: } sil_vtable Foo { - #Foo.subscript!getter: @Foo_subscript_getter + #Foo.subscript!getter: @Foo_subscript_getter [nonoverridden] + #Foo.subscript!setter: @Foo_subscript_setter +} + +// CHECK-LABEL: sil_vtable Foo2 { +// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [inherited] +// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter [override] +// CHECK: } +sil_vtable Foo2 { + #Foo.subscript!getter: @Foo_subscript_getter [inherited] #Foo.subscript!setter: @Foo_subscript_setter [override] } diff --git a/test/SIL/memory_lifetime.sil b/test/SIL/memory_lifetime.sil index f9bf57bf5cfa9..ae06853e8a5db 100644 --- a/test/SIL/memory_lifetime.sil +++ b/test/SIL/memory_lifetime.sil @@ -377,3 +377,20 @@ bb6(%45 : @owned $Error): br bb4(%45 : $Error) } +sil [ossa] @test_memory_lifetime_select_enum : $@convention(thin) (@in_guaranteed Optional) -> () { +bb0(%0 : $*Optional): + %2 = integer_literal $Builtin.Int1, 0 + %3 = integer_literal $Builtin.Int1, 1 + %4 = select_enum_addr %0 : $*Optional, case #Optional.none!enumelt: %2, case #Optional.some!enumelt: %3 : $Builtin.Int1 + cond_br %4, bb1, bb2 + +bb1: + br bb3 + +bb2: + br bb3 + +bb3: + %9999 = tuple() + return %9999 : $() +} diff --git a/test/SIL/ownership-verifier/load_borrow_invalidation_test.sil b/test/SIL/ownership-verifier/load_borrow_invalidation_test.sil index 384b3ac9a7ad3..ccefe097ce8d1 100644 --- a/test/SIL/ownership-verifier/load_borrow_invalidation_test.sil +++ b/test/SIL/ownership-verifier/load_borrow_invalidation_test.sil @@ -8,6 +8,8 @@ import Builtin // patterns look next door for verifier error checks. sil @inoutCallee : $@convention(thin) (@inout Builtin.NativeObject) -> () +sil @guaranteedUser : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () +sil @useRawPointer : $@convention(thin) (Builtin.RawPointer) -> () ////////////////////////// // InOut Argument Tests // @@ -375,3 +377,21 @@ bb3: %9999 = tuple() return %9999 : $() } + +sil [ossa] @pointer_to_address_is_assumed_to_be_safe : $@convention(thin) (@owned Builtin.NativeObject) -> () { +bb0(%0 : @owned $Builtin.NativeObject): + %1 = alloc_stack $Builtin.NativeObject + store %0 to [init] %1 : $*Builtin.NativeObject + %2 = load_borrow %1 : $*Builtin.NativeObject + %gUser = function_ref @guaranteedUser : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + apply %gUser(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + end_borrow %2 : $Builtin.NativeObject + %3 = address_to_pointer %1 : $*Builtin.NativeObject to $Builtin.RawPointer + %4 = mark_dependence %3 : $Builtin.RawPointer on %1 : $*Builtin.NativeObject + %rawPointerUser = function_ref @useRawPointer : $@convention(thin) (Builtin.RawPointer) -> () + apply %rawPointerUser(%4) : $@convention(thin) (Builtin.RawPointer) -> () + destroy_addr %1 : $*Builtin.NativeObject + dealloc_stack %1 : $*Builtin.NativeObject + %9999 = tuple() + return %9999 : $() +} diff --git a/test/SILOptimizer/basic-callee-printer.sil b/test/SILOptimizer/basic-callee-printer.sil index 7b922899c3e6a..d4afd330fabcf 100644 --- a/test/SILOptimizer/basic-callee-printer.sil +++ b/test/SILOptimizer/basic-callee-printer.sil @@ -340,7 +340,7 @@ sil_vtable private_base { } sil_vtable private_derived { - #private_base.foo: @private_derived_foo + #private_base.foo: @private_derived_foo [override] } sil_vtable internal_base { @@ -349,8 +349,8 @@ sil_vtable internal_base { } sil_vtable internal_derived { - #internal_base.foo: @internal_derived_foo - #internal_base.bar: @internal_derived_bar + #internal_base.foo: @internal_derived_foo [override] + #internal_base.bar: @internal_derived_bar [override] } sil_vtable public_base { @@ -360,9 +360,9 @@ sil_vtable public_base { } sil_vtable public_derived { - #public_base.foo: @public_derived_foo - #public_base.bar: @public_derived_bar - #public_base.baz: @public_derived_baz + #public_base.foo: @public_derived_foo [override] + #public_base.bar: @public_derived_bar [override] + #public_base.baz: @public_derived_baz [override] } private protocol private_proto_1 { @@ -659,8 +659,8 @@ sil_vtable SomeItem { } sil_vtable SomeChildItem { - #SomeItem.init!allocator: @SomeChildItem_allocator - #SomeItem.init!initializer: @SomeChildItem_initializer + #SomeItem.init!allocator: @SomeChildItem_allocator [override] + #SomeItem.init!initializer: @SomeChildItem_initializer [override] #SomeChildItem.deinit!deallocator: @SomeChildItem_destructor } diff --git a/test/SILOptimizer/dead_func_init_method.sil b/test/SILOptimizer/dead_func_init_method.sil index 5777044b30567..41d203027d410 100644 --- a/test/SILOptimizer/dead_func_init_method.sil +++ b/test/SILOptimizer/dead_func_init_method.sil @@ -36,7 +36,7 @@ sil_vtable Base { } sil_vtable Derived { - #Base.init!allocator: @DerivedInit + #Base.init!allocator: @DerivedInit [override] } diff --git a/test/SILOptimizer/devirt_access.sil b/test/SILOptimizer/devirt_access.sil index b310d00b947a4..9efd7bc38e7e8 100644 --- a/test/SILOptimizer/devirt_access.sil +++ b/test/SILOptimizer/devirt_access.sil @@ -151,8 +151,8 @@ sil_vtable X { } sil_vtable Y { - #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int - #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y + #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited] + #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override] } sil_vtable A { @@ -161,6 +161,6 @@ sil_vtable A { } sil_vtable B { - #A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si // devirt_access2.B.ping (devirt_access2.B)() -> Swift.Int - #A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ // devirt_access2.B.init (devirt_access2.B.Type)() -> devirt_access2.B + #A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si [override] + #A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ [override] } diff --git a/test/SILOptimizer/devirt_access_ownership.sil b/test/SILOptimizer/devirt_access_ownership.sil index 3d4c8a844fd73..73acc56fb2972 100644 --- a/test/SILOptimizer/devirt_access_ownership.sil +++ b/test/SILOptimizer/devirt_access_ownership.sil @@ -147,8 +147,8 @@ sil_vtable X { } sil_vtable Y { - #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int - #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y + #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited] + #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override] } sil_vtable A { @@ -157,6 +157,6 @@ sil_vtable A { } sil_vtable B { - #A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si // devirt_access2.B.ping (devirt_access2.B)() -> Swift.Int - #A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ // devirt_access2.B.init (devirt_access2.B.Type)() -> devirt_access2.B + #A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si [override] + #A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ [override] } diff --git a/test/SILOptimizer/devirt_access_serialized.sil b/test/SILOptimizer/devirt_access_serialized.sil index 740c05c525065..88c787254af88 100644 --- a/test/SILOptimizer/devirt_access_serialized.sil +++ b/test/SILOptimizer/devirt_access_serialized.sil @@ -52,6 +52,6 @@ sil_vtable X { } sil_vtable Y { - #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int - #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y + #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited] + #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [inherited] } diff --git a/test/SILOptimizer/devirt_access_serialized_ownership.sil b/test/SILOptimizer/devirt_access_serialized_ownership.sil index 96dce13801b74..b2ecc2e1685cb 100644 --- a/test/SILOptimizer/devirt_access_serialized_ownership.sil +++ b/test/SILOptimizer/devirt_access_serialized_ownership.sil @@ -50,6 +50,6 @@ sil_vtable X { } sil_vtable Y { - #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int - #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y + #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited] + #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override] } diff --git a/test/SILOptimizer/devirt_override.sil b/test/SILOptimizer/devirt_override.sil index a8f8dd307194a..1c3ed84419dbd 100644 --- a/test/SILOptimizer/devirt_override.sil +++ b/test/SILOptimizer/devirt_override.sil @@ -16,6 +16,8 @@ class MD5 : Hash { } +sil @_TFC4test4HashcfMS0_FT_S0_ : $@convention(method) (@owned Hash) -> @owned Hash + sil @_TFC4test3MD5cfMS0_FT_S0_ : $@convention(method) (@owned MD5) -> @owned MD5 { bb0(%0 : $MD5): release_value %0 : $MD5 @@ -64,14 +66,15 @@ bb0: sil_vtable Hash { #Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ #Hash.hash: @_TFC4test4Hash4hashfS0_FT3MsgVs5UInt8_T_ + #Hash.init!initializer: @_TFC4test4HashcfMS0_FT_S0_ } sil_vtable MD5 { // vtable should be keyed with the least-derived method, otherwise // devirtualizer will choose the wrong function ref. - #Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ - #MD5.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_ - #Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ + #Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ [override] + #Hash.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_ [override] + #Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ [override] } class C { @@ -127,9 +130,9 @@ sil_vtable C { } sil_vtable D { - #C.doIt: @_TFC1b1D4doItfS0_FT_T_ + #C.doIt: @_TFC1b1D4doItfS0_FT_T_ [override] } sil_vtable E { - #C.doIt: @_TFC1b1E4doItfS0_FT_T_ + #C.doIt: @_TFC1b1E4doItfS0_FT_T_ [override] } diff --git a/test/SILOptimizer/devirt_override_ownership.sil b/test/SILOptimizer/devirt_override_ownership.sil index 8b4502d1bb319..e7f4b612d3c53 100644 --- a/test/SILOptimizer/devirt_override_ownership.sil +++ b/test/SILOptimizer/devirt_override_ownership.sil @@ -70,9 +70,9 @@ sil_vtable Hash { sil_vtable MD5 { // vtable should be keyed with the least-derived method, otherwise // devirtualizer will choose the wrong function ref. - #Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ + #Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ [override] #MD5.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_ - #Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ + #Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ [override] } class C { @@ -129,9 +129,9 @@ sil_vtable C { } sil_vtable D { - #C.doIt: @_TFC1b1D4doItfS0_FT_T_ + #C.doIt: @_TFC1b1D4doItfS0_FT_T_ [override] } sil_vtable E { - #C.doIt: @_TFC1b1E4doItfS0_FT_T_ + #C.doIt: @_TFC1b1E4doItfS0_FT_T_ [override] } diff --git a/test/SILOptimizer/devirt_speculative.sil b/test/SILOptimizer/devirt_speculative.sil index 5d30b50e980dc..a6aca304276be 100644 --- a/test/SILOptimizer/devirt_speculative.sil +++ b/test/SILOptimizer/devirt_speculative.sil @@ -41,8 +41,8 @@ sil_vtable Base { } sil_vtable Sub { - #Base.foo: @_TSubFooFun - #Base.exit: @Sub_exit + #Base.foo: @_TSubFooFun [override] + #Base.exit: @Sub_exit [override] } sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () { @@ -97,7 +97,7 @@ sil_vtable Base2 { } sil_vtable Sub2 { - #Base2.foo: @_TSub2FooFun + #Base2.foo: @_TSub2FooFun [override] } sil @test_objc_ancestry2 : $@convention(thin) (@guaranteed Base2) -> () { diff --git a/test/SILOptimizer/devirt_try_apply.sil b/test/SILOptimizer/devirt_try_apply.sil index 9f6e0f46b9a62..acb692b403658 100644 --- a/test/SILOptimizer/devirt_try_apply.sil +++ b/test/SILOptimizer/devirt_try_apply.sil @@ -848,7 +848,7 @@ sil_vtable D1 { } sil_vtable D3 { - #D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A// devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A + #D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A [override] // devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A } @@ -856,35 +856,35 @@ sil_vtable Base { #Base.foo: @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ #Base.boo1: @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ #Base.boo2: @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ - #Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD #Base.init!initializer: @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ + #Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD } sil_vtable Derived1 { - #Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ - #Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ - #Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ - #Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ + #Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ [override] + #Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ [override] + #Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ [override] + #Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ [override] #Derived1.deinit!deallocator: @_TFC16devirt_try_apply8Derived1D } sil_vtable Derived2 { - #Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 - #Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ - #Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ - #Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ + #Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 [override] + #Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ [override] + #Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ [override] + #Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ [override] #Derived2.deinit!deallocator: @_TFC16devirt_try_apply8Derived2D } sil_vtable CP1 { #CP1.foo: @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 - #CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D #CP1.init!initializer: @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_ + #CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D } sil_vtable CP2 { - #CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 - #CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ + #CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 [override] + #CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ [override] #CP2.deinit!deallocator: @_TFC16devirt_try_apply3CP2D } diff --git a/test/SILOptimizer/devirt_try_apply_ownership.sil b/test/SILOptimizer/devirt_try_apply_ownership.sil index 8484ebf278fff..dbafa34e9d331 100644 --- a/test/SILOptimizer/devirt_try_apply_ownership.sil +++ b/test/SILOptimizer/devirt_try_apply_ownership.sil @@ -800,11 +800,11 @@ sil_vtable A { } sil_vtable D1 { - #D1.f1: @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_// devirt_try_apply.D1.f1 () throws -> Swift.Optional + #D1.f1: @_TFC16devirt_try_apply2D12f1fzT_GSqCS_1A_ } sil_vtable D3 { - #D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A// devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A + #D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A [override] } @@ -812,35 +812,35 @@ sil_vtable Base { #Base.foo: @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_ #Base.boo1: @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_ #Base.boo2: @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__ - #Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD #Base.init!initializer: @_TFC16devirt_try_apply4BasecfMS0_FT_S0_ + #Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD } sil_vtable Derived1 { - #Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ - #Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ - #Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ - #Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ + #Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ [override] + #Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ [override] + #Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ [override] + #Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ [override] #Derived1.deinit!deallocator: @_TFC16devirt_try_apply8Derived1D } sil_vtable Derived2 { - #Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 - #Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ - #Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ - #Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ + #Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 [override] + #Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ [override] + #Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ [override] + #Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ [override] #Derived2.deinit!deallocator: @_TFC16devirt_try_apply8Derived2D } sil_vtable CP1 { #CP1.foo: @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32 - #CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D #CP1.init!initializer: @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_ + #CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D } sil_vtable CP2 { - #CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 - #CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ + #CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 [override] + #CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ [override] #CP2.deinit!deallocator: @_TFC16devirt_try_apply3CP2D } diff --git a/test/SILOptimizer/devirtualize.sil b/test/SILOptimizer/devirtualize.sil index 5b5aec40dc770..ea1404073dcae 100644 --- a/test/SILOptimizer/devirtualize.sil +++ b/test/SILOptimizer/devirtualize.sil @@ -152,5 +152,5 @@ sil_vtable B { } sil_vtable C { - #B.foo: @_TZFC4metaP33_7026FC13D35FB9700BACF693F51A99011B3foofMS0_FT_Si + #B.foo: @_TZFC4metaP33_7026FC13D35FB9700BACF693F51A99011B3foofMS0_FT_Si [inherited] } diff --git a/test/SILOptimizer/devirtualize2.sil b/test/SILOptimizer/devirtualize2.sil index f541edd1433f8..ccece5b436105 100644 --- a/test/SILOptimizer/devirtualize2.sil +++ b/test/SILOptimizer/devirtualize2.sil @@ -119,7 +119,7 @@ sil_vtable Bar { } sil_vtable Foo { - #Bar.ping: @_TFC4main3Foo4pingfS0_FT_T_ + #Bar.ping: @_TFC4main3Foo4pingfS0_FT_T_ [override] } diff --git a/test/SILOptimizer/devirtualize2_ownership.sil b/test/SILOptimizer/devirtualize2_ownership.sil index 72a9ced481dfb..4bec04b9738db 100644 --- a/test/SILOptimizer/devirtualize2_ownership.sil +++ b/test/SILOptimizer/devirtualize2_ownership.sil @@ -122,7 +122,7 @@ sil_vtable Bar { } sil_vtable Foo { - #Bar.ping: @_TFC4main3Foo4pingfS0_FT_T_ + #Bar.ping: @_TFC4main3Foo4pingfS0_FT_T_ [override] } diff --git a/test/SILOptimizer/devirtualize_ownership.sil b/test/SILOptimizer/devirtualize_ownership.sil index 7cbd0ed2e43a1..9003178eed2c2 100644 --- a/test/SILOptimizer/devirtualize_ownership.sil +++ b/test/SILOptimizer/devirtualize_ownership.sil @@ -153,5 +153,5 @@ sil_vtable B { } sil_vtable C { - #B.foo: @_TZFC4metaP33_7026FC13D35FB9700BACF693F51A99011B3foofMS0_FT_Si + #B.foo: @_TZFC4metaP33_7026FC13D35FB9700BACF693F51A99011B3foofMS0_FT_Si [inherited] } diff --git a/test/SILOptimizer/existential_spl_witness_method.swift b/test/SILOptimizer/existential_spl_witness_method.swift new file mode 100644 index 0000000000000..69b7d3198a450 --- /dev/null +++ b/test/SILOptimizer/existential_spl_witness_method.swift @@ -0,0 +1,45 @@ +// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=GenericSpecializer -Xllvm -sil-disable-pass=EarlyInliner -Xllvm -sil-disable-pass=PerfInliner -Xllvm -sil-disable-pass=LateInliner -emit-sil -sil-verify-all %s | %FileCheck %s + +// Test for ExistentialSpecializer when an existential type is passed to a witness_method func representation +protocol P { +@inline(never) + func myfuncP(_ q:Q) -> Int +} + +protocol Q { +@inline(never) + func myfuncQ() -> Int +} + +class C : P { + var id = 10 +@inline(never) + func myfuncP(_ q:Q) -> Int { + return id + } +} + +class D : Q { + var id = 20 +@inline(never) + func myfuncQ() -> Int { + return id + } +} + +// CHECK-LABEL: @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed Q, @in_guaranteed C) -> Int { +// CHECK: [[FR1:%.*]] = function_ref @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTWTf4en_n : $@convention(thin) <Ï„_0_0 where Ï„_0_0 : Q> (@in_guaranteed Ï„_0_0, @in_guaranteed C) -> Int +// CHECK: apply [[FR1]] +// CHECK-LABEL: } // end sil function '$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW' + +// CHECK-LABEL : @$s30existential_spl_witness_method3bazyyAA1P_p_AA1Q_ptFTf4ee_n : $@convention(thin) <Ï„_0_0, Ï„_0_1 where Ï„_0_0 : P, Ï„_0_1 : Q> (@in_guaranteed Ï„_0_0, @in_guaranteed Ï„_0_1) -> () { +// CHECK: [[FR2:%.*]] = function_ref @$s30existential_spl_witness_method1CCAA1PA2aDP7myfuncPySiAA1Q_pFTW : $@convention(witness_method: P) (@in_guaranteed Q, @in_guaranteed C) -> Int +// CHECK: apply [[FR2]] +// CHECK-LABEL: } // end sil function '$s30existential_spl_witness_method3bazyyAA1P_p_AA1Q_ptFTf4ee_n' +@inline(never) +func baz(_ p : P, _ q : Q) { + p.myfuncP(q) +} + +baz(C(), D()); + diff --git a/test/SILOptimizer/function_order.sil b/test/SILOptimizer/function_order.sil index a1a1aa8838027..b441f8c23ba15 100644 --- a/test/SILOptimizer/function_order.sil +++ b/test/SILOptimizer/function_order.sil @@ -280,7 +280,7 @@ sil_vtable private_base { } sil_vtable private_derived { - #private_base.foo: @private_derived_foo + #private_base.foo: @private_derived_foo [override] } sil_vtable internal_base { @@ -289,8 +289,8 @@ sil_vtable internal_base { } sil_vtable internal_derived { - #internal_base.foo: @internal_derived_foo - #internal_base.bar: @internal_derived_bar + #internal_base.foo: @internal_derived_foo [override] + #internal_base.bar: @internal_derived_bar [override] } sil_vtable public_base { @@ -300,9 +300,9 @@ sil_vtable public_base { } sil_vtable public_derived { - #public_base.foo: @public_derived_foo - #public_base.bar: @public_derived_bar - #public_base.baz: @public_derived_baz + #public_base.foo: @public_derived_foo [override] + #public_base.bar: @public_derived_bar [override] + #public_base.baz: @public_derived_baz [override] } private protocol private_proto_1 { diff --git a/test/SILOptimizer/mm_inlinecaches_multiple.sil b/test/SILOptimizer/mm_inlinecaches_multiple.sil index 434dbdac54e3f..df60e6f834f39 100644 --- a/test/SILOptimizer/mm_inlinecaches_multiple.sil +++ b/test/SILOptimizer/mm_inlinecaches_multiple.sil @@ -53,6 +53,6 @@ sil_vtable Foo { } sil_vtable Bar { - #Foo.ping: @_TFC8testcase3Foo4pingfS0_FT_T_ // testcase.Foo.ping (testcase.Foo)() -> () - #Foo.init!initializer: @_TFC8testcase3FoocfMS0_FT_S0_ // testcase.Foo.init (testcase.Foo.Type)() -> testcase.Foo + #Foo.ping: @_TFC8testcase3Foo4pingfS0_FT_T_ [inherited] + #Foo.init!initializer: @_TFC8testcase3FoocfMS0_FT_S0_ [inherited] } diff --git a/test/SILOptimizer/optimize_never.sil b/test/SILOptimizer/optimize_never.sil index f2ec719295843..2bcad7ba5011c 100644 --- a/test/SILOptimizer/optimize_never.sil +++ b/test/SILOptimizer/optimize_never.sil @@ -469,13 +469,13 @@ bb0(%0 : $Base): sil_vtable C { #C.foo: @$s14optimize_never1CC3foos5Int32VyF - #C.deinit!deallocator: @$s14optimize_never1CCfD #C.init!initializer: @$s14optimize_never1CCACycfc + #C.deinit!deallocator: @$s14optimize_never1CCfD } sil_vtable D { - #C.foo: @$s14optimize_never1DC3foos5Int32VyF - #C.init!initializer: @$s14optimize_never1DCACycfc + #C.foo: @$s14optimize_never1DC3foos5Int32VyF [override] + #C.init!initializer: @$s14optimize_never1DCACycfc [override] #D.deinit!deallocator: @$s14optimize_never1DCfD } @@ -485,12 +485,12 @@ sil_vtable Base { } sil_vtable Derived1 { - #Base.foo: @$s14optimize_never8Derived1C3foos5Int32VyF - #Base.boo: @$s14optimize_never8Derived1C3boos5Int32VyF + #Base.foo: @$s14optimize_never8Derived1C3foos5Int32VyF [override] + #Base.boo: @$s14optimize_never8Derived1C3boos5Int32VyF [override] } sil_vtable Derived2 { - #Base.foo: @$s14optimize_never8Derived2C3foos5Int32VyF - #Base.boo: @$s14optimize_never8Derived2C3boos5Int32VyF + #Base.foo: @$s14optimize_never8Derived2C3foos5Int32VyF [override] + #Base.boo: @$s14optimize_never8Derived2C3boos5Int32VyF [override] } diff --git a/test/SILOptimizer/polymorphic_inline_caches.sil b/test/SILOptimizer/polymorphic_inline_caches.sil index 86e6b2b509324..27750c07b4752 100644 --- a/test/SILOptimizer/polymorphic_inline_caches.sil +++ b/test/SILOptimizer/polymorphic_inline_caches.sil @@ -112,15 +112,15 @@ sil_vtable A { } sil_vtable B { - #A.ping: @_TFC25polymorphic_inline_caches1B4pingfS0_FBi32_Bi32_ + #A.ping: @_TFC25polymorphic_inline_caches1B4pingfS0_FBi32_Bi32_ [override] } sil_vtable C { - #A.ping: @_TFC25polymorphic_inline_caches1C4pingfS0_FBi32_Bi32_ + #A.ping: @_TFC25polymorphic_inline_caches1C4pingfS0_FBi32_Bi32_ [override] } sil_vtable D { - #A.ping: @_TFC25polymorphic_inline_caches1D4pingfS0_FBi32_Bi32_ + #A.ping: @_TFC25polymorphic_inline_caches1D4pingfS0_FBi32_Bi32_ [override] } protocol P { @@ -223,9 +223,9 @@ sil_vtable E { } sil_vtable F { - #E.foo: @_TFC5casts1F3foofS0_FT_T_ + #E.foo: @_TFC5casts1F3foofS0_FT_T_ [override] } sil_vtable G { - #E.foo: @_TFC5casts1G3foofS0_FT_T_ + #E.foo: @_TFC5casts1G3foofS0_FT_T_ [override] } diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil index 1c42c761f9996..f36740dc8c9d2 100644 --- a/test/SILOptimizer/semantic-arc-opts.sil +++ b/test/SILOptimizer/semantic-arc-opts.sil @@ -2548,3 +2548,16 @@ bb1: bb2(%39 : @owned $Klass): unreachable } + +// CHECK-LABEL: sil [ossa] @struct_with_multiple_nontrivial_operands : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { +// CHECK-NOT: copy_value +// CHECK: } // end sil function 'struct_with_multiple_nontrivial_operands' +sil [ossa] @struct_with_multiple_nontrivial_operands : $@convention(thin) (@guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { +bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject): + %0a = copy_value %0 : $Builtin.NativeObject + %1a = copy_value %1 : $Builtin.NativeObject + %2 = struct $NativeObjectPair(%0a : $Builtin.NativeObject, %1a : $Builtin.NativeObject) + destroy_value %2 : $NativeObjectPair + %9999 = tuple() + return %9999 : $() +} \ No newline at end of file diff --git a/test/SILOptimizer/sink.sil b/test/SILOptimizer/sink.sil index 56480b29be310..0774c50fdc1f8 100644 --- a/test/SILOptimizer/sink.sil +++ b/test/SILOptimizer/sink.sil @@ -244,7 +244,7 @@ sil_vtable X { } sil_vtable Y { - #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int - #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y + #X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited] + #X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override] } diff --git a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift index bd6e5057b9a47..d7c25eaa06f5f 100644 --- a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift +++ b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift @@ -22,7 +22,7 @@ let moduleDependencyGraph = try! decoder.decode( func findModuleBuildingCommand(_ moduleName: String) -> [String]? { for (_, dep) in moduleDependencyGraph.modules { - if dep.modulePath.hasSuffix(moduleName) { + if URL(fileURLWithPath: dep.modulePath).lastPathComponent == moduleName { switch dep.details { case .swift(let details): return details.commandLine @@ -39,6 +39,8 @@ func findModuleBuildingCommand(_ moduleName: String) -> [String]? { if let command = findModuleBuildingCommand(moduleName) { var result = swiftPath command.forEach { result += " \($0)"} + // Pass down additional args to the Swift invocation. + CommandLine.arguments.dropFirst(4).forEach { result += " \($0)"} print(result) exit(0) } else { diff --git a/test/ScanDependencies/Inputs/Swift/A.swiftinterface b/test/ScanDependencies/Inputs/Swift/A.swiftinterface index 1b6292940c2bf..d284ad329d832 100644 --- a/test/ScanDependencies/Inputs/Swift/A.swiftinterface +++ b/test/ScanDependencies/Inputs/Swift/A.swiftinterface @@ -1,5 +1,6 @@ // swift-interface-format-version: 1.0 // swift-module-flags: -module-name A +import Swift @_exported import A public func overlayFuncA() { } diff --git a/test/ScanDependencies/Inputs/Swift/G.swiftinterface b/test/ScanDependencies/Inputs/Swift/G.swiftinterface index ae9d32b2c8e24..e6fea1948fbe5 100644 --- a/test/ScanDependencies/Inputs/Swift/G.swiftinterface +++ b/test/ScanDependencies/Inputs/Swift/G.swiftinterface @@ -2,7 +2,7 @@ // swift-module-flags: -module-name G -swift-version 5 #if swift(>=5.0) - +import Swift @_exported import G public func overlayFuncG() { } diff --git a/test/ScanDependencies/Inputs/Swift/SubE.swiftinterface b/test/ScanDependencies/Inputs/Swift/SubE.swiftinterface new file mode 100644 index 0000000000000..5623089bda83d --- /dev/null +++ b/test/ScanDependencies/Inputs/Swift/SubE.swiftinterface @@ -0,0 +1,5 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name SubE +import Swift +import E +public func funcSubE() {} diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index 72885e5072f9b..3e11657ec02d4 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules // Check the contents of the JSON output // RUN: %FileCheck %s < %t/deps.json @@ -22,20 +22,23 @@ // RUN: %target-build-swift %S/Inputs/ModuleDependencyGraph.swift %t/BuildModules/main.swift -o %t/ModuleBuilder // RUN: %target-codesign %t/ModuleBuilder -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/A-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path B.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/B-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path C.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/C-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/A-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path E.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/E-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path F.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/F-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path G.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/G-*.swiftmodule +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path SwiftShims.pcm -o %t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/SwiftShims.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.pcm -o %t/clang-module-cache/A.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path B.pcm -o %t/clang-module-cache/B.pcm -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/A.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/B.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path C.pcm -o %t/clang-module-cache/C.pcm -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/B.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/C.pcm + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.swiftmodule -o %t/clang-module-cache/A.swiftmodule -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/A.pcm -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A.swiftmodule + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path E.swiftmodule -o %t/clang-module-cache/E.swiftmodule -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/E.swiftmodule + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path SubE.swiftmodule -o %t/clang-module-cache/SubE.swiftmodule -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/SwiftShims.pcm -swift-module-file %t/clang-module-cache/E.swiftmodule | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/SubE.swiftmodule // REQUIRES: executable_test // REQUIRES: objc_interop @@ -43,6 +46,7 @@ import C import E import G +import SubE // CHECK: "mainModuleName": "deps" @@ -62,6 +66,9 @@ import G // CHECK-NEXT: "swift": "G" // CHECK-NEXT: } // CHECK-NEXT: { +// CHECK-NEXT: "swift": "SubE" +// CHECK-NEXT: } +// CHECK-NEXT: { // CHECK-NEXT: "swift": "Swift" // CHECK-NEXT: } // CHECK-NEXT: { @@ -105,11 +112,10 @@ import G // CHECK: "commandLine": [ // CHECK-NEXT: "-frontend" +// CHECK-NEXT: "-only-use-extra-clang-opts" // CHECK-NEXT: "-Xcc" -// CHECK-NEXT: "-Xclang" -// CHECK-NEXT: "-Xcc" -// CHECK-NEXT: "-cc1" -// CHECK: "-remove-preceeding-explicit-module-build-incompatible-options" +// CHECK-NEXT: "clang" +// CHECK: "-fno-implicit-modules" /// --------Swift module E // CHECK: "swift": "E" @@ -125,7 +131,10 @@ import G // CHECK-LABEL: "modulePath": "G.swiftmodule" // CHECK: "directDependencies" // CHECK-NEXT: { -// CHECK-NEXT: "clang": "G" +// CHECK-NEXT: "swift": "Swift" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang": "G" // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "details": { @@ -135,8 +144,6 @@ import G // CHECK: "-compile-module-from-interface" // CHECK: "-target" // CHECK: "-sdk" -// CHECK: "-o" -// CHECK: /clang-module-cache/G-{{.*}}.swiftmodule" // CHECK: "-module-name" // CHECK: "G" // CHECK: "-swift-version" @@ -155,7 +162,10 @@ import G // CHECK: directDependencies // CHECK-NEXT: { -// CHECK-NEXT: "clang": "A" +// CHECK-NEXT: "swift": "Swift" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang": "A" // CHECK-NEXT: } /// --------Clang module B diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift index 2c4c24dc5f330..39e89779ddf0d 100644 --- a/test/Sema/enum_raw_representable.swift +++ b/test/Sema/enum_raw_representable.swift @@ -97,11 +97,11 @@ func rdar32431736() { let myE1: E = items1.first // expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}} - // expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: }} {{29-29=!)}} + // expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: }} {{29-29=!) ?? <#default value#>}} let myE2: E = items2?.first // expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}} - // expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: (}} {{30-30=)!)}} + // expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: (}} {{30-30=)!) ?? <#default value#>}} } // rdar://problem/32431165 - improve diagnostic for raw representable argument mismatch @@ -122,29 +122,39 @@ rdar32431165_1(.baz) // expected-error@-1 {{reference to member 'baz' cannot be resolved without a contextual type}} rdar32431165_1("") -// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{16-16=E_32431165(rawValue: }} {{18-18=)}} +// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} rdar32431165_1(42, "") -// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=)}} +// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=) ?? <#default value#>}} func rdar32431165_2(_: String) {} func rdar32431165_2(_: Int) {} func rdar32431165_2(_: Int, _: String) {} rdar32431165_2(E_32431165.bar) -// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{16-16=}} {{30-30=.rawValue}} +// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{30-30=.rawValue}} rdar32431165_2(42, E_32431165.bar) -// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{20-20=}} {{34-34=.rawValue}} +// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{34-34=.rawValue}} E_32431165.bar == "bar" -// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{1-1=}} {{15-15=.rawValue}} +// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{15-15=.rawValue}} "bar" == E_32431165.bar -// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{10-10=}} {{24-24=.rawValue}} +// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{24-24=.rawValue}} + +func rdar32431165_overloaded() -> Int { 42 } // expected-note {{found candidate with type 'Int'}} +func rdar32431165_overloaded() -> String { "A" } // expected-note {{'rdar32431165_overloaded()' produces 'String', not the expected contextual result type 'E_32431165'}} + +func test_candidate_diagnostic() { + func test_argument(_: E_32431165) {} + + let _: E_32431165 = rdar32431165_overloaded() // expected-error {{no exact matches in call to global function 'rdar32431165_overloaded'}} + test_argument(rdar32431165_overloaded()) // expected-error {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{17-17=E_32431165(rawValue: }} {{42-42=) ?? <#default value#>}} +} func rdar32432253(_ condition: Bool = false) { let choice: E_32431165 = condition ? .foo : .bar let _ = choice == "bar" - // expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}} + // expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{17-17=.rawValue}} } func sr8150_helper1(_: Int) {} @@ -161,13 +171,13 @@ func sr8150_helper4(_: Foo) {} func sr8150(bar: Bar) { sr8150_helper1(bar) - // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}} + // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{21-21=.rawValue}} sr8150_helper2(bar) - // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}} + // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{21-21=.rawValue}} sr8150_helper3(0.0) - // expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}} + // expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=) ?? <#default value#>}} sr8150_helper4(0.0) - // expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}} + // expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=) ?? <#default value#>}} } class SR8150Box { @@ -177,11 +187,20 @@ class SR8150Box { // Bonus problem with mutable values being passed. func sr8150_mutable(obj: SR8150Box) { sr8150_helper1(obj.bar) - // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{25-25=.rawValue}} + // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{25-25=.rawValue}} var bar = obj.bar sr8150_helper1(bar) - // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}} + // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{21-21=.rawValue}} + + func test(_ opt: Bar?) { + sr8150_helper1(opt) + // expected-error@-1 {{cannot convert value of type 'Bar?' to expected argument type 'Double'}} {{23-23=?.rawValue ?? <#default value#>}} + sr8150_helper1(opt ?? Bar.a) + // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{20-20=(}} {{32-32=).rawValue}} + let _: Double? = opt + // expected-error@-1 {{cannot convert value of type 'Bar?' to specified type 'Double?'}} {{25-25=?.rawValue}} + } } struct NotEquatable { } diff --git a/test/SourceKit/CodeComplete/complete_build_session.swift b/test/SourceKit/CodeComplete/complete_build_session.swift index fa6b7c7860587..291595855c266 100644 --- a/test/SourceKit/CodeComplete/complete_build_session.swift +++ b/test/SourceKit/CodeComplete/complete_build_session.swift @@ -1,3 +1,4 @@ +// REQUIRES: rdar60881337 import Foo func test() { diff --git a/test/SourceKit/CodeComplete/complete_sequence_innertype.swift b/test/SourceKit/CodeComplete/complete_sequence_innertype.swift new file mode 100644 index 0000000000000..e6d114e5654b5 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_sequence_innertype.swift @@ -0,0 +1,10 @@ +func test() { + class C: +} + +// RUN: %sourcekitd-test \ +// RUN: -req=complete -pos=2:11 -repeat-request=2 %s -- %s -parse-as-library \ +// RUN: | %FileCheck %s + +// CHECK: key.results: [ +// CHECK: description: "Int", diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Availability.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Basic.swift similarity index 65% rename from test/SymbolGraph/Symbols/Mixins/Availability/Availability.swift rename to test/SymbolGraph/Symbols/Mixins/Availability/Basic.swift index 32bee2c712005..7f7eb9eefc714 100644 --- a/test/SymbolGraph/Symbols/Mixins/Availability/Availability.swift +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Basic.swift @@ -1,7 +1,9 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -module-name Availability -emit-module -emit-module-path %t/ -// RUN: %target-swift-symbolgraph-extract -module-name Availability -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/Availability.symbols.json +// RUN: %target-build-swift %s -module-name Basic -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name Basic -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/Basic.symbols.json + +// REQUIRES: OS=macosx @available(macOS, introduced: 10.9, deprecated: 10.10, obsoleted: 10.11, message: "Everyone makes mistakes", renamed: "S2") public struct S {} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedFilled.swift new file mode 100644 index 0000000000000..d588617bc6ca8 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedFilled.swift @@ -0,0 +1,25 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name DeprecatedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name DeprecatedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/DeprecatedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, introduced: 10.0) +@available(macOS, deprecated: 10.1) +public func foo() {} + +// CHECK-LABEL: "precise": "s:16DeprecatedFilled3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedReplaced.swift new file mode 100644 index 0000000000000..aed37f934592c --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedReplaced.swift @@ -0,0 +1,38 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name DeprecatedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name DeprecatedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=DEPRECATED +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=NOTDEPRECATED + +// REQUIRES: OS=macosx + +@available(macOS, deprecated: 7.0) +@available(macOS, deprecated: 11.0) +public func foo() {} + +// Last `deprecated` wins. +// DEPRECATED-LABEL: "precise": "s:18DeprecatedReplaced3fooyyF", +// DEPRECATED: "availability": [ +// DEPRECATED-NEXT: { +// DEPRECATED-NEXT: "domain": "macOS", +// DEPRECATED-NEXT: "deprecated": { +// DEPRECATED-NEXT: "major": 11, +// DEPRECATED-NEXT: "minor": 0 +// DEPRECATED-NEXT: } +// DEPRECATED-NEXT: } +// DEPRECATED-NEXT: ] + +@available(macOS, deprecated: 10.0) +@available(macOS, introduced: 10.0) +public func noLongerDeprecated() {} + +// NOTDEPRECATED: "precise": "s:18DeprecatedReplaced08noLongerA0yyF", +// NOTDEPRECATED: "availability": [ +// NOTDEPRECATED-NEXT: { +// NOTDEPRECATED-NEXT: "domain": "macOS", +// NOTDEPRECATED-NEXT: "introduced": { +// NOTDEPRECATED-NEXT: "major": 10, +// NOTDEPRECATED-NEXT: "minor": 0 +// NOTDEPRECATED-NEXT: } +// NOTDEPRECATED-NEXT: } +// NOTDEPRECATED-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedFilled.swift new file mode 100644 index 0000000000000..9c6d7cd2d2538 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedFilled.swift @@ -0,0 +1,23 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name IntroducedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name IntroducedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/IntroducedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, deprecated: 10.0) +@available(macOS, introduced: 10.0) +public func foo() {} + +// This effectively erases the deprecation. + +// CHECK: "precise": "s:16IntroducedFilled3fooyyF" +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 0 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedReplaced.swift new file mode 100644 index 0000000000000..4aaad721995c6 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedReplaced.swift @@ -0,0 +1,23 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name IntroducedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name IntroducedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/IntroducedReplaced.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, introduced: 10.12) +@available(macOS, introduced: 10.11) +@available(macOS, introduced: 10.10) +public func foo() {} + +// Highest `introduced` wins. +// CHECK-LABEL: "precise": "s:18IntroducedReplaced3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 12 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift new file mode 100644 index 0000000000000..157ea906da57d --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift @@ -0,0 +1,25 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name MessageLastWins -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name MessageLastWins -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/MessageLastWins.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, deprecated, message: "first") +@available(macOS, deprecated, message: "second") +@available(iOS, deprecated, message: "iOS") +public func foo() {} + +// CHECK-LABEL: "precise": "s:15MessageLastWins3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "message": "second", +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "iOS", +// CHECK-NEXT: "message": "iOS", +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedFilled.swift new file mode 100644 index 0000000000000..d53a3b70d3396 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedFilled.swift @@ -0,0 +1,25 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name ObsoletedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name ObsoletedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/ObsoletedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, introduced: 10.0) +@available(macOS, obsoleted: 10.999) +public func foo() {} + +// CHECK-LABEL: "precise": "s:15ObsoletedFilled3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "introduced": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 999 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedReplaced.swift new file mode 100644 index 0000000000000..d092882998e42 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedReplaced.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name ObsoletedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name ObsoletedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/ObsoletedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, obsoleted: 10.999) +@available(macOS, obsoleted: 10.888) +public func foo() {} + +// CHECK: "precise": "s:15ObsoletedFilled3fooyyF" +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 888 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedFilled.swift new file mode 100644 index 0000000000000..2ffebb9152889 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedFilled.swift @@ -0,0 +1,41 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name DeprecatedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name DeprecatedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/DeprecatedFilled.symbols.json +// RUN: %FileCheck %s --input-file %t/DeprecatedFilled.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, deprecated: 10.15) +public struct S { + public func foo() {} +} + +// CHECK-LABEL: "precise": "s:16DeprecatedFilled1SV3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "deprecated": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 15 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(macOS, deprecated: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:16DeprecatedFilled5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "deprecated": { + // TRANSITIVE-NEXT: "major": 10, + // TRANSITIVE-NEXT: "minor": 15 + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: ] + public func foo() {} + } +} + diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedReplaced.swift new file mode 100644 index 0000000000000..0c63463dcda8c --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedReplaced.swift @@ -0,0 +1,98 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name DeprecatedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name DeprecatedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=LESSTHAN +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=GREATERTHAN +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=EQUAL +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=TRANSITIVELESSTHAN +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=TRANSITIVEGREATERTHAN +// RUN: %FileCheck %s --input-file %t/DeprecatedReplaced.symbols.json --check-prefix=TRANSITIVEEQUAL + +// REQUIRES: OS=macosx + +@available(macOS, deprecated: 10.15) +public struct S { +// LESSTHAN-LABEL: "precise": "s:18DeprecatedReplaced1SV8lessThanyyF", +// LESSTHAN: "availability": [ +// LESSTHAN-NEXT: { +// LESSTHAN-NEXT: "domain": "macOS", +// LESSTHAN-NEXT: "deprecated": { +// LESSTHAN-NEXT: "major": 10, +// LESSTHAN-NEXT: "minor": 10 +// LESSTHAN-NEXT: } +// LESSTHAN-NEXT: } +// LESSTHAN-NEXT: ] + @available(macOS, deprecated: 10.10) + public func lessThan() {} + +// GREATERTHAN-LABEL: "precise": "s:18DeprecatedReplaced1SV11greaterThanyyF", +// GREATERTHAN: "availability": [ +// GREATERTHAN-NEXT: { +// GREATERTHAN-NEXT: "domain": "macOS", +// GREATERTHAN-NEXT: "deprecated": { +// GREATERTHAN-NEXT: "major": 10, +// GREATERTHAN-NEXT: "minor": 15 +// GREATERTHAN-NEXT: } +// GREATERTHAN-NEXT: } +// GREATERTHAN-NEXT: ] + @available(macOS, deprecated: 10.16) + public func greaterThan() {} + +// EQUAL-LABEL: "precise": "s:18DeprecatedReplaced1SV5equalyyF", +// EQUAL: "availability": [ +// EQUAL-NEXT: { +// EQUAL-NEXT: "domain": "macOS", +// EQUAL-NEXT: "deprecated": { +// EQUAL-NEXT: "major": 10, +// EQUAL-NEXT: "minor": 15 +// EQUAL-NEXT: } +// EQUAL-NEXT: } +// EQUAL-NEXT: ] + @available(macOS, deprecated: 10.15) + public func equal() {} +} + +@available(macOS, deprecated: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVELESSTHAN-LABEL: "precise": "s:18DeprecatedReplaced5OuterV5InnerV8lessThanyyF" + // TRANSITIVELESSTHAN: "availability": [ + // TRANSITIVELESSTHAN-NEXT: { + // TRANSITIVELESSTHAN-NEXT: "domain": "macOS", + // TRANSITIVELESSTHAN-NEXT: "deprecated": { + // TRANSITIVELESSTHAN-NEXT: "major": 10, + // TRANSITIVELESSTHAN-NEXT: "minor": 10 + // TRANSITIVELESSTHAN-NEXT: } + // TRANSITIVELESSTHAN-NEXT: } + // TRANSITIVELESSTHAN-NEXT: ] + @available(macOS, deprecated: 10.10) + public func lessThan() {} + + // TRANSITIVEGREATERTHAN-LABEL: "precise": "s:18DeprecatedReplaced5OuterV5InnerV11greaterThanyyF", + // TRANSITIVEGREATERTHAN: "availability": [ + // TRANSITIVEGREATERTHAN-NEXT: { + // TRANSITIVEGREATERTHAN-NEXT: "domain": "macOS", + // TRANSITIVEGREATERTHAN-NEXT: "deprecated": { + // TRANSITIVEGREATERTHAN-NEXT: "major": 10, + // TRANSITIVEGREATERTHAN-NEXT: "minor": 15 + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: ] + @available(macOS, deprecated: 10.16) + public func greaterThan() {} + + // TRANSITIVEEQUAL-LABEL:"precise": "s:18DeprecatedReplaced5OuterV5InnerV5equalyyF" + // TRANSITIVEEQUAL: "availability": [ + // TRANSITIVEEQUAL-NEXT: { + // TRANSITIVEEQUAL-NEXT: "domain": "macOS", + // TRANSITIVEEQUAL-NEXT: "deprecated": { + // TRANSITIVEEQUAL-NEXT: "major": 10, + // TRANSITIVEEQUAL-NEXT: "minor": 15 + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: ] + @available(macOS, deprecated: 10.15) + public func equal() {} + } +} + diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedFilled.swift new file mode 100644 index 0000000000000..bee360c3235f2 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedFilled.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name IntroducedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name IntroducedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/IntroducedFilled.symbols.json +// RUN: %FileCheck %s --input-file %t/IntroducedFilled.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, introduced: 10.15) +public struct S { + // CHECK-LABEL: "precise": "s:16IntroducedFilled1SV3fooyyF", + // CHECK: "availability": [ + // CHECK-NEXT: { + // CHECK-NEXT: "domain": "macOS", + // CHECK-NEXT: "introduced": { + // CHECK-NEXT: "major": 10, + // CHECK-NEXT: "minor": 15 + // CHECK-NEXT: } + // CHECK-NEXT: } + // CHECK-NEXT: ] + public func foo() {} +} + +@available(macOS, introduced: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:16IntroducedFilled5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "introduced": { + // TRANSITIVE-NEXT: "major": 10, + // TRANSITIVE-NEXT: "minor": 15 + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: ] + public func foo() {} + } +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedReplaced.swift new file mode 100644 index 0000000000000..79bbf24ca5169 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedReplaced.swift @@ -0,0 +1,73 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name IntroducedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name IntroducedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/IntroducedReplaced.symbols.json --check-prefix=GREATERTHAN +// RUN: %FileCheck %s --input-file %t/IntroducedReplaced.symbols.json --check-prefix=EQUAL +// RUN: %FileCheck %s --input-file %t/IntroducedReplaced.symbols.json --check-prefix=TRANSITIVEGREATERTHAN +// RUN: %FileCheck %s --input-file %t/IntroducedReplaced.symbols.json --check-prefix=TRANSITIVEEQUAL + +// REQUIRES: OS=macosx + +@available(macOS, introduced: 10.15) +public struct S { + // Not possible: declarations cannot be more available than an enclosing scope + // @available(macOS, introduced: 10.10) + // public func lessThan() {} + + // GREATERTHAN-LABEL: "precise": "s:18IntroducedReplaced1SV11greaterThanyyF" + // GREATERTHAN: "availability": [ + // GREATERTHAN-NEXT: { + // GREATERTHAN-NEXT: "domain": "macOS", + // GREATERTHAN-NEXT: "introduced": { + // GREATERTHAN-NEXT: "major": 10, + // GREATERTHAN-NEXT: "minor": 16 + // GREATERTHAN-NEXT: } + // GREATERTHAN-NEXT: } + // GREATERTHAN-NEXT: ] + @available(macOS, introduced: 10.16) + public func greaterThan() {} + + // EQUAL-LABEL: "precise": "s:18IntroducedReplaced1SV5equalyyF", + // EQUAL: "availability": [ + // EQUAL-NEXT: { + // EQUAL-NEXT: "domain": "macOS", + // EQUAL-NEXT: "introduced": { + // EQUAL-NEXT: "major": 10, + // EQUAL-NEXT: "minor": 15 + // EQUAL-NEXT: } + // EQUAL-NEXT: } + // EQUAL-NEXT: ] + @available(macOS, introduced: 10.15) + public func equal() {} +} + +@available(macOS, introduced: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVEGREATERTHAN-LABEL: "precise": "s:18IntroducedReplaced5OuterV5InnerV11greaterThanyyF" + // TRANSITIVEGREATERTHAN: "availability": [ + // TRANSITIVEGREATERTHAN-NEXT: { + // TRANSITIVEGREATERTHAN-NEXT: "domain": "macOS", + // TRANSITIVEGREATERTHAN-NEXT: "introduced": { + // TRANSITIVEGREATERTHAN-NEXT: "major": 10, + // TRANSITIVEGREATERTHAN-NEXT: "minor": 16 + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: ] + @available(macOS, introduced: 10.16) + public func greaterThan() {} + + // TRANSITIVEEQUAL-LABEL: precise": "s:18IntroducedReplaced5OuterV5InnerV5equalyyF" + // TRANSITIVEEQUAL: "availability": [ + // TRANSITIVEEQUAL-NEXT: { + // TRANSITIVEEQUAL-NEXT: "domain": "macOS", + // TRANSITIVEEQUAL-NEXT: "introduced": { + // TRANSITIVEEQUAL-NEXT: "major": 10, + // TRANSITIVEEQUAL-NEXT: "minor": 15 + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: ] + @available(macOS, introduced: 10.15) + public func equal() {} + } +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageFilled.swift new file mode 100644 index 0000000000000..db311d67391d3 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageFilled.swift @@ -0,0 +1,38 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name MessageFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name MessageFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/MessageFilled.symbols.json +// RUN: %FileCheck %s --input-file %t/MessageFilled.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, deprecated, message: "S message") +public struct S { + @available(macOS, deprecated) + public func foo() {} +} + +// A child never inherits its parent's availability message because it +// may not make sense 100% of the time. + +// CHECK-LABEL: "precise": "s:13MessageFilled1SV3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: } + +@available(macOS, deprecated, message: "Outer message") +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:13MessageFilled5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "isUnconditionallyDeprecated": true + // TRANSITIVE-NEXT: } + @available(macOS, deprecated) + public func foo() {} + } +} + diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageReplaced.swift new file mode 100644 index 0000000000000..b59480c8e2ae8 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageReplaced.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name MessageFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name MessageFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/MessageFilled.symbols.json +// RUN: %FileCheck %s --input-file %t/MessageFilled.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, deprecated, message: "S message") +public struct S { + // A child never inherits its parent's availability message because it + // may not make sense 100% of the time. + + // CHECK-LABEL: "precise": "s:13MessageFilled1SV3fooyyF" + // CHECK: "availability": [ + // CHECK-NEXT: { + // CHECK-NEXT: "domain": "macOS", + // CHECK-NEXT: "message": "foo() message", + // CHECK-NEXT: "isUnconditionallyDeprecated": true + // CHECK-NEXT: } + @available(macOS, deprecated, message: "foo() message") + public func foo() {} +} + + +@available(macOS, deprecated, message: "Outer message") +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:13MessageFilled5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "message": "Inner.foo() message", + // TRANSITIVE-NEXT: "isUnconditionallyDeprecated": true + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: ] + @available(macOS, deprecated, message: "Inner.foo() message") + public func foo() {} + } +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedFilled.swift new file mode 100644 index 0000000000000..d50718b4c34fe --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedFilled.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name IntroducedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name IntroducedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/IntroducedFilled.symbols.json +// RUN: %FileCheck %s --input-file %t/IntroducedFilled.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, obsoleted: 10.15) +public struct S { + public func foo() {} +} + +// CHECK-LABEL: "precise": "s:16IntroducedFilled1SV3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "obsoleted": { +// CHECK-NEXT: "major": 10, +// CHECK-NEXT: "minor": 15 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] + +@available(macOS, obsoleted: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:16IntroducedFilled5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "obsoleted": { + // TRANSITIVE-NEXT: "major": 10, + // TRANSITIVE-NEXT: "minor": 15 + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: ] + public func foo() {} + } +} diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedReplaced.swift new file mode 100644 index 0000000000000..7ac2ebe996032 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedReplaced.swift @@ -0,0 +1,98 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name ObsoletedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name ObsoletedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=LESSTHAN +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=GREATERTHAN +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=EQUAL +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=TRANSITIVELESSTHAN +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=TRANSITIVEGREATERTHAN +// RUN: %FileCheck %s --input-file %t/ObsoletedReplaced.symbols.json --check-prefix=TRANSITIVEEQUAL + +// REQUIRES: OS=macosx + +@available(macOS, obsoleted: 10.15) +public struct S { + // LESSTHAN-LABEL: "precise": "s:17ObsoletedReplaced1SV8lessThanyyF", + // LESSTHAN: "availability": [ + // LESSTHAN-NEXT: { + // LESSTHAN-NEXT: "domain": "macOS", + // LESSTHAN-NEXT: "obsoleted": { + // LESSTHAN-NEXT: "major": 10, + // LESSTHAN-NEXT: "minor": 10 + // LESSTHAN-NEXT: } + // LESSTHAN-NEXT: } + // LESSTHAN-NEXT: ] + @available(macOS, obsoleted: 10.10) + public func lessThan() {} + + // GREATERTHAN-LABEL: "precise": "s:17ObsoletedReplaced1SV11greaterThanyyF", + // GREATERTHAN: "availability": [ + // GREATERTHAN-NEXT: { + // GREATERTHAN-NEXT: "domain": "macOS", + // GREATERTHAN-NEXT: "obsoleted": { + // GREATERTHAN-NEXT: "major": 10, + // GREATERTHAN-NEXT: "minor": 15 + // GREATERTHAN-NEXT: } + // GREATERTHAN-NEXT: } + // GREATERTHAN-NEXT: ] + @available(macOS, obsoleted: 10.16) + public func greaterThan() {} + + // EQUAL-LABEL: "precise": "s:17ObsoletedReplaced1SV5equalyyF", + // EQUAL: "availability": [ + // EQUAL-NEXT: { + // EQUAL-NEXT: "domain": "macOS", + // EQUAL-NEXT: "obsoleted": { + // EQUAL-NEXT: "major": 10, + // EQUAL-NEXT: "minor": 15 + // EQUAL-NEXT: } + // EQUAL-NEXT: } + // EQUAL-NEXT: ] + @available(macOS, obsoleted: 10.15) + public func equal() {} +} + +@available(macOS, obsoleted: 10.15) +public struct Outer { + public struct Inner { + // TRANSITIVELESSTHAN-LABEL: "precise": "s:17ObsoletedReplaced5OuterV5InnerV8lessThanyyF" + // TRANSITIVELESSTHAN: "availability": [ + // TRANSITIVELESSTHAN-NEXT: { + // TRANSITIVELESSTHAN-NEXT: "domain": "macOS", + // TRANSITIVELESSTHAN-NEXT: "obsoleted": { + // TRANSITIVELESSTHAN-NEXT: "major": 10, + // TRANSITIVELESSTHAN-NEXT: "minor": 10 + // TRANSITIVELESSTHAN-NEXT: } + // TRANSITIVELESSTHAN-NEXT: } + // TRANSITIVELESSTHAN-NEXT: ] + @available(macOS, obsoleted: 10.10) + public func lessThan() {} + + // TRANSITIVEGREATERTHAN-LABEL:"precise": "s:17ObsoletedReplaced5OuterV5InnerV11greaterThanyyF" + // TRANSITIVEGREATERTHAN: "availability": [ + // TRANSITIVEGREATERTHAN-NEXT: { + // TRANSITIVEGREATERTHAN-NEXT: "domain": "macOS", + // TRANSITIVEGREATERTHAN-NEXT: "obsoleted": { + // TRANSITIVEGREATERTHAN-NEXT: "major": 10, + // TRANSITIVEGREATERTHAN-NEXT: "minor": 15 + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: } + // TRANSITIVEGREATERTHAN-NEXT: ] + @available(macOS, obsoleted: 10.16) + public func greaterThan() {} + + // TRANSITIVEEQUAL-LABEL:"precise": "s:17ObsoletedReplaced5OuterV5InnerV5equalyyF" + // TRANSITIVEEQUAL: "availability": [ + // TRANSITIVEEQUAL-NEXT: { + // TRANSITIVEEQUAL-NEXT: "domain": "macOS", + // TRANSITIVEEQUAL-NEXT: "obsoleted": { + // TRANSITIVEEQUAL-NEXT: "major": 10, + // TRANSITIVEEQUAL-NEXT: "minor": 15 + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: } + // TRANSITIVEEQUAL-NEXT: ] + @available(macOS, obsoleted: 10.15) + public func equal() {} + } +} + diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedFilled.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedFilled.swift new file mode 100644 index 0000000000000..801a027679268 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedFilled.swift @@ -0,0 +1,25 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name RenamedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name RenamedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/RenamedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, deprecated, renamed: "S.bar") +public struct S { + public func foo() {} +} + +@available(macOS, deprecated, renamed: "Other") +public struct Outer { + public struct Inner { + public func foo() {} + } +} + +// A parent's `renamed` field should never replace a child's. +// It wouldn't make sense for a parent and child to both be renamed to the same thing. + +// This will definitely be on the parents, so this is enough to check that it wasn't +// applied to the child. +// CHECK-COUNT-2: "availability": diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedNoVersion.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedNoVersion.swift new file mode 100644 index 0000000000000..89559c435cb8e --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedNoVersion.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name RenamedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name RenamedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/RenamedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, renamed: "S.bar") +public struct S { + public func foo() {} +} + +// There is no version information or unconditional deprecation here, +// so we will not expect to see an empty availability mix-in with +// just the `renamed` field, even though there is a domain listed. +// CHECK-NOT: "availability": diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedReplaced.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedReplaced.swift new file mode 100644 index 0000000000000..99d9fa15227bd --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedReplaced.swift @@ -0,0 +1,42 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name RenamedReplaced -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name RenamedReplaced -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/RenamedReplaced.symbols.json +// RUN: %FileCheck %s --input-file %t/RenamedReplaced.symbols.json --check-prefix=TRANSITIVE + +// REQUIRES: OS=macosx + +@available(macOS, deprecated, renamed: "S.bar") +public struct S { + // A parent's `renamed` field should never replace a child's. + // It wouldn't make sense for a parent and child to both be renamed to the same thing. + + // CHECK-LABEL: "precise": "s:15RenamedReplaced1SV3fooyyF" + // CHECK: "availability": [ + // CHECK-NEXT: { + // CHECK-NEXT: "domain": "macOS", + // CHECK-NEXT: "renamed": "foo.bar", + // CHECK-NEXT: "isUnconditionallyDeprecated": true + // CHECK-NEXT: } + // CHECK-NEXT: ] + @available(macOS, deprecated, renamed: "foo.bar") + public func foo() {} +} + + +@available(macOS, deprecated, renamed: "Other") +public struct Outer { + public struct Inner { + // TRANSITIVE-LABEL: "precise": "s:15RenamedReplaced5OuterV5InnerV3fooyyF" + // TRANSITIVE: "availability": [ + // TRANSITIVE-NEXT: { + // TRANSITIVE-NEXT: "domain": "macOS", + // TRANSITIVE-NEXT: "renamed": "bar", + // TRANSITIVE-NEXT: "isUnconditionallyDeprecated": true + // TRANSITIVE-NEXT: } + // TRANSITIVE-NEXT: ] + @available(macOS, deprecated, renamed: "bar") + public func foo() {} + } +} + diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/UnconditionallyDeprecated.swift b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/UnconditionallyDeprecated.swift new file mode 100644 index 0000000000000..ee45ab7f9faf0 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/Availability/Inherited/UnconditionallyDeprecated.swift @@ -0,0 +1,19 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name DeprecatedFilled -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name DeprecatedFilled -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/DeprecatedFilled.symbols.json + +// REQUIRES: OS=macosx + +@available(macOS, deprecated) +public struct S { + public func foo() {} +} + +// CHECK-LABEL: "precise": "s:16DeprecatedFilled1SV3fooyyF", +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "macOS", +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/Availability/UnconditionallyDeprecated.swift b/test/SymbolGraph/Symbols/Mixins/Availability/UnconditionallyDeprecated.swift index 899beff3e4eec..a973a0a205207 100644 --- a/test/SymbolGraph/Symbols/Mixins/Availability/UnconditionallyDeprecated.swift +++ b/test/SymbolGraph/Symbols/Mixins/Availability/UnconditionallyDeprecated.swift @@ -6,5 +6,9 @@ @available(*, deprecated) public struct UnconditionallyDeprecated {} -// CHECK-NOT: domain -// CHECK: "isUnconditionallyDeprecated": true +// CHECK: "availability": [ +// CHECK-NEXT: { +// CHECK-NEXT: "domain": "*", +// CHECK-NEXT: "isUnconditionallyDeprecated": true +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift deleted file mode 100644 index 2c46cf5c7c853..0000000000000 --- a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift +++ /dev/null @@ -1,60 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -module-name Basic -emit-module -emit-module-path %t/ -// RUN: %target-swift-symbolgraph-extract -module-name Basic -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/Basic.symbols.json - -public func foo(f: @escaping () -> (), ext int: Int = 2, s: S) {} - -// CHECK-LABEL: {{^ }}"declarationFragments": - -// CHECK: "kind": "keyword", -// CHECK-NEXT: "spelling": "func" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": " " - -// CHECK: "kind": "identifier", -// CHECK-NEXT: "spelling": "foo" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": "<" - -// CHECK: "kind": "genericParameter", -// CHECK-NEXT: "spelling": "S" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": ">(" - -// CHECK: "kind": "externalParam", -// CHECK-NEXT: "spelling": "f" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": ": () -> (), " - -// CHECK:"kind": "externalParam", -// CHECK-NEXT:"spelling": "ext" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": " " - -// CHECK:"kind": "internalParam", -// CHECK-NEXT:"spelling": "int" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": ": " - -// CHECK: "kind": "typeIdentifier", -// CHECK-NEXT: "spelling": "Int", -// CHECK-NEXT: "preciseIdentifier": "s:Si" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": " = 2, " - -// CHECK: "kind": "externalParam", -// CHECK-NEXT: "spelling": "s" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": ": S" - -// CHECK: "kind": "text", -// CHECK-NEXT: "spelling": ")" diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Function.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Function.swift new file mode 100644 index 0000000000000..a23284f1a1f34 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Function.swift @@ -0,0 +1,95 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name Function -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name Function -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/Function.symbols.json --match-full-lines --strict-whitespace + +public func foo(f: @escaping () -> (), ext int: Int = 2, s: S) where S: Sequence {} + +// CHECK-LABEL:{{^ }}"declarationFragments": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "keyword", +// CHECK-NEXT: "spelling": "func" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "identifier", +// CHECK-NEXT: "spelling": "foo" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": "<" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "genericParameter", +// CHECK-NEXT: "spelling": "S" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ">(" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "externalParam", +// CHECK-NEXT: "spelling": "f" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ": () -> (), " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "externalParam", +// CHECK-NEXT: "spelling": "ext" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "internalParam", +// CHECK-NEXT: "spelling": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ": " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "typeIdentifier", +// CHECK-NEXT: "spelling": "Int", +// CHECK-NEXT: "preciseIdentifier": "s:Si" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " = 2, " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "externalParam", +// CHECK-NEXT: "spelling": "s" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ": S" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": ") " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "keyword", +// CHECK-NEXT: "spelling": "where" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " S" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "text", +// CHECK-NEXT: "spelling": " : " +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "typeIdentifier", +// CHECK-NEXT: "spelling": "Sequence", +// CHECK-NEXT: "preciseIdentifier": "s:ST" +// CHECK-NEXT: } +// CHECK-NEXT: ], diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/NominalTypes.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/NominalTypes.swift new file mode 100644 index 0000000000000..31e5c69fc1e6b --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/NominalTypes.swift @@ -0,0 +1,208 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name NominalTypes -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name NominalTypes -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=STRUCT +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=CLASS +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=ENUM +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=TYPEALIAS + +public struct S where T: Sequence {} + +// STRUCT-LABEL: "precise": "s:12NominalTypes1SV", +// STRUCT: "declarationFragments": [ +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "keyword", +// STRUCT-NEXT: "spelling": "struct" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "text", +// STRUCT-NEXT: "spelling": " " +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "identifier", +// STRUCT-NEXT: "spelling": "S" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "text", +// STRUCT-NEXT: "spelling": "<" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "genericParameter", +// STRUCT-NEXT: "spelling": "T" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "text", +// STRUCT-NEXT: "spelling": "> " +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "keyword", +// STRUCT-NEXT: "spelling": "where" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "text", +// STRUCT-NEXT: "spelling": " T" +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "text", +// STRUCT-NEXT: "spelling": " : " +// STRUCT-NEXT: }, +// STRUCT-NEXT: { +// STRUCT-NEXT: "kind": "typeIdentifier", +// STRUCT-NEXT: "spelling": "Sequence", +// STRUCT-NEXT: "preciseIdentifier": "s:ST" +// STRUCT-NEXT: } +// STRUCT-NEXT: ] + +public class C where T: Sequence {} + +// CLASS-LABEL: "precise": "s:12NominalTypes1CC", +// CLASS: "declarationFragments": [ +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "keyword", +// CLASS-NEXT: "spelling": "class" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "text", +// CLASS-NEXT: "spelling": " " +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "identifier", +// CLASS-NEXT: "spelling": "C" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "text", +// CLASS-NEXT: "spelling": "<" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "genericParameter", +// CLASS-NEXT: "spelling": "T" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "text", +// CLASS-NEXT: "spelling": "> " +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "keyword", +// CLASS-NEXT: "spelling": "where" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "text", +// CLASS-NEXT: "spelling": " T" +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "text", +// CLASS-NEXT: "spelling": " : " +// CLASS-NEXT: }, +// CLASS-NEXT: { +// CLASS-NEXT: "kind": "typeIdentifier", +// CLASS-NEXT: "spelling": "Sequence", +// CLASS-NEXT: "preciseIdentifier": "s:ST" +// CLASS-NEXT: } +// CLASS-NEXT: ], + +public enum E where T: Sequence {} + +// ENUM-LABEL: "precise": "s:12NominalTypes1EO", +// ENUM: "declarationFragments": [ +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "keyword", +// ENUM-NEXT: "spelling": "enum" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "text", +// ENUM-NEXT: "spelling": " " +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "identifier", +// ENUM-NEXT: "spelling": "E" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "text", +// ENUM-NEXT: "spelling": "<" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "genericParameter", +// ENUM-NEXT: "spelling": "T" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "text", +// ENUM-NEXT: "spelling": "> " +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "keyword", +// ENUM-NEXT: "spelling": "where" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "text", +// ENUM-NEXT: "spelling": " T" +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "text", +// ENUM-NEXT: "spelling": " : " +// ENUM-NEXT: }, +// ENUM-NEXT: { +// ENUM-NEXT: "kind": "typeIdentifier", +// ENUM-NEXT: "spelling": "Sequence", +// ENUM-NEXT: "preciseIdentifier": "s:ST" +// ENUM-NEXT: } +// ENUM-NEXT: ], + +public typealias TA = S where T: Sequence + +// TYPEALIAS-LABEL: "precise": "s:12NominalTypes2TAa", +// TYPEALIAS: "declarationFragments": [ +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "keyword", +// TYPEALIAS-NEXT: "spelling": "typealias" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": " " +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "identifier", +// TYPEALIAS-NEXT: "spelling": "TA" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": "<" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "genericParameter", +// TYPEALIAS-NEXT: "spelling": "T" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": "> = " +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "typeIdentifier", +// TYPEALIAS-NEXT: "spelling": "S", +// TYPEALIAS-NEXT: "preciseIdentifier": "s:12NominalTypes1SV" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": " " +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "keyword", +// TYPEALIAS-NEXT: "spelling": "where" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": " T" +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "text", +// TYPEALIAS-NEXT: "spelling": " : " +// TYPEALIAS-NEXT: }, +// TYPEALIAS-NEXT: { +// TYPEALIAS-NEXT: "kind": "typeIdentifier", +// TYPEALIAS-NEXT: "spelling": "Sequence", +// TYPEALIAS-NEXT: "preciseIdentifier": "s:ST" +// TYPEALIAS-NEXT: } +// TYPEALIAS-NEXT: ], diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/ComputedProperties.swift similarity index 100% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/ComputedProperties.swift diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/ProtocolRequirements.swift similarity index 100% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/ProtocolRequirements.swift diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/Subscripts.swift similarity index 100% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Properties/Subscripts.swift diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Navigator.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Navigator/Navigator.swift similarity index 100% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Navigator.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Navigator/Navigator.swift diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragments.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/Function.swift similarity index 83% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragments.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/Function.swift index 08d7f0c1147f4..fb3f52a1f90e7 100644 --- a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragments.swift +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/Function.swift @@ -1,13 +1,13 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -module-name SubheadingDeclarationFragments -emit-module -emit-module-path %t/ -// RUN: %target-swift-symbolgraph-extract -module-name SubheadingDeclarationFragments -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragments.symbols.json +// RUN: %target-build-swift %s -module-name Function -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name Function -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/Function.symbols.json public func foo(f: @escaping () -> (), ext int: Int = 2, s: S) where S: Sequence {} // Subheading fragments should not contain internalParam kinds. -// CHECK-LABEL: "precise": "s:30SubheadingDeclarationFragments3foo1f3ext1syyyc_SixtSTRzlF" +// CHECK-LABEL: "precise": "s:8Function3foo1f3ext1syyyc_SixtSTRzlF" // CHECK: names // CHECK-NEXT: "title": "foo(f:ext:s:)" // CHECK: "subHeading": [ diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragmentsTypes.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/NominalTypes.swift similarity index 63% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragmentsTypes.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/NominalTypes.swift index 72f700561e38b..e3df5c6f7b70f 100644 --- a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/SubheadingDeclarationFragmentsTypes.swift +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Subheading/NominalTypes.swift @@ -1,13 +1,13 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -module-name SubheadingDeclarationFragmentsTypes -emit-module -emit-module-path %t/ -// RUN: %target-swift-symbolgraph-extract -module-name SubheadingDeclarationFragmentsTypes -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragmentsTypes.symbols.json --check-prefix=STRUCT -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragmentsTypes.symbols.json --check-prefix=ENUM -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragmentsTypes.symbols.json --check-prefix=PROTOCOL -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragmentsTypes.symbols.json --check-prefix=CLASS -// RUN: %FileCheck %s --input-file %t/SubheadingDeclarationFragmentsTypes.symbols.json --check-prefix=TYPEALIAS +// RUN: %target-build-swift %s -module-name NominalTypes -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name NominalTypes -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=STRUCT +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=ENUM +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=PROTOCOL +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=CLASS +// RUN: %FileCheck %s --input-file %t/NominalTypes.symbols.json --check-prefix=TYPEALIAS -// STRUCT-LABEL: "precise": "s:35SubheadingDeclarationFragmentsTypes6StructV" +// STRUCT-LABEL: "precise": "s:12NominalTypes6StructV" // STRUCT: subHeading // STRUCT-NEXT { // STRUCT-NEXT "kind": "keyword", @@ -23,7 +23,7 @@ // STRUCT-NEXT } public struct Struct where T: Sequence {} -// ENUM-LABEL: "precise": "s:35SubheadingDeclarationFragmentsTypes4EnumO" +// ENUM-LABEL: "precise": "s:12NominalTypes4EnumO" // ENUM: subHeading // ENUM-NEXT: { // ENUM-NEXT: "kind": "keyword", @@ -39,7 +39,7 @@ public struct Struct where T: Sequence {} // ENUM-NEXT: } public enum Enum where T: Sequence {} -// PROTOCOL-LABEL: "precise": "s:35SubheadingDeclarationFragmentsTypes8ProtocolP" +// PROTOCOL-LABEL: "precise": "s:12NominalTypes8ProtocolP" // PROTOCOL: subHeading // PROTOCOL-NEXT: { // PROTOCOL-NEXT: "kind": "keyword", @@ -57,7 +57,7 @@ public protocol Protocol where T: Sequence { associatedtype T } -// CLASS-LABEL: "precise": "s:35SubheadingDeclarationFragmentsTypes5ClassC" +// CLASS-LABEL: "precise": "s:12NominalTypes5ClassC" // CLASS: subHeading // CLASS-NEXT { // CLASS-NEXT "kind": "keyword", @@ -73,7 +73,7 @@ public protocol Protocol where T: Sequence { // CLASS-NEXT } public class Class where T: Sequence {} -// TYPEALIAS-LABEL: "precise": "s:35SubheadingDeclarationFragmentsTypes9TypeAliasa" +// TYPEALIAS-LABEL: "precise": "s:12NominalTypes9TypeAliasa" // TYPEALIAS: subHeading // TYPEALIAS-NEXT: { // TYPEALIAS-NEXT: "kind": "keyword", diff --git a/test/TypeDecoder/opaque_return_type.swift b/test/TypeDecoder/opaque_return_type.swift index c13afa1f31a0f..94b139ad48d1e 100644 --- a/test/TypeDecoder/opaque_return_type.swift +++ b/test/TypeDecoder/opaque_return_type.swift @@ -10,8 +10,16 @@ extension Int: P {} func foo() -> some P { return 0 } var prop: some P { return 0 } +func bar() -> some Sequence { return [] } + // DEMANGLE: $s18opaque_return_type3fooQryFQOyQo_ // CHECK: some P // DEMANGLE: $s18opaque_return_type4propQrvpQOyQo_ // CHECK: some P + +// DEMANGLE: $s18opaque_return_type3barQryFQOyQo_ +// CHECK: some Sequence + +// DEMANGLE: $s18opaque_return_type3barQryFQOyQo_7ElementSTQxD +// CHECK: (some Sequence).Element diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index dfb287c445dfb..0870461fede85 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -142,8 +142,8 @@ static bool swiftCodeCompleteImpl( SwiftConsumer.setContext(&CI.getASTContext(), &CI.getInvocation(), &CompletionContext); - auto SF = CI.getCodeCompletionFile(); - performCodeCompletionSecondPass(*SF.get(), *callbacksFactory); + auto *SF = CI.getCodeCompletionFile(); + performCodeCompletionSecondPass(*SF, *callbacksFactory); SwiftConsumer.clearContext(); }); } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp b/tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp index 62ef9c6d25191..42db5bc49f7ae 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp @@ -42,8 +42,8 @@ static bool swiftConformingMethodListImpl( ide::makeConformingMethodListCallbacksFactory(ExpectedTypeNames, Consumer)); - auto SF = CI.getCodeCompletionFile(); - performCodeCompletionSecondPass(*SF.get(), *callbacksFactory); + auto *SF = CI.getCodeCompletionFile(); + performCodeCompletionSecondPass(*SF, *callbacksFactory); }); } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftTypeContextInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftTypeContextInfo.cpp index 2ea49522cc25b..db6a6ed03f176 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftTypeContextInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftTypeContextInfo.cpp @@ -39,8 +39,8 @@ static bool swiftTypeContextInfoImpl( std::unique_ptr callbacksFactory( ide::makeTypeContextInfoCallbacksFactory(Consumer)); - auto SF = CI.getCodeCompletionFile(); - performCodeCompletionSecondPass(*SF.get(), *callbacksFactory); + auto *SF = CI.getCodeCompletionFile(); + performCodeCompletionSecondPass(*SF, *callbacksFactory); }); } diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp index 4523df82f1f42..6a7e3f846d479 100644 --- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp +++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp @@ -95,8 +95,10 @@ static void resolveDeclFromMangledNameList( } } -static void resolveTypeFromMangledNameList( - swift::ASTContext &Ctx, llvm::ArrayRef MangledNames) { +static void +resolveTypeFromMangledNameList(swift::ASTContext &Ctx, + llvm::ArrayRef MangledNames, + bool QualifyTypes) { for (auto &Mangled : MangledNames) { swift::Type ResolvedType = swift::Demangle::getTypeForMangling(Ctx, Mangled); @@ -104,6 +106,8 @@ static void resolveTypeFromMangledNameList( llvm::outs() << "Can't resolve type of " << Mangled << "\n"; } else { swift::PrintOptions PO; + PO.FullyQualifiedTypesIfAmbiguous = QualifyTypes; + PO.QualifyImportedTypes = QualifyTypes; PO.PrintStorageRepresentationAttrs = true; ResolvedType->print(llvm::outs(), PO); llvm::outs() << "\n"; @@ -233,6 +237,9 @@ int main(int argc, char **argv) { "dummy-dwarfimporter", desc("Install a dummy DWARFImporterDelegate"), cat(Visible)); + opt QualifyTypes("qualify-types", desc("Qualify dumped types"), + cat(Visible)); + ParseCommandLineOptions(argc, argv); // Unregister our options so they don't interfere with the command line @@ -352,14 +359,14 @@ int main(int argc, char **argv) { if (DumpModule) { llvm::SmallVector Decls; Module->getTopLevelDecls(Decls); - for (auto Decl : Decls) { + for (auto Decl : Decls) Decl->dump(llvm::outs()); - } } if (!DumpTypeFromMangled.empty()) { llvm::SmallVector MangledNames; collectMangledNames(DumpTypeFromMangled, MangledNames); - resolveTypeFromMangledNameList(CI.getASTContext(), MangledNames); + resolveTypeFromMangledNameList(CI.getASTContext(), MangledNames, + QualifyTypes); } if (!DumpDeclFromMangled.empty()) { llvm::SmallVector MangledNames; diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index f6468b7366a59..e129ce62e0de8 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -74,6 +74,25 @@ static llvm::cl::opt Classify("classify", llvm::cl::desc("Display symbol classification characters")); +/// Options that are primarily used for testing. +/// \{ +static llvm::cl::opt DisplayStdlibModule( + "display-stdlib-module", llvm::cl::init(true), + llvm::cl::desc("Qualify types originating from the Swift standard library"), + llvm::cl::Hidden); + +static llvm::cl::opt DisplayObjCModule( + "display-objc-module", llvm::cl::init(true), + llvm::cl::desc("Qualify types originating from the __ObjC module"), + llvm::cl::Hidden); + +static llvm::cl::opt HidingModule( + "hiding-module", + llvm::cl::desc("Don't qualify types originating from this module"), + llvm::cl::Hidden); +/// \} + + static llvm::cl::list InputNames(llvm::cl::Positional, llvm::cl::desc("[mangled name...]"), llvm::cl::ZeroOrMore); @@ -233,6 +252,9 @@ int main(int argc, char **argv) { options.SynthesizeSugarOnTypes = !DisableSugar; if (Simplified) options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions(); + options.DisplayStdlibModule = DisplayStdlibModule; + options.DisplayObjCModule = DisplayObjCModule; + options.HidingCurrentModule = HidingModule; if (InputNames.empty()) { CompactMode = true; diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 99e4d514b828f..08a8b008e60a2 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -794,8 +794,8 @@ static bool doCodeCompletionImpl( CodeCompletionDiagnostics ? &PrintDiags : nullptr, [&](CompilerInstance &CI, bool reusingASTContext) { assert(!reusingASTContext && "reusing AST context without enabling it"); - auto SF = CI.getCodeCompletionFile(); - performCodeCompletionSecondPass(*SF.get(), *callbacksFactory); + auto *SF = CI.getCodeCompletionFile(); + performCodeCompletionSecondPass(*SF, *callbacksFactory); }); return isSuccess ? 0 : 1; } diff --git a/unittests/AST/ArithmeticEvaluator.cpp b/unittests/AST/ArithmeticEvaluator.cpp index b41928fbf2feb..00c3a495d9a32 100644 --- a/unittests/AST/ArithmeticEvaluator.cpp +++ b/unittests/AST/ArithmeticEvaluator.cpp @@ -16,6 +16,7 @@ #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/Evaluator.h" #include "swift/AST/SimpleRequest.h" +#include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" #include "gtest/gtest.h" #include @@ -218,10 +219,11 @@ TEST(ArithmeticEvaluator, Simple) { SourceManager sourceMgr; DiagnosticEngine diags(sourceMgr); - Evaluator evaluator(diags, - /*debugDumpCycles=*/false, - /*buildDependencyGraph=*/true, - /*privateDependencies*/false); + LangOptions opts; + opts.DebugDumpCycles = false; + opts.BuildRequestDependencyGraph = true; + opts.EnableExperientalPrivateIntransitiveDependencies = false; + Evaluator evaluator(diags, opts); evaluator.registerRequestFunctions(Zone::ArithmeticEvaluator, arithmeticRequestFunctions); @@ -344,10 +346,11 @@ TEST(ArithmeticEvaluator, Cycle) { SourceManager sourceMgr; DiagnosticEngine diags(sourceMgr); - Evaluator evaluator(diags, - /*debugDumpCycles=*/false, - /*buildDependencyGraph=*/false, - /*privateDependencies*/false); + LangOptions opts; + opts.DebugDumpCycles = false; + opts.BuildRequestDependencyGraph = false; + opts.EnableExperientalPrivateIntransitiveDependencies = false; + Evaluator evaluator(diags, opts); evaluator.registerRequestFunctions(Zone::ArithmeticEvaluator, arithmeticRequestFunctions); diff --git a/utils/gyb_syntax_support/__init__.py b/utils/gyb_syntax_support/__init__.py index e3960dc95c813..b24c5387b7497 100644 --- a/utils/gyb_syntax_support/__init__.py +++ b/utils/gyb_syntax_support/__init__.py @@ -1,21 +1,17 @@ import textwrap +from . import Classification # noqa: I201 +from . import Token from .AttributeNodes import ATTRIBUTE_NODES # noqa: I201 from .AvailabilityNodes import AVAILABILITY_NODES # noqa: I201 -from . import Classification # noqa: I201 from .CommonNodes import COMMON_NODES # noqa: I201 from .DeclNodes import DECL_NODES # noqa: I201 from .ExprNodes import EXPR_NODES # noqa: I201 from .GenericNodes import GENERIC_NODES # noqa: I201 - -from . import Token - from .NodeSerializationCodes import SYNTAX_NODE_SERIALIZATION_CODES, \ get_serialization_code, \ verify_syntax_node_serialization_codes - from .PatternNodes import PATTERN_NODES # noqa: I201 from .StmtNodes import STMT_NODES # noqa: I201 - from .Trivia import TRIVIAS # noqa: I201 from .TypeNodes import TYPE_NODES # noqa: I201 diff --git a/validation-test/compiler_crashers_2_fixed/rdar54394068.swift b/validation-test/compiler_crashers_2_fixed/rdar54394068.swift new file mode 100644 index 0000000000000..6863a22e28cf5 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar54394068.swift @@ -0,0 +1,55 @@ +// RUN: %target-swift-frontend -typecheck -verify %s + +protocol A { + associatedtype BType: B where BType.AType == Self + associatedtype CType: C where CType.AType == Self + + var b: BType { get } + var c: CType { get set } + + func bGetter() -> BType + mutating func cSetter(_ newC: CType) + + subscript (b: BType) -> CType { get set } +} + +protocol B { + associatedtype AType: A +} + +protocol C { + associatedtype AType: A +} + +struct AImpl: A { + typealias BType = BImpl + typealias CType = CImpl + + let b: BImpl + var c: CImpl + + func bGetter() -> BImpl { + return b + } + + mutating func cSetter(_ newC: CImpl) { + c = newC + } + + subscript(b: BImpl) -> CImpl { + get { + return c + } + set { + c = newValue + } + } +} + +struct BImpl: B { + typealias AType = AImpl +} + +struct CImpl: C { + typealias AType = AImpl +} diff --git a/validation-test/compiler_crashers_2_fixed/sr7002.swift b/validation-test/compiler_crashers_2_fixed/sr7002.swift new file mode 100644 index 0000000000000..72b3c6d092350 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr7002.swift @@ -0,0 +1,8 @@ +// RUN: not %target-swift-frontend -typecheck %s + +struct Foo: OptionSet { + let rawValue: Int + static let none = Foo(rawValue: 1 << 0) +} + +extension Foo: ExpressibleByIntegerLiteral { } diff --git a/validation-test/compiler_scale/scale_neighbouring_getset.gyb b/validation-test/compiler_scale/scale_neighbouring_getset.gyb index 4a6281a7f4412..de31ed75bcaf3 100644 --- a/validation-test/compiler_scale/scale_neighbouring_getset.gyb +++ b/validation-test/compiler_scale/scale_neighbouring_getset.gyb @@ -1,4 +1,4 @@ -// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select TypeCheckFunctionBodyUntilRequest %s +// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select TypeCheckFunctionBodyRequest %s // REQUIRES: asserts struct Struct${N} {