From fd98ce10c7f709a9d62914fb10f597388e439060 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 25 Mar 2020 07:22:26 -0700 Subject: [PATCH 001/108] Update PassManager's function worklist for newly added SILFunctions The PassManager should transform all functions in bottom up order. This is necessary because when optimizations like inlining looks at the callee function bodies to compute profitability, the callee functions should have already undergone optimizations to get better profitability estimates. The PassManager builds its function worklist based on bottom up order on initialization. However, newly created SILFunctions due to specialization etc, are simply appended to the function worklist. This can cause us to make bad inlining decisions due to inaccurate profitability estimates. This change now updates the function worklist such that, all the callees of the newly added SILFunction are proccessed before it by the PassManager. Fixes rdar://52202680 --- .../SILOptimizer/Analysis/FunctionOrder.h | 27 ++++++----- lib/SILOptimizer/Analysis/FunctionOrder.cpp | 4 -- lib/SILOptimizer/PassManager/PassManager.cpp | 46 ++++++++++++++++++- .../UtilityPasses/FunctionOrderPrinter.cpp | 4 +- test/DebugInfo/inlined-generics-basic.swift | 2 +- 5 files changed, 62 insertions(+), 21 deletions(-) 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/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/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index 369ad70e03d88..b9f1142591446 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); + } } } 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/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", From 95c16fc9e1d1caa0f586a7bdf7675647e3eb9ec9 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sat, 16 May 2020 08:06:53 +0300 Subject: [PATCH 002/108] [NFC] AST: Optimize GenericSignatureImpl::getInnermostGenericParams --- lib/AST/GenericSignature.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 05b04cc03bb1a..ca2ab13955da9 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -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( From f5258ed9c9f344e2f974b769e9a20ae7bc079525 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 22 May 2020 22:09:40 -0400 Subject: [PATCH 003/108] ASTDemangler: Add support for member types of opaque result types Fixes . --- lib/AST/ASTDemangler.cpp | 29 +++++++++++++++++------ test/TypeDecoder/opaque_return_type.swift | 8 +++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 558452d3af46e..9b833d3d8ff08 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -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/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 From 8326e11ec21b165364e90170c0bfb012ac2e818d Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Mon, 25 May 2020 15:19:18 +0200 Subject: [PATCH 004/108] Update LLVM development policy State explicitly that we want to eliminate all differences between `apple/master` and `llvm.org/master`. All new LLVM development should happen upstream. --- docs/Branches.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Branches.md b/docs/Branches.md index e533c3af5e351..ea86504c4c20e 100644 --- a/docs/Branches.md +++ b/docs/Branches.md @@ -62,7 +62,7 @@ You can use any of the branch names as the argument to `--scheme`, such as `mast ... 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. + 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` From b5392e8fb3fd5edfc58552d6e6f01e0d60335dfc Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sun, 26 Apr 2020 21:22:03 +0200 Subject: [PATCH 005/108] Refactors internal func _applyMapping using _FixedArray16 --- .../public/core/UnicodeScalarProperties.swift | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) 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) } } From 4e227f8a76deb1d189a0e62694124a11dbbe1792 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Sat, 23 May 2020 09:50:25 -0700 Subject: [PATCH 006/108] [Index] Apply -index-ignore-system-modules to clang modules --- lib/Index/IndexRecord.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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. From d6bf31cb97d9f3b0ba5615408b6450d38472b2a6 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 27 May 2020 17:03:58 -0700 Subject: [PATCH 007/108] [Diagnostics] Add a distinct diagnostic for missing raw representable init 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. --- lib/Sema/CSDiagnostics.cpp | 28 ++++++++++++++++++++++++++++ lib/Sema/CSDiagnostics.h | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index b704deb84fa24..74b2d9b7cf5c1 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6389,3 +6389,31 @@ bool UnableToInferKeyPathRootFailure::diagnoseAsError() { .fixItInsertAfter(keyPathExpr->getStartLoc(), "<#Root#>"); return true; } + +bool MissingRawRepresentativeInitFailure::diagnoseAsError() { + auto *locator = getLocator(); + + Optional> message; + + if (locator->isForContextualType()) { + message = diag::cannot_convert_initializer_value; + } else if (locator->isForAssignment()) { + message = diag::cannot_convert_assign; + } else if (locator->isLastElement()) { + message = diag::cannot_convert_argument_value; + } + + if (!message) + return false; + + auto diagnostic = emitDiagnostic(*message, ValueType, RawReprType); + + if (auto *E = getAsExpr(getAnchor())) { + auto range = E->getSourceRange(); + diagnostic + .fixItInsert(range.Start, RawReprType->getString() + "(rawValue: ") + .fixItInsertAfter(range.End, ") ?? <#default value#>"); + } + + return true; +} diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 72670b9f3fd4e..b65334551817d 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2102,6 +2102,33 @@ class UnableToInferKeyPathRootFailure final : public FailureDiagnostic { bool diagnoseAsError() override; }; +/// 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 MissingRawRepresentativeInitFailure final : public FailureDiagnostic { + Type RawReprType; + Type ValueType; + +public: + MissingRawRepresentativeInitFailure(const Solution &solution, + Type rawReprType, Type valueType, + ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), RawReprType(rawReprType), + ValueType(valueType) {} + + bool diagnoseAsError() override; +}; + } // end namespace constraints } // end namespace swift From 959c6d56062b0ddf21906b582543003c68783e18 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 27 May 2020 17:52:46 -0700 Subject: [PATCH 008/108] [CSFix] Move type verification out of `ExplicitlyConstructRawRepresentable` Do the verification during constraint repair and provide fix itself with raw representative type and its raw value to be used for diagnostics. --- lib/Sema/CSFix.cpp | 23 ++++++++++++----------- lib/Sema/CSFix.h | 20 +++++++++++++------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 7e68315383a1f..bbe75fa4d3d05 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1144,18 +1144,19 @@ 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)); +bool ExplicitlyConstructRawRepresentable::diagnose(const Solution &solution, + bool asNote) const { + MissingRawRepresentativeInitFailure failure(solution, RawReprType, ValueType, + getLocator()); + return failure.diagnose(asNote); +} - return nullptr; +ExplicitlyConstructRawRepresentable * +ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, + Type rawReprType, Type valueType, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + ExplicitlyConstructRawRepresentable(cs, rawReprType, valueType, locator); } UseValueTypeOfRawRepresentative * diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index ad3b45633bc70..3662d22999550 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -1594,21 +1594,27 @@ 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 ValueType; + + ExplicitlyConstructRawRepresentable(ConstraintSystem &cs, Type rawReprType, + Type valueType, ConstraintLocator *locator) - : AllowArgumentMismatch(cs, FixKind::ExplicitlyConstructRawRepresentable, - argType, paramType, locator) {} + : ConstraintFix(cs, FixKind::ExplicitlyConstructRawRepresentable, + locator), + RawReprType(rawReprType), ValueType(valueType) {} 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 valueType, + ConstraintLocator *locator); }; class UseValueTypeOfRawRepresentative final : public AllowArgumentMismatch { From 20f4ef93dec0c0eaa31fc3cb1e2732ae0ed68dae Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 22 May 2020 12:33:30 -0700 Subject: [PATCH 009/108] IRGen: Default to clang's frame pointer elimination settings Clang provides options to override that default value. These options are accessible via the -Xcc flag. Some Swift functions explicitly disable the frame pointer. The clang options will not override those. --- include/swift/AST/IRGenOptions.h | 7 +-- include/swift/Option/Options.td | 4 -- lib/Driver/ToolChains.cpp | 2 - lib/Frontend/CompilerInvocation.cpp | 3 -- lib/IRGen/GenMeta.cpp | 4 +- lib/IRGen/IRGenModule.cpp | 68 ++++++++--------------------- lib/IRGen/IRGenModule.h | 4 +- lib/IRGen/MetadataRequest.cpp | 8 ++-- test/IRGen/framepointer.sil | 30 ++++++++++++- test/IRGen/framepointer_arm64.sil | 4 +- 10 files changed, 57 insertions(+), 77 deletions(-) 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/Option/Options.td b/include/swift/Option/Options.td index 8a9971367dd69..a430124cc7f27 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1010,10 +1010,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/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a9c5476839867..4f9ac680af66e 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -288,8 +288,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/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c5bf8daeec430..bcde1fa61cf8e 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1514,9 +1514,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/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 7eca86628b80c..f982a848754de 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -177,7 +177,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); @@ -2234,7 +2234,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/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 a04212ba9b958..37e6e734ed175 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -1305,8 +1305,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/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 3ab7bcd4f9237..018700368776f 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -1615,7 +1615,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. @@ -1997,8 +1997,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); @@ -2469,7 +2469,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/test/IRGen/framepointer.sil b/test/IRGen/framepointer.sil index ab1d393011a36..d580f6f836a9d 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 -Xcc -mno-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECK-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 +// RUN: %target-swift-frontend -primary-file %s -emit-ir -Xcc -fomit-frame-pointer | %FileCheck %s --check-prefix=NOFP // REQUIRES: CPU=x86_64 @@ -46,6 +48,32 @@ entry(%i : $Int32): // CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" +// 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: attributes [[ATTR]] = {{{.*}}"frame-pointer"="non-leaf" + +// 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 From bd65f7418bb6952dd4e3a8295119739ca8265412 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 May 2020 13:37:43 -0700 Subject: [PATCH 010/108] [Diagnostics] Add fix-its to suggest explicit raw representable initialization This makes logic in `ContextualFailure::tryRawRepresentableFixIts` partially obsolete. --- lib/Sema/CSDiagnostics.cpp | 47 +++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 74b2d9b7cf5c1..c8e0757a4da88 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6410,9 +6410,50 @@ bool MissingRawRepresentativeInitFailure::diagnoseAsError() { if (auto *E = getAsExpr(getAnchor())) { auto range = E->getSourceRange(); - diagnostic - .fixItInsert(range.Start, RawReprType->getString() + "(rawValue: ") - .fixItInsertAfter(range.End, ") ?? <#default value#>"); + auto rawReprObjType = RawReprType->getOptionalObjectType(); + auto valueObjType = ValueType->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#>"); + } } return true; From 87a00793370ca5fc05d0a1d164e35dac2d81f5f4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 May 2020 15:35:51 -0700 Subject: [PATCH 011/108] [Diagnostic] Always resolve types required for raw representative construction Since both raw representable and value types originated in constraint system they can have type variables which need to be resolved before types could be used in a diagnostic and fix-it. --- lib/Sema/CSDiagnostics.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index b65334551817d..e17f41ee1b2e9 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2123,8 +2123,9 @@ class MissingRawRepresentativeInitFailure final : public FailureDiagnostic { MissingRawRepresentativeInitFailure(const Solution &solution, Type rawReprType, Type valueType, ConstraintLocator *locator) - : FailureDiagnostic(solution, locator), RawReprType(rawReprType), - ValueType(valueType) {} + : FailureDiagnostic(solution, locator), + RawReprType(resolveType(rawReprType)), + ValueType(resolveType(valueType)) {} bool diagnoseAsError() override; }; From 7034fb3eb7c8da2f642519b3f9041ab752e17d49 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 28 May 2020 16:22:12 -0700 Subject: [PATCH 012/108] [Diagnostic] Add a note to missing explicit raw representative init diagnostic --- lib/Sema/CSDiagnostics.cpp | 34 +++++++++++++++++++++++++++++++++- lib/Sema/CSDiagnostics.h | 4 ++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index c8e0757a4da88..32d7828ffc762 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6407,7 +6407,12 @@ bool MissingRawRepresentativeInitFailure::diagnoseAsError() { return false; auto diagnostic = emitDiagnostic(*message, ValueType, RawReprType); + fixIt(diagnostic); + return true; +} +void MissingRawRepresentativeInitFailure::fixIt( + InFlightDiagnostic &diagnostic) const { if (auto *E = getAsExpr(getAnchor())) { auto range = E->getSourceRange(); auto rawReprObjType = RawReprType->getOptionalObjectType(); @@ -6455,6 +6460,33 @@ bool MissingRawRepresentativeInitFailure::diagnoseAsError() { .fixItInsertAfter(range.End, ") ?? <#default value#>"); } } +} - return true; +bool MissingRawRepresentativeInitFailure::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(), ValueType, 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; } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index e17f41ee1b2e9..1376b7d8588c3 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2128,6 +2128,10 @@ class MissingRawRepresentativeInitFailure final : public FailureDiagnostic { ValueType(resolveType(valueType)) {} bool diagnoseAsError() override; + bool diagnoseAsNote() override; + +private: + void fixIt(InFlightDiagnostic &diagnostic) const; }; } // end namespace constraints From 66c333d6e293e1003b4c7eb988453a9d6643306f Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Fri, 29 May 2020 09:41:22 +0200 Subject: [PATCH 013/108] Submitting to swift/master-next is still allowed. Add additional clarification that submitting to `swift/master-next` continues to be allowed. --- docs/Branches.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Branches.md b/docs/Branches.md index ea86504c4c20e..d5c04ee77bb2d 100644 --- a/docs/Branches.md +++ b/docs/Branches.md @@ -62,12 +62,16 @@ You can use any of the branch names as the argument to `--scheme`, such as `mast ... 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. Note that no new changes should be submitted directly to `apple/master`. We are actively working on eliminating the differences from upstream LLVM. + 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` ...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.)* + 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 Some branches are *automerged* into other branches, to keep them in sync. This is just a process that runs `git merge` at a regular interval. These are run by Apple and are either on a "frequent" (sub-hourly) or nightly schedule. From f048652a2bd3bec070524980584cf9bfe6b9dd12 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 20 May 2020 11:48:15 -0700 Subject: [PATCH 014/108] [ConstraintSystem] Do more checking before suggesting to explicitly contruct raw representable Introduce `repairByExplicitRawRepresentativeUse` which is used for assignment, argument-to-parameter conversions and contextual mismatches. It checks whether `to` side is a raw representable type and tries to match `from` side to its `rawValue`. --- lib/Sema/CSSimplify.cpp | 51 +++++++++++++++++++++++--- test/Migrator/rdar31892850.swift | 2 +- test/Sema/enum_raw_representable.swift | 22 ++++++++--- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 51bc765d50ed6..8a3c646fa0ca0 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3135,6 +3135,39 @@ bool ConstraintSystem::repairFailures( return false; }; + // Check whether given `rawReprType` does indeed conform to `RawRepresentable` + // and if so check that given `valueType` 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 repairByExplicitRawRepresentativeUse = + [&](Type origValueType, Type origRawReprType) -> bool { + auto rawReprType = origRawReprType; + // Let's unwrap a single level of optionality since + // diagnostic is going to suggest failable initializer anyway. + if (auto objType = rawReprType->getOptionalObjectType()) + rawReprType = objType; + + auto valueType = origValueType; + // If value is optional diagnostic would suggest using `Optional.map` in + // combination with `(rawValue: ...)` initializer. + if (auto objType = valueType->getOptionalObjectType()) + valueType = objType; + + auto rawValue = isRawRepresentable(*this, rawReprType); + if (!rawValue) + return false; + + auto result = matchTypes(valueType, rawValue, ConstraintKind::Conversion, + TMF_ApplyingFix, locator); + + if (result.isFailure()) + return false; + + conversionsOrFixes.push_back(ExplicitlyConstructRawRepresentable::create( + *this, origRawReprType, origValueType, getConstraintLocator(locator))); + return true; + }; + auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) { return llvm::any_of(conversionsOrFixes, [kind](const RestrictionOrFix correction) { @@ -3351,6 +3384,10 @@ bool ConstraintSystem::repairFailures( conversionsOrFixes, locator)) return true; + // `rhs` - is an assignment destination and `lhs` is its source. + if (repairByExplicitRawRepresentativeUse(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,12 +3620,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); @@ -3624,6 +3655,10 @@ bool ConstraintSystem::repairFailures( if (lhs->hasHole() || rhs->hasHole()) return true; + // `lhs` - is an argument and `rhs` is a parameter type. + if (repairByExplicitRawRepresentativeUse(lhs, rhs)) + break; + if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; @@ -3854,6 +3889,10 @@ bool ConstraintSystem::repairFailures( })) break; + // `lhs` - is an result type and `rhs` is a contextual type. + if (repairByExplicitRawRepresentativeUse(lhs, rhs)) + break; + conversionsOrFixes.push_back(IgnoreContextualType::create( *this, lhs, rhs, getConstraintLocator(locator))); break; 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/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift index 2c4c24dc5f330..b6b21ba7a6d9d 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,9 +122,9 @@ 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) {} @@ -141,6 +141,16 @@ E_32431165.bar == "bar" "bar" == E_32431165.bar // expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{10-10=}} {{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" @@ -165,9 +175,9 @@ func sr8150(bar: Bar) { sr8150_helper2(bar) // expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{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 { From 03938f9ec556bb366c9d0c9e6d341928dd19f8c5 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 May 2020 12:14:30 -0700 Subject: [PATCH 015/108] [Diagnostics] NFC: Remove obsolete logic from `ContextualFailure::tryRawRepresentableFixIts` --- lib/Sema/CSDiagnostics.cpp | 71 -------------------------------------- 1 file changed, 71 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 32d7828ffc762..9b0ba480857c6 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2569,84 +2569,13 @@ bool ContextualFailure::tryRawRepresentableFixIts( } 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; From 942d96729726f3dbaa7415c0e7215cd2c36c458d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 May 2020 12:18:03 -0700 Subject: [PATCH 016/108] [CSFix] Move type verification out of `UseValueTypeOfRawRepresentative` --- lib/Sema/CSFix.cpp | 45 ++++++++++++--------------------------------- lib/Sema/CSFix.h | 22 ++++++++++++++-------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index bbe75fa4d3d05..d26e7a4b1590d 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, @@ -1159,18 +1137,19 @@ ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, ExplicitlyConstructRawRepresentable(cs, rawReprType, valueType, locator); } -UseValueTypeOfRawRepresentative * -UseValueTypeOfRawRepresentative::attempt(ConstraintSystem &cs, Type argType, - Type paramType, - ConstraintLocatorBuilder locator) { - auto rawRepresentableType = argType->lookThroughAllOptionalTypes(); - auto valueType = paramType->lookThroughAllOptionalTypes(); - - if (isValueOfRawRepresentable(cs, rawRepresentableType, valueType)) - return new (cs.getAllocator()) UseValueTypeOfRawRepresentative( - cs, rawRepresentableType, valueType, cs.getConstraintLocator(locator)); +bool UseValueTypeOfRawRepresentative::diagnose(const Solution &solution, + bool asNote) const { + ArgumentMismatchFailure failure(solution, RawReprType, ValueType, + getLocator()); + return failure.diagnose(asNote); +} - return nullptr; +UseValueTypeOfRawRepresentative * +UseValueTypeOfRawRepresentative::create(ConstraintSystem &cs, Type rawReprType, + Type valueType, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + UseValueTypeOfRawRepresentative(cs, rawReprType, valueType, locator); } unsigned AllowArgumentMismatch::getParamIdx() const { diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 3662d22999550..1a0f08dcb34ba 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -1617,20 +1617,26 @@ class ExplicitlyConstructRawRepresentable final : public ConstraintFix { ConstraintLocator *locator); }; -class UseValueTypeOfRawRepresentative final : public AllowArgumentMismatch { - UseValueTypeOfRawRepresentative(ConstraintSystem &cs, Type argType, - Type paramType, ConstraintLocator *locator) - : AllowArgumentMismatch(cs, FixKind::UseValueTypeOfRawRepresentative, - argType, paramType, locator) {} +class UseValueTypeOfRawRepresentative final : public ConstraintFix { + Type RawReprType; + Type ValueType; + + UseValueTypeOfRawRepresentative(ConstraintSystem &cs, Type rawReprType, + Type valueType, ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::UseValueTypeOfRawRepresentative, locator), + RawReprType(rawReprType), ValueType(valueType) {} 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 UseValueTypeOfRawRepresentative *create(ConstraintSystem &cs, + Type rawReprType, + Type valueType, + ConstraintLocator *locator); }; /// Replace a coercion ('as') with a forced checked cast ('as!'). From 761657f398d9cf3c7b933ccb4cdd74bd11f67b99 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 May 2020 13:24:27 -0700 Subject: [PATCH 017/108] [Diagnostics] Extract common logic for raw representable diagnostics into `AbstractRawRepresentableFailure` --- lib/Sema/CSDiagnostics.cpp | 18 +++++++++------- lib/Sema/CSDiagnostics.h | 43 +++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 9b0ba480857c6..4e4ae3ba5ce52 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6319,23 +6319,27 @@ bool UnableToInferKeyPathRootFailure::diagnoseAsError() { return true; } -bool MissingRawRepresentativeInitFailure::diagnoseAsError() { +Optional> +AbstractRawRepresentableFailure::getDiagnostic() const { auto *locator = getLocator(); - Optional> message; - if (locator->isForContextualType()) { - message = diag::cannot_convert_initializer_value; + return diag::cannot_convert_initializer_value; } else if (locator->isForAssignment()) { - message = diag::cannot_convert_assign; + return diag::cannot_convert_assign; } else if (locator->isLastElement()) { - message = diag::cannot_convert_argument_value; + return diag::cannot_convert_argument_value; } + return None; +} + +bool AbstractRawRepresentableFailure::diagnoseAsError() { + auto message = getDiagnostic(); if (!message) return false; - auto diagnostic = emitDiagnostic(*message, ValueType, RawReprType); + auto diagnostic = emitDiagnostic(*message, getFromType(), getToType()); fixIt(diagnostic); return true; } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 1376b7d8588c3..ca1a13a985f79 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2102,6 +2102,30 @@ class UnableToInferKeyPathRootFailure final : public FailureDiagnostic { bool diagnoseAsError() override; }; +class AbstractRawRepresentableFailure : public FailureDiagnostic { +protected: + Type RawReprType; + Type ValueType; + + AbstractRawRepresentableFailure(const Solution &solution, Type rawReprType, + Type valueType, ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), + RawReprType(resolveType(rawReprType)), + ValueType(resolveType(valueType)) {} + +public: + virtual Type getFromType() const = 0; + virtual Type getToType() const = 0; + + bool diagnoseAsError() override; + bool diagnoseAsNote() override { return false; } + +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. /// @@ -2115,23 +2139,22 @@ class UnableToInferKeyPathRootFailure final : public FailureDiagnostic { /// /// `0` has to be wrapped into `E(rawValue: 0)` and either defaulted via `??` or /// force unwrapped to constitute a valid binding. -class MissingRawRepresentativeInitFailure final : public FailureDiagnostic { - Type RawReprType; - Type ValueType; - +class MissingRawRepresentativeInitFailure final + : public AbstractRawRepresentableFailure { public: MissingRawRepresentativeInitFailure(const Solution &solution, Type rawReprType, Type valueType, ConstraintLocator *locator) - : FailureDiagnostic(solution, locator), - RawReprType(resolveType(rawReprType)), - ValueType(resolveType(valueType)) {} + : AbstractRawRepresentableFailure(solution, rawReprType, valueType, + locator) {} + + Type getFromType() const override { return ValueType; } + Type getToType() const override { return RawReprType; } - bool diagnoseAsError() override; bool diagnoseAsNote() override; -private: - void fixIt(InFlightDiagnostic &diagnostic) const; +protected: + void fixIt(InFlightDiagnostic &diagnostic) const override; }; } // end namespace constraints From b38d11d24a5cf7779432834e9dd3ce06a7380e8e Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 29 May 2020 14:39:48 -0700 Subject: [PATCH 018/108] [Diagnostics] Add a distinct diagnostic for use of raw representable instead of its raw value 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. --- lib/Sema/CSDiagnostics.cpp | 29 +++++++++++++++++++++++++++++ lib/Sema/CSDiagnostics.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 4e4ae3ba5ce52..68b75871141e8 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6423,3 +6423,32 @@ bool MissingRawRepresentativeInitFailure::diagnoseAsNote() { return false; } + +void UseOfRawRepresentableInsteadOfItsRawValueFailure::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 += ".map { $0.rawValue } "; + + if (!ValueType->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 ca1a13a985f79..064a815294917 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2157,6 +2157,35 @@ class MissingRawRepresentativeInitFailure final 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 UseOfRawRepresentableInsteadOfItsRawValueFailure final + : public AbstractRawRepresentableFailure { +public: + UseOfRawRepresentableInsteadOfItsRawValueFailure(const Solution &solution, + Type rawReprType, + Type valueType, + ConstraintLocator *locator) + : AbstractRawRepresentableFailure(solution, rawReprType, valueType, + locator) {} + + Type getFromType() const override { return RawReprType; } + Type getToType() const override { return ValueType; } + +private: + void fixIt(InFlightDiagnostic &diagnostic) const override; +}; + } // end namespace constraints } // end namespace swift From cd838963a098d72806cfb9adad3c92d570b6b0f9 Mon Sep 17 00:00:00 2001 From: Bruno Rocha Date: Fri, 29 May 2020 23:13:00 +0200 Subject: [PATCH 019/108] Index objcdynamic --- include/swift/AST/ASTWalker.h | 1 + lib/IDE/SourceEntityWalker.cpp | 6 ++++++ test/Index/index_objc_dynamic_refs.swift | 26 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 test/Index/index_objc_dynamic_refs.swift 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/lib/IDE/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp index b57a33811927c..7b1d389c068ed 100644 --- a/lib/IDE/SourceEntityWalker.cpp +++ b/lib/IDE/SourceEntityWalker.cpp @@ -511,6 +511,12 @@ std::pair SemaAnnotator::walkToExprPre(Expr *E) { return doSkipChildren(); } + } else if (auto DMRE = dyn_cast(E)) { + if (!passReference(DMRE->getMember().getDecl(), DMRE->getType(), + DMRE->getNameLoc(), + ReferenceMetaData(SemaReferenceKind::DynamicMemberRef, + OpAccess))) + return stopTraversal; } return { true, E }; diff --git a/test/Index/index_objc_dynamic_refs.swift b/test/Index/index_objc_dynamic_refs.swift new file mode 100644 index 0000000000000..5700787017178 --- /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]]:23 | instance-method/Swift | dynamicMethod() | [[DynamicMethod_USR]] | Ref + // CHECK: [[@LINE-2]]:9 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + _ = objcDelegate?.property + // CHECK: [[@LINE-1]]:27 | instance-property/Swift | property | [[DynamicProperty_USR]] | Ref + // CHECK: [[@LINE-2]]:13 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + } +} From 3e200b77837a6ef83e6dc468af5efcfb3c91e0aa Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 28 May 2020 19:45:05 -0700 Subject: [PATCH 020/108] [CodeCompletion] Skip typechecking unrelated statements in func bodies rdar://problem/58687608 --- lib/IDE/CodeCompletion.cpp | 4 +++- lib/IDE/ConformingMethodList.cpp | 4 +--- lib/IDE/TypeContextInfo.cpp | 4 +--- lib/Sema/TypeCheckStmt.cpp | 25 +++++++++++-------------- test/IDE/complete_skipbody.swift | 26 ++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 test/IDE/complete_skipbody.swift diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 63d59acd325a5..245451ec2a608 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -5736,7 +5736,9 @@ void CodeCompletionCallbacksImpl::doneParsing() { typeCheckContextUntil( CurDeclContext, - CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); + ParsedExpr + ? ParsedExpr->getLoc() + : CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); // Add keywords even if type checking fails completely. addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index 30c6600f53222..b986997a39fb8 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()); + typeCheckContextUntil(CurDeclContext, ParsedExpr->getLoc()); Type T = ParsedExpr->getType(); diff --git a/lib/IDE/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index 68e7b672c92d8..0c9fc7a4a9a7b 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -88,9 +88,7 @@ void ContextInfoCallbacks::doneParsing() { if (!ParsedExpr) return; - typeCheckContextUntil( - CurDeclContext, - CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc()); + typeCheckContextUntil(CurDeclContext, ParsedExpr->getLoc()); ExprContextInfo Info(CurDeclContext, ParsedExpr); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 2a0f34f76ef6e..5369d4e65197f 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1563,12 +1563,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 (EndTypeCheckLoc.isValid()) { + if (SM.isBeforeInBuffer(EndTypeCheckLoc, 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 == EndTypeCheckLoc || + SM.isBeforeInBuffer(endLoc, EndTypeCheckLoc)) + continue; + } + + if (auto *SubExpr = elem.dyn_cast()) { // Type check the expression. TypeCheckExprOptions options = TypeCheckExprFlags::IsExprStmt; bool isDiscarded = (!getASTContext().LangOpts.Playground && @@ -1607,22 +1614,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); } diff --git a/test/IDE/complete_skipbody.swift b/test/IDE/complete_skipbody.swift new file mode 100644 index 0000000000000..c8e9913f440d7 --- /dev/null +++ b/test/IDE/complete_skipbody.swift @@ -0,0 +1,26 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token COMPLETE -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 } +} + +func test(value: MyStruct) { + + let FORBIDDEN_localVar = 1 + let unrelated = FORBIDDEN_Struct() + guard let a = unrelated.FORBIDDEN_method() else { + return + } + + _ = value.#^COMPLETE^# +} + +// 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 From a22fd6fc410b179ca00189061c4df705f5382ed4 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 May 2020 10:37:14 -0700 Subject: [PATCH 021/108] [TypeChecker] Typecheck statement condition on demand from NamingPatternRequest. --- lib/Sema/TypeCheckConstraints.cpp | 23 +++++++++++++++++++++++ lib/Sema/TypeCheckDecl.cpp | 28 +++++++++++++++++++--------- lib/Sema/TypeCheckStmt.cpp | 14 ++++---------- lib/Sema/TypeChecker.h | 11 ++++++++++- test/IDE/complete_skipbody.swift | 14 ++++++++++++-- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 8d3a82dbe8251..072e429f41233 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2564,6 +2564,29 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, return false; } +bool TypeChecker::typeCheckConditionForStatement(LabeledConditionalStmt *stmt, + DeclContext *dc) { + Diag<> diagnosticForAlwaysTrue = diag::invalid_diagnostic; + switch (stmt->getKind()) { + case StmtKind::If: + diagnosticForAlwaysTrue = diag::if_always_true; + break; + case StmtKind::While: + diagnosticForAlwaysTrue = diag::while_always_true; + break; + case StmtKind::Guard: + diagnosticForAlwaysTrue = diag::guard_always_succeeds; + break; + default: + llvm_unreachable("unknown LabeledConditionalStmt kind"); + } + + StmtCondition cond = stmt->getCond(); + bool result = typeCheckStmtCondition(cond, dc, diagnosticForAlwaysTrue); + stmt->setCond(cond); + return result; +} + /// Find the '~=` operator that can compare an expression inside a pattern to a /// value of a given type. bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 146b59ee3117f..97dc8dc431b4a 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2360,23 +2360,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/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 5369d4e65197f..6b7aa8898fac4 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -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(); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index cbae4220752e6..f997756b1a613 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -756,7 +756,16 @@ 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 +/// Type check the given 'if', 'while', or 'guard' statement condition. +/// +/// \param stmt The conditional statement to type-check, which will be modified +/// in place. +/// +/// \returns true if an error occurred, false otherwise. +bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt, + DeclContext *dc); + +/// Type check the given 'if', 'while', or 'guard' statement condition, which /// either converts an expression to a logic value or bind variables to the /// contents of an Optional. /// diff --git a/test/IDE/complete_skipbody.swift b/test/IDE/complete_skipbody.swift index c8e9913f440d7..b66fa2691a8c1 100644 --- a/test/IDE/complete_skipbody.swift +++ b/test/IDE/complete_skipbody.swift @@ -8,15 +8,25 @@ struct MyStruct { var y: Int { 1 } } -func test(value: MyStruct) { +func test(valueOptOpt: MyStruct??) { let FORBIDDEN_localVar = 1 let unrelated = FORBIDDEN_Struct() + + let valueOpt = valueOptOpt! + guard let a = unrelated.FORBIDDEN_method() else { return } - _ = value.#^COMPLETE^# + guard let value = valueOpt else { + return + } + + if (value.x == 1) { + let unrelated2 = FORBIDDEN_Struct() + _ = value.#^COMPLETE^# + } } // CHECK: Begin completions, 3 items From 0a72d023f39d3e22a2d867840a0f584c34f96d85 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 May 2020 10:54:12 -0700 Subject: [PATCH 022/108] [TypeChecker] Rename 'typeCheckAbstractFunctionBodyUntil()' to 'typeCheckAbstractFunctionBodyNodeAt()' because that only typecheck a statement at the position. --- include/swift/AST/TypeCheckRequests.h | 4 +-- include/swift/AST/TypeCheckerTypeIDZone.def | 2 +- include/swift/Sema/IDETypeChecking.h | 4 +-- lib/AST/TypeCheckRequests.cpp | 4 +-- lib/IDE/ExprContextAnalysis.cpp | 2 +- lib/Sema/TypeCheckStmt.cpp | 36 ++++++++----------- lib/Sema/TypeChecker.cpp | 7 ++-- lib/Sema/TypeChecker.h | 2 -- test/Misc/stats_dir_profiler.swift | 2 +- .../scale_neighbouring_getset.gyb | 2 +- 10 files changed, 29 insertions(+), 36 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 8fffe1e39a6ba..024939b260a3e 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -872,8 +872,8 @@ class LazyStoragePropertyRequest : /// /// 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: diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index f69a109bf4693..444cf2cae924a 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -196,7 +196,7 @@ SWIFT_REQUEST(TypeChecker, SuperclassTypeRequest, SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest, AccessorDecl *(AbstractStorageDecl *, AccessorKind), SeparatelyCached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyUntilRequest, +SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyRequest, bool(AbstractFunctionDecl *, SourceLoc), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *), diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 91edfc0ae81b5..790d8de6fcd07 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -134,8 +134,8 @@ namespace swift { bool typeCheckExpression(DeclContext *DC, Expr *&parsedExpr); /// Partially typecheck the specified function body. - bool typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc); + bool typeCheckAbstractFunctionBodyNodeAt(AbstractFunctionDecl *AFD, + SourceLoc TargetLoc); /// Typecheck top-level code parsed during code completion. /// 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/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 9b906ec2a8e74..419bbf3450f58 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -79,7 +79,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::typeCheckAbstractFunctionBodyNodeAt(AFD, Loc); } else { assert(bodyRange.isInvalid() && "The body should not be parsed if the " "completion happens in the signature"); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 6b7aa8898fac4..a4066e2ebaa59 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -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; @@ -1557,15 +1557,15 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) { } for (auto &elem : BS->getElements()) { - if (EndTypeCheckLoc.isValid()) { - if (SM.isBeforeInBuffer(EndTypeCheckLoc, elem.getStartLoc())) + 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 == EndTypeCheckLoc || - SM.isBeforeInBuffer(endLoc, EndTypeCheckLoc)) + if (endLoc == TargetTypeCheckLoc || + SM.isBeforeInBuffer(endLoc, TargetTypeCheckLoc)) continue; } @@ -1577,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; @@ -1635,7 +1635,9 @@ static Type getFunctionBuilderType(FuncDecl *FD) { } bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) { - auto res = TypeChecker::typeCheckAbstractFunctionBodyUntil(AFD, SourceLoc()); + auto res = + evaluateOrDefault(AFD->getASTContext().evaluator, + TypeCheckFunctionBodyRequest{AFD, SourceLoc()}, true); TypeChecker::checkFunctionErrorHandling(AFD); TypeChecker::computeCaptures(AFD); return res; @@ -1835,9 +1837,9 @@ static void checkClassConstructorBody(ClassDecl *classDecl, } bool -TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator, - AbstractFunctionDecl *AFD, - SourceLoc endTypeCheckLoc) const { +TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, + AbstractFunctionDecl *AFD, + SourceLoc targetTypeCheckLoc) const { ASTContext &ctx = AFD->getASTContext(); Optional timer; @@ -1894,7 +1896,7 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator, bool hadError = false; if (!alreadyTypeChecked) { StmtChecker SC(AFD); - SC.EndTypeCheckLoc = endTypeCheckLoc; + SC.TargetTypeCheckLoc = targetTypeCheckLoc; hadError = SC.typeCheckBody(body); } @@ -1925,20 +1927,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 && targetTypeCheckLoc.isInvalid()) 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/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index faf691e6fa501..d20fd76b993f2 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -540,11 +540,12 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { return !resultTy; } -bool swift::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, - SourceLoc EndTypeCheckLoc) { +bool swift::typeCheckAbstractFunctionBodyNodeAt(AbstractFunctionDecl *AFD, + SourceLoc TargetLoc) { auto &Ctx = AFD->getASTContext(); DiagnosticSuppression suppression(Ctx.Diags); - return !TypeChecker::typeCheckAbstractFunctionBodyUntil(AFD, EndTypeCheckLoc); + return !evaluateOrDefault(Ctx.evaluator, + TypeCheckFunctionBodyRequest{AFD, TargetLoc}, true); } bool swift::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index f997756b1a613..b67078388e8de 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 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/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} { From 6c61e605f2bb97380571b79488642b830c06e8a1 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 May 2020 11:09:59 -0700 Subject: [PATCH 023/108] [CodeCompletion] Skip typechecking preceding top level decls --- lib/IDE/ExprContextAnalysis.cpp | 17 +---------------- test/IDE/complete_skipbody.swift | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 419bbf3450f58..945eeccc04075 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -104,22 +104,7 @@ void swift::ide::typeCheckContextUntil(DeclContext *DC, SourceLoc Loc) { 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); } diff --git a/test/IDE/complete_skipbody.swift b/test/IDE/complete_skipbody.swift index b66fa2691a8c1..b3785e58738e1 100644 --- a/test/IDE/complete_skipbody.swift +++ b/test/IDE/complete_skipbody.swift @@ -1,4 +1,6 @@ -// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token COMPLETE -debug-forbid-typecheck-prefix FORBIDDEN | %FileCheck %s +// 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 } } @@ -8,6 +10,13 @@ struct MyStruct { 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 @@ -20,15 +29,27 @@ func test(valueOptOpt: MyStruct??) { } guard let value = valueOpt else { + let FORBIDDEN_localVar2 = 1 return } if (value.x == 1) { let unrelated2 = FORBIDDEN_Struct() - _ = value.#^COMPLETE^# + _ = value.#^FUNCTIONBODY^# } } +let globalValue = globalValueOpt! + +let FORBIDDEN_localVar = 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 From 0e985be3f4814c6a6d1e4f7cb3e5447ee03a01db Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 29 May 2020 13:28:24 -0700 Subject: [PATCH 024/108] [silgen] Create a function level scope when open coding implicit value initializers. The Original Bug ---------------- In ffbfcfa131465daca2018fbdd34015899a9c0d00, we fixed a bug around implicit value initializers but did not cherry-pick it to 5.3. While investigating a bug that turned out to be that same bug (no worries!), I noticed that there is additional code that is "unsafely" correct in this area and that while ffbfcfa131465daca2018fbdd34015899a9c0d00 is correct in the small, we can expand on the fix to prevent future bugs. The Larger Bug -------------- Here we are still open coding using ManagedValue/Cleanup APIs /without/ a top level function scope. The code is only correct since we never emit unconditional cleanups and always manually forward conditional cleanups. If we did not do either of these things, we would have another instance of this bug, namely a cleanup that is never actually emitted. So the code on master today is correct, albeit unsafe, and we already have coverage for this (namely the test case from ffbfcfa131465daca2018fbdd34015899a9c0d00). That being said, in general when working with ManagedValue APIs (especially in utility functions) we assume that we have a scope already created for us by our caller. So by fixing this issue we are standardizing to safer SILGen invariants. Building on ffbfcfa131465daca2018fbdd34015899a9c0d00 ---------------------------------------------------- This commit builds on the shoulders of ffbfcfa131465daca2018fbdd34015899a9c0d00 by adding the function level scope mentioned in the previous section so that we are now "safely" correct. While looking at this I also realized that just using a normal scope when open coding here may be a bit bugprone for open coding situations like this since: 1. If one just creates a scope in open coding situations, the scope will fire at end of the c++ function /after/ one has probably emitted a return. 2. Once one has emitted the return, the insertion point will no longer be set implying =><=. To avoid this, I created a move only composition type on top of Scope called AssertingManualScope. This type just asserts in its destructor if the scope it contains has not been popped yet. While, one can pop it by ones self, I added an overload of createReturnInst on SILGenBuilder that also takes an AssertingManualScope and pops it at the appropriate time. So now when performing simple open coding tasks, we have the ability to in code tie together the function level scope to the actual creation of return inst, simulating the hand-off of lifetimes/resources from caller/callee that often happens in the epilog of functions. --- lib/SILGen/SILGenBuilder.cpp | 7 ++++++ lib/SILGen/SILGenBuilder.h | 4 +++ lib/SILGen/SILGenConstructor.cpp | 9 +++++-- lib/SILGen/Scope.h | 43 ++++++++++++++++++++++++++++++-- 4 files changed, 59 insertions(+), 4 deletions(-) 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/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 From ae624f3947e40dbf420266ff6e11adb9321ce0f3 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 29 May 2020 16:13:41 -0700 Subject: [PATCH 025/108] [gardening] Fix a double "the" in a comment --- lib/AST/ASTVerifier.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 1ad1f9e509a42..96fb15260c247 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -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)) { From ab6c15f4b3c009a16cc6e54ca21b0af8a8731368 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Fri, 29 May 2020 16:13:42 -0700 Subject: [PATCH 026/108] [Frontend] Bail early if the stdlib is missing Rather than trying to continue the compilation with an empty main module, let's bail out early if we expect an implicit stdlib import and fail to load in the stdlib. --- include/swift/Frontend/Frontend.h | 7 ++++--- lib/Frontend/Frontend.cpp | 27 ++++++++++----------------- lib/FrontendTool/FrontendTool.cpp | 11 +++++++++++ lib/IDE/CompletionInstance.cpp | 13 +++++++------ 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 33d62e639499f..7bc32492775dc 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -646,10 +646,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/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index aca792d419588..21676b0cfd7ce 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -740,17 +740,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 +802,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() { diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 2cab277dfddbd..48384a17a74a2 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1250,6 +1250,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/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 6f60d681e6d9a..99095abeb8032 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -527,15 +527,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 completionFile = CI.getCodeCompletionFile(); auto *state = completionFile.get()->getDelayedParserState(); if (!state->hasCodeCompletionDelayedDeclState()) return true; From 52e13af93d121a0eed1a55c175e62ca7c2494849 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 29 May 2020 16:17:17 -0700 Subject: [PATCH 027/108] Add a demangler option to hide the "Swift" module name. This part of a series of patches to bring ASTPrinter and Swift Demangler to feature parity, which is needed by LLDB, which depends on using the strings produced by either interchangibly. --- include/swift/Demangling/Demangle.h | 3 ++- lib/Demangling/NodePrinter.cpp | 12 +++++++----- test/Demangle/demangle-special-options.test | 4 ++++ test/Demangle/lit.local.cfg | 2 ++ tools/swift-demangle/swift-demangle.cpp | 10 ++++++++++ 5 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 test/Demangle/demangle-special-options.test create mode 100644 test/Demangle/lit.local.cfg diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index ce3a4b5d439c3..4d1bb361b9cdc 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,8 @@ struct DemangleOptions { bool ShortenArchetype = false; bool ShowPrivateDiscriminators = true; bool ShowFunctionArgumentTypes = true; + bool DisplayDebuggerGeneratedModule = true; + bool DisplayStdlibModule = true; std::function GenericParameterName = genericParameterName; diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 655cbac01ea24..e234663b950f1 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -243,9 +243,11 @@ 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().startswith(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX)) + return Options.DisplayDebuggerGeneratedModule; } return true; } @@ -1945,8 +1947,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/test/Demangle/demangle-special-options.test b/test/Demangle/demangle-special-options.test new file mode 100644 index 0000000000000..61b92d1d8404f --- /dev/null +++ b/test/Demangle/demangle-special-options.test @@ -0,0 +1,4 @@ +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$}} 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/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index f6468b7366a59..d0d5710253591 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -74,6 +74,15 @@ 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::list InputNames(llvm::cl::Positional, llvm::cl::desc("[mangled name...]"), llvm::cl::ZeroOrMore); @@ -233,6 +242,7 @@ int main(int argc, char **argv) { options.SynthesizeSugarOnTypes = !DisableSugar; if (Simplified) options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions(); + options.DisplayStdlibModule = DisplayStdlibModule; if (InputNames.empty()) { CompactMode = true; From fe93b1984262b7bb0e459c582105b3a6d2c64a33 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 29 May 2020 17:09:39 -0700 Subject: [PATCH 028/108] Add a demangler option to hide the "__C" module name. This part of a series of patches to bring ASTPrinter and Swift Demangler to feature parity, which is needed by LLDB, which depends on using the strings produced by either interchangibly. rdar://problem/63700540 --- include/swift/Demangling/Demangle.h | 1 + lib/Demangling/NodePrinter.cpp | 2 ++ test/Demangle/demangle-special-options.test | 5 +++++ tools/swift-demangle/swift-demangle.cpp | 6 ++++++ 4 files changed, 14 insertions(+) diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index 4d1bb361b9cdc..b248e626686f4 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -58,6 +58,7 @@ struct DemangleOptions { bool ShowFunctionArgumentTypes = true; bool DisplayDebuggerGeneratedModule = true; bool DisplayStdlibModule = true; + bool DisplayObjCModule = true; std::function GenericParameterName = genericParameterName; diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index e234663b950f1..9defd5a3de815 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -246,6 +246,8 @@ class NodePrinter { 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().startswith(LLDB_EXPRESSIONS_MODULE_NAME_PREFIX)) return Options.DisplayDebuggerGeneratedModule; } diff --git a/test/Demangle/demangle-special-options.test b/test/Demangle/demangle-special-options.test index 61b92d1d8404f..78522cf9af23c 100644 --- a/test/Demangle/demangle-special-options.test +++ b/test/Demangle/demangle-special-options.test @@ -2,3 +2,8 @@ RUN: swift-demangle -display-stdlib-module=true sSi | %FileCheck %s --check-pref 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$}} diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index d0d5710253591..f9967c653b315 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -80,6 +80,11 @@ 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); /// \} @@ -243,6 +248,7 @@ int main(int argc, char **argv) { if (Simplified) options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions(); options.DisplayStdlibModule = DisplayStdlibModule; + options.DisplayObjCModule = DisplayObjCModule; if (InputNames.empty()) { CompactMode = true; From 051becaf0d30c0fa8ee35fc993c727effab5e98d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 29 May 2020 17:20:42 -0700 Subject: [PATCH 029/108] Add a demangler option to hide a current module. This is analogous to ASTPrinter's FullyQualifiedTypesIfAmbiguous option. This part of a series of patches to bring ASTPrinter and Swift Demangler to feature parity, which is needed by LLDB, which depends on using the strings produced by either interchangibly. rdar://problem/63700540 --- include/swift/Demangling/Demangle.h | 3 +++ lib/Demangling/NodePrinter.cpp | 2 ++ test/Demangle/demangle-special-options.test | 3 +++ tools/swift-demangle/swift-demangle.cpp | 6 ++++++ 4 files changed, 14 insertions(+) diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index b248e626686f4..4d809e7268078 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -59,6 +59,9 @@ struct DemangleOptions { 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/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 9defd5a3de815..50888f04a24d8 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -248,6 +248,8 @@ class NodePrinter { 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; } diff --git a/test/Demangle/demangle-special-options.test b/test/Demangle/demangle-special-options.test index 78522cf9af23c..87c54ca483780 100644 --- a/test/Demangle/demangle-special-options.test +++ b/test/Demangle/demangle-special-options.test @@ -7,3 +7,6 @@ RUN: swift-demangle -display-objc-module=true sSo6CGRectVD | %FileCheck %s --che 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/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index f9967c653b315..e129ce62e0de8 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -85,6 +85,11 @@ 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); /// \} @@ -249,6 +254,7 @@ int main(int argc, char **argv) { options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions(); options.DisplayStdlibModule = DisplayStdlibModule; options.DisplayObjCModule = DisplayObjCModule; + options.HidingCurrentModule = HidingModule; if (InputNames.empty()) { CompactMode = true; From 2cb2760ed99f3bf12b6a130eca2ae0969413768f Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 29 May 2020 19:02:12 -0700 Subject: [PATCH 030/108] ASTPrinter: Add an option to qualify ClangImported types. This part of a series of patches to bring ASTPrinter and Swift Demangler to feature parity, which is needed by LLDB, which depends on using the strings produced by either interchangibly. rdar://problem/63700540 --- include/swift/AST/PrintOptions.h | 3 +++ lib/AST/ASTPrinter.cpp | 11 ++++++----- test/DebugInfo/ASTPrinter-imported-names.swift | 12 ++++++++++++ .../lldb-moduleimport-test.cpp | 17 ++++++++++++----- 4 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 test/DebugInfo/ASTPrinter-imported-names.swift diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index c6c17c891d810..abfdc4e5a1732 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -435,6 +435,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/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index c727d487d340b..f4dd68ea24278 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3641,11 +3641,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/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/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; From 286b6cbb8f4c413941a5acb81c26d79d9161dc51 Mon Sep 17 00:00:00 2001 From: Bruno Rocha Date: Sat, 30 May 2020 14:34:42 +0200 Subject: [PATCH 031/108] Visit base first --- lib/IDE/SourceEntityWalker.cpp | 5 +++++ test/Index/index_objc_dynamic_refs.swift | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/IDE/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp index 7b1d389c068ed..f2dc3e165a072 100644 --- a/lib/IDE/SourceEntityWalker.cpp +++ b/lib/IDE/SourceEntityWalker.cpp @@ -512,11 +512,16 @@ 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/test/Index/index_objc_dynamic_refs.swift b/test/Index/index_objc_dynamic_refs.swift index 5700787017178..c42805b38b5fc 100644 --- a/test/Index/index_objc_dynamic_refs.swift +++ b/test/Index/index_objc_dynamic_refs.swift @@ -17,10 +17,10 @@ class AClass { func doSomething() { objcDelegate?.dynamicMethod?() - // CHECK: [[@LINE-1]]:23 | instance-method/Swift | dynamicMethod() | [[DynamicMethod_USR]] | Ref - // CHECK: [[@LINE-2]]:9 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + // 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]]:27 | instance-property/Swift | property | [[DynamicProperty_USR]] | Ref - // CHECK: [[@LINE-2]]:13 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + // CHECK: [[@LINE-1]]:13 | instance-property/Swift | objcDelegate | [[Delegate_USR]] | Ref + // CHECK: [[@LINE-2]]:27 | instance-property/Swift | property | [[DynamicProperty_USR]] | Ref } } From 21c9996a1f6162f2ab3acf47f3eaba5e00c49220 Mon Sep 17 00:00:00 2001 From: omochimetaru Date: Sat, 30 May 2020 22:58:45 +0900 Subject: [PATCH 032/108] [ConstraintSystem][NFC] add test cases for argument matching --- test/Constraints/argument_matching.swift | 388 ++++++++++++++++++++++- 1 file changed, 384 insertions(+), 4 deletions(-) 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}} } } From cf9fcb975d5429a0a8e08cad8f5c026ca48b4b63 Mon Sep 17 00:00:00 2001 From: eunjiChung <> Date: Sun, 31 May 2020 17:43:22 +0900 Subject: [PATCH 033/108] [stdlib] Add flatMap example in Result.swift --- stdlib/public/core/Result.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift index f92818baa5f21..5c0db142e719e 100644 --- a/stdlib/public/core/Result.swift +++ b/stdlib/public/core/Result.swift @@ -89,6 +89,21 @@ public enum Result { /// Returns a new result, mapping any success value using the given /// transformation and unwrapping the produced result. /// + /// Use this method when you need to transform the value of a `Result` + /// instance eventhough it produces a nested 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 { /* ... */ } + /// func getNextAfterInteger() -> Result { /* ... */ } + /// + /// 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` From c4690aa467d279b756540f778e37ff4b2f737584 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Jun 2020 14:01:22 +0300 Subject: [PATCH 034/108] stdlib: Drop a redundant generic parameter --- stdlib/public/core/EitherSequence.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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)) } } From 9fd1aa5d59925c1fc4e3f353fb43d55bea508e87 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 1 Jun 2020 15:39:29 +0300 Subject: [PATCH 035/108] [NFC] Pre- increment and decrement where possible --- include/swift/Remote/Failure.h | 2 +- include/swift/Runtime/Concurrent.h | 2 +- .../SwiftRemoteMirrorLegacyInterop.h | 2 +- lib/AST/ASTContext.cpp | 2 +- lib/AST/ASTDemangler.cpp | 2 +- lib/AST/ASTPrinter.cpp | 2 +- lib/AST/ASTVerifier.cpp | 4 ++-- lib/AST/Builtins.cpp | 8 +++---- lib/AST/ClangTypeConverter.cpp | 2 +- lib/AST/Decl.cpp | 4 ++-- lib/AST/DeclContext.cpp | 2 +- lib/AST/DiagnosticEngine.cpp | 2 +- lib/AST/GenericSignature.cpp | 2 +- lib/AST/GenericSignatureBuilder.cpp | 6 ++--- lib/AST/ImportCache.cpp | 16 ++++++------- lib/AST/Module.cpp | 4 ++-- lib/AST/NameLookup.cpp | 4 ++-- lib/AST/RequirementEnvironment.cpp | 2 +- lib/AST/SubstitutionMap.cpp | 2 +- lib/AST/Type.cpp | 2 +- lib/Basic/Mangler.cpp | 6 ++--- lib/Basic/PrimitiveParsing.cpp | 2 +- lib/Basic/Statistic.cpp | 8 +++---- lib/ClangImporter/ImportDecl.cpp | 10 ++++---- lib/ClangImporter/ImportType.cpp | 3 ++- lib/Demangling/Demangler.cpp | 15 ++++++------ lib/Demangling/NodePrinter.cpp | 10 ++++---- lib/Demangling/OldDemangler.cpp | 2 +- lib/Demangling/OldRemangler.cpp | 4 ++-- lib/Demangling/Punycode.cpp | 2 +- lib/Demangling/Remangler.cpp | 2 +- lib/Driver/Compilation.cpp | 4 ++-- lib/Driver/Driver.cpp | 2 +- lib/Frontend/DiagnosticVerifier.cpp | 6 ++--- lib/IDE/CodeCompletion.cpp | 18 +++++++------- lib/IDE/CodeCompletionResultPrinter.cpp | 4 ++-- lib/IDE/Formatting.cpp | 2 +- lib/IDE/IDERequests.cpp | 6 ++--- lib/IDE/ModuleInterfacePrinting.cpp | 2 +- lib/IDE/REPLCodeCompletion.cpp | 2 +- lib/IDE/Refactoring.cpp | 4 ++-- lib/IDE/SyntaxModel.cpp | 8 +++---- lib/IDE/Utils.cpp | 2 +- lib/IRGen/EnumPayload.cpp | 2 +- lib/IRGen/GenBuiltin.cpp | 6 ++--- lib/IRGen/GenCall.cpp | 2 +- lib/IRGen/GenClangType.cpp | 2 +- lib/IRGen/GenConstant.cpp | 6 ++--- lib/IRGen/GenDecl.cpp | 4 ++-- lib/IRGen/GenEnum.cpp | 6 ++--- lib/IRGen/GenFunc.cpp | 2 +- lib/IRGen/GenKeyPath.cpp | 2 +- lib/IRGen/GenOpaque.cpp | 2 +- lib/IRGen/IRGen.cpp | 2 +- lib/IRGen/LoadableByAddress.cpp | 2 +- lib/IRGen/MetadataLayout.cpp | 8 +++---- lib/IRGen/StructLayout.cpp | 4 ++-- lib/LLVMPasses/LLVMARCContract.cpp | 24 +++++++++---------- lib/LLVMPasses/LLVMInlineTree.cpp | 10 ++++---- lib/Markup/AST.cpp | 4 ++-- lib/Markup/LineList.cpp | 2 +- lib/Parse/ParseDecl.cpp | 12 +++++----- lib/Parse/ParsePattern.cpp | 2 +- lib/SIL/IR/AbstractionPattern.cpp | 2 +- lib/SIL/IR/SILBasicBlock.cpp | 2 +- lib/SIL/IR/SILFunctionType.cpp | 4 ++-- lib/SIL/IR/SILPrinter.cpp | 2 +- lib/SIL/IR/SILWitnessTable.cpp | 2 +- lib/SIL/Parser/ParseSIL.cpp | 6 ++--- lib/SIL/Utils/DynamicCasts.cpp | 4 ++-- lib/SIL/Utils/Projection.cpp | 14 +++++------ lib/SIL/Verifier/MemoryLifetime.cpp | 2 +- lib/SIL/Verifier/SILVerifier.cpp | 4 ++-- lib/SILGen/SILGenApply.cpp | 2 +- lib/SILGen/SILGenBridging.cpp | 4 ++-- lib/SILGen/SILGenPattern.cpp | 6 ++--- lib/SILGen/SILGenPoly.cpp | 2 +- lib/SILOptimizer/Analysis/EscapeAnalysis.cpp | 2 +- .../Analysis/SimplifyInstruction.cpp | 4 ++-- .../Differentiation/JVPEmitter.cpp | 2 +- lib/SILOptimizer/Differentiation/Thunk.cpp | 6 ++--- lib/SILOptimizer/IPO/ClosureSpecializer.cpp | 4 ++-- .../IPO/DeadFunctionElimination.cpp | 6 ++--- lib/SILOptimizer/IPO/GlobalOpt.cpp | 2 +- lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp | 2 +- .../LoopTransforms/ArrayPropertyOpt.cpp | 2 +- .../LoopTransforms/ForEachLoopUnroll.cpp | 8 +++---- .../LoopTransforms/LoopRotate.cpp | 2 +- .../Mandatory/ClosureLifetimeFixup.cpp | 2 +- .../Mandatory/DIMemoryUseCollector.cpp | 12 +++++----- .../Mandatory/DefiniteInitialization.cpp | 4 ++-- .../Mandatory/DiagnoseStaticExclusivity.cpp | 8 +++---- .../Mandatory/DiagnoseUnreachable.cpp | 18 +++++++------- .../Mandatory/OSLogOptimization.cpp | 2 +- lib/SILOptimizer/PassManager/PassManager.cpp | 2 +- lib/SILOptimizer/SILCombiner/SILCombine.cpp | 2 +- .../SILCombiner/SILCombinerApplyVisitors.cpp | 7 +++--- .../SILCombiner/SILCombinerMiscVisitors.cpp | 16 ++++++------- lib/SILOptimizer/Transforms/CSE.cpp | 10 ++++---- .../Transforms/DeadCodeElimination.cpp | 2 +- .../Transforms/ObjectOutliner.cpp | 2 +- lib/SILOptimizer/Transforms/Outliner.cpp | 6 ++--- .../Transforms/PerformanceInliner.cpp | 4 ++-- .../RedundantOverflowCheckRemoval.cpp | 4 ++-- .../Transforms/ReleaseDevirtualizer.cpp | 2 +- lib/SILOptimizer/Transforms/SILCodeMotion.cpp | 14 +++++------ lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 22 ++++++++--------- lib/SILOptimizer/Transforms/SILSROA.cpp | 2 +- lib/SILOptimizer/Transforms/SimplifyCFG.cpp | 6 ++--- lib/SILOptimizer/Transforms/Sink.cpp | 4 ++-- .../Transforms/SpeculativeDevirtualizer.cpp | 6 ++--- .../Transforms/StackPromotion.cpp | 2 +- .../Transforms/TempRValueElimination.cpp | 2 +- lib/SILOptimizer/UtilityPasses/InstCount.cpp | 8 +++---- .../UtilityPasses/SILDebugInfoGenerator.cpp | 2 +- .../Utils/CheckedCastBrJumpThreading.cpp | 8 +++---- lib/SILOptimizer/Utils/ConstExpr.cpp | 2 +- lib/SILOptimizer/Utils/Devirtualize.cpp | 4 ++-- lib/SILOptimizer/Utils/Generics.cpp | 14 +++++------ lib/SILOptimizer/Utils/InstOptUtils.cpp | 8 +++---- .../Utils/OptimizerStatsUtils.cpp | 2 +- lib/SILOptimizer/Utils/ValueLifetime.cpp | 4 ++-- lib/Sema/BuilderTransform.cpp | 4 ++-- lib/Sema/CSApply.cpp | 6 ++--- lib/Sema/CSDiagnostics.cpp | 4 ++-- lib/Sema/CSGen.cpp | 2 +- lib/Sema/ConstantnessSemaDiagnostics.cpp | 2 +- lib/Sema/ConstraintGraph.cpp | 8 +++---- lib/Sema/ConstraintSystem.cpp | 14 +++++------ lib/Sema/DerivedConformanceComparable.cpp | 4 ++-- .../DerivedConformanceEquatableHashable.cpp | 4 ++-- .../DerivedConformanceRawRepresentable.cpp | 2 +- lib/Sema/ImportResolution.cpp | 4 ++-- lib/Sema/LookupVisibleDecls.cpp | 2 +- lib/Sema/MiscDiagnostics.cpp | 6 ++--- lib/Sema/PCMacro.cpp | 2 +- lib/Sema/TypeCheckAttr.cpp | 2 +- lib/Sema/TypeCheckAvailability.cpp | 4 ++-- lib/Sema/TypeCheckDecl.cpp | 2 +- lib/Sema/TypeCheckDeclObjC.cpp | 4 ++-- lib/Sema/TypeCheckDeclPrimary.cpp | 2 +- lib/Sema/TypeCheckPropertyWrapper.cpp | 2 +- lib/Sema/TypeCheckProtocol.cpp | 4 ++-- lib/Sema/TypeCheckStorage.cpp | 4 ++-- lib/Sema/TypeCheckSwitchStmt.cpp | 4 ++-- lib/Sema/TypeCheckType.cpp | 4 ++-- lib/Serialization/Deserialization.cpp | 6 ++--- lib/Serialization/DeserializeSIL.cpp | 16 ++++++------- lib/Syntax/SyntaxData.cpp | 4 ++-- lib/TBDGen/TBDGen.cpp | 2 +- stdlib/public/Darwin/os/format.m | 24 +++++++++---------- stdlib/public/Darwin/os/os_trace_blob.h | 2 +- stdlib/public/Reflection/TypeLowering.cpp | 10 ++++---- stdlib/public/Reflection/TypeRef.cpp | 4 ++-- stdlib/public/runtime/Metadata.cpp | 4 ++-- stdlib/public/runtime/ProtocolConformance.cpp | 2 +- stdlib/public/runtime/SwiftDtoa.cpp | 6 ++--- stdlib/public/stubs/CommandLine.cpp | 2 +- stdlib/public/stubs/Stubs.cpp | 2 +- .../Compatibility50/ProtocolConformance.cpp | 2 +- stdlib/toolchain/Compatibility51/Concurrent.h | 2 +- .../Compatibility51/ProtocolConformance.cpp | 2 +- 162 files changed, 398 insertions(+), 397 deletions(-) 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/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/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..7714fef90ca3e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3846,7 +3846,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..9bf3fdf11b236 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]; diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index fb1d6472fc5b8..aa511e82f9431 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); diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 1ad1f9e509a42..dad012bf90fa0 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; } @@ -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 4ad4df3636fc2..a63f19bc6057a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5035,7 +5035,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 { @@ -5195,7 +5195,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/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index a1a36e38096a4..9ee8ab2dc12a8 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 diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index c8d4463477ef3..8342e306772a4 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -3431,7 +3431,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. @@ -3444,7 +3444,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( @@ -3822,7 +3822,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 68beaa0b785f6..234485a8fc7fb 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -554,7 +554,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); @@ -709,7 +709,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, 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/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/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/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..5c9ac8a8679e0 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -990,7 +990,7 @@ void NodePrinter::printSpecializationPrefix(NodePointer node, print(child); } } - argNum++; + ++argNum; break; } } @@ -1583,13 +1583,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 +1880,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 +1897,7 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { NodePointer repr = Node->getChild(Idx); print(repr); Printer << " "; - Idx++; + ++Idx; } NodePointer type = Node->getChild(Idx); 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/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/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 63d59acd325a5..188698d54750a 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; } @@ -6311,7 +6311,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/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/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/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/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/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/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/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..cff3408235418 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(); @@ -4503,7 +4503,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. @@ -5248,7 +5248,7 @@ bool Parser::skipBracedBlock() { HasOperatorDeclarations, HasNestedClassDeclarations); if (consumeIf(tok::r_brace)) - OpenBraces--; + --OpenBraces; return OpenBraces != 0; } @@ -6376,7 +6376,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. 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/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/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..ef5e5ae96391c 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -3569,7 +3569,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..9f42eb8cdec0d 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 = 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/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/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 7c666a3bd0886..6f56dfa6ce7b6 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -3568,7 +3568,7 @@ class SILVerifier : public SILVerifierBase { fromCanTy = fromMetaty.getInstanceType(); toCanTy = toMetaty.getInstanceType(); - MetatyLevel++; + ++MetatyLevel; } if (isExact) { @@ -5530,7 +5530,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/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/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/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/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 f36705d985435..53bf14034d127 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -173,7 +173,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..27e64b09ab15d 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -875,7 +875,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/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/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 498a4ea2d3b59..c2e3dce722804 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -811,7 +811,7 @@ swift::devirtualizeClassMethod(FullApplySite applySite, *applySite.getInstruction()) << "Devirtualized call to class method " << NV("Method", f); }); - NumClassDevirt++; + ++NumClassDevirt; return {newAI, changedCFG}; } @@ -1046,7 +1046,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..a8951fe026b28 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. diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 78232a90851c2..493a2cb631cb5 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 @@ -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/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index b704deb84fa24..1f991c955e01a 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -651,7 +651,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { break; // Disregard optional payload element to look at its source. - toDrop++; + ++toDrop; } path = path.drop_back(toDrop); @@ -1103,7 +1103,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 }; } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index f87d0fc5c686c..9495fed6cf327 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -669,7 +669,7 @@ namespace { assert(!AFD->hasImplicitSelfDecl()); for (auto param : *AFD->getParameters()) { if (!param->isDefaultArgument()) - nNoDefault++; + ++nNoDefault; } } else { nNoDefault = nOperands; 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 40ad7edae7db1..c0d3ae404f785 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -87,15 +87,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() { @@ -599,12 +599,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; } }; @@ -1911,7 +1911,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; @@ -3191,7 +3191,7 @@ static void extendPreorderIndexMap( std::pair walkToExprPre(Expr *E) override { IndexMap[E] = Index; - Index++; + ++Index; return { true, E }; } }; 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..57e73e34733dd 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -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(); } @@ -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..238025ad7947e 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; } @@ -1834,7 +1834,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/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 146b59ee3117f..ee260bf4ad243 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)); 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/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/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..39b45d4c1c39a 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -739,7 +739,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, return fn; } - NumDeserializedFunc++; + ++NumDeserializedFunc; assert(!(fn->getGenericEnvironment() && !fn->empty()) && "function already has context generic params?!"); @@ -1457,7 +1457,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 +1494,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 +1527,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 +2084,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 +3081,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 +3361,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 +3500,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/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/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/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp index f97b6723153e2..d9d437f234ff0 100644 --- a/stdlib/public/Reflection/TypeLowering.cpp +++ b/stdlib/public/Reflection/TypeLowering.cpp @@ -1031,7 +1031,7 @@ class ExistentialTypeInfoBuilder { continue; case FieldDescriptorKind::ClassProtocol: Representation = ExistentialTypeRepresentation::Class; - WitnessTableCount++; + ++WitnessTableCount; if (auto *Superclass = TC.getBuilder().lookupSuperclass(P)) { auto *SuperclassTI = TC.getTypeInfo(Superclass); @@ -1057,7 +1057,7 @@ class ExistentialTypeInfoBuilder { continue; case FieldDescriptorKind::Protocol: - WitnessTableCount++; + ++WitnessTableCount; continue; case FieldDescriptorKind::ObjCClass: case FieldDescriptorKind::Struct: @@ -1203,7 +1203,7 @@ class ExistentialTypeInfoBuilder { break; } - for (unsigned i = 0; i < WitnessTableCount; i++) + for (unsigned i = 0; i < WitnessTableCount; ++i) builder.addField("wtable", TC.getRawPointerTypeRef()); return builder.build(); @@ -1227,7 +1227,7 @@ class ExistentialTypeInfoBuilder { RecordTypeInfoBuilder builder(TC, RecordKind::ExistentialMetatype); builder.addField("metadata", TC.getAnyMetatypeTypeRef()); - for (unsigned i = 0; i < WitnessTableCount; i++) + for (unsigned i = 0; i < WitnessTableCount; ++i) builder.addField("wtable", TC.getRawPointerTypeRef()); return builder.build(); @@ -1772,7 +1772,7 @@ class EnumTypeInfoBuilder { for (auto Case : Fields) { if (Case.TR == nullptr) { - NoPayloadCases++; + ++NoPayloadCases; addCase(Case.Name); } else { PayloadCases.push_back(Case); diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp index e775c72ac352d..1034f42f9259f 100644 --- a/stdlib/public/Reflection/TypeRef.cpp +++ b/stdlib/public/Reflection/TypeRef.cpp @@ -1121,7 +1121,7 @@ bool TypeRef::deriveSubstitutions(GenericArgumentMap &Subs, S->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/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index fbafd97872c12..03c3975de837a 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -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]); 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/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/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) { From f5a75dcefdae8bfd9c591d62c0278ac27d6f7520 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 30 May 2020 12:42:58 -0700 Subject: [PATCH 036/108] build: simplify macOS path (NFC) It does not make sense to use the `cl` frontend to clang to build for macOS. Remove the unnecessary condition and always perform the operation. --- cmake/modules/AddSwift.cmake | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 6ac3c62315c9f..09c3afe831906 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -546,14 +546,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}) From 71d4c3ac5591d7002d83486d7cddee6c2c1a19b6 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 1 Jun 2020 10:41:27 -0700 Subject: [PATCH 037/108] Add a Test Demonstrating Superfluous Cascading Across Module Boundaries The idea is this: If we can have private intra-module dependencies, why not also have private inter-module dependencies. Currently, this is impossible because all edges from the CompilerInstance-level DependencyTracker are unconditionally registered as cascading. In addition, module loads are charged as depenendents to all files in a given batch, which means the exact set of external dependencies is some (non-deterministic) superset of the external dependencies of each files in the batch. This test case demonstrates one outcome of this approach: we recompile *way* too much when a dependent module changes. --- .../doesNotUseLib.swift | 3 ++ .../main.swift | 1 + .../ofm.json | 22 +++++++++++ .../submodule/lib-after.swift | 8 ++++ .../submodule/lib-before.swift | 7 ++++ .../submodule/ofm.json | 10 +++++ .../usesLib.swift | 7 ++++ .../usesLibTransitively.swift | 3 ++ .../superfluous-cascade-across-modules.swift | 39 +++++++++++++++++++ 9 files changed, 100 insertions(+) create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift create mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift create mode 100644 test/Incremental/superfluous-cascade-across-modules.swift diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift new file mode 100644 index 0000000000000..caa55673f93b5 --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift @@ -0,0 +1,3 @@ +extension Map { + func pin() {} +} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift @@ -0,0 +1 @@ + diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json b/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json new file mode 100644 index 0000000000000..2d6538c292696 --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json @@ -0,0 +1,22 @@ +{ + "main.swift": { + "object": "./main.o", + "swift-dependencies": "./main.swiftdeps" + }, + "usesLib.swift": { + "object": "./usesLib.o", + "swift-dependencies": "./usesLib.swiftdeps" + }, + "usesLibTransitively.swift": { + "object": "./usesLib.o", + "swift-dependencies": "./usesLib.swiftdeps" + }, + "doesNotUseLib.swift": { + "object": "./doesNotUseLib.o", + "swift-dependencies": "./doesNotUseLib.swiftdeps" + }, + "": { + "swift-dependencies": "./main~buildrecord.swiftdeps" + } +} + diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift new file mode 100644 index 0000000000000..347f0da653baa --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift @@ -0,0 +1,8 @@ +public struct Library { + var catalog: [Book] +} + +public struct Book { + var title: String + var checkOutCount: Int +} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift new file mode 100644 index 0000000000000..c9bb3d05e9d03 --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift @@ -0,0 +1,7 @@ +public struct Library { + var catalog: [Book] +} + +public struct Book { + var title: String +} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json new file mode 100644 index 0000000000000..d2f9889464c48 --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json @@ -0,0 +1,10 @@ +{ + "lib.swift": { + "object": "./lib.o", + "swift-dependencies": "./lib.swiftdeps" + }, + "": { + "swift-dependencies": "./submodule~buildrecord.swiftdeps" + } +} + diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift new file mode 100644 index 0000000000000..96bb74c8750cd --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift @@ -0,0 +1,7 @@ +import Lib + +public struct District { + var libraries: [Library] +} + +struct Map {} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift new file mode 100644 index 0000000000000..a205027f286c7 --- /dev/null +++ b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift @@ -0,0 +1,3 @@ +struct County { + var districts: [District] +} diff --git a/test/Incremental/superfluous-cascade-across-modules.swift b/test/Incremental/superfluous-cascade-across-modules.swift new file mode 100644 index 0000000000000..0c76afd0864ad --- /dev/null +++ b/test/Incremental/superfluous-cascade-across-modules.swift @@ -0,0 +1,39 @@ +// ============================================================================= +// Without private dependencies +// ============================================================================= + +// First, build a submodule + +// RUN: %empty-directory(%t) +// RUN: cp %S/Inputs/superfluous-cascade-across-modules/*.swift %t +// RUN: cp %S/Inputs/superfluous-cascade-across-modules/*.json %t + +// RUN: %target-build-swift %S/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift -emit-module -emit-library -module-name Lib -module-link-name Lib -emit-module-path %t/Lib.swiftmodule -o %t/%target-library-name(Lib) + +// Build the main executable that depends on the submodule we just built + +// RUN: cd %t && %swiftc_driver -emit-module -enable-batch-mode -j2 -incremental -driver-show-incremental -I %t -L %t -lLib -module-name main \ +// RUN: -output-file-map ofm.json \ +// RUN: main.swift \ +// RUN: doesNotUseLib.swift \ +// RUN: usesLib.swift \ +// RUN: usesLibTransitively.swift >&output1 + +// Rebuild the submodule + +// RUN: %target-build-swift %S/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift -emit-module -emit-library -module-name Lib -module-link-name Lib -emit-module-path %t/Lib.swiftmodule -o %t/%target-library-name(Lib) + +// Rebuild the main executable + +// RUN: cd %t && %swiftc_driver -emit-module -enable-batch-mode -j2 -incremental -driver-show-incremental -I %t -L %t -lLib -module-name main \ +// RUN: -output-file-map ofm.json \ +// RUN: main.swift \ +// RUN: doesNotUseLib.swift \ +// RUN: usesLib.swift \ +// RUN: usesLibTransitively.swift >&output2 + +// RUN: %FileCheck -check-prefix=CHECK-STATUS-QUO-RECOMPILED %s < %t/output2 + +// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: main +// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: usesLib +// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: doesNotUseLib From 80c4aa6e807e16a864c8ea43193bc084d36a5c44 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Jun 2020 12:17:49 -0700 Subject: [PATCH 038/108] [Diagnostics] NFC: Rename `ValueType` to `ExpectedType` in raw representable fix/diagnostics --- lib/Sema/CSDiagnostics.cpp | 6 +++--- lib/Sema/CSDiagnostics.h | 18 +++++++++--------- lib/Sema/CSFix.cpp | 16 ++++++++-------- lib/Sema/CSFix.h | 16 ++++++++-------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 68b75871141e8..94c8406cd4f63 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6349,7 +6349,7 @@ void MissingRawRepresentativeInitFailure::fixIt( if (auto *E = getAsExpr(getAnchor())) { auto range = E->getSourceRange(); auto rawReprObjType = RawReprType->getOptionalObjectType(); - auto valueObjType = ValueType->getOptionalObjectType(); + auto valueObjType = ExpectedType->getOptionalObjectType(); if (rawReprObjType && valueObjType) { std::string mapCodeFix; @@ -6407,7 +6407,7 @@ bool MissingRawRepresentativeInitFailure::diagnoseAsNote() { if (auto *decl = overload->choice.getDeclOrNull()) { diagnostic.emplace(emitDiagnosticAt( decl, diag::cannot_convert_candidate_result_to_contextual_type, - decl->getName(), ValueType, RawReprType)); + decl->getName(), ExpectedType, RawReprType)); } } else if (auto argConv = locator->getLastElementAs()) { @@ -6444,7 +6444,7 @@ void UseOfRawRepresentableInsteadOfItsRawValueFailure::fixIt( if (RawReprType->getOptionalObjectType()) { fix += ".map { $0.rawValue } "; - if (!ValueType->getOptionalObjectType()) + if (!ExpectedType->getOptionalObjectType()) fix += "?? <#default value#>"; } else { fix += ".rawValue"; diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 064a815294917..7cc203bfffd80 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2105,13 +2105,13 @@ class UnableToInferKeyPathRootFailure final : public FailureDiagnostic { class AbstractRawRepresentableFailure : public FailureDiagnostic { protected: Type RawReprType; - Type ValueType; + Type ExpectedType; AbstractRawRepresentableFailure(const Solution &solution, Type rawReprType, - Type valueType, ConstraintLocator *locator) + Type expectedType, ConstraintLocator *locator) : FailureDiagnostic(solution, locator), RawReprType(resolveType(rawReprType)), - ValueType(resolveType(valueType)) {} + ExpectedType(resolveType(expectedType)) {} public: virtual Type getFromType() const = 0; @@ -2143,12 +2143,12 @@ class MissingRawRepresentativeInitFailure final : public AbstractRawRepresentableFailure { public: MissingRawRepresentativeInitFailure(const Solution &solution, - Type rawReprType, Type valueType, + Type rawReprType, Type expectedType, ConstraintLocator *locator) - : AbstractRawRepresentableFailure(solution, rawReprType, valueType, + : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, locator) {} - Type getFromType() const override { return ValueType; } + Type getFromType() const override { return ExpectedType; } Type getToType() const override { return RawReprType; } bool diagnoseAsNote() override; @@ -2174,13 +2174,13 @@ class UseOfRawRepresentableInsteadOfItsRawValueFailure final public: UseOfRawRepresentableInsteadOfItsRawValueFailure(const Solution &solution, Type rawReprType, - Type valueType, + Type expectedType, ConstraintLocator *locator) - : AbstractRawRepresentableFailure(solution, rawReprType, valueType, + : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, locator) {} Type getFromType() const override { return RawReprType; } - Type getToType() const override { return ValueType; } + Type getToType() const override { return ExpectedType; } private: void fixIt(InFlightDiagnostic &diagnostic) const override; diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index d26e7a4b1590d..2533e3c8b7e47 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1124,32 +1124,32 @@ bool ExpandArrayIntoVarargs::diagnose(const Solution &solution, bool ExplicitlyConstructRawRepresentable::diagnose(const Solution &solution, bool asNote) const { - MissingRawRepresentativeInitFailure failure(solution, RawReprType, ValueType, - getLocator()); + MissingRawRepresentativeInitFailure failure(solution, RawReprType, + ExpectedType, getLocator()); return failure.diagnose(asNote); } ExplicitlyConstructRawRepresentable * ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, - Type rawReprType, Type valueType, + Type rawReprType, Type expectedType, ConstraintLocator *locator) { - return new (cs.getAllocator()) - ExplicitlyConstructRawRepresentable(cs, rawReprType, valueType, locator); + return new (cs.getAllocator()) ExplicitlyConstructRawRepresentable( + cs, rawReprType, expectedType, locator); } bool UseValueTypeOfRawRepresentative::diagnose(const Solution &solution, bool asNote) const { - ArgumentMismatchFailure failure(solution, RawReprType, ValueType, + ArgumentMismatchFailure failure(solution, RawReprType, ExpectedType, getLocator()); return failure.diagnose(asNote); } UseValueTypeOfRawRepresentative * UseValueTypeOfRawRepresentative::create(ConstraintSystem &cs, Type rawReprType, - Type valueType, + Type expectedType, ConstraintLocator *locator) { return new (cs.getAllocator()) - UseValueTypeOfRawRepresentative(cs, rawReprType, valueType, locator); + UseValueTypeOfRawRepresentative(cs, rawReprType, expectedType, locator); } unsigned AllowArgumentMismatch::getParamIdx() const { diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 1a0f08dcb34ba..a99a0a2944e5e 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -1596,14 +1596,14 @@ class ExpandArrayIntoVarargs final : public AllowArgumentMismatch { class ExplicitlyConstructRawRepresentable final : public ConstraintFix { Type RawReprType; - Type ValueType; + Type ExpectedType; ExplicitlyConstructRawRepresentable(ConstraintSystem &cs, Type rawReprType, - Type valueType, + Type expectedType, ConstraintLocator *locator) : ConstraintFix(cs, FixKind::ExplicitlyConstructRawRepresentable, locator), - RawReprType(rawReprType), ValueType(valueType) {} + RawReprType(rawReprType), ExpectedType(expectedType) {} public: std::string getName() const override { @@ -1613,18 +1613,18 @@ class ExplicitlyConstructRawRepresentable final : public ConstraintFix { bool diagnose(const Solution &solution, bool asNote = false) const override; static ExplicitlyConstructRawRepresentable * - create(ConstraintSystem &cs, Type rawTypeRepr, Type valueType, + create(ConstraintSystem &cs, Type rawTypeRepr, Type expectedType, ConstraintLocator *locator); }; class UseValueTypeOfRawRepresentative final : public ConstraintFix { Type RawReprType; - Type ValueType; + Type ExpectedType; UseValueTypeOfRawRepresentative(ConstraintSystem &cs, Type rawReprType, - Type valueType, ConstraintLocator *locator) + Type expectedType, ConstraintLocator *locator) : ConstraintFix(cs, FixKind::UseValueTypeOfRawRepresentative, locator), - RawReprType(rawReprType), ValueType(valueType) {} + RawReprType(rawReprType), ExpectedType(expectedType) {} public: std::string getName() const override { @@ -1635,7 +1635,7 @@ class UseValueTypeOfRawRepresentative final : public ConstraintFix { static UseValueTypeOfRawRepresentative *create(ConstraintSystem &cs, Type rawReprType, - Type valueType, + Type expectedType, ConstraintLocator *locator); }; From 564c1a5eec3d50d9529ba8017c5f3c67ef475dc0 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Mon, 1 Jun 2020 12:24:18 -0700 Subject: [PATCH 039/108] Add a [nonoverridden] kind for SILVTable entries. This will let us track class methods that must exist for pass ordering, interface, or ABI reasons, but which can be given more efficient runtime representation because they have no overrides. --- include/swift/SIL/SILVTable.h | 3 +++ lib/SIL/IR/SILPrinter.cpp | 3 +++ lib/SIL/Parser/ParseSIL.cpp | 3 +++ lib/Serialization/DeserializeSIL.cpp | 2 ++ lib/Serialization/ModuleFormat.h | 2 +- lib/Serialization/SILFormat.h | 1 + lib/Serialization/SerializeSIL.cpp | 2 ++ 7 files changed, 15 insertions(+), 1 deletion(-) 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/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index dd9c3b93b1110..7207fd6795ae5 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; diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 94521a73a4d69..761bcf9e9b875 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -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/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 5fbd28c55672b..5709a1b267298 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; 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; } From ebc99c60fbbd43a03acdef72a63ace7dffec104b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 May 2020 20:34:34 -0700 Subject: [PATCH 040/108] [CodeCompletion] Separate TypeCheckFunctionBodyAtLocRequest from TypeCheckFunctionBodyRequest, and only do necessary operations. --- include/swift/AST/TypeCheckRequests.h | 27 ++++++++++--- include/swift/AST/TypeCheckerTypeIDZone.def | 4 +- include/swift/Sema/IDETypeChecking.h | 6 +-- lib/IDE/ExprContextAnalysis.cpp | 12 +++--- lib/Sema/TypeCheckStmt.cpp | 43 +++++++++++++++++---- lib/Sema/TypeChecker.cpp | 7 ++-- 6 files changed, 73 insertions(+), 26 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 024939b260a3e..cdf7e9db865d4 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 TypeCheckFunctionBodyRequest : public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -883,9 +882,7 @@ class TypeCheckFunctionBodyRequest : 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 TypeCheckFunctionBodyRequest : 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 diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 444cf2cae924a..d7b7a420f603d 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -197,8 +197,10 @@ SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest, AccessorDecl *(AbstractStorageDecl *, AccessorKind), SeparatelyCached, NoLocationInfo) 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/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 790d8de6fcd07..f8ef4a42ca6da 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -133,9 +133,9 @@ namespace swift { /// Typecheck the given expression. bool typeCheckExpression(DeclContext *DC, Expr *&parsedExpr); - /// Partially typecheck the specified function body. - bool typeCheckAbstractFunctionBodyNodeAt(AbstractFunctionDecl *AFD, - SourceLoc TargetLoc); + /// 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/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 945eeccc04075..265fa479a70e7 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -79,7 +79,7 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) { auto &SM = DC->getASTContext().SourceMgr; auto bodyRange = AFD->getBodySourceRange(); if (SM.rangeContainsTokenLoc(bodyRange, Loc)) { - swift::typeCheckAbstractFunctionBodyNodeAt(AFD, Loc); + swift::typeCheckAbstractFunctionBodyAtLoc(AFD, Loc); } else { assert(bodyRange.isInvalid() && "The body should not be parsed if the " "completion happens in the signature"); @@ -866,10 +866,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."); @@ -1003,8 +1003,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/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index a4066e2ebaa59..b09a7c9de91de 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1635,9 +1635,8 @@ static Type getFunctionBuilderType(FuncDecl *FD) { } bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) { - auto res = - evaluateOrDefault(AFD->getASTContext().evaluator, - TypeCheckFunctionBodyRequest{AFD, SourceLoc()}, true); + auto res = evaluateOrDefault(AFD->getASTContext().evaluator, + TypeCheckFunctionBodyRequest{AFD}, true); TypeChecker::checkFunctionErrorHandling(AFD); TypeChecker::computeCaptures(AFD); return res; @@ -1836,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 TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, - AbstractFunctionDecl *AFD, - SourceLoc targetTypeCheckLoc) const { + AbstractFunctionDecl *AFD) const { ASTContext &ctx = AFD->getASTContext(); Optional timer; @@ -1896,7 +1926,6 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, bool hadError = false; if (!alreadyTypeChecked) { StmtChecker SC(AFD); - SC.TargetTypeCheckLoc = targetTypeCheckLoc; hadError = SC.typeCheckBody(body); } @@ -1927,7 +1956,7 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator, AFD->setBody(body, AbstractFunctionDecl::BodyKind::TypeChecked); // If nothing went wrong yet, perform extra checking. - if (!hadError && targetTypeCheckLoc.isInvalid()) + if (!hadError) performAbstractFuncDeclDiagnostics(AFD); return hadError; diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index d20fd76b993f2..230adc8ca4e47 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -540,12 +540,13 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { return !resultTy; } -bool swift::typeCheckAbstractFunctionBodyNodeAt(AbstractFunctionDecl *AFD, - SourceLoc TargetLoc) { +bool swift::typeCheckAbstractFunctionBodyAtLoc(AbstractFunctionDecl *AFD, + SourceLoc TargetLoc) { auto &Ctx = AFD->getASTContext(); DiagnosticSuppression suppression(Ctx.Diags); return !evaluateOrDefault(Ctx.evaluator, - TypeCheckFunctionBodyRequest{AFD, TargetLoc}, true); + TypeCheckFunctionBodyAtLocRequest{AFD, TargetLoc}, + true); } bool swift::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { From 759d1dd4991df2b75405690cf69d25cda2a5cb7e Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 May 2020 21:45:16 -0700 Subject: [PATCH 041/108] [TypeChecker] Merge typeCheckConditionForStmt() with typeCheckStmtCondition() --- lib/Sema/TypeCheckConstraints.cpp | 50 ++++++++++++++----------------- lib/Sema/TypeChecker.h | 10 ------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 072e429f41233..4aaf554e2f28c 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2492,11 +2492,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 +2505,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 +2530,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,37 +2558,29 @@ 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); - } - return false; -} - -bool TypeChecker::typeCheckConditionForStatement(LabeledConditionalStmt *stmt, - DeclContext *dc) { - Diag<> diagnosticForAlwaysTrue = diag::invalid_diagnostic; - switch (stmt->getKind()) { - case StmtKind::If: - diagnosticForAlwaysTrue = diag::if_always_true; - break; - case StmtKind::While: - diagnosticForAlwaysTrue = diag::while_always_true; - break; - case StmtKind::Guard: - diagnosticForAlwaysTrue = diag::guard_always_succeeds; - break; - default: - llvm_unreachable("unknown LabeledConditionalStmt kind"); + 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); } - StmtCondition cond = stmt->getCond(); - bool result = typeCheckStmtCondition(cond, dc, diagnosticForAlwaysTrue); stmt->setCond(cond); - return result; + return false; } /// Find the '~=` operator that can compare an expression inside a pattern to a diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index b67078388e8de..c3bd2d9384d70 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -763,16 +763,6 @@ bool typeCheckCondition(Expr *&expr, DeclContext *dc); bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt, DeclContext *dc); -/// Type check the given 'if', 'while', or 'guard' statement condition, which -/// either converts an expression to a logic value or bind variables to the -/// contents of an Optional. -/// -/// \param cond The condition 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); - /// Determine the semantics of a checked cast operation. /// /// \param fromType The source type of the cast. From 36123a7ed34fa968d1a264dc603b9938c6df9b4b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 30 May 2020 09:07:28 -0700 Subject: [PATCH 042/108] Update a test case --- test/IDE/complete_skipbody.swift | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/IDE/complete_skipbody.swift b/test/IDE/complete_skipbody.swift index b3785e58738e1..9b9d3f61e13b2 100644 --- a/test/IDE/complete_skipbody.swift +++ b/test/IDE/complete_skipbody.swift @@ -35,13 +35,19 @@ func test(valueOptOpt: MyStruct??) { if (value.x == 1) { let unrelated2 = FORBIDDEN_Struct() - _ = value.#^FUNCTIONBODY^# + switch value.x { + case let x where x < 2: + let unrelated3 = FORBIDDEN_Struct() + if x == value.#^FUNCTIONBODY^# {} + default: + break + } } } let globalValue = globalValueOpt! -let FORBIDDEN_localVar = 1 +let FORBIDDEN_globalVar = 1 switch glovalValue.x { case let x where x < 2: From e6ce361042ef7759449381f64796d326acc865f5 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 30 May 2020 09:09:31 -0700 Subject: [PATCH 043/108] [CodeCompletion] Rename typeCheckContextUntil to typeCheckContextAt --- lib/IDE/CodeCompletion.cpp | 2 +- lib/IDE/ConformingMethodList.cpp | 2 +- lib/IDE/ExprContextAnalysis.cpp | 4 ++-- lib/IDE/ExprContextAnalysis.h | 2 +- lib/IDE/TypeContextInfo.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 245451ec2a608..1501b7bb88fb7 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -5734,7 +5734,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { CurDeclContext = DC; } - typeCheckContextUntil( + typeCheckContextAt( CurDeclContext, ParsedExpr ? ParsedExpr->getLoc() diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index b986997a39fb8..9a843b82f0cc0 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -67,7 +67,7 @@ void ConformingMethodListCallbacks::doneParsing() { if (!ParsedExpr) return; - typeCheckContextUntil(CurDeclContext, ParsedExpr->getLoc()); + typeCheckContextAt(CurDeclContext, ParsedExpr->getLoc()); Type T = ParsedExpr->getType(); diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 265fa479a70e7..d9ea2c5f9d86e 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -37,7 +37,7 @@ using namespace swift; using namespace ide; //===----------------------------------------------------------------------===// -// typeCheckContextUntil(DeclContext, SourceLoc) +// typeCheckContextAt(DeclContext, SourceLoc) //===----------------------------------------------------------------------===// namespace { @@ -99,7 +99,7 @@ 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(); 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/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index 0c9fc7a4a9a7b..f442f662fc52c 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -88,7 +88,7 @@ void ContextInfoCallbacks::doneParsing() { if (!ParsedExpr) return; - typeCheckContextUntil(CurDeclContext, ParsedExpr->getLoc()); + typeCheckContextAt(CurDeclContext, ParsedExpr->getLoc()); ExprContextInfo Info(CurDeclContext, ParsedExpr); From 9805b0ab89c4178e3a213676d8a7391aab0dcf48 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Jun 2020 14:10:24 -0700 Subject: [PATCH 044/108] [ConstraintSystem] Do more checking before suggesting to use of `.rawValue` Introduce `repairByUsingRawValueOfRawRepresentableType` which is used for assignment, argument-to-parameter conversions and contextual mismatches. It checks whether `from` side is a raw representable type and tries to match `to` side to its `rawValue`. Also extract logic common for `repairByUsingRawValueOfRawRepresentableType` and `repairByExplicitRawRepresentativeUse` into `isValueOfRawRepresentable`. --- lib/Sema/CSFix.cpp | 4 +- lib/Sema/CSSimplify.cpp | 58 ++++++++++++++++++-------- test/Sema/enum_raw_representable.swift | 27 ++++++++---- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 2533e3c8b7e47..04a20bc190047 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1139,8 +1139,8 @@ ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, bool UseValueTypeOfRawRepresentative::diagnose(const Solution &solution, bool asNote) const { - ArgumentMismatchFailure failure(solution, RawReprType, ExpectedType, - getLocator()); + UseOfRawRepresentableInsteadOfItsRawValueFailure failure( + solution, RawReprType, ExpectedType, getLocator()); return failure.diagnose(asNote); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8a3c646fa0ca0..2fedf8efe8234 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3135,36 +3135,57 @@ bool ConstraintSystem::repairFailures( return false; }; - // Check whether given `rawReprType` does indeed conform to `RawRepresentable` - // and if so check that given `valueType` 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 repairByExplicitRawRepresentativeUse = - [&](Type origValueType, Type origRawReprType) -> bool { - auto rawReprType = origRawReprType; - // Let's unwrap a single level of optionality since + // 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; - auto valueType = origValueType; // 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(); + }; - if (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 repairByExplicitRawRepresentativeUse = [&](Type expectedType, + Type rawReprType) -> bool { + if (!isValueOfRawRepresentable(expectedType, rawReprType)) return false; conversionsOrFixes.push_back(ExplicitlyConstructRawRepresentable::create( - *this, origRawReprType, origValueType, getConstraintLocator(locator))); + *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(UseValueTypeOfRawRepresentative::create( + *this, rawReprType, expectedType, getConstraintLocator(locator))); return true; }; @@ -3388,6 +3409,9 @@ bool ConstraintSystem::repairFailures( if (repairByExplicitRawRepresentativeUse(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. @@ -3620,12 +3644,6 @@ bool ConstraintSystem::repairFailures( 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.: @@ -3659,6 +3677,9 @@ bool ConstraintSystem::repairFailures( if (repairByExplicitRawRepresentativeUse(lhs, rhs)) break; + if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) + break; + if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; @@ -3877,6 +3898,9 @@ bool ConstraintSystem::repairFailures( break; } + if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) + break; + if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift index b6b21ba7a6d9d..2ca4a3eda4248 100644 --- a/test/Sema/enum_raw_representable.swift +++ b/test/Sema/enum_raw_representable.swift @@ -131,15 +131,15 @@ 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'}} @@ -154,7 +154,7 @@ func test_candidate_diagnostic() { 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) {} @@ -171,9 +171,9 @@ 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=) ?? <#default value#>}} sr8150_helper4(0.0) @@ -187,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=.map { $0.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=.map { $0.rawValue }}} + } } struct NotEquatable { } From 0e6dcabc5401fe301508a2932ec35e434ec994b3 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Jun 2020 14:24:39 -0700 Subject: [PATCH 045/108] [Diagnostics] Share `diagnoseAsNote` for raw representable diagnostics --- lib/Sema/CSDiagnostics.cpp | 6 +++--- lib/Sema/CSDiagnostics.h | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 94c8406cd4f63..72c1fc9172ec6 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6395,7 +6395,7 @@ void MissingRawRepresentativeInitFailure::fixIt( } } -bool MissingRawRepresentativeInitFailure::diagnoseAsNote() { +bool AbstractRawRepresentableFailure::diagnoseAsNote() { auto *locator = getLocator(); Optional diagnostic; @@ -6442,10 +6442,10 @@ void UseOfRawRepresentableInsteadOfItsRawValueFailure::fixIt( // out first and then, if destination is not optional, allow to specify // default value. if (RawReprType->getOptionalObjectType()) { - fix += ".map { $0.rawValue } "; + fix += ".map { $0.rawValue }"; if (!ExpectedType->getOptionalObjectType()) - fix += "?? <#default value#>"; + fix += " ?? <#default value#>"; } else { fix += ".rawValue"; } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 7cc203bfffd80..6260f696affa5 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2118,7 +2118,7 @@ class AbstractRawRepresentableFailure : public FailureDiagnostic { virtual Type getToType() const = 0; bool diagnoseAsError() override; - bool diagnoseAsNote() override { return false; } + bool diagnoseAsNote() override; protected: Optional> getDiagnostic() const; @@ -2151,8 +2151,6 @@ class MissingRawRepresentativeInitFailure final Type getFromType() const override { return ExpectedType; } Type getToType() const override { return RawReprType; } - bool diagnoseAsNote() override; - protected: void fixIt(InFlightDiagnostic &diagnostic) const override; }; From 4d9566c0287b81d24098153fcd098dfff82b3b1f Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 1 Jun 2020 14:29:36 -0700 Subject: [PATCH 046/108] [Diagnostics] NFC: Remove obsolete logic related to raw representable --- lib/Sema/CSDiagnostics.cpp | 65 -------------------------------------- lib/Sema/CSDiagnostics.h | 18 ----------- 2 files changed, 83 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 72c1fc9172ec6..9e9e82b42ce7a 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(); @@ -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,59 +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); - } - }; - - if (auto rawTy = isRawRepresentable(fromType, rawRepresentableProtocol)) { - if (conformsToKnownProtocol(toType, rawRepresentableProtocol)) { - std::string convWrapBefore; - std::string convWrapAfter = ".rawValue"; - if (auto *E = getAsExpr(anchor)) - fixIt(convWrapBefore, convWrapAfter, E); - return true; - } - } - - return false; -} - bool ContextualFailure::tryIntegerCastFixIts( InFlightDiagnostic &diagnostic) const { auto fromType = getFromType(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 6260f696affa5..fd70d3877f94b 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 From 88c82f477fd18f120fc1a52b3077da6105f053e6 Mon Sep 17 00:00:00 2001 From: Miller Date: Tue, 2 Jun 2020 04:58:33 +0600 Subject: [PATCH 047/108] change bash to sh this code blocks don't have anything specific to bash. --- docs/DebuggingTheCompiler.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 ``` From bc939d798422ce2eb0fe7ac2000866ac98913670 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 2 Jun 2020 00:47:59 -0400 Subject: [PATCH 048/108] Add regression test for https://bugs.swift.org/browse/SR-7002 --- validation-test/compiler_crashers_2_fixed/sr7002.swift | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 validation-test/compiler_crashers_2_fixed/sr7002.swift 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 { } From 4f87899f9f95bddf871e3e4178982ab1010fd451 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 2 Jun 2020 00:48:20 -0400 Subject: [PATCH 049/108] Add regression test for rdar://54394068 --- .../rdar54394068.swift | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 validation-test/compiler_crashers_2_fixed/rdar54394068.swift 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 +} From e60c7fe547a17281e74bc32e4f1b5ea515b33f99 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 2 Jun 2020 09:10:35 -0700 Subject: [PATCH 050/108] Add request to query primary files Remove the `PrimarySourceFiles` vector from the frontend and replace it with a request on ModuleDecl that retrieves the primary files for the main module. This is in preparation for having `CompilerInstance::getMainModule` automatically populate the main module with files when queried. --- include/swift/AST/Module.h | 4 +++ include/swift/AST/SourceFile.h | 9 ++++++- include/swift/AST/TypeCheckRequests.h | 20 +++++++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 2 ++ include/swift/Frontend/Frontend.h | 14 ++++------- lib/AST/Module.cpp | 28 +++++++++++++++++++-- lib/Frontend/Frontend.cpp | 6 ++--- 7 files changed, 67 insertions(+), 16 deletions(-) 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/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..a28312666ccdf 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2459,6 +2459,26 @@ 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; } +}; + // 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..91847912a2315 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -151,6 +151,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) diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 33d62e639499f..26282a42f26ee 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -451,11 +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; @@ -536,7 +531,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 +541,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(); } } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 6b1ae78787496..6eb972efd0ea2 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -511,6 +511,27 @@ 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}, {}); +} + #define FORWARD(name, args) \ for (const FileUnit *file : getFiles()) \ file->name args; @@ -2182,12 +2203,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/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index aca792d419588..7a768c68798ad 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -870,7 +870,7 @@ void CompilerInstance::forEachFileToTypeCheck( fn(*SF); } } else { - for (auto *SF : PrimarySourceFiles) { + for (auto *SF : getPrimarySourceFiles()) { fn(*SF); } } @@ -900,11 +900,10 @@ 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(); } @@ -923,7 +922,6 @@ void CompilerInstance::freeASTContext() { SML = nullptr; MemoryBufferLoader = nullptr; PrimaryBufferIDs.clear(); - PrimarySourceFiles.clear(); } /// Perform "stable" optimizations that are invariant across compiler versions. From e7f38db2358bfe75220ef9e990f9b4cc443a36ed Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Thu, 28 May 2020 14:21:08 -0700 Subject: [PATCH 051/108] [NFC] Have Evaluator's Constructor Read LangOptions It's a touch cleaner to do this than passing around a pile of bools. --- include/swift/AST/Evaluator.h | 5 +---- lib/AST/ASTContext.cpp | 5 +---- lib/AST/Evaluator.cpp | 16 ++++++++-------- unittests/AST/ArithmeticEvaluator.cpp | 19 +++++++++++-------- 4 files changed, 21 insertions(+), 24 deletions(-) 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/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8d6e5295cc654..d5a1ec4c45ae7 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)), diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index 472a5387e0f5d..5d2b626db8d2f 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; 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); From 4804616fc18c01eb32bdb147df8d3a3d0dacdfe8 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Mon, 1 Jun 2020 10:42:59 -0700 Subject: [PATCH 052/108] Fix an edge case in ExistentialSpecializer ExistentialSpecializer could be building the function type from a witness_method. We cannot attach a witnessProtocolConformance to the newly specialized thin function. --- .../ExistentialTransform.cpp | 3 +- .../existential_spl_witness_method.swift | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/SILOptimizer/existential_spl_witness_method.swift 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/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()); + From 2711018bcd427b47593272ba07567179d3dfd326 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 2 Jun 2020 11:18:00 -0700 Subject: [PATCH 053/108] test: adjust test to repair the test on Windows The test overfit for non-Windows platform. --- test/DebugInfo/curry_thunk.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 118e7c3cdab3c5a15bed33655563e0fb702007d7 Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Thu, 28 May 2020 16:53:51 -0700 Subject: [PATCH 054/108] [SymbolGraph] Inherit availability from parent contexts Also be a little smarter about encountering duplicate `@available` attributes on the same declaration. rdar://63570830 --- lib/SymbolGraphGen/AvailabilityMixin.cpp | 187 ++++++++++++++++++ lib/SymbolGraphGen/AvailabilityMixin.h | 78 ++++++++ lib/SymbolGraphGen/CMakeLists.txt | 1 + lib/SymbolGraphGen/Symbol.cpp | 152 +++++++------- lib/SymbolGraphGen/Symbol.h | 6 +- .../{Availability.swift => Basic.swift} | 8 +- .../Duplicated/DeprecatedFilled.swift | 25 +++ .../Duplicated/DeprecatedReplaced.swift | 38 ++++ .../Duplicated/IntroducedFilled.swift | 23 +++ .../Duplicated/IntroducedReplaced.swift | 23 +++ .../Duplicated/MessageLastWins.swift | 25 +++ .../Duplicated/ObsoletedFilled.swift | 25 +++ .../Duplicated/ObsoletedReplaced.swift | 21 ++ .../Inherited/DeprecatedFilled.swift | 41 ++++ .../Inherited/DeprecatedReplaced.swift | 98 +++++++++ .../Inherited/IntroducedFilled.swift | 39 ++++ .../Inherited/IntroducedReplaced.swift | 73 +++++++ .../Inherited/MessageFilled.swift | 38 ++++ .../Inherited/MessageReplaced.swift | 40 ++++ .../Inherited/ObsoletedFilled.swift | 40 ++++ .../Inherited/ObsoletedReplaced.swift | 98 +++++++++ .../Inherited/RenamedFilled.swift | 25 +++ .../Inherited/RenamedNoVersion.swift | 16 ++ .../Inherited/RenamedReplaced.swift | 42 ++++ .../Inherited/UnconditionallyDeprecated.swift | 19 ++ .../UnconditionallyDeprecated.swift | 8 +- 26 files changed, 1099 insertions(+), 90 deletions(-) create mode 100644 lib/SymbolGraphGen/AvailabilityMixin.cpp create mode 100644 lib/SymbolGraphGen/AvailabilityMixin.h rename test/SymbolGraph/Symbols/Mixins/Availability/{Availability.swift => Basic.swift} (65%) create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/DeprecatedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/IntroducedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/MessageLastWins.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Duplicated/ObsoletedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/DeprecatedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/IntroducedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/MessageReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/ObsoletedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedFilled.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedNoVersion.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/RenamedReplaced.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/Availability/Inherited/UnconditionallyDeprecated.swift 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/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: ] From 975d2520e81a5b3b656a70bea241dc2e6ba422fb Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Mon, 1 Jun 2020 11:30:55 -0700 Subject: [PATCH 055/108] [SymbolGraph] Print where clause in full declaration fragments rdar://63233737 --- lib/SymbolGraphGen/SymbolGraph.cpp | 3 +- .../Mixins/DeclarationFragments/Basic.swift | 60 ----- .../DeclarationFragments/Full/Function.swift | 95 ++++++++ .../Full/NominalTypes.swift | 208 ++++++++++++++++++ .../Properties/ComputedProperties.swift | 0 .../Properties/ProtocolRequirements.swift | 0 .../{ => Full}/Properties/Subscripts.swift | 0 .../{ => Navigator}/Navigator.swift | 0 .../Function.swift} | 8 +- .../NominalTypes.swift} | 24 +- 10 files changed, 321 insertions(+), 77 deletions(-) delete mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Function.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/NominalTypes.swift rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{ => Full}/Properties/ComputedProperties.swift (100%) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{ => Full}/Properties/ProtocolRequirements.swift (100%) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{ => Full}/Properties/Subscripts.swift (100%) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{ => Navigator}/Navigator.swift (100%) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{SubheadingDeclarationFragments.swift => Subheading/Function.swift} (83%) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{SubheadingDeclarationFragmentsTypes.swift => Subheading/NominalTypes.swift} (63%) 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/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", From 58e49dbd456c2429c5311ec32ea8fbcb5bf721a2 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Tue, 2 Jun 2020 11:37:51 -0700 Subject: [PATCH 056/108] [ownership] Add support for handling address_to_pointer to LoadBorrowInvalidationChecker. We treat address_to_pointer as an explicit opt in escape from the protection we provide. The code emitter must instead provide other manners of guaranteeing safety such as using mark_dependence. So we just treat the instruction as a non-write instruction. This verifier is not enabled in 5.3, so this does not need to be cherry-picked to there. --- .../LoadBorrowInvalidationChecker.cpp | 7 +++++++ .../load_borrow_invalidation_test.sil | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+) 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/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 : $() +} From a4bcbfab48b814935b72a4d46ee2ce3344fd2a40 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 2 Jun 2020 10:12:46 -0700 Subject: [PATCH 057/108] [NFC] Remove a Dead Parameter From Clang Module Loading The only caller consuming the data that resulted from this bit has it set to false. Additionally, the side effect of force-loading the overlays is already handled unconditionally by the call to namelookup::getAllImports. --- lib/ClangImporter/ClangImporter.cpp | 14 ++++---------- lib/ClangImporter/ImporterImpl.h | 3 +-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 6b11ca1992bd9..48411fec7a4e6 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1779,8 +1779,7 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang( if (!clangModule) return nullptr; - return finishLoadingClangModule(importLoc, clangModule, - /*preferOverlay=*/false); + return finishLoadingClangModule(importLoc, clangModule); } ModuleDecl * @@ -1800,7 +1799,7 @@ ModuleDecl *ClangImporter::Implementation::loadModule( } ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( - SourceLoc importLoc, const clang::Module *clangModule, bool findOverlay) { + SourceLoc importLoc, const clang::Module *clangModule) { assert(clangModule); // Bump the generation count. @@ -1842,17 +1841,13 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( } if (clangModule->isSubModule()) { - finishLoadingClangModule(importLoc, clangModule->getTopLevelModule(), true); + finishLoadingClangModule(importLoc, clangModule->getTopLevelModule()); } else { ModuleDecl *&loaded = SwiftContext.LoadedModules[result->getName()]; if (!loaded) loaded = result; } - if (findOverlay) - if (ModuleDecl *overlay = wrapperUnit->getOverlayModule()) - result = overlay; - return result; } @@ -1876,8 +1871,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(diagLoc, ImportedHeaderExports[i]); } } diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 7963151dda780..67127fc15db6c 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -926,8 +926,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Constructs a Swift module for the given Clang module. ModuleDecl *finishLoadingClangModule(SourceLoc importLoc, - const clang::Module *clangModule, - bool preferOverlay); + const clang::Module *clangModule); /// Call finishLoadingClangModule on each deferred import collected /// while scanning a bridging header or PCH. From c8077e8974a538356c695cb7d93df485530d050d Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 2 Jun 2020 11:00:40 -0700 Subject: [PATCH 058/108] [Gardening] Add a SourceLoc For Cross-Import Overlay Diagnostics --- lib/ClangImporter/ClangImporter.cpp | 12 ++++++------ lib/ClangImporter/ImporterImpl.h | 7 ++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 48411fec7a4e6..0ca7686f31fb2 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1779,7 +1779,7 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang( if (!clangModule) return nullptr; - return finishLoadingClangModule(importLoc, clangModule); + return finishLoadingClangModule(clangModule, importLoc); } ModuleDecl * @@ -1799,7 +1799,7 @@ ModuleDecl *ClangImporter::Implementation::loadModule( } ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( - SourceLoc importLoc, const clang::Module *clangModule) { + const clang::Module *clangModule, SourceLoc importLoc) { assert(clangModule); // Bump the generation count. @@ -1841,7 +1841,7 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( } if (clangModule->isSubModule()) { - finishLoadingClangModule(importLoc, clangModule->getTopLevelModule()); + finishLoadingClangModule(clangModule->getTopLevelModule(), importLoc); } else { ModuleDecl *&loaded = SwiftContext.LoadedModules[result->getName()]; if (!loaded) @@ -1871,7 +1871,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]); + (void)finishLoadingClangModule(ImportedHeaderExports[i], diagLoc); } } @@ -2012,7 +2012,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; @@ -2027,7 +2027,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/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 67127fc15db6c..3a52658176ba2 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -922,11 +922,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); + ModuleDecl *finishLoadingClangModule(const clang::Module *clangModule, + SourceLoc importLoc); /// Call finishLoadingClangModule on each deferred import collected /// while scanning a bridging header or PCH. From d2e1336af72c33f54d55391449fdcd31cc3bd994 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 2 Jun 2020 11:19:11 -0700 Subject: [PATCH 059/108] [NFC] Use getWrapperForModule to Simplify Clang Module Loading --- lib/ClangImporter/ClangImporter.cpp | 39 ++++++----------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 0ca7686f31fb2..be31c41d0f621 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1805,38 +1805,13 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule( // 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); } From f9e99ed35c53db5c99e88f491bd1187971134d0d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 2 Jun 2020 12:15:54 -0700 Subject: [PATCH 060/108] [Diagnostics] NFC: Align `diagnoseAsNote` with `diagnoseAsError` for `AbstractRawRepresentableFailure` --- lib/Sema/CSDiagnostics.cpp | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 9e9e82b42ce7a..0467ed630608f 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6279,6 +6279,35 @@ bool AbstractRawRepresentableFailure::diagnoseAsError() { 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 MissingRawRepresentativeInitFailure::fixIt( InFlightDiagnostic &diagnostic) const { if (auto *E = getAsExpr(getAnchor())) { @@ -6330,35 +6359,6 @@ void MissingRawRepresentativeInitFailure::fixIt( } } -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 UseOfRawRepresentableInsteadOfItsRawValueFailure::fixIt( InFlightDiagnostic &diagnostic) const { auto *E = getAsExpr(getAnchor()); From 734f5b660c7972b40012a100296215d127acf1b4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 2 Jun 2020 12:24:42 -0700 Subject: [PATCH 061/108] [Diagnostics] NFC: Fix typo(s) raw `representative` -> `representable` --- lib/Sema/CSDiagnostics.cpp | 2 +- lib/Sema/CSDiagnostics.h | 8 ++++---- lib/Sema/CSFix.cpp | 4 ++-- lib/Sema/CSSimplify.cpp | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 0467ed630608f..6f75e4c34e2ee 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6308,7 +6308,7 @@ bool AbstractRawRepresentableFailure::diagnoseAsNote() { return false; } -void MissingRawRepresentativeInitFailure::fixIt( +void MissingRawRepresentableInitFailure::fixIt( InFlightDiagnostic &diagnostic) const { if (auto *E = getAsExpr(getAnchor())) { auto range = E->getSourceRange(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index fd70d3877f94b..10538bec125f5 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2121,12 +2121,12 @@ class AbstractRawRepresentableFailure : public FailureDiagnostic { /// /// `0` has to be wrapped into `E(rawValue: 0)` and either defaulted via `??` or /// force unwrapped to constitute a valid binding. -class MissingRawRepresentativeInitFailure final +class MissingRawRepresentableInitFailure final : public AbstractRawRepresentableFailure { public: - MissingRawRepresentativeInitFailure(const Solution &solution, - Type rawReprType, Type expectedType, - ConstraintLocator *locator) + MissingRawRepresentableInitFailure(const Solution &solution, Type rawReprType, + Type expectedType, + ConstraintLocator *locator) : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, locator) {} diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 04a20bc190047..4552a51cf3633 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1124,8 +1124,8 @@ bool ExpandArrayIntoVarargs::diagnose(const Solution &solution, bool ExplicitlyConstructRawRepresentable::diagnose(const Solution &solution, bool asNote) const { - MissingRawRepresentativeInitFailure failure(solution, RawReprType, - ExpectedType, getLocator()); + MissingRawRepresentableInitFailure failure(solution, RawReprType, + ExpectedType, getLocator()); return failure.diagnose(asNote); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 2fedf8efe8234..79285a8862ffa 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3164,8 +3164,8 @@ bool ConstraintSystem::repairFailures( // 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 repairByExplicitRawRepresentativeUse = [&](Type expectedType, - Type rawReprType) -> bool { + auto repairByConstructingRawRepresentableType = + [&](Type expectedType, Type rawReprType) -> bool { if (!isValueOfRawRepresentable(expectedType, rawReprType)) return false; @@ -3406,7 +3406,7 @@ bool ConstraintSystem::repairFailures( return true; // `rhs` - is an assignment destination and `lhs` is its source. - if (repairByExplicitRawRepresentativeUse(lhs, rhs)) + if (repairByConstructingRawRepresentableType(lhs, rhs)) return true; if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) @@ -3674,7 +3674,7 @@ bool ConstraintSystem::repairFailures( return true; // `lhs` - is an argument and `rhs` is a parameter type. - if (repairByExplicitRawRepresentativeUse(lhs, rhs)) + if (repairByConstructingRawRepresentableType(lhs, rhs)) break; if (repairByUsingRawValueOfRawRepresentableType(lhs, rhs)) @@ -3914,7 +3914,7 @@ bool ConstraintSystem::repairFailures( break; // `lhs` - is an result type and `rhs` is a contextual type. - if (repairByExplicitRawRepresentativeUse(lhs, rhs)) + if (repairByConstructingRawRepresentableType(lhs, rhs)) break; conversionsOrFixes.push_back(IgnoreContextualType::create( From 660384f8dd7d49e877355e405dfa0a13cb767c8f Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Tue, 2 Jun 2020 12:00:35 -0700 Subject: [PATCH 062/108] [semantic-arc-opts] Perform a rename/add some comments after talking with @atrick. This should add additional clarity to the pass's impl. --- .../Transforms/SemanticARCOpts.cpp | 90 ++++++++++++------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index c0901db5b29f3..ea0afca1a56de 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -47,7 +47,25 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow, 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 +89,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 +111,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, @@ -194,7 +221,7 @@ class LiveRange { } // end anonymous namespace -struct LiveRange::OperandToUser { +struct OwnershipLiveRange::OperandToUser { OperandToUser() {} SILInstruction *operator()(const Operand *use) const { @@ -203,11 +230,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 +352,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 +405,7 @@ void LiveRange::insertEndBorrowsAtDestroys( } } -void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { +void OwnershipLiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && { while (!ownershipForwardingUses.empty()) { auto *i = ownershipForwardingUses.back()->getUser(); ownershipForwardingUses = ownershipForwardingUses.drop_back(); @@ -437,8 +465,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,9 +483,9 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue, std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } -void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks, - ValueLifetimeAnalysis::Frontier &scratch, - InstModCallbacks callbacks) && { +void OwnershipLiveRange::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); @@ -481,8 +509,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()) { @@ -853,7 +881,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(); @@ -963,7 +991,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; } @@ -1014,7 +1042,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. // @@ -1267,10 +1295,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; } @@ -1377,7 +1406,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst // we need to handle the phi arg uses, we bail. After we reach a fixed point, // we will try to eliminate this value then. if (hasUnknownConsumingUseState == - LiveRange::HasConsumingUse_t::YesButAllPhiArgs) { + OwnershipLiveRange::HasConsumingUse_t::YesButAllPhiArgs) { auto *op = lr.getSingleUnknownConsumingUse(); assert(op); unsigned opNum = op->getOperandNumber(); @@ -1392,7 +1421,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst }; auto *arg = succBlock->getSILPhiArguments()[opNum]; - LiveRange phiArgLR(arg); + OwnershipLiveRange phiArgLR(arg); if (bool(phiArgLR.hasUnknownConsumingUse())) { return false; } @@ -1663,7 +1692,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 +1701,7 @@ class StorageGuaranteesLoadVisitor public: StorageGuaranteesLoadVisitor(SemanticARCOptVisitor &arcOpt, LoadInst *load, - const LiveRange &liveRange) + const OwnershipLiveRange &liveRange) : ARCOpt(arcOpt), liveRange(liveRange), currentAddress(load->getOperand()) {} @@ -1920,7 +1949,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 +1968,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; From 0f6665cae618629811e498a6238cf863b5c1b13d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 2 Jun 2020 12:50:13 -0700 Subject: [PATCH 063/108] [Diagnostics] Adjust fix-it when `.rawValue` is missing from optional type --- lib/Sema/CSDiagnostics.cpp | 2 +- test/Sema/enum_raw_representable.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 6f75e4c34e2ee..340ea0707e9c4 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6377,7 +6377,7 @@ void UseOfRawRepresentableInsteadOfItsRawValueFailure::fixIt( // out first and then, if destination is not optional, allow to specify // default value. if (RawReprType->getOptionalObjectType()) { - fix += ".map { $0.rawValue }"; + fix += "?.rawValue"; if (!ExpectedType->getOptionalObjectType()) fix += " ?? <#default value#>"; diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift index 2ca4a3eda4248..39e89779ddf0d 100644 --- a/test/Sema/enum_raw_representable.swift +++ b/test/Sema/enum_raw_representable.swift @@ -195,11 +195,11 @@ func sr8150_mutable(obj: SR8150Box) { func test(_ opt: Bar?) { sr8150_helper1(opt) - // expected-error@-1 {{cannot convert value of type 'Bar?' to expected argument type 'Double'}} {{23-23=.map { $0.rawValue } ?? <#default value#>}} + // 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=.map { $0.rawValue }}} + // expected-error@-1 {{cannot convert value of type 'Bar?' to specified type 'Double?'}} {{25-25=?.rawValue}} } } From 314411996646e476ab2ffef225901aee8eb99f2b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 2 Jun 2020 10:27:31 -0700 Subject: [PATCH 064/108] Invalidate binding VarDecls if the initializer fails to type check Ensure to make them "typechecked". --- lib/Sema/TypeCheckConstraints.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 4aaf554e2f28c..dd0c1043dc64d 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2355,23 +2355,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; } From d26f4148a918a7b9e9b4d5b78bcaa3ec060d7d38 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Tue, 2 Jun 2020 14:25:28 -0700 Subject: [PATCH 065/108] [CodeCompletion] Replace main module instead of file Rather than replacing the code completion file on the `CompilerInstance` whenever we do a cached top-level completion, let's set a new main module instead. This allows us to properly update the `LoadedModules` map, and allows the retrieval of the code completion file to be turned into a request. --- include/swift/AST/TypeCheckRequests.h | 19 +++++++++++ include/swift/AST/TypeCheckerTypeIDZone.def | 2 ++ include/swift/Frontend/Frontend.h | 15 ++++----- include/swift/IDE/CompletionInstance.h | 1 - lib/AST/Module.cpp | 14 ++++++++ lib/Frontend/Frontend.cpp | 18 ++++++---- lib/IDE/CompletionInstance.cpp | 33 ++++++++----------- .../lib/SwiftLang/SwiftCompletion.cpp | 4 +-- .../SwiftLang/SwiftConformingMethodList.cpp | 4 +-- .../lib/SwiftLang/SwiftTypeContextInfo.cpp | 4 +-- tools/swift-ide-test/swift-ide-test.cpp | 4 +-- 11 files changed, 75 insertions(+), 43 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index a28312666ccdf..f8b0125cf9fc4 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2479,6 +2479,25 @@ class PrimarySourceFilesRequest 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 91847912a2315..98e1c6a892a23 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) diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 5ea5d4c96a395..c955bb3061eaf 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -451,9 +451,6 @@ class CompilerInstance { /// considered primaries. llvm::SetVector PrimaryBufferIDs; - /// 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; @@ -509,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; @@ -557,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 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/lib/AST/Module.cpp b/lib/AST/Module.cpp index d85b3f93ea36e..41c4ac32330e0 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -532,6 +532,20 @@ ArrayRef ModuleDecl::getPrimarySourceFiles() const { 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; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 27827e89766b4..71aa8c679613e 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -489,6 +489,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 +713,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(); @@ -899,12 +911,6 @@ SourceFile *CompilerInstance::createSourceFileForMainModule( if (isPrimary) { inputFile->enableInterfaceHash(); } - - if (bufferID == SourceMgr.getCodeCompletionBufferID()) { - assert(!CodeCompletionFile && "Multiple code completion files?"); - CodeCompletionFile = inputFile; - } - return inputFile; } diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 99095abeb8032..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; @@ -536,8 +533,7 @@ bool CompletionInstance::performNewOperation( CI.performParseAndResolveImportsOnly(); // If we didn't find a code completion token, bail. - auto completionFile = CI.getCodeCompletionFile(); - auto *state = completionFile.get()->getDelayedParserState(); + auto *state = CI.getCodeCompletionFile()->getDelayedParserState(); if (!state->hasCodeCompletionDelayedDeclState()) return true; @@ -554,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/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/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; } From 3b97b8647cbd91aa5208ba3212d64b6cada6d3d8 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 27 May 2020 17:02:55 -0700 Subject: [PATCH 066/108] [CodeCompletion] Suggest 'Self' inside struct, enum and classe In 'protocol', 'Self' is implicitly declared as a generic parameter. In 'struct' and 'enum', 'Self' is just an alias for the nominal type. In 'class', 'Self' is a dynamic type and usable only in result types and inside function bodies. rdar://problem/61307680 --- lib/IDE/CodeCompletion.cpp | 52 +++++++- test/IDE/complete_sself.swift | 223 ++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 test/IDE/complete_sself.swift diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 188698d54750a..55d8c3779732b 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -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; @@ -5783,6 +5828,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { auto DoPostfixExprBeginning = [&] (){ SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc(); Lookup.getValueCompletionsInDeclContext(Loc); + Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false); }; switch (Kind) { @@ -5933,8 +5979,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; } 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^# + } + } +} From aca0dceb3b4d25e35b70a8488f69beb55b6b5a96 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 2 Jun 2020 15:20:13 -0700 Subject: [PATCH 067/108] [NFC] Use The 'isPrimary' Bit --- lib/AST/Evaluator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index 472a5387e0f5d..0e112cfe927de 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -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; } From 3a214d99f6cee222d7a8c109db90b0aebc4b0e47 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 1 Jun 2020 10:30:54 -0700 Subject: [PATCH 068/108] Frontend: add an argument to disable implicitly built Swift modules --- include/swift/ClangImporter/ClangImporter.h | 1 + include/swift/Frontend/FrontendOptions.h | 7 +++ .../swift/Frontend/ModuleInterfaceLoader.h | 18 +++++-- include/swift/Option/FrontendOptions.td | 5 ++ lib/ClangImporter/ClangImporter.cpp | 6 ++- lib/ClangImporter/ImporterImpl.h | 3 ++ .../ArgsToFrontendOptionsConverter.cpp | 6 +++ lib/Frontend/Frontend.cpp | 3 +- lib/Frontend/ModuleInterfaceLoader.cpp | 51 +++++++++++++++---- lib/FrontendTool/FrontendTool.cpp | 4 +- lib/FrontendTool/ScanDependencies.cpp | 3 +- test/ScanDependencies/module_deps.swift | 2 +- 12 files changed, 90 insertions(+), 19 deletions(-) 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/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 710efc42f9368..37e4540a904c9 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -258,6 +258,13 @@ 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 paths to a set of explicitly built modules from interfaces. + std::vector ExplicitSwiftModules; + /// 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..30261fa735550 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -138,12 +138,13 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules, bool RemarkOnRebuildFromInterface, bool IgnoreSwiftSourceInfoFile, - bool DisableInterfaceFileLock) + bool DisableInterfaceFileLock, bool DisableImplicitSwiftModule) : SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir), RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface), DisableInterfaceFileLock(DisableInterfaceFileLock), + DisableImplicitSwiftModule(DisableImplicitSwiftModule), PreferInterfaceForModules(PreferInterfaceForModules) {} @@ -151,6 +152,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { std::string PrebuiltCacheDir; bool RemarkOnRebuildFromInterface; bool DisableInterfaceFileLock; + bool DisableImplicitSwiftModule; ArrayRef PreferInterfaceForModules; std::error_code findModuleFilesInDirectory( @@ -170,14 +172,16 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { ArrayRef PreferInterfaceForModules = {}, bool RemarkOnRebuildFromInterface = false, bool IgnoreSwiftSourceInfoFile = false, - bool DisableInterfaceFileLock = false) { + bool DisableInterfaceFileLock = false, + bool DisableImplicitSwiftModule = false) { return std::unique_ptr( new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir, tracker, loadMode, PreferInterfaceForModules, RemarkOnRebuildFromInterface, IgnoreSwiftSourceInfoFile, - DisableInterfaceFileLock)); + DisableInterfaceFileLock, + DisableImplicitSwiftModule)); } /// Append visible module names to \p names. Note that names are possibly @@ -192,10 +196,12 @@ 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); + bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock, + bool DisableImplicitSwiftModules); }; struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { @@ -238,7 +244,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { bool serializeDependencyHashes, bool trackSystemDependencies, bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock); + bool disableInterfaceFileLock, + bool disableImplicitSwiftModule); bool runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, @@ -258,6 +265,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { llvm::SmallString<256> &OutPath, StringRef &CacheHash); std::string getCacheHash(StringRef useInterfacePath); + void addExtraClangArg(StringRef Arg); }; } diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 177f97dd5cae3..375ba13bf2cbc 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -214,6 +214,11 @@ 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_EQ : Joined<["-"], "swift-module-file=">, + HelpText<"Specify Swift module explicitly built from textual interface">; } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 6b11ca1992bd9..f48862287582b 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -957,6 +957,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 +969,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( diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 7963151dda780..1e5b433f5bf3d 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; diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 14f5ac00ec9cf..202996991df34 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -83,6 +83,12 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.TrackSystemDeps |= Args.hasArg(OPT_track_system_dependencies); + Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules); + + for (auto A: Args.getAllArgValues(OPT_swift_module_file_EQ)) { + Opts.ExplicitSwiftModules.push_back(A); + } + // 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/Frontend.cpp b/lib/Frontend/Frontend.cpp index 27827e89766b4..7b58eb453d8d0 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -460,7 +460,8 @@ bool CompilerInstance::setUpModuleLoaders() { getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules, FEOpts.RemarkOnRebuildFromModuleInterface, IgnoreSourceInfoFile, - FEOpts.DisableInterfaceFileLock); + FEOpts.DisableInterfaceFileLock, + FEOpts.DisableImplicitModules); Context->addModuleLoader(std::move(PIML)); } diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 884c5fa9f47bf..6e47ba9a5b378 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -341,12 +341,13 @@ class ModuleInterfaceLoaderImpl { const ModuleLoadingMode loadMode; const bool remarkOnRebuildFromInterface; const bool disableInterfaceLock; + const bool disableImplicitSwiftModule; ModuleInterfaceLoaderImpl( ASTContext &ctx, StringRef modulePath, StringRef interfacePath, StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, SourceLoc diagLoc, bool remarkOnRebuildFromInterface, - bool disableInterfaceLock, + bool disableInterfaceLock, bool disableImplicitSwiftModule, DependencyTracker *dependencyTracker = nullptr, ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags), @@ -355,7 +356,8 @@ class ModuleInterfaceLoaderImpl { cacheDir(cacheDir), diagnosticLoc(diagLoc), dependencyTracker(dependencyTracker), loadMode(loadMode), remarkOnRebuildFromInterface(remarkOnRebuildFromInterface), - disableInterfaceLock(disableInterfaceLock) {} + disableInterfaceLock(disableInterfaceLock), + disableImplicitSwiftModule(disableImplicitSwiftModule) {} /// Constructs the full path of the dependency \p dep by prepending the SDK /// path if necessary. @@ -835,7 +837,8 @@ class ModuleInterfaceLoaderImpl { /*serializeDependencyHashes*/false, trackSystemDependencies, remarkOnRebuildFromInterface, - disableInterfaceLock); + disableInterfaceLock, + disableImplicitSwiftModule); // 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( @@ -965,6 +968,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( Ctx, ModPath, InPath, ModuleName, CacheDir, PrebuiltCacheDir, ModuleID.Loc, RemarkOnRebuildFromInterface, DisableInterfaceFileLock, + DisableImplicitSwiftModule, dependencyTracker, llvm::is_contained(PreferInterfaceForModules, ModuleName) ? @@ -1000,10 +1004,12 @@ 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) { + bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock, + bool DisableImplicitSwiftModule) { InterfaceSubContextDelegateImpl astDelegate(SourceMgr, Diags, SearchPathOpts, LangOpts, /*clangImporter*/nullptr, @@ -1012,7 +1018,15 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( SerializeDependencyHashes, TrackSystemDependencies, RemarkOnRebuildFromInterface, - DisableInterfaceFileLock); + DisableInterfaceFileLock, + DisableImplicitSwiftModule); + // 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); @@ -1158,6 +1172,12 @@ 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, @@ -1170,7 +1190,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( bool serializeDependencyHashes, bool trackSystemDependencies, bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock): SM(SM), Diags(Diags), ArgSaver(Allocator) { + bool disableInterfaceFileLock, + bool disableImplicitSwiftModule): SM(SM), Diags(Diags), ArgSaver(Allocator) { inheritOptionsForBuildingInterface(searchPathOpts, langOpts); // Configure front-end input. auto &SubFEOpts = subInvocation.getFrontendOptions(); @@ -1190,10 +1211,22 @@ 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 (disableImplicitSwiftModule) { + subInvocation.getFrontendOptions().DisableImplicitModules = true; + GenericArgs.push_back("-disable-implicit-swift-modules"); + } 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; diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 48384a17a74a2..314d103676de7 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -781,12 +781,14 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { 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.DisableInterfaceFileLock, + FEOpts.DisableImplicitModules); } static bool compileLLVMIR(CompilerInstance &Instance) { diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index 31ce01280bf81..0a4d48a59ee74 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -78,7 +78,8 @@ static std::vector resolveDirectDependencies( FEOpts.SerializeModuleInterfaceDependencyHashes, FEOpts.TrackSystemDeps, FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock); + FEOpts.DisableInterfaceFileLock, + FEOpts.DisableImplicitModules); // Find the dependencies of every module this module directly depends on. std::vector result; for (auto dependsOn : knownDependencies.getModuleDependencies()) { diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index 72885e5072f9b..f6ad2f54f8441 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 From 1ae70a5b26db65208e0ceb0b4932e77b26756b2e Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 1 Jun 2020 12:37:18 -0700 Subject: [PATCH 069/108] DependenciesScanner: avoid reporting output file path because build system should specify it --- .../ClangModuleDependencyScanner.cpp | 43 ------------------- lib/Frontend/ModuleInterfaceLoader.cpp | 4 -- .../Inputs/BuildModulesFromGraph.swift | 2 + test/ScanDependencies/module_deps.swift | 25 ++++------- 4 files changed, 11 insertions(+), 63 deletions(-) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 3d2b1d256137e..eb6fb2856b956 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)) @@ -265,24 +235,11 @@ void ClangImporter::recordModuleDependencies( 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/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 6e47ba9a5b378..eb6ef369829e9 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1368,10 +1368,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 diff --git a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift index bd6e5057b9a47..f2fdefffd9a97 100644 --- a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift +++ b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift @@ -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/module_deps.swift b/test/ScanDependencies/module_deps.swift index f6ad2f54f8441..aab47e58fb828 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -22,20 +22,15 @@ // 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 + // REQUIRES: executable_test // REQUIRES: objc_interop @@ -135,8 +130,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" From 28b0b22a42e549c1c6530bbda16d87a37f483178 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 1 Jun 2020 15:04:21 -0700 Subject: [PATCH 070/108] ModuleInterface: refactor several configuration values into an Option struct --- .../swift/Frontend/ModuleInterfaceLoader.h | 43 ++++++++--------- lib/Frontend/Frontend.cpp | 7 ++- lib/Frontend/ModuleInterfaceLoader.cpp | 48 +++++++------------ lib/FrontendTool/FrontendTool.cpp | 5 +- lib/FrontendTool/ScanDependencies.cpp | 7 ++- 5 files changed, 45 insertions(+), 65 deletions(-) diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 30261fa735550..c5ba052c8ffd4 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -127,6 +127,16 @@ class LangOptions; class SearchPathOptions; class CompilerInvocation; +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,23 +147,17 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules, - bool RemarkOnRebuildFromInterface, bool IgnoreSwiftSourceInfoFile, - bool DisableInterfaceFileLock, bool DisableImplicitSwiftModule) + bool IgnoreSwiftSourceInfoFile, ModuleInterfaceLoaderOptions Opts) : SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir), - RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface), - DisableInterfaceFileLock(DisableInterfaceFileLock), - DisableImplicitSwiftModule(DisableImplicitSwiftModule), - PreferInterfaceForModules(PreferInterfaceForModules) - {} + PreferInterfaceForModules(PreferInterfaceForModules), + Opts(Opts) {} std::string CacheDir; std::string PrebuiltCacheDir; - bool RemarkOnRebuildFromInterface; - bool DisableInterfaceFileLock; - bool DisableImplicitSwiftModule; ArrayRef PreferInterfaceForModules; + ModuleInterfaceLoaderOptions Opts; std::error_code findModuleFilesInDirectory( AccessPathElem ModuleID, @@ -170,18 +174,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, - bool DisableImplicitSwiftModule = false) { + ModuleInterfaceLoaderOptions Opts = ModuleInterfaceLoaderOptions(), + bool IgnoreSwiftSourceInfoFile = false) { return std::unique_ptr( new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir, tracker, loadMode, PreferInterfaceForModules, - RemarkOnRebuildFromInterface, IgnoreSwiftSourceInfoFile, - DisableInterfaceFileLock, - DisableImplicitSwiftModule)); + Opts)); } /// Append visible module names to \p names. Note that names are possibly @@ -200,8 +200,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock, - bool DisableImplicitSwiftModules); + ModuleInterfaceLoaderOptions Opts); }; struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { @@ -237,15 +236,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 disableImplicitSwiftModule); + bool trackSystemDependencies); bool runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 7b58eb453d8d0..91a59e4907bd4 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -455,13 +455,12 @@ bool CompilerInstance::setUpModuleLoaders() { 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, - FEOpts.DisableImplicitModules); + LoaderOpts, + IgnoreSourceInfoFile); Context->addModuleLoader(std::move(PIML)); } diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index eb6ef369829e9..77e809e33a4c5 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -339,25 +339,19 @@ class ModuleInterfaceLoaderImpl { const SourceLoc diagnosticLoc; DependencyTracker *const dependencyTracker; const ModuleLoadingMode loadMode; - const bool remarkOnRebuildFromInterface; - const bool disableInterfaceLock; - const bool disableImplicitSwiftModule; + ModuleInterfaceLoaderOptions Opts; ModuleInterfaceLoaderImpl( ASTContext &ctx, StringRef modulePath, StringRef interfacePath, StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, - SourceLoc diagLoc, bool remarkOnRebuildFromInterface, - bool disableInterfaceLock, bool disableImplicitSwiftModule, + 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), - disableImplicitSwiftModule(disableImplicitSwiftModule) {} + dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts) {} /// Constructs the full path of the dependency \p dep by prepending the SDK /// path if necessary. @@ -830,21 +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, - disableImplicitSwiftModule); + 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. @@ -907,7 +899,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); @@ -967,8 +959,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( ModuleInterfaceLoaderImpl Impl( Ctx, ModPath, InPath, ModuleName, CacheDir, PrebuiltCacheDir, ModuleID.Loc, - RemarkOnRebuildFromInterface, DisableInterfaceFileLock, - DisableImplicitSwiftModule, + Opts, dependencyTracker, llvm::is_contained(PreferInterfaceForModules, ModuleName) ? @@ -1008,18 +999,15 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock, - bool DisableImplicitSwiftModule) { + ModuleInterfaceLoaderOptions LoaderOpts) { InterfaceSubContextDelegateImpl astDelegate(SourceMgr, Diags, SearchPathOpts, LangOpts, + LoaderOpts, /*clangImporter*/nullptr, /*CreateCacheDirIfAbsent*/true, CacheDir, PrebuiltCacheDir, SerializeDependencyHashes, - TrackSystemDependencies, - RemarkOnRebuildFromInterface, - DisableInterfaceFileLock, - DisableImplicitSwiftModule); + 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 @@ -1029,7 +1017,7 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( } 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, @@ -1183,15 +1171,13 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( 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 disableImplicitSwiftModule): 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(); @@ -1211,7 +1197,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( if (trackSystemDependencies) { GenericArgs.push_back("-track-system-dependencies"); } - if (disableImplicitSwiftModule) { + if (LoaderOpts.disableImplicitSwiftModule) { subInvocation.getFrontendOptions().DisableImplicitModules = true; GenericArgs.push_back("-disable-implicit-swift-modules"); } @@ -1244,8 +1230,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"); } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 314d103676de7..f322da4198ae4 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -778,6 +778,7 @@ 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(), @@ -786,9 +787,7 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { PrebuiltCachePath, Invocation.getModuleName(), InputPath, Invocation.getOutputFilename(), FEOpts.SerializeModuleInterfaceDependencyHashes, - FEOpts.TrackSystemDeps, FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock, - FEOpts.DisableImplicitModules); + FEOpts.TrackSystemDeps, LoaderOpts); } static bool compileLLVMIR(CompilerInstance &Instance) { diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index 0a4d48a59ee74..f8974d96ea6f2 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -69,17 +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.DisableImplicitModules); + FEOpts.TrackSystemDeps); // Find the dependencies of every module this module directly depends on. std::vector result; for (auto dependsOn : knownDependencies.getModuleDependencies()) { From 38b3d81905fe059af65f0f1fd289591cc297eb3a Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 1 Jun 2020 16:19:28 -0700 Subject: [PATCH 071/108] ModuleInterface: pass-down explicit Swift module paths when building module from interface --- include/swift/Frontend/ModuleInterfaceLoader.h | 4 +++- lib/Frontend/ModuleInterfaceLoader.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index c5ba052c8ffd4..cf35b3483b38b 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -131,10 +131,12 @@ struct ModuleInterfaceLoaderOptions { bool remarkOnRebuildFromInterface = false; bool disableInterfaceLock = false; bool disableImplicitSwiftModule = false; + std::vector explicitSwiftModules; ModuleInterfaceLoaderOptions(const FrontendOptions &Opts): remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), disableInterfaceLock(Opts.DisableInterfaceFileLock), - disableImplicitSwiftModule(Opts.DisableImplicitModules) {} + disableImplicitSwiftModule(Opts.DisableImplicitModules), + explicitSwiftModules(Opts.ExplicitSwiftModules) {} ModuleInterfaceLoaderOptions() = default; }; /// A ModuleLoader that runs a subordinate \c CompilerInvocation and diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 77e809e33a4c5..7ace142562092 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1201,6 +1201,14 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( subInvocation.getFrontendOptions().DisableImplicitModules = true; GenericArgs.push_back("-disable-implicit-swift-modules"); } + subInvocation.getFrontendOptions().ExplicitSwiftModules = + LoaderOpts.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: LoaderOpts.explicitSwiftModules) { + GenericArgs.push_back(ArgSaver.save((llvm::Twine("-swift-module-file=") + EM).str())); + } 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=, From 9e88549199d435f2e8aa97dc9b9dbd17a1d48917 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 2 Jun 2020 11:50:15 -0700 Subject: [PATCH 072/108] ModuleInterface: teach module interface building to use explicitly built PCMs --- .../ClangImporter/ClangImporterOptions.h | 4 ++++ include/swift/Option/FrontendOptions.td | 2 ++ lib/ClangImporter/ClangImporter.cpp | 3 +++ .../ClangModuleDependencyScanner.cpp | 21 ++++++++----------- lib/Frontend/CompilerInvocation.cpp | 2 ++ test/ScanDependencies/module_deps.swift | 13 ++++++++---- 6 files changed, 29 insertions(+), 16 deletions(-) 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/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 375ba13bf2cbc..8de4fb8eb3d9a 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -717,4 +717,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/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index f48862287582b..cf8f68afa2086 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] diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index eb6fb2856b956..739aa8444d22a 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -211,30 +211,27 @@ 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) { + for (auto arg: allArgs) { addClangArg(arg); } - // Add all args reported from the Clang dependencies scanner. - for(auto arg: clangModuleDep.NonPathCommandLine) { - addClangArg(arg); - } - // Swift frontend action: -emit-pcm swiftArgs.push_back("-emit-pcm"); swiftArgs.push_back("-module-name"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 17f28871d3243..78c78ed0c05fc 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); diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index aab47e58fb828..72f30ba975ee8 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -31,6 +31,12 @@ // 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 + // REQUIRES: executable_test // REQUIRES: objc_interop @@ -100,11 +106,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" From 01c18d01c19940978855856841b998adbb12fda5 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 2 Jun 2020 12:38:12 -0700 Subject: [PATCH 073/108] Frontend: move ExplicitSwiftModules into SearchPathOptions, NFC --- include/swift/AST/SearchPathOptions.h | 3 +++ include/swift/Frontend/FrontendOptions.h | 3 --- include/swift/Frontend/ModuleInterfaceLoader.h | 4 +--- lib/Frontend/ArgsToFrontendOptionsConverter.cpp | 4 ---- lib/Frontend/CompilerInvocation.cpp | 3 +++ lib/Frontend/ModuleInterfaceLoader.cpp | 6 +++--- 6 files changed, 10 insertions(+), 13 deletions(-) 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/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 37e4540a904c9..201202cd983a1 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -262,9 +262,6 @@ class FrontendOptions { /// built and given to the compiler invocation. bool DisableImplicitModules = false; - /// The paths to a set of explicitly built modules from interfaces. - std::vector ExplicitSwiftModules; - /// 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 cf35b3483b38b..c5ba052c8ffd4 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -131,12 +131,10 @@ struct ModuleInterfaceLoaderOptions { bool remarkOnRebuildFromInterface = false; bool disableInterfaceLock = false; bool disableImplicitSwiftModule = false; - std::vector explicitSwiftModules; ModuleInterfaceLoaderOptions(const FrontendOptions &Opts): remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), disableInterfaceLock(Opts.DisableInterfaceFileLock), - disableImplicitSwiftModule(Opts.DisableImplicitModules), - explicitSwiftModules(Opts.ExplicitSwiftModules) {} + disableImplicitSwiftModule(Opts.DisableImplicitModules) {} ModuleInterfaceLoaderOptions() = default; }; /// A ModuleLoader that runs a subordinate \c CompilerInvocation and diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 202996991df34..f5f28b1a4e793 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -85,10 +85,6 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules); - for (auto A: Args.getAllArgValues(OPT_swift_module_file_EQ)) { - Opts.ExplicitSwiftModules.push_back(A); - } - // 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 78c78ed0c05fc..b268f6a50edb9 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -865,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_EQ)) { + Opts.ExplicitSwiftModules.push_back(resolveSearchPath(A->getValue())); + } // Opts.RuntimeIncludePath is set by calls to // setRuntimeIncludePath() or setMainExecutablePath(). // Opts.RuntimeImportPath is set by calls to diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 7ace142562092..50900245caafd 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1201,12 +1201,12 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( subInvocation.getFrontendOptions().DisableImplicitModules = true; GenericArgs.push_back("-disable-implicit-swift-modules"); } - subInvocation.getFrontendOptions().ExplicitSwiftModules = - LoaderOpts.explicitSwiftModules; + 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: LoaderOpts.explicitSwiftModules) { + for (auto EM: searchPathOpts.ExplicitSwiftModules) { GenericArgs.push_back(ArgSaver.save((llvm::Twine("-swift-module-file=") + EM).str())); } if (clangImporter) { From 0d74428575feacefd6dcad82c503c491f99695ae Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 2 Jun 2020 13:36:41 -0700 Subject: [PATCH 074/108] Front-end: use separate flag for -swift-module-file instead of EQ --- include/swift/Option/FrontendOptions.td | 5 +++-- lib/Frontend/CompilerInvocation.cpp | 2 +- lib/Frontend/ModuleInterfaceLoader.cpp | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 8de4fb8eb3d9a..9ba2fc6ed4fe8 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -217,8 +217,9 @@ def enable_resilience : Flag<["-"], "enable-resilience">, def disable_implicit_swift_modules: Flag<["-"], "disable-implicit-swift-modules">, HelpText<"Disable building Swift modules explicitly by the compiler">; -def swift_module_file_EQ : Joined<["-"], "swift-module-file=">, - HelpText<"Specify Swift module explicitly built from textual interface">; +def swift_module_file + : Separate<["-"], "swift-module-file">, MetaVarName<"">, + HelpText<"Specify Swift module explicitly built from textual interface">; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b268f6a50edb9..fb6db28526628 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -865,7 +865,7 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, Opts.DisableModulesValidateSystemDependencies |= Args.hasArg(OPT_disable_modules_validate_system_headers); - for (auto A: Args.filtered(OPT_swift_module_file_EQ)) { + for (auto A: Args.filtered(OPT_swift_module_file)) { Opts.ExplicitSwiftModules.push_back(resolveSearchPath(A->getValue())); } // Opts.RuntimeIncludePath is set by calls to diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 50900245caafd..7b2845f3c6267 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1207,7 +1207,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( // Adding these argumnets may not be necessary. // FIXME: remove it? for (auto EM: searchPathOpts.ExplicitSwiftModules) { - GenericArgs.push_back(ArgSaver.save((llvm::Twine("-swift-module-file=") + EM).str())); + 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 From 9a3e2aa5d029535e1a220137feeca3ab5f8d1a2f Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 2 Jun 2020 19:21:56 -0700 Subject: [PATCH 075/108] Revert "Add a Test Demonstrating Superfluous Cascading Across Module Boundaries" This reverts commit 71d4c3ac5591d7002d83486d7cddee6c2c1a19b6. --- .../doesNotUseLib.swift | 3 -- .../main.swift | 1 - .../ofm.json | 22 ----------- .../submodule/lib-after.swift | 8 ---- .../submodule/lib-before.swift | 7 ---- .../submodule/ofm.json | 10 ----- .../usesLib.swift | 7 ---- .../usesLibTransitively.swift | 3 -- .../superfluous-cascade-across-modules.swift | 39 ------------------- 9 files changed, 100 deletions(-) delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift delete mode 100644 test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift delete mode 100644 test/Incremental/superfluous-cascade-across-modules.swift diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift deleted file mode 100644 index caa55673f93b5..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/doesNotUseLib.swift +++ /dev/null @@ -1,3 +0,0 @@ -extension Map { - func pin() {} -} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/main.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json b/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json deleted file mode 100644 index 2d6538c292696..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/ofm.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "main.swift": { - "object": "./main.o", - "swift-dependencies": "./main.swiftdeps" - }, - "usesLib.swift": { - "object": "./usesLib.o", - "swift-dependencies": "./usesLib.swiftdeps" - }, - "usesLibTransitively.swift": { - "object": "./usesLib.o", - "swift-dependencies": "./usesLib.swiftdeps" - }, - "doesNotUseLib.swift": { - "object": "./doesNotUseLib.o", - "swift-dependencies": "./doesNotUseLib.swiftdeps" - }, - "": { - "swift-dependencies": "./main~buildrecord.swiftdeps" - } -} - diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift deleted file mode 100644 index 347f0da653baa..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift +++ /dev/null @@ -1,8 +0,0 @@ -public struct Library { - var catalog: [Book] -} - -public struct Book { - var title: String - var checkOutCount: Int -} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift deleted file mode 100644 index c9bb3d05e9d03..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift +++ /dev/null @@ -1,7 +0,0 @@ -public struct Library { - var catalog: [Book] -} - -public struct Book { - var title: String -} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json b/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json deleted file mode 100644 index d2f9889464c48..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/submodule/ofm.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lib.swift": { - "object": "./lib.o", - "swift-dependencies": "./lib.swiftdeps" - }, - "": { - "swift-dependencies": "./submodule~buildrecord.swiftdeps" - } -} - diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift deleted file mode 100644 index 96bb74c8750cd..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLib.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Lib - -public struct District { - var libraries: [Library] -} - -struct Map {} diff --git a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift b/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift deleted file mode 100644 index a205027f286c7..0000000000000 --- a/test/Incremental/Inputs/superfluous-cascade-across-modules/usesLibTransitively.swift +++ /dev/null @@ -1,3 +0,0 @@ -struct County { - var districts: [District] -} diff --git a/test/Incremental/superfluous-cascade-across-modules.swift b/test/Incremental/superfluous-cascade-across-modules.swift deleted file mode 100644 index 0c76afd0864ad..0000000000000 --- a/test/Incremental/superfluous-cascade-across-modules.swift +++ /dev/null @@ -1,39 +0,0 @@ -// ============================================================================= -// Without private dependencies -// ============================================================================= - -// First, build a submodule - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/superfluous-cascade-across-modules/*.swift %t -// RUN: cp %S/Inputs/superfluous-cascade-across-modules/*.json %t - -// RUN: %target-build-swift %S/Inputs/superfluous-cascade-across-modules/submodule/lib-before.swift -emit-module -emit-library -module-name Lib -module-link-name Lib -emit-module-path %t/Lib.swiftmodule -o %t/%target-library-name(Lib) - -// Build the main executable that depends on the submodule we just built - -// RUN: cd %t && %swiftc_driver -emit-module -enable-batch-mode -j2 -incremental -driver-show-incremental -I %t -L %t -lLib -module-name main \ -// RUN: -output-file-map ofm.json \ -// RUN: main.swift \ -// RUN: doesNotUseLib.swift \ -// RUN: usesLib.swift \ -// RUN: usesLibTransitively.swift >&output1 - -// Rebuild the submodule - -// RUN: %target-build-swift %S/Inputs/superfluous-cascade-across-modules/submodule/lib-after.swift -emit-module -emit-library -module-name Lib -module-link-name Lib -emit-module-path %t/Lib.swiftmodule -o %t/%target-library-name(Lib) - -// Rebuild the main executable - -// RUN: cd %t && %swiftc_driver -emit-module -enable-batch-mode -j2 -incremental -driver-show-incremental -I %t -L %t -lLib -module-name main \ -// RUN: -output-file-map ofm.json \ -// RUN: main.swift \ -// RUN: doesNotUseLib.swift \ -// RUN: usesLib.swift \ -// RUN: usesLibTransitively.swift >&output2 - -// RUN: %FileCheck -check-prefix=CHECK-STATUS-QUO-RECOMPILED %s < %t/output2 - -// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: main -// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: usesLib -// CHECK-STATUS-QUO-RECOMPILED-DAG: Queuing because of external dependencies: {compile: doesNotUseLib From f76169be58957b2fd45616798e4ff09f5cd67b11 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 3 Jun 2020 00:50:15 -0700 Subject: [PATCH 076/108] [AutoDiff] Improve Array.TangentVector precondition messages. (#32154) Improve count-related precondition messages. Co-authored-by: Richard Wei --- .../ArrayDifferentiation.swift | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) 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.. Date: Wed, 3 Jun 2020 10:37:27 +0200 Subject: [PATCH 077/108] Test C++ out-of-line operator functions (#32081) Add tests to verify that C++ out-of-line operator functions are imported correctly. --- .../Cxx/operators/Inputs/module.modulemap | 4 ++++ .../Inputs/non-member-out-of-line.cpp | 5 ++++ .../operators/Inputs/non-member-out-of-line.h | 10 ++++++++ .../non-member-out-of-line-irgen.swift | 8 +++++++ .../non-member-out-of-line-silgen.swift | 10 ++++++++ .../operators/non-member-out-of-line.swift | 23 +++++++++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp create mode 100644 test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h create mode 100644 test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift create mode 100644 test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift create mode 100644 test/Interop/Cxx/operators/non-member-out-of-line.swift 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..c3b3ed123837c --- /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 [[NAME:@(_Zpl6IntBoxS_|"\?\?H@YA\?AUIntBox@@U0@0@Z")]](i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) +// CHECK: declare {{(dso_local )?}}i32 [[NAME]](i32, i32) 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() From b938f960df6d724207a3dd5a898808ced634c5f9 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 3 Jun 2020 08:48:33 -0700 Subject: [PATCH 078/108] [Diagnostics] NFC: Rename a fix/diagnostic for missing `.rawValue` reference --- lib/Sema/CSDiagnostics.cpp | 3 +-- lib/Sema/CSDiagnostics.h | 9 +++------ lib/Sema/CSFix.cpp | 16 +++++++--------- lib/Sema/CSFix.h | 21 ++++++++++----------- lib/Sema/CSSimplify.cpp | 4 ++-- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 340ea0707e9c4..812eca350df91 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -6359,8 +6359,7 @@ void MissingRawRepresentableInitFailure::fixIt( } } -void UseOfRawRepresentableInsteadOfItsRawValueFailure::fixIt( - InFlightDiagnostic &diagnostic) const { +void MissingRawValueFailure::fixIt(InFlightDiagnostic &diagnostic) const { auto *E = getAsExpr(getAnchor()); if (!E) return; diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 10538bec125f5..be251b6da89e6 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2149,13 +2149,10 @@ class MissingRawRepresentableInitFailure final /// ``` /// /// `E.one` has to use `.rawValue` to match `Int` expected by pattern binding. -class UseOfRawRepresentableInsteadOfItsRawValueFailure final - : public AbstractRawRepresentableFailure { +class MissingRawValueFailure final : public AbstractRawRepresentableFailure { public: - UseOfRawRepresentableInsteadOfItsRawValueFailure(const Solution &solution, - Type rawReprType, - Type expectedType, - ConstraintLocator *locator) + MissingRawValueFailure(const Solution &solution, Type rawReprType, + Type expectedType, ConstraintLocator *locator) : AbstractRawRepresentableFailure(solution, rawReprType, expectedType, locator) {} diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 4552a51cf3633..ab31071816944 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1137,19 +1137,17 @@ ExplicitlyConstructRawRepresentable::create(ConstraintSystem &cs, cs, rawReprType, expectedType, locator); } -bool UseValueTypeOfRawRepresentative::diagnose(const Solution &solution, - bool asNote) const { - UseOfRawRepresentableInsteadOfItsRawValueFailure failure( - solution, RawReprType, ExpectedType, getLocator()); +bool UseRawValue::diagnose(const Solution &solution, bool asNote) const { + MissingRawValueFailure failure(solution, RawReprType, ExpectedType, + getLocator()); return failure.diagnose(asNote); } -UseValueTypeOfRawRepresentative * -UseValueTypeOfRawRepresentative::create(ConstraintSystem &cs, Type rawReprType, - Type expectedType, - ConstraintLocator *locator) { +UseRawValue *UseRawValue::create(ConstraintSystem &cs, Type rawReprType, + Type expectedType, + ConstraintLocator *locator) { return new (cs.getAllocator()) - UseValueTypeOfRawRepresentative(cs, rawReprType, expectedType, locator); + UseRawValue(cs, rawReprType, expectedType, locator); } unsigned AllowArgumentMismatch::getParamIdx() const { diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index a99a0a2944e5e..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, @@ -1617,13 +1618,13 @@ class ExplicitlyConstructRawRepresentable final : public ConstraintFix { ConstraintLocator *locator); }; -class UseValueTypeOfRawRepresentative final : public ConstraintFix { +class UseRawValue final : public ConstraintFix { Type RawReprType; Type ExpectedType; - UseValueTypeOfRawRepresentative(ConstraintSystem &cs, Type rawReprType, - Type expectedType, ConstraintLocator *locator) - : ConstraintFix(cs, FixKind::UseValueTypeOfRawRepresentative, locator), + UseRawValue(ConstraintSystem &cs, Type rawReprType, Type expectedType, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::UseRawValue, locator), RawReprType(rawReprType), ExpectedType(expectedType) {} public: @@ -1633,10 +1634,8 @@ class UseValueTypeOfRawRepresentative final : public ConstraintFix { bool diagnose(const Solution &solution, bool asNote = false) const override; - static UseValueTypeOfRawRepresentative *create(ConstraintSystem &cs, - Type rawReprType, - Type expectedType, - ConstraintLocator *locator); + 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/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 79285a8862ffa..b293a05d8b3fd 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3184,7 +3184,7 @@ bool ConstraintSystem::repairFailures( if (!isValueOfRawRepresentable(expectedType, rawReprType)) return false; - conversionsOrFixes.push_back(UseValueTypeOfRawRepresentative::create( + conversionsOrFixes.push_back(UseRawValue::create( *this, rawReprType, expectedType, getConstraintLocator(locator))); return true; }; @@ -9578,7 +9578,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: From 3126a4e6aea7cc7cc780391675019fb0a7ed8368 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 3 Jun 2020 09:23:01 -0700 Subject: [PATCH 079/108] gyb: clean up some linter warnings These showed up after the python 2, python 3 compatibility cleanup. --- utils/gyb_syntax_support/__init__.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 From b14d9655ca4e1c32cf3a055bd9d4be2f5bf3471f Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 3 Jun 2020 10:26:59 -0700 Subject: [PATCH 080/108] [CSGen] Allow `is` patterns to infer type from enclosing context Instead of assuming type of its sub-pattern `is` should be able to infer type from context and then propagate that to the sub-pattern via conversion. This enables support for patterns like `.foo(_ as Foo)` where `is` would have a type different from `_` which gets inferred from associated value of `foo` and converted to `Foo` that becomes a type of `_` pattern. Resolves: rdar://problem/63510989 --- lib/Sema/CSGen.cpp | 12 +++++++++++- test/Constraints/patterns.swift | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1486e63f7f839..3f432cfa3f9c7 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2544,7 +2544,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/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}} + } +} From 8eb5cbe6a3f3445c1c0cb28b931c3bbd0189b572 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 3 Jun 2020 11:04:28 -0700 Subject: [PATCH 081/108] add test by @nathawes --- .../Store/driver-ignore-system-modules.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/Index/Store/driver-ignore-system-modules.swift diff --git a/test/Index/Store/driver-ignore-system-modules.swift b/test/Index/Store/driver-ignore-system-modules.swift new file mode 100644 index 0000000000000..7147488165fdf --- /dev/null +++ b/test/Index/Store/driver-ignore-system-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 From 17b681bf20a37863ab1c1d3e8fc6d8f09dc833bf Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 25 Mar 2020 11:55:25 -0700 Subject: [PATCH 082/108] [SourceKit] Disable complete_build_session.swift test file while investigating --- test/SourceKit/CodeComplete/complete_build_session.swift | 1 + 1 file changed, 1 insertion(+) 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() { From 258ceda02fade5ba21cfad26b552803698f44cb5 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 3 Jun 2020 11:13:45 -0700 Subject: [PATCH 083/108] rename test --- ...ore-system-modules.swift => ignore-system-clang-modules.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/Index/Store/{driver-ignore-system-modules.swift => ignore-system-clang-modules.swift} (100%) diff --git a/test/Index/Store/driver-ignore-system-modules.swift b/test/Index/Store/ignore-system-clang-modules.swift similarity index 100% rename from test/Index/Store/driver-ignore-system-modules.swift rename to test/Index/Store/ignore-system-clang-modules.swift From baa3a7dc109525562c0a8ec6db2354ce32bfa928 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Wed, 3 Jun 2020 12:06:39 -0700 Subject: [PATCH 084/108] [benchmarks] Add a benchmark for printing using mirrors (#32150) * Add a benchmark for mirrors and typename->string conversion --- benchmark/CMakeLists.txt | 1 + benchmark/single-source/Mirror.swift | 105 +++++++++++++++++++++++++++ benchmark/utils/main.swift | 3 + 3 files changed, 109 insertions(+) create mode 100644 benchmark/single-source/Mirror.swift 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) From 14dd90953b371e78bd3fb07ea89795d246dd6676 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 3 Jun 2020 12:12:08 -0700 Subject: [PATCH 085/108] test: repair the test after accidental merge without testing --- test/IRGen/c_globals.swift | 44 ++++++++++++++++++++++++------------- test/IRGen/framepointer.sil | 15 ++++++++----- 2 files changed, 38 insertions(+), 21 deletions(-) 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 d580f6f836a9d..62062ec2eef11 100644 --- a/test/IRGen/framepointer.sil +++ b/test/IRGen/framepointer.sil @@ -1,7 +1,7 @@ -// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK -// RUN: %target-swift-frontend -primary-file %s -emit-ir -Xcc -mno-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 +// 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 @@ -33,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: @@ -46,7 +47,8 @@ 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: @@ -59,7 +61,8 @@ entry(%i : $Int32): // LEAF: ret i32 %1 // LEAF: } -// LEAF: attributes [[ATTR]] = {{{.*}}"frame-pointer"="non-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: From 1f01103cc1500a4ea50255922be9f1675687d385 Mon Sep 17 00:00:00 2001 From: Nathan Hawes Date: Wed, 3 Jun 2020 13:30:27 -0700 Subject: [PATCH 086/108] [Index] Add regression test case for @dynamicMemberLookup on a protocol. --- test/Index/index_keypath_member_lookup.swift | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) 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 + } +} From bd0bb64ce056bfc4ad53bbc05723a1f73d12076c Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Wed, 3 Jun 2020 14:38:18 -0700 Subject: [PATCH 087/108] Fix dependency scanner test-case to use explicit imports. --- test/ScanDependencies/Inputs/Swift/A.swiftinterface | 1 + test/ScanDependencies/Inputs/Swift/G.swiftinterface | 2 +- test/ScanDependencies/module_deps.swift | 10 ++++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) 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/module_deps.swift b/test/ScanDependencies/module_deps.swift index 72f30ba975ee8..2c4908b1b6b46 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -125,7 +125,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": { @@ -153,7 +156,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 From 41095aaa5cad9935652516662f4f3f386c60c96b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 30 May 2020 16:09:49 -0700 Subject: [PATCH 088/108] ABI: qualify use of `StringRef` and `Optional` (NFC) This simply uses the qualified names for `StringRef` and `Optional` to help with use of regular expressions to identify the usage to help migrate the references away from `LLVMSupport` to enable explicitly vending a custom `LLVMSupport` in the runtime. --- include/swift/ABI/Metadata.h | 14 +++++++------- include/swift/ABI/TypeIdentity.h | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) 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; } From 8538a2afcc34b16afd9d59d998e89bca9bc9528d Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 3 Jun 2020 16:26:33 -0700 Subject: [PATCH 089/108] SIL: Verify kinds of vtable entries. Validate that inherited entries are not left at "normal" state, and that non-overridden entries do not in fact have overrides. --- lib/SIL/IR/SILDeclRef.cpp | 7 +- lib/SIL/Verifier/SILVerifier.cpp | 67 ++++++++++++++++++- lib/Sema/TypeCheckDecl.cpp | 4 ++ test/SIL/Parser/basic.sil | 17 ++++- test/SILOptimizer/basic-callee-printer.sil | 16 ++--- test/SILOptimizer/dead_func_init_method.sil | 2 +- test/SILOptimizer/devirt_access.sil | 8 +-- test/SILOptimizer/devirt_access_ownership.sil | 8 +-- .../SILOptimizer/devirt_access_serialized.sil | 4 +- .../devirt_access_serialized_ownership.sil | 4 +- test/SILOptimizer/devirt_override.sil | 13 ++-- .../devirt_override_ownership.sil | 8 +-- test/SILOptimizer/devirt_speculative.sil | 6 +- test/SILOptimizer/devirt_try_apply.sil | 26 +++---- .../devirt_try_apply_ownership.sil | 28 ++++---- test/SILOptimizer/devirtualize.sil | 2 +- test/SILOptimizer/devirtualize2.sil | 2 +- test/SILOptimizer/devirtualize2_ownership.sil | 2 +- test/SILOptimizer/devirtualize_ownership.sil | 2 +- test/SILOptimizer/function_order.sil | 12 ++-- .../SILOptimizer/mm_inlinecaches_multiple.sil | 4 +- test/SILOptimizer/optimize_never.sil | 14 ++-- .../polymorphic_inline_caches.sil | 10 +-- test/SILOptimizer/sink.sil | 4 +- 24 files changed, 178 insertions(+), 92 deletions(-) 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/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 9ff86c7a2b419..63d0f0c4cfb21 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -5360,8 +5360,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 +5417,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; + } + } } } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 0b3c87267419f..6529f0ca38818 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -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. 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/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/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/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] } From 0bed967ce72dbac7357ecb1d68ad7af200674ef2 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Tue, 2 Jun 2020 21:29:50 -0700 Subject: [PATCH 090/108] [semantic-arc-opts] Create an explicit composition type for "ownership phi operands". This is letting me refactor the implementation of every place that I work with branches as "ownership phi operands" to instead work with OwnershipPhiOperand. In a future commit, I am going to use this to add support for optimizing structs and tuples that have multiple owned incoming values. --- include/swift/SIL/OwnershipUtils.h | 30 ++- include/swift/SIL/SILArgument.h | 26 ++ lib/SIL/IR/SILArgument.cpp | 22 ++ .../Transforms/SemanticARCOpts.cpp | 223 +++++++++++++----- 4 files changed, 246 insertions(+), 55 deletions(-) diff --git a/include/swift/SIL/OwnershipUtils.h b/include/swift/SIL/OwnershipUtils.h index a66c74221aefb..349ee45531ba2 100644 --- a/include/swift/SIL/OwnershipUtils.h +++ b/include/swift/SIL/OwnershipUtils.h @@ -598,8 +598,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: @@ -619,6 +623,28 @@ 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::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/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/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index ea0afca1a56de..d9df231b33c74 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -41,6 +41,92 @@ 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, + }; + +private: + Operand *op; + + OwnershipPhiOperand(Operand *op) : op(op) {} + +public: + static Optional get(const Operand *op) { + switch (op->getUser()->getKind()) { + case SILInstructionKind::BranchInst: + return {{const_cast(op)}}; + default: + return None; + } + } + + Kind getKind() const { + switch (op->getUser()->getKind()) { + case SILInstructionKind::BranchInst: + return Kind::Branch; + 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; + } + } + + 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::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 //===----------------------------------------------------------------------===// @@ -189,9 +275,10 @@ class OwnershipLiveRange { /// 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. /// @@ -203,11 +290,9 @@ class OwnershipLiveRange { /// /// 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 @@ -483,17 +568,41 @@ void OwnershipLiveRange::convertToGuaranteedAndRAUW( std::move(*this).convertOwnedGeneralForwardingUsesToGuaranteed(); } -void OwnershipLiveRange::convertArgToGuaranteed( +// 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::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) && { - // First convert the phi argument to be guaranteed. - auto *phiArg = cast(introducer.value); - phiArg->setOwnershipKind(ValueOwnershipKind::Guaranteed); - // 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()) { @@ -534,7 +643,7 @@ OwnershipLiveRange::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; } @@ -900,10 +1009,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 @@ -918,7 +1027,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; } @@ -962,9 +1072,16 @@ 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; + }); } llvm_unreachable("Unhandled joined live range?!"); @@ -979,7 +1096,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 { @@ -1021,11 +1138,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 @@ -1078,25 +1193,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; @@ -1404,24 +1519,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 == OwnershipLiveRange::HasConsumingUse_t::YesButAllPhiArgs) { - auto *op = lr.getSingleUnknownConsumingUse(); - assert(op); - unsigned opNum = op->getOperandNumber(); - auto *br = cast(op->getUser()); + 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]; - OwnershipLiveRange phiArgLR(arg); + OwnershipLiveRange phiArgLR(value); if (bool(phiArgLR.hasUnknownConsumingUse())) { return false; } @@ -1433,11 +1545,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; From 9a93b61f674ab21c995dac263d823a4f91c7b2ef Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Wed, 3 Jun 2020 20:16:30 -0400 Subject: [PATCH 091/108] [stdlib][cmake] OpenBSD target requires -lpthread. Like FreeBSD, OpenBSD needs -lpthread for a target link. This is necessary to get the swift-reflection-test to link and build correctly. --- stdlib/cmake/modules/AddSwiftStdlib.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 05123d1d8e127..f94c5e641a9e3 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -351,6 +351,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") From bd782be654a7db465301330d9935218b2d10100b Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Wed, 3 Jun 2020 12:05:46 -0700 Subject: [PATCH 092/108] Front-end: add a new module loader that loads explicitly built Swift modules To support -disable-implicit-swift-modules, the explicitly built modules are passed down as compiler arguments. We need this new module loader to handle these modules. This patch also stops ModuleInterfaceLoader from building module from interface when -disable-implicit-swift-modules is set. --- include/swift/AST/DiagnosticsFrontend.def | 2 + .../swift/Frontend/ModuleInterfaceLoader.h | 33 ++++++++ .../Serialization/SerializedModuleLoader.h | 3 + lib/Frontend/Frontend.cpp | 10 +++ lib/Frontend/ModuleInterfaceLoader.cpp | 82 +++++++++++++++++++ lib/Serialization/ModuleFile.cpp | 24 ++++++ lib/Serialization/ModuleFile.h | 4 + lib/Serialization/SerializedModuleLoader.cpp | 6 ++ .../Inputs/BuildModulesFromGraph.swift | 2 +- .../Inputs/Swift/SubE.swiftinterface | 5 ++ test/ScanDependencies/module_deps.swift | 6 ++ 11 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 test/ScanDependencies/Inputs/Swift/SubE.swiftinterface 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/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index c5ba052c8ffd4..22c183beb2c69 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -127,6 +127,38 @@ 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; @@ -137,6 +169,7 @@ struct ModuleInterfaceLoaderOptions { 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 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/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index f39fe20f71962..2f862316262a7 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -450,6 +450,16 @@ 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); diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 7b2845f3c6267..5e573ceb6412b 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -880,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; @@ -1397,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/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/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/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift index f2fdefffd9a97..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 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 2c4908b1b6b46..3e11657ec02d4 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -37,6 +37,8 @@ // 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 @@ -44,6 +46,7 @@ import C import E import G +import SubE // CHECK: "mainModuleName": "deps" @@ -63,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: { From ebf291c4848409359d05e7c60057a62599d3336b Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 3 Jun 2020 19:28:37 -0700 Subject: [PATCH 093/108] [memory-lifetime] Teach the verifier that select_enum_addr doesn't write to memory. This is an older verifier that checks that uses of addresses from things like in_guaranteed parameters are never written to. We just never hit this before. --- lib/SIL/Verifier/SILVerifier.cpp | 1 + test/SIL/memory_lifetime.sil | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 9ff86c7a2b419..aa8776fecdede 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 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 : $() +} From 3cb33ac7ef80c495ca648b6dd5e6ab25e7eabb58 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 3 Jun 2020 14:14:06 -0700 Subject: [PATCH 094/108] [semantic-arc-opts] Teach semantic-arc-opts how to handle structs with multiple non-trivial values. Just like br inst, structs are phis in the ownership graph that one can induce on top of the def-use graph. In this commit, I basically fill in the relevant blanks in the ADT for such phis for struct so that the optimization for branches is generalized onto structs. --- include/swift/SIL/OwnershipUtils.h | 8 ++++++ lib/SIL/Utils/OwnershipUtils.cpp | 3 +++ .../Transforms/SemanticARCOpts.cpp | 27 +++++++++++++++++++ test/SILOptimizer/semantic-arc-opts.sil | 13 +++++++++ 4 files changed, 51 insertions(+) diff --git a/include/swift/SIL/OwnershipUtils.h b/include/swift/SIL/OwnershipUtils.h index 349ee45531ba2..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())) { @@ -614,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: @@ -631,6 +638,7 @@ struct OwnedValueIntroducer { switch (kind) { case OwnedValueIntroducerKind::Phi: return true; + case OwnedValueIntroducerKind::Struct: case OwnedValueIntroducerKind::Copy: case OwnedValueIntroducerKind::LoadCopy: case OwnedValueIntroducerKind::Apply: 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/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp index d9df231b33c74..8b22cc85b36af 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp @@ -54,6 +54,7 @@ class OwnershipPhiOperand { public: enum Kind { Branch, + Struct, }; private: @@ -65,6 +66,7 @@ class OwnershipPhiOperand { static Optional get(const Operand *op) { switch (op->getUser()->getKind()) { case SILInstructionKind::BranchInst: + case SILInstructionKind::StructInst: return {{const_cast(op)}}; default: return None; @@ -75,6 +77,8 @@ class OwnershipPhiOperand { switch (op->getUser()->getKind()) { case SILInstructionKind::BranchInst: return Kind::Branch; + case SILInstructionKind::StructInst: + return Kind::Struct; default: llvm_unreachable("unhandled case?!"); } @@ -100,6 +104,8 @@ class OwnershipPhiOperand { switch (getKind()) { case Kind::Branch: return true; + case Kind::Struct: + return false; } } @@ -113,6 +119,8 @@ class OwnershipPhiOperand { 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(); @@ -576,6 +584,11 @@ static SILValue convertIntroducerToGuaranteed(OwnedValueIntroducer introducer) { 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: @@ -1084,6 +1097,20 @@ static bool getIncomingJoinedLiveRangeOperands( }); } + 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?!"); } 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 From 690d6c446b94ef24600e6b7b654fc24b6e0bc725 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 3 Jun 2020 22:26:20 -0700 Subject: [PATCH 095/108] [AST] Record whether a closure was type-checked in its enclosing expression Rather than using various "applied function builder" and "is single expression body" checks to determine whether a closure was type-checked in its enclosing expression, record in the closure expression whether it actually *was* type-checked as part of its enclosing expression. --- include/swift/AST/Expr.h | 24 +++++++++++++++++++----- lib/AST/Expr.cpp | 3 ++- lib/Sema/CSClosure.cpp | 2 ++ lib/Sema/MiscDiagnostics.cpp | 4 ++-- lib/Sema/TypeCheckStmt.cpp | 6 +++--- 5 files changed, 28 insertions(+), 11 deletions(-) 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/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 79ea2455f9eb0..70fc36bcb37ba 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) diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index 592fca0024441..3096fbf0e273e 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -331,6 +331,7 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution( fn.setBody(newBody, /*isSingleExpression=*/false); if (closure) { closure->setAppliedFunctionBuilder(); + closure->setTypeCheckedInEnclosingContext(); solution.setExprTypes(closure); } @@ -343,6 +344,7 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution( solution, closure, closureFnType->getResult(), rewriteTarget); application.visit(fn.getBody()); + closure->setTypeCheckedInEnclosingContext(); return SolutionApplicationToFunctionResult::Success; } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 57e73e34733dd..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; } @@ -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; } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 096b1c939bf38..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); From f55e7643fabfb37fda9c7e28b4b0f8971b71fe89 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 3 Jun 2020 22:48:58 -0700 Subject: [PATCH 096/108] [Constaint system] Add a predicate for when to check closures in enclosing expr Introduce a new predicate, shouldTypeCheckInEnclosingExpression(), to determine when the body of a closure should be checked as part of the enclosing expression rather than separately, and use it in the various places where "hasSingleExpressionBody()" was used for that purpose. --- lib/Sema/BuilderTransform.cpp | 7 +++++++ lib/Sema/CSApply.cpp | 6 +++--- lib/Sema/CSClosure.cpp | 7 +++++-- lib/Sema/CSGen.cpp | 3 ++- lib/Sema/CSSimplify.cpp | 9 ++++----- lib/Sema/ConstraintSystem.h | 6 ++++++ lib/Sema/TypeCheckAvailability.cpp | 3 ++- lib/Sema/TypeCheckConstraints.cpp | 9 ++++++--- 8 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index a8951fe026b28..b7ae0510c49c6 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -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 493a2cb631cb5..ec5fb98be762d 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -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; diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index 3096fbf0e273e..7aafe866c370b 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -336,10 +336,13 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution( } 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()); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1486e63f7f839..37a0048728cc0 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2248,7 +2248,8 @@ namespace { // as potential hole right away. resultTy = CS.createTypeVariable( resultLoc, - closure->hasSingleExpressionBody() ? 0 : TVO_CanBindToHole); + shouldTypeCheckInEnclosingExpression(closure) + ? 0 : TVO_CanBindToHole); } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index f3a146f9ba32a..7a01584e7a027 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7157,14 +7157,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 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/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 238025ad7947e..3cc7d89b10253 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -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()) { diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index dd0c1043dc64d..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 @@ -4058,3 +4057,7 @@ HasDynamicCallableAttributeRequest::evaluate(Evaluator &evaluator, return type->hasDynamicCallableAttribute(); }); } + +bool swift::shouldTypeCheckInEnclosingExpression(ClosureExpr *expr) { + return expr->hasSingleExpressionBody(); +} From ad42d477f75eafea4b8808b9f73e2353859321d9 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 3 Jun 2020 22:55:23 -0700 Subject: [PATCH 097/108] [AST] Remove some pointless uses of hasSingleExpressionBody(). --- lib/AST/ASTDumper.cpp | 6 +----- lib/AST/Expr.cpp | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) 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/Expr.cpp b/lib/AST/Expr.cpp index 70fc36bcb37ba..34d70a3ad815c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2365,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, From ffe471ada81d72a4bbb3a46b125e8de5d4ad074f Mon Sep 17 00:00:00 2001 From: eunjiChung <> Date: Thu, 4 Jun 2020 21:39:12 +0900 Subject: [PATCH 098/108] [stdlib] Add flatMap example in Result.swift --- stdlib/public/core/Result.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stdlib/public/core/Result.swift b/stdlib/public/core/Result.swift index 5c0db142e719e..d7276880dbb54 100644 --- a/stdlib/public/core/Result.swift +++ b/stdlib/public/core/Result.swift @@ -89,14 +89,18 @@ public enum Result { /// Returns a new result, mapping any success value using the given /// transformation and unwrapping the produced result. /// - /// Use this method when you need to transform the value of a `Result` - /// instance eventhough it produces a nested result type. + /// 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 { /* ... */ } - /// func getNextAfterInteger() -> Result { /* ... */ } + /// func getNextInteger() -> Result { + /// .success(4) + /// } + /// func getNextAfterInteger(_ n: Int) -> Result { + /// .success(n + 1) + /// } /// /// let result = getNextInteger().map({ getNextAfterInteger($0) }) /// // result == .success(.success(5)) From f2fb53967c7f9a622288db4eaadfc1a720d4c670 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Tue, 2 Jun 2020 11:22:32 -0400 Subject: [PATCH 099/108] [Runtime] Unify debug variable parsing from the environment and avoid getenv when possible. There are a few environment variables used to enable debugging options in the runtime, and we'll likely add more over time. These are implemented with scattered getenv() calls at the point of use. This is inefficient, as most/all OSes have to do a linear scan of the environment for each call. It's also not discoverable, since the only way to find these variables is to inspect the source. This commit places all of these variables in a central location. stdlib/public/runtime/EnvironmentVariables.def defines all of the debug variables including their name, type, default value, and a help string. On OSes which make an `environ` array available, the entire array is scanned in a single pass the first time any debug variable is requested. By quickly rejecting variables that do not start with `SWIFT_`, we optimize for the common case where no debug variables are set. We also have a fallback to repeated `getenv()` calls when a full scan is not possible. Setting `SWIFT_HELP=YES` will print out all available debug variables along with a brief description of what they do. --- include/swift/Runtime/EnvironmentVariables.h | 41 ++++ stdlib/public/runtime/CMakeLists.txt | 1 + .../public/runtime/EnvironmentVariables.cpp | 190 ++++++++++++++++++ .../public/runtime/EnvironmentVariables.def | 40 ++++ stdlib/public/runtime/Metadata.cpp | 37 ++-- stdlib/public/runtime/SwiftObject.mm | 18 +- stdlib/public/stubs/GlobalObjects.cpp | 4 +- test/Runtime/environment_variables.swift | 16 ++ 8 files changed, 311 insertions(+), 36 deletions(-) create mode 100644 include/swift/Runtime/EnvironmentVariables.h create mode 100644 stdlib/public/runtime/EnvironmentVariables.cpp create mode 100644 stdlib/public/runtime/EnvironmentVariables.def create mode 100644 test/Runtime/environment_variables.swift 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/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/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/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index fbafd97872c12..5d8cabca493c7 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" @@ -5505,21 +5506,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 +5656,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/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm index 34e87a9b1e99f..09cd6c312b3b2 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" @@ -1478,22 +1479,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/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/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 From f9128bac81090e74c44118de01ec574d0990330f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 25 Apr 2020 10:12:13 -0700 Subject: [PATCH 100/108] build: use the same pattern for detecting Darwin platforms The host platform should be using `CMAKE_SYSTEM_NAME STREQUAL Darwin`. However, we currently drive the host side of the compilation against custom variables. This makes the migration simpler by ensuring that the entire file uses the same pattern. Since `is_darwin_based_sdk` is now used only in the standard library build, sink it to the standard library build. --- cmake/modules/AddSwift.cmake | 21 +++------------------ stdlib/cmake/modules/AddSwiftStdlib.cmake | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 09c3afe831906..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. diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 05123d1d8e127..3adcdf3ddeda4 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 From 23bfee2078b9bffddb439558bc0e37df76150caf Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 4 Jun 2020 08:55:57 -0700 Subject: [PATCH 101/108] runtime: silence -Wunused-variable warning (NFC) `classMetadata` is only used in the ObjC path, resulting in a `-Wunused-variable` warning. Sink the variable into the ObjC path. Because the conversion of the metadata does not rely on the type metadata bits in the metadata, it is safe to delay the definition and bit adjustment to the point where it is used unifying the two ObjC paths. --- stdlib/public/runtime/Metadata.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 03c3975de837a..51dff44d4a530 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -113,15 +113,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) From 4e0fad869c440489053753d059c57a4ea9dd66e6 Mon Sep 17 00:00:00 2001 From: martinboehme Date: Thu, 4 Jun 2020 18:31:06 +0200 Subject: [PATCH 102/108] Add note that LLDB changes should be cherry-picked to `swift/master` (#32133) * Add note that LLDB changes should be cherry-picked to `swift/master` * New Swift-dependent commits should go to `swift/master`, not `swift/master-next`. * Update naming scheme for release branches * Fix indentation --- docs/Branches.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/Branches.md b/docs/Branches.md index d5c04ee77bb2d..083f89610419d 100644 --- a/docs/Branches.md +++ b/docs/Branches.md @@ -58,17 +58,20 @@ 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. + 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` (_not_ an `apple/stable/*` branch, as these shouldn't contain changes that depend on Swift). - 2) Changes that depend on Swift (this only applies to LLDB): new commits go to `swift/master-next` + - Then cherry-pick these commits to `swift/master-next`. - ...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.)* + - 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. From e5e34fa3c9aaadf305f8f86d064bf3700cc5221c Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Thu, 4 Jun 2020 19:10:04 +0200 Subject: [PATCH 103/108] Revert "Test C++ out-of-line operator functions (#32081)" (#32181) This reverts commit f7473a7432d2a31b4bd208354d065c6fa870781e. --- .../Cxx/operators/Inputs/module.modulemap | 4 ---- .../Inputs/non-member-out-of-line.cpp | 5 ---- .../operators/Inputs/non-member-out-of-line.h | 10 -------- .../non-member-out-of-line-irgen.swift | 8 ------- .../non-member-out-of-line-silgen.swift | 10 -------- .../operators/non-member-out-of-line.swift | 23 ------------------- 6 files changed, 60 deletions(-) delete mode 100644 test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp delete mode 100644 test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h delete mode 100644 test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift delete mode 100644 test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift delete mode 100644 test/Interop/Cxx/operators/non-member-out-of-line.swift diff --git a/test/Interop/Cxx/operators/Inputs/module.modulemap b/test/Interop/Cxx/operators/Inputs/module.modulemap index 2cc3fa14cd834..3fad5697d2a02 100644 --- a/test/Interop/Cxx/operators/Inputs/module.modulemap +++ b/test/Interop/Cxx/operators/Inputs/module.modulemap @@ -1,7 +1,3 @@ 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 deleted file mode 100644 index d6bccca7e7be0..0000000000000 --- a/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#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 deleted file mode 100644 index a0466d812d8c5..0000000000000 --- a/test/Interop/Cxx/operators/Inputs/non-member-out-of-line.h +++ /dev/null @@ -1,10 +0,0 @@ -#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 deleted file mode 100644 index c3b3ed123837c..0000000000000 --- a/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift +++ /dev/null @@ -1,8 +0,0 @@ -// 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 [[NAME:@(_Zpl6IntBoxS_|"\?\?H@YA\?AUIntBox@@U0@0@Z")]](i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) -// CHECK: declare {{(dso_local )?}}i32 [[NAME]](i32, i32) 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 deleted file mode 100644 index 302efa7cf8a1d..0000000000000 --- a/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift +++ /dev/null @@ -1,10 +0,0 @@ -// 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 deleted file mode 100644 index 55a4fc8506650..0000000000000 --- a/test/Interop/Cxx/operators/non-member-out-of-line.swift +++ /dev/null @@ -1,23 +0,0 @@ -// 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() From 158332c08886fdd0e7a7f0750d605f3f52cc1b8c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 4 Jun 2020 10:50:29 -0700 Subject: [PATCH 104/108] runtime: remove `llvm/DataTypes.h`, `llvm-c/DataTypes.h` Inline the standard headers that they included and remove the extra include path. --- include/swift/Remote/MetadataReader.h | 2 + stdlib/include/llvm-c/DataTypes.h | 84 ------------------- stdlib/include/llvm/ADT/Hashing.h | 2 +- stdlib/include/llvm/Support/Atomic.h | 2 +- stdlib/include/llvm/Support/DataTypes.h | 16 ---- .../llvm/Support/PointerLikeTypeTraits.h | 2 +- stdlib/public/runtime/Demangle.cpp | 1 + stdlib/public/runtime/Exclusivity.cpp | 1 + stdlib/public/runtime/SwiftObject.mm | 1 + 9 files changed, 8 insertions(+), 103 deletions(-) delete mode 100644 stdlib/include/llvm-c/DataTypes.h delete mode 100644 stdlib/include/llvm/Support/DataTypes.h 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/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/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/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/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm index 09cd6c312b3b2..af7489d33cb11 100644 --- a/stdlib/public/runtime/SwiftObject.mm +++ b/stdlib/public/runtime/SwiftObject.mm @@ -43,6 +43,7 @@ #if SWIFT_OBJC_INTEROP #include #endif +#include #include #include #include From bdfe1b1b08b117eb98626551a5fba72049e99813 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 4 Jun 2020 14:25:18 -0700 Subject: [PATCH 105/108] [Parse] Avoid delayed member parsing for type decl with missing brace Cache empty member list so that 'IterableDeclContext::loadAllMembers()' doesn't perform delayed member parsing. Fixes: rdar://problem/63921896 --- include/swift/Parse/Parser.h | 5 +- lib/Parse/ParseDecl.cpp | 66 ++++++++----------- .../complete_sequence_innertype.swift | 10 +++ 3 files changed, 39 insertions(+), 42 deletions(-) create mode 100644 test/SourceKit/CodeComplete/complete_sequence_innertype.swift 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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index cff3408235418..09010264d323f 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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( @@ -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(); @@ -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/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", From 67791cceac323d0ff58acb7eb27f2f4887e9bf61 Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Thu, 4 Jun 2020 14:40:05 -0700 Subject: [PATCH 106/108] [docs] Add a how-to guide on running IWYU on the Swift project. (#32151) --- docs/HowToGuides/RunningIncludeWhatYouUse.md | 286 +++++++++++++++++++ docs/README.md | 3 + 2 files changed, 289 insertions(+) create mode 100644 docs/HowToGuides/RunningIncludeWhatYouUse.md 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/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 From 09ea5fd1f7fd61ed2ce8be380f1efc3c120a5ba6 Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Thu, 4 Jun 2020 14:40:17 -0700 Subject: [PATCH 107/108] [docs] Add module build related definitions to Lexicon. (#32153) --- docs/Lexicon.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) 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 From 501e4cb6fe35305e611b5f2622b2c4852b4ffcf1 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 5 Jun 2020 11:50:00 +0100 Subject: [PATCH 108/108] runtime: fix SwapByteOrder.h when building for WASI --- stdlib/include/llvm/Support/SwapByteOrder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/include/llvm/Support/SwapByteOrder.h b/stdlib/include/llvm/Support/SwapByteOrder.h index 890cb4690596b..19c600a896471 100644 --- a/stdlib/include/llvm/Support/SwapByteOrder.h +++ b/stdlib/include/llvm/Support/SwapByteOrder.h @@ -21,7 +21,7 @@ #include #endif -#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) +#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || defined(__wasi__) #include #elif defined(_AIX) #include