From 3a2e9975d6617d7b39be97e4574319988d1323f3 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 9 Jan 2020 10:28:09 -0800 Subject: [PATCH 001/625] Adapt to upstream LLVM changes. --- include/swift/AST/Evaluator.h | 2 +- lib/AST/Expr.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 4b4e89a8e3c43..654fc49ca5e85 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -354,7 +354,7 @@ class Evaluator { // Check for a cycle. if (checkDependency(getCanonicalRequest(request))) { return llvm::Error( - llvm::make_unique>(request, *this)); + std::make_unique>(request, *this)); } // Make sure we remove this from the set of active requests once we're diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 72dde8c11666a..e3bc4d0a34512 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -807,15 +807,15 @@ APInt BuiltinIntegerWidth::parse(StringRef text, unsigned radix, bool negate, static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text, const llvm::fltSemantics &Semantics) { APFloat Val(Semantics); - APFloat::opStatus Res = + auto Res = Val.convertFromString(Text, llvm::APFloat::rmNearestTiesToEven); - assert(Res != APFloat::opInvalidOp && "Sema didn't reject invalid number"); - (void)Res; + assert(Res && "Sema didn't reject invalid number"); + consumeError(Res.takeError()); if (IsNegative) { auto NegVal = APFloat::getZero(Semantics, /*negative*/ true); Res = NegVal.subtract(Val, llvm::APFloat::rmNearestTiesToEven); - assert(Res != APFloat::opInvalidOp && "Sema didn't reject invalid number"); - (void)Res; + assert(Res && "Sema didn't reject invalid number"); + consumeError(Res.takeError()); return NegVal; } return Val; From f2310cff379ce86bedea308f199ef2b72d3a16ce Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Mon, 14 Oct 2019 16:55:29 -0700 Subject: [PATCH 002/625] [Statistic] Adjust for LLVM r374490 Use appropriate member functions instead of accessing Value directly. --- lib/Sema/CSSolver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index a6e70c84f934a..83d687125491b 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -410,11 +410,11 @@ ConstraintSystem::SolverState::~SolverState() { // Update the "largest" statistics if this system is larger than the // previous one. // FIXME: This is not at all thread-safe. - if (NumStatesExplored > LargestNumStatesExplored.Value) { - LargestSolutionAttemptNumber.Value = SolutionAttempt-1; + if (NumStatesExplored > LargestNumStatesExplored.getValue()) { + LargestSolutionAttemptNumber = SolutionAttempt-1; ++LargestSolutionAttemptNumber; #define CS_STATISTIC(Name, Description) \ - JOIN2(Largest,Name).Value = Name-1; \ + JOIN2(Largest,Name) = Name-1; \ ++JOIN2(Largest,Name); #include "ConstraintSolverStats.def" } From 10cd0fc1b7dac5d68ac11510081fc0cd44bffc54 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 10 Jan 2020 09:58:27 -0800 Subject: [PATCH 003/625] Adapt to upstream LLVM changes. (cherry picked from commit 06906ab6b9f17038d05ed6667761ddac6beade6b) --- lib/IRGen/IRGenDebugInfo.cpp | 3 ++- test/DebugInfo/basic.swift | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index efc41025a8d0b..59a3b75da9305 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -2311,7 +2311,8 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration( if (!Var) Expr = DBuilder.createConstantValueExpression(0); auto *GV = DBuilder.createGlobalVariableExpression( - MainModule, Name, LinkageName, File, L.Line, DITy, IsLocalToUnit, Expr); + MainModule, Name, LinkageName, File, L.Line, DITy, IsLocalToUnit, true, + Expr); if (Var) Var->addDebugInfo(GV); } diff --git a/test/DebugInfo/basic.swift b/test/DebugInfo/basic.swift index e8ab11b2f4236..9be8bc95e24d7 100644 --- a/test/DebugInfo/basic.swift +++ b/test/DebugInfo/basic.swift @@ -85,7 +85,7 @@ func foo(_ a: Int64, _ b: Int64) -> Int64 { // CHECK-DAG: ![[MAINMODULE]] = !DIModule({{.*}}, name: "basic" // DWARF Version -// DWARF-CHECK-DAG: i32 2, !"Dwarf Version", i32 4} +// DWARF-CHECK-DAG: i32 7, !"Dwarf Version", i32 4} // CV-CHECK-DAG: i32 2, !"CodeView", i32 1} // Debug Info Version From 612c53be8fca9c4a29172759808683db2f1594ad Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 14 Jan 2020 11:33:04 -0800 Subject: [PATCH 004/625] Update testcase for upstream LLVM changes. (cherry picked from commit 8ed230fb73bc63aa3cae54d9d6f1a4bacc829417) --- test/DebugInfo/ErrorVar.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/DebugInfo/ErrorVar.swift b/test/DebugInfo/ErrorVar.swift index b66f3d877cde5..ca921180dce4a 100644 --- a/test/DebugInfo/ErrorVar.swift +++ b/test/DebugInfo/ErrorVar.swift @@ -11,7 +11,10 @@ enum MyError : Error { // thrown error we create a shadow stack location holding the address of the // location that holds the pointer to the error instead. func simple(_ placeholder: Int64) throws -> () { - // CHECK: define {{.*}}void @"$s8ErrorVar6simpleyys5Int64VKF"(i64, %swift.refcounted* swiftself, %swift.error** noalias nocapture dereferenceable(4)) + // CHECK: define {{.*}}void @"$s8ErrorVar6simpleyys5Int64VKF"( + // CHECK-SAME: i64 + // CHECK-SAME: %swift.refcounted* {{.*}}swiftself + // CHECK-SAME: %swift.error** noalias nocapture dereferenceable(4) // CHECK: call void @llvm.dbg.declare // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[ERROR:[0-9]+]], metadata !DIExpression(DW_OP_deref)) // CHECK: ![[ERRTY:.*]] = !DICompositeType({{.*}}identifier: "$ss5Error_pD" From 18b03171c4a56027c549a4baaaefa973ad906f56 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 16 Jan 2020 10:14:35 +0100 Subject: [PATCH 005/625] Fix build after removal of PointerUnion3/4 Commit 2948ec5ca98f8593584f2117bc92fe8d75f6f098 removed the PointerUnion3 and PointerUnion4 aliases and migrated everything to the variadic template. Let's do the same here to get the build running. --- include/swift/AST/ClangNode.h | 4 ++-- include/swift/SIL/SILLocation.h | 2 +- lib/Sema/ConstraintSystem.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/ClangNode.h b/include/swift/AST/ClangNode.h index cbf120840b661..608ba9ada8af4 100644 --- a/include/swift/AST/ClangNode.h +++ b/include/swift/AST/ClangNode.h @@ -48,8 +48,8 @@ class ClangNode { template using Box = detail::ClangNodeBox; - llvm::PointerUnion4, Box, - Box, Box> Ptr; + llvm::PointerUnion, Box, + Box, Box> Ptr; public: ClangNode() = default; diff --git a/include/swift/SIL/SILLocation.h b/include/swift/SIL/SILLocation.h index 60bedd6f8ef31..92e68396b03f9 100644 --- a/include/swift/SIL/SILLocation.h +++ b/include/swift/SIL/SILLocation.h @@ -65,7 +65,7 @@ class SILLocation { using type = Pattern; }; - using ASTNodeTy = llvm::PointerUnion4; + using ASTNodeTy = llvm::PointerUnion; public: enum LocationKind : unsigned { diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 75d1aad3ca788..3a86a70558595 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -749,8 +749,8 @@ struct Score { /// An AST node that can gain type information while solving. using TypedNode = - llvm::PointerUnion3; + llvm::PointerUnion; /// Display a score. llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const Score &score); From 334ec53c178b90a61766847d54d2f39678ddb45c Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 16 Jan 2020 11:05:57 +0100 Subject: [PATCH 006/625] Fix Python 3.x error in Tuple.swift.gyb due concatenating "range + list" This was failing with the following error on my Python3 system: FAILED: stdlib/public/core/8/Tuple.swift cd /home/teemperor/work/swift/swift/stdlib/public/core && /usr/bin/cmake -E make_directory /home/teemperor/work/swift/build/Ninja-ReleaseAssert+stdlib-Release/swift-linux-x86_64/stdlib/public/core/8 && /usr/bin/python /home/teemperor/work/swift/swift/utils/gyb -DunicodeGraphemeBreakPropertyFile=/home/teemperor/work/swift/swift/utils/UnicodeData/GraphemeBreakProperty.txt -DunicodeGraphemeBreakTestFile=/home/teemperor/work/swift/swift/utils/UnicodeData/GraphemeBreakTest.txt -DCMAKE_SIZEOF_VOID_P=8 -o /home/teemperor/work/swift/build/Ninja-ReleaseAssert+stdlib-Release/swift-linux-x86_64/stdlib/public/core/8/Tuple.swift.tmp Tuple.swift.gyb && /usr/bin/cmake -E copy_if_different /home/teemperor/work/swift/build/Ninja-ReleaseAssert+stdlib-Release/swift-linux-x86_64/stdlib/public/core/8/Tuple.swift.tmp /home/teemperor/work/swift/build/Ninja-ReleaseAssert+stdlib-Release/swift-linux-x86_64/stdlib/public/core/8/Tuple.swift && /usr/bin/cmake -E remove /home/teemperor/work/swift/build/Ninja-ReleaseAssert+stdlib-Release/swift-linux-x86_64/stdlib/public/core/8/Tuple.swift.tmp Traceback (most recent call last): File "/home/teemperor/work/swift/swift/utils/gyb", line 3, in gyb.main() File "/home/teemperor/work/swift/swift/utils/gyb.py", line 1263, in main args.target.write(execute_template(ast, args.line_directive, **bindings)) File "/home/teemperor/work/swift/swift/utils/gyb.py", line 1131, in execute_template ast.execute(execution_context) File "/home/teemperor/work/swift/swift/utils/gyb.py", line 635, in execute x.execute(context) File "/home/teemperor/work/swift/swift/utils/gyb.py", line 721, in execute result = eval(self.code, context.local_bindings) File "/home/teemperor/work/swift/swift/stdlib/public/core/Tuple.swift.gyb", line 109, in % typeParams = [chr(ord("A") + i) for i in range(arity)] File "/home/teemperor/work/swift/swift/utils/gyb.py", line 635, in execute x.execute(context) File "/home/teemperor/work/swift/swift/utils/gyb.py", line 721, in execute result = eval(self.code, context.local_bindings) File "/home/teemperor/work/swift/swift/stdlib/public/core/Tuple.swift.gyb", line 114, in % greaterTuple = "(\"a\", {})".format(", ".join(map(str, range(1, arity - 1) + [arity]))) TypeError: unsupported operand type(s) for +: 'range' and 'list' This commit just converts the range to a list so we can concatenate this on Python 3.x (where the implicit conversion from range to list is no longer possible). --- stdlib/public/core/Tuple.swift.gyb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/Tuple.swift.gyb b/stdlib/public/core/Tuple.swift.gyb index 29548c92d0e17..63d7ee25f0c96 100644 --- a/stdlib/public/core/Tuple.swift.gyb +++ b/stdlib/public/core/Tuple.swift.gyb @@ -111,7 +111,7 @@ public func >=(lhs: (), rhs: ()) -> Bool { % equatableTypeParams = ", ".join(["{}: Equatable".format(c) for c in typeParams]) % originalTuple = "(\"a\", {})".format(", ".join(map(str, range(1, arity)))) -% greaterTuple = "(\"a\", {})".format(", ".join(map(str, range(1, arity - 1) + [arity]))) +% greaterTuple = "(\"a\", {})".format(", ".join(map(str, list(range(1, arity - 1)) + [arity]))) /// Returns a Boolean value indicating whether the corresponding components of /// two tuples are equal. From 1577506f3198af05281e23f1482548507d441fe7 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 10 Jan 2020 17:03:00 -0800 Subject: [PATCH 007/625] Reflection: Implement a TypeRef -> Demangle tree adapter. To allow more pervasive use of TypeRefs in LLDB, we need a way to build mangled names from TypeRef pointers to allow round-tripping between TypeRefs and AST types. The goal is to experiment with making lldb::CompilerType backed by TypeRefs instead of AST types. (cherry picked from commit ea2b5eced9824b570b55d3acfe812f87ee502f96) --- include/swift/Reflection/TypeRef.h | 3 + stdlib/public/Reflection/TypeRef.cpp | 289 ++++++++++++++++++ .../SwiftRemoteMirror/SwiftRemoteMirror.cpp | 12 + stdlib/public/runtime/Demangle.cpp | 5 +- validation-test/Reflection/existentials.swift | 44 +++ .../Reflection/existentials_objc.swift | 5 + 6 files changed, 356 insertions(+), 2 deletions(-) diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h index d0c3d3249557a..a6f161825c23b 100644 --- a/include/swift/Reflection/TypeRef.h +++ b/include/swift/Reflection/TypeRef.h @@ -150,6 +150,9 @@ class alignas(void *) TypeRef { void dump() const; void dump(FILE *file, unsigned Indent = 0) const; + /// Build a demangle tree from this TypeRef. + Demangle::NodePointer getDemangling(Demangle::Demangler &Dem) const; + bool isConcrete() const; bool isConcreteAfterSubstitutions(const GenericArgumentMap &Subs) const; diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp index 3503dd1e79e91..154f5837571b7 100644 --- a/stdlib/public/Reflection/TypeRef.cpp +++ b/stdlib/public/Reflection/TypeRef.cpp @@ -376,6 +376,295 @@ void TypeRef::dump(FILE *file, unsigned Indent) const { fprintf(file, "\n"); } +class DemanglingForTypeRef + : public TypeRefVisitor { + Demangle::Demangler &Dem; + +public: + DemanglingForTypeRef(Demangle::Demangler &Dem) : Dem(Dem) {} + + Demangle::NodePointer visitBuiltinTypeRef(const BuiltinTypeRef *B) { + return Dem.demangleType(B->getMangledName()); + } + + Demangle::NodePointer visitNominalTypeRef(const NominalTypeRef *N) { + if (auto parent = N->getParent()) + assert(false && "not implemented"); + return Dem.demangleType(N->getMangledName()); + } + + Demangle::NodePointer + visitBoundGenericTypeRef(const BoundGenericTypeRef *BG) { + Node::Kind nodeKind; + Node::Kind genericNodeKind; + if (BG->isStruct()) { + nodeKind = Node::Kind::Structure; + genericNodeKind = Node::Kind::BoundGenericStructure; + } else if (BG->isEnum()) { + nodeKind = Node::Kind::Enum; + genericNodeKind = Node::Kind::BoundGenericEnum; + } else if (BG->isClass()) { + nodeKind = Node::Kind::Class; + genericNodeKind = Node::Kind::BoundGenericClass; + } else { + nodeKind = Node::Kind::OtherNominalType; + genericNodeKind = Node::Kind::BoundGenericOtherNominalType; + } + auto unspecializedType = Dem.demangleType(BG->getMangledName()); + + auto genericArgsList = Dem.createNode(Node::Kind::TypeList); + for (auto param : BG->getGenericParams()) + genericArgsList->addChild(visit(param), Dem); + + auto genericNode = Dem.createNode(genericNodeKind); + genericNode->addChild(unspecializedType, Dem); + genericNode->addChild(genericArgsList, Dem); + + if (auto parent = BG->getParent()) + assert(false && "not implemented"); + + auto top = Dem.createNode(Node::Kind::Type); + top->addChild(genericNode, Dem); + return top; + } + + Demangle::NodePointer visitTupleTypeRef(const TupleTypeRef *T) { + auto tuple = Dem.createNode(Node::Kind::Tuple); + if (T->isVariadic()) { + auto tupleElt = Dem.createNode(Node::Kind::TupleElement); + tupleElt->addChild(Dem.createNode(Node::Kind::VariadicMarker), Dem); + tuple->addChild(tupleElt, Dem); + return tuple; + } + + for (auto element : T->getElements()) { + auto tupleElt = Dem.createNode(Node::Kind::TupleElement); + tupleElt->addChild(visit(element), Dem); + tuple->addChild(tupleElt, Dem); + } + return tuple; + } + + Demangle::NodePointer visitFunctionTypeRef(const FunctionTypeRef *F) { + Node::Kind kind; + switch (F->getFlags().getConvention()) { + case FunctionMetadataConvention::Swift: + kind = !F->getFlags().isEscaping() ? Node::Kind::NoEscapeFunctionType + : Node::Kind::FunctionType; + break; + case FunctionMetadataConvention::Block: + kind = Node::Kind::ObjCBlock; + break; + case FunctionMetadataConvention::Thin: + kind = Node::Kind::ThinFunctionType; + break; + case FunctionMetadataConvention::CFunctionPointer: + kind = Node::Kind::CFunctionPointer; + break; + } + + SmallVector, 8> inputs; + for (const auto ¶m : F->getParameters()) { + auto flags = param.getFlags(); + auto input = visit(param.getType()); + + auto wrapInput = [&](Node::Kind kind) { + auto parent = Dem.createNode(kind); + parent->addChild(input, Dem); + input = parent; + }; + switch (flags.getValueOwnership()) { + case ValueOwnership::Default: + /* nothing */ + break; + case ValueOwnership::InOut: + wrapInput(Node::Kind::InOut); + break; + case ValueOwnership::Shared: + wrapInput(Node::Kind::Shared); + break; + case ValueOwnership::Owned: + wrapInput(Node::Kind::Owned); + break; + } + + inputs.push_back({input, flags.isVariadic()}); + } + NodePointer totalInput = nullptr; + // FIXME: this is copy&paste from Demangle.cpp + switch (inputs.size()) { + case 1: { + auto singleParam = inputs.front(); + + // If the sole unlabeled parameter has a non-tuple type, encode + // the parameter list as a single type. + if (!singleParam.second) { + auto singleType = singleParam.first; + if (singleType->getKind() == Node::Kind::Type) + singleType = singleType->getFirstChild(); + if (singleType->getKind() != Node::Kind::Tuple) { + totalInput = singleParam.first; + break; + } + } + + // Otherwise it requires a tuple wrapper. + LLVM_FALLTHROUGH; + } + + // This covers both none and multiple parameters. + default: + auto tuple = Dem.createNode(Node::Kind::Tuple); + for (auto &input : inputs) { + NodePointer eltType; + bool isVariadic; + std::tie(eltType, isVariadic) = input; + + // Tuple element := variadic-marker label? type + auto tupleElt = Dem.createNode(Node::Kind::TupleElement); + + if (isVariadic) + tupleElt->addChild(Dem.createNode(Node::Kind::VariadicMarker), Dem); + + if (eltType->getKind() == Node::Kind::Type) { + tupleElt->addChild(eltType, Dem); + } else { + auto type = Dem.createNode(Node::Kind::Type); + type->addChild(eltType, Dem); + tupleElt->addChild(type, Dem); + } + + tuple->addChild(tupleElt, Dem); + } + totalInput = tuple; + break; + } + + NodePointer parameters = Dem.createNode(Node::Kind::ArgumentTuple); + NodePointer paramType = Dem.createNode(Node::Kind::Type); + + paramType->addChild(totalInput, Dem); + parameters->addChild(paramType, Dem); + + NodePointer resultTy = visit(F->getResult()); + NodePointer result = Dem.createNode(Node::Kind::ReturnType); + result->addChild(resultTy, Dem); + + auto funcNode = Dem.createNode(kind); + if (F->getFlags().throws()) + funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + funcNode->addChild(parameters, Dem); + funcNode->addChild(result, Dem); + return funcNode; + } + + Demangle::NodePointer + visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) { + auto type_list = Dem.createNode(Node::Kind::TypeList); + for (auto protocol : PC->getProtocols()) + type_list->addChild(visit(protocol), Dem); + + auto proto_list = Dem.createNode(Node::Kind::ProtocolList); + proto_list->addChild(type_list, Dem); + + auto node = proto_list; + if (auto superclass = PC->getSuperclass()) { + node = Dem.createNode(Node::Kind::ProtocolListWithClass); + node->addChild(proto_list, Dem); + node->addChild(visit(superclass), Dem); + } else if (PC->hasExplicitAnyObject()) { + node = Dem.createNode(Node::Kind::ProtocolListWithAnyObject); + node->addChild(proto_list, Dem); + } + auto typeNode = Dem.createNode(Node::Kind::Type); + typeNode->addChild(node, Dem); + return typeNode; + } + + Demangle::NodePointer visitMetatypeTypeRef(const MetatypeTypeRef *M) { + auto node = Dem.createNode(Node::Kind::Metatype); + assert(!M->wasAbstract() && "not implemented"); + node->addChild(visit(M->getInstanceType()), Dem); + auto typeNode = Dem.createNode(Node::Kind::Type); + typeNode->addChild(node, Dem); + return typeNode; + } + + Demangle::NodePointer + visitExistentialMetatypeTypeRef(const ExistentialMetatypeTypeRef *EM) { + auto node = Dem.createNode(Node::Kind::Metatype); + node->addChild(visit(EM->getInstanceType()), Dem); + return node; + } + + Demangle::NodePointer + visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) { + assert(false && "not tested"); + auto node = Dem.createNode(Node::Kind::DependentGenericParamType); + node->addChild(Dem.createNode(Node::Kind::Index, GTP->getDepth()), Dem); + node->addChild(Dem.createNode(Node::Kind::Index, GTP->getIndex()), Dem); + return node; + } + + Demangle::NodePointer + visitDependentMemberTypeRef(const DependentMemberTypeRef *DM) { + assert(false && "not tested"); + assert(DM->getProtocol().empty() && "not implemented"); + auto node = Dem.createNode(Node::Kind::DependentMemberType); + node->addChild(visit(DM->getBase()), Dem); + node->addChild(Dem.createNode(Node::Kind::Identifier, DM->getMember()), + Dem); + return node; + } + + Demangle::NodePointer visitForeignClassTypeRef(const ForeignClassTypeRef *F) { + assert(false && "not implemented"); + return nullptr; + } + + Demangle::NodePointer visitObjCClassTypeRef(const ObjCClassTypeRef *OC) { + auto module = Dem.createNode(Node::Kind::Module, MANGLING_MODULE_OBJC); + auto node = Dem.createNode(Node::Kind::Class); + node->addChild(module, Dem); + node->addChild(Dem.createNode(Node::Kind::Identifier, OC->getName()), Dem); + return node; + } + + Demangle::NodePointer + visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OC) { + auto module = Dem.createNode(Node::Kind::Module, MANGLING_MODULE_OBJC); + auto node = Dem.createNode(Node::Kind::Protocol); + node->addChild(module, Dem); + node->addChild(Dem.createNode(Node::Kind::Identifier, OC->getName()), Dem); + auto typeNode = Dem.createNode(Node::Kind::Type); + typeNode->addChild(node, Dem); + return typeNode; + } + +#define REF_STORAGE(Name, name, ...) \ + Demangle::NodePointer visit##Name##StorageTypeRef( \ + const Name##StorageTypeRef *US) { \ + auto node = Dem.createNode(Node::Kind::Name); \ + node->addChild(visit(US->getType()), Dem); \ + return node; \ + } +#include "swift/AST/ReferenceStorage.def" + + Demangle::NodePointer visitSILBoxTypeRef(const SILBoxTypeRef *SB) { + auto node = Dem.createNode(Node::Kind::SILBoxType); + node->addChild(visit(SB->getBoxedType()), Dem); + return node; + } + + Demangle::NodePointer visitOpaqueTypeRef(const OpaqueTypeRef *O) { + return Dem.createNode(Node::Kind::OpaqueType); + } +}; + +Demangle::NodePointer TypeRef::getDemangling(Demangle::Demangler &Dem) const { + return DemanglingForTypeRef(Dem).visit(this); +} + bool TypeRef::isConcrete() const { GenericArgumentMap Subs; return TypeRefIsConcrete(Subs).visit(this); diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index 9cfda37a6c4b9..c73d7194e101c 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -19,6 +19,7 @@ SWIFT_REMOTE_MIRROR_LINKAGE unsigned long long swift_reflection_classIsSwiftMask = 2; } +#include "swift/Demangling/Demangler.h" #include "swift/Reflection/ReflectionContext.h" #include "swift/Reflection/TypeLowering.h" #include "swift/Remote/CMemoryReader.h" @@ -431,6 +432,17 @@ void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef, fprintf(stdout, "\n"); } else { TI->dump(stdout); + Demangle::Demangler Dem; + std::string MangledName = mangleNode(TR->getDemangling(Dem)); + fprintf(stdout, "Mangled name: %s%s\n", MANGLING_PREFIX_STR, + MangledName.c_str()); +#ifndef NDEBUG + auto *Reconstructed = reinterpret_cast( + swift_reflection_typeRefForMangledTypeName( + ContextRef, MangledName.c_str(), MangledName.size())); + assert(mangleNode(TR->getDemangling(Dem)) == MangledName && + "round-trip diff"); +#endif } } diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index c71bc385613f5..f082e47e015aa 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -10,12 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "swift/Basic/Range.h" +#include "Private.h" #include "swift/ABI/TypeIdentity.h" +#include "swift/Basic/Range.h" +#include "swift/Reflection/TypeRef.h" #include "swift/Runtime/Metadata.h" #include "swift/Runtime/Portability.h" #include "swift/Strings.h" -#include "Private.h" #include diff --git a/validation-test/Reflection/existentials.swift b/validation-test/Reflection/existentials.swift index a1f131c38ab87..99af19706d9be 100644 --- a/validation-test/Reflection/existentials.swift +++ b/validation-test/Reflection/existentials.swift @@ -67,6 +67,7 @@ reflect(any: mc) // CHECK-64-NEXT: (struct Swift.Int)) // CHECK-64: Type info: // CHECK-64: (reference kind=strong refcounting=native) +// CHECK-64: Mangled name: $s12existentials7MyClassCyS2iG // CHECK-32: Reflecting an existential. // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} @@ -76,6 +77,7 @@ reflect(any: mc) // CHECK-32-NEXT: (struct Swift.Int)) // CHECK-32: Type info: // CHECK-32: (reference kind=strong refcounting=native) +// CHECK-32: Mangled name: $s12existentials7MyClassCyS2iG // This value fits in the 3-word buffer in the container. var smallStruct = MyStruct(x: 1, y: 2, z: 3) @@ -103,6 +105,7 @@ reflect(any: smallStruct) // CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-64-NEXT: (field name=_value offset=0 // CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))) +// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVyS3iG // CHECK-32: Reflecting an existential. // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} @@ -126,6 +129,7 @@ reflect(any: smallStruct) // CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-32-NEXT: (field name=_value offset=0 // CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))) +// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVyS3iG // This value will be copied into a heap buffer, with a // pointer to it in the existential. @@ -192,6 +196,7 @@ reflect(any: largeStruct) // CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-64-NEXT: (field name=_value offset=0 // CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))) +// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG // CHECK-32: Reflecting an existential. // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} @@ -253,6 +258,41 @@ reflect(any: largeStruct) // CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-32-NEXT: (field name=_value offset=0 // CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))) +// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG + +// Function type: +reflect(any: {largeStruct}) +// CHECK-64: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itGyc +// CHECK-32: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itGyc + +// Protocol composition: +protocol P {} +protocol Q {} +protocol Composition : P, Q {} +struct S : Composition {} +func getComposition() -> P & Q { return S() } +reflect(any: getComposition()) +// CHECK-64: Mangled name: $s12existentials1P_AA1Qp +// CHECK-32: Mangled name: $s12existentials1P_AA1Qp + +// Metatype: +reflect(any: Int.self) +// CHECK-64: Mangled name: $sSim +// CHECK-32: Mangled name: $sSim + +protocol WithType { + associatedtype T + func f() -> T +} +struct S1 : WithType { + typealias T = Int + func f() -> Int { return 0 } +} +func getWithType(_ t: T) where T: WithType { + reflect(any: T.self) +} +getWithType(S1()) + var he = HasError(singleError: MyError(), errorInComposition: MyError(), customError: MyCustomError(), customErrorInComposition: MyCustomError()) reflect(any: he) @@ -290,6 +330,7 @@ reflect(any: he) // CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1)) // CHECK-64-NEXT: (field name=wtable offset=40 // CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1))))) +// CHECK-64-NEXT: Mangled name: $s12existentials8HasErrorV // CHECK-32: Reflecting an existential. // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} @@ -324,6 +365,7 @@ reflect(any: he) // CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1)) // CHECK-32-NEXT: (field name=wtable offset=20 // CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1))))) +// CHECK-32-NEXT: Mangled name: $s12existentials8HasErrorV reflect(error: MyError()) @@ -338,6 +380,7 @@ reflect(error: MyError()) // CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-64-NEXT: (field name=_value offset=0 // CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))) +// CHECK-64-NEXT: Mangled name: $s12existentials7MyErrorV // CHECK-32: Reflecting an error existential. // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} @@ -350,5 +393,6 @@ reflect(error: MyError()) // CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1 // CHECK-32-NEXT: (field name=_value offset=0 // CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))) +// CHECK-32-NEXT: Mangled name: $s12existentials7MyErrorV doneReflecting() diff --git a/validation-test/Reflection/existentials_objc.swift b/validation-test/Reflection/existentials_objc.swift index 143c07ed2f1e0..b631fe61061c8 100644 --- a/validation-test/Reflection/existentials_objc.swift +++ b/validation-test/Reflection/existentials_objc.swift @@ -27,6 +27,11 @@ if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { // CHECK: Type reference: // CHECK: (objective_c_class name=__NSCFNumber) reflect(object: NSNumber(123)) + + // Objective-C protocol: + // CHECK: Type info: + // CHECK: $sSo9NSCopying_Xl + reflect(any: { () -> NSCopying in NSString("abc") }()) } else { // The Swift 5.0 libraries don't support this test. class SkipTheTest {} From 984247abfc6ff7b9e11cf11605e6262ec01de058 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 21 Jan 2020 20:22:44 -0800 Subject: [PATCH 008/625] [build-script] Disable LZMA for swift-lldb (cherry picked from commit 774dd07c0e811dbfea5423b8e83790fecce6b5ab) --- utils/build-script-impl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/build-script-impl b/utils/build-script-impl index 05da81a05c59e..8997f825aaf96 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1893,10 +1893,11 @@ for host in "${ALL_HOSTS[@]}"; do -DLLVM_DIR:PATH=${llvm_build_dir}/lib/cmake/llvm -DClang_DIR:PATH=${llvm_build_dir}/lib/cmake/clang -DSwift_DIR:PATH=${swift_build_dir}/lib/cmake/swift - -DLLDB_ENABLE_LUA=OFF - -DLLDB_ENABLE_PYTHON=ON - -DLLDB_ENABLE_LIBEDIT=ON -DLLDB_ENABLE_CURSES=ON + -DLLDB_ENABLE_LIBEDIT=ON + -DLLDB_ENABLE_PYTHON=ON + -DLLDB_ENABLE_LZMA=OFF + -DLLDB_ENABLE_LUA=OFF -DLLDB_PATH_TO_SWIFT_SOURCE:PATH="${SWIFT_SOURCE_DIR}" -DLLDB_IS_BUILDBOT_BUILD:BOOL="${LLDB_IS_BUILDBOT_BUILD}" -DLLDB_BUILD_DATE:STRING="\"${LLDB_BUILD_DATE}\"" From 5b5d2f600fde4a7b76c13ca203b68cc4619c1d8a Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Wed, 22 Jan 2020 14:34:19 -0800 Subject: [PATCH 009/625] Adjust to upstream changes Commit 7b30370e5bcf569fcdc15204d4c592163fd78cb3 from llvm-project changed DIBuilder::createModule. Adjust accordingly. --- lib/IRGen/IRGenDebugInfo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 1e047b2060f00..dc673907a0b86 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -661,8 +661,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; llvm::DIModule *M = - DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath, - Sysroot); + DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); return M; } From 06a829c72e102c827985ee9f2b653f55c5b63b8c Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 28 Jan 2020 19:32:52 -0800 Subject: [PATCH 010/625] IRGenDebugInfo: Pass Sysroot to DIBuilder::createModule (#29524) --- lib/IRGen/IRGenDebugInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 8fffd34ac6ef6..0fb4e53d302c8 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -660,8 +660,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; - llvm::DIModule *M = - DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); + llvm::DIModule *M = DBuilder.createModule(Parent, Name, ConfigMacros, + RemappedIncludePath, Sysroot); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); return M; } From d1e6438cbb6aa4c9359d02f58995b29e0779fee2 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Fri, 31 Jan 2020 13:08:04 -0800 Subject: [PATCH 011/625] Revert "IRGenDebugInfo: Pass Sysroot to DIBuilder::createModule (#29524)" (#29572) This reverts commit 06a829c72e102c827985ee9f2b653f55c5b63b8c. --- lib/IRGen/IRGenDebugInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 0fb4e53d302c8..8fffd34ac6ef6 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -660,8 +660,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; - llvm::DIModule *M = DBuilder.createModule(Parent, Name, ConfigMacros, - RemappedIncludePath, Sysroot); + llvm::DIModule *M = + DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); return M; } From 4a4a5fabb035844cfea18057e02809f4ebf4dd0b Mon Sep 17 00:00:00 2001 From: Fred Riss Date: Fri, 31 Jan 2020 15:31:25 -0800 Subject: [PATCH 012/625] Adapt the llvm.org DIBuilder API change. --- lib/IRGen/IRGenDebugInfo.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 8fffd34ac6ef6..743cbb7eae615 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -659,7 +659,6 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } } - StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; llvm::DIModule *M = DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); @@ -1691,13 +1690,18 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts, DBuilder.createFile(DebugPrefixMap.remapPath(SourcePath), DebugPrefixMap.remapPath(Opts.DebugCompilationDir)); + llvm::StringRef SysRoot = IGM.Context.SearchPathOpts.SDKPath; TheCU = DBuilder.createCompileUnit( Lang, MainFile, Producer, Opts.shouldOptimize(), Opts.getDebugFlags(PD), MajorRuntimeVersion, SplitName, Opts.DebugInfoLevel > IRGenDebugInfoLevel::LineTables ? llvm::DICompileUnit::FullDebug - : llvm::DICompileUnit::LineTablesOnly); + : llvm::DICompileUnit::LineTablesOnly, + /* DWOId */ 0, /* SplitDebugInlining */ true, + /* DebugInfoForProfiling */ false, + llvm::DICompileUnit::DebugNameTableKind::Default, + /* RangesBaseAddress */ false, SysRoot); // Because the swift compiler relies on Clang to setup the Module, // the clang CU is always created first. Several dwarf-reading From a3afd8b1554cc4956233c33dad2b4ce46bafb0e3 Mon Sep 17 00:00:00 2001 From: Fred Riss Date: Fri, 31 Jan 2020 15:31:50 -0800 Subject: [PATCH 013/625] Adapt to llvm.org StringRef API change --- include/swift/ABI/TypeIdentity.h | 20 ++++----- include/swift/AST/Identifier.h | 4 +- include/swift/Basic/LangOptions.h | 2 +- include/swift/Demangling/TypeDecoder.h | 6 +-- include/swift/Remote/MetadataReader.h | 2 +- include/swift/SIL/SILFunction.h | 2 +- lib/AST/ASTContext.cpp | 2 +- lib/AST/ASTPrinter.cpp | 4 +- lib/AST/DiagnosticEngine.cpp | 2 +- lib/AST/FineGrainedDependencies.cpp | 2 +- ...endenciesSourceFileDepGraphConstructor.cpp | 44 +++++++++---------- lib/AST/Module.cpp | 2 +- lib/AST/SwiftNameTranslation.cpp | 2 +- lib/AST/USRGeneration.cpp | 6 +-- lib/ASTSectionImporter/ASTSectionImporter.cpp | 2 +- lib/Basic/SourceLoc.cpp | 2 +- lib/ClangImporter/ClangImporter.cpp | 19 ++++---- lib/Demangling/NodePrinter.cpp | 5 ++- lib/Demangling/OldRemangler.cpp | 2 +- lib/Driver/CoarseGrainedDependencyGraph.cpp | 7 +-- lib/Driver/Driver.cpp | 42 ++++++++++-------- .../FineGrainedDependencyDriverGraph.cpp | 24 +++++----- lib/Driver/Job.cpp | 20 ++++----- lib/Driver/ParseableOutput.cpp | 8 ++-- lib/Driver/SourceComparator.cpp | 4 +- lib/Driver/ToolChains.cpp | 8 ++-- .../ArgsToFrontendOptionsConverter.cpp | 4 +- .../ArgsToFrontendOutputsConverter.cpp | 12 ++--- lib/Frontend/CompilerInvocation.cpp | 41 +++++++++-------- lib/Frontend/DiagnosticVerifier.cpp | 2 +- lib/Frontend/Frontend.cpp | 2 +- lib/Frontend/ModuleInterfaceBuilder.cpp | 6 +-- lib/Frontend/ModuleInterfaceLoader.cpp | 13 +++--- lib/FrontendTool/FrontendTool.cpp | 39 ++++++++-------- lib/IDE/APIDigesterData.cpp | 4 +- lib/IDE/CodeCompletion.cpp | 22 +++++----- lib/IDE/CodeCompletionCache.cpp | 6 +-- lib/IDE/Formatting.cpp | 7 +-- lib/IDE/ModuleInterfacePrinting.cpp | 2 +- lib/IDE/REPLCodeCompletion.cpp | 4 +- lib/IDE/Refactoring.cpp | 9 ++-- lib/IDE/Utils.cpp | 10 ++--- lib/IRGen/GenMeta.cpp | 8 ++-- lib/IRGen/GenObjC.cpp | 2 +- lib/IRGen/GenReflection.cpp | 2 +- lib/IRGen/Linking.cpp | 2 +- lib/IRGen/MetadataRequest.cpp | 2 +- lib/Index/IndexRecord.cpp | 19 ++++---- lib/LLVMPasses/LLVMInlineTree.cpp | 11 ++--- lib/Migrator/APIDiffMigratorPass.cpp | 13 +++--- lib/Migrator/EditorAdapter.cpp | 2 +- lib/Migrator/FixitApplyDiagnosticConsumer.cpp | 2 +- lib/Migrator/MigrationState.cpp | 4 +- lib/Migrator/Migrator.cpp | 5 ++- lib/ParseSIL/ParseSIL.cpp | 2 +- lib/RemoteAST/RemoteAST.cpp | 6 +-- lib/SIL/SILConstants.cpp | 2 +- lib/SIL/SILCoverageMap.cpp | 2 +- lib/SIL/SILDeclRef.cpp | 6 +-- lib/SILGen/SILGenApply.cpp | 2 +- lib/SILGen/SILGenGlobalVariable.cpp | 2 +- .../LoopTransforms/ArrayPropertyOpt.cpp | 2 +- .../Mandatory/DIMemoryUseCollector.cpp | 2 +- .../Mandatory/DefiniteInitialization.cpp | 2 +- lib/SILOptimizer/PassManager/PassManager.cpp | 4 +- lib/Sema/CSDiagnostics.cpp | 4 +- lib/Sema/CalleeCandidateInfo.cpp | 10 ++--- lib/Sema/InstrumenterSupport.cpp | 3 +- lib/Sema/TypeCheckType.cpp | 2 +- lib/Serialization/SerializeDoc.cpp | 4 +- lib/Serialization/SerializedModuleLoader.cpp | 2 +- lib/TBDGen/TBDGen.cpp | 2 +- stdlib/public/Reflection/TypeRefBuilder.cpp | 23 +++++----- .../include/SourceKit/Support/Logging.h | 2 +- .../SourceKit/lib/Core/NotificationCenter.cpp | 4 +- .../lib/Support/ImmutableTextBuffer.cpp | 2 +- tools/SourceKit/lib/Support/UIDRegistry.cpp | 3 +- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 8 ++-- .../lib/SwiftLang/SwiftASTManager.cpp | 12 ++--- .../lib/SwiftLang/SwiftCompletion.cpp | 2 +- .../lib/SwiftLang/SwiftDocSupport.cpp | 10 ++--- tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp | 6 +-- .../lib/SwiftLang/SwiftEditorInterfaceGen.cpp | 20 ++++----- .../SourceKit/lib/SwiftLang/SwiftIndexing.cpp | 2 +- .../lib/SwiftLang/SwiftLangSupport.cpp | 6 +-- .../lib/SwiftLang/SwiftSourceDocInfo.cpp | 6 +-- .../tools/complete-test/complete-test.cpp | 6 +-- .../tools/sourcekitd-test/sourcekitd-test.cpp | 26 +++++------ .../bin/InProc/sourcekitdInProc.cpp | 2 +- .../sourcekitd/bin/XPC/Service/XPCService.cpp | 2 +- .../sourcekitd/lib/API/DocStructureArray.cpp | 8 ++-- .../tools/sourcekitd/lib/API/Requests.cpp | 16 +++---- .../lib/API/sourcekitdAPI-Common.cpp | 2 +- tools/driver/autolink_extract_main.cpp | 5 ++- tools/driver/modulewrap_main.cpp | 5 ++- tools/driver/swift_indent_main.cpp | 5 ++- .../lldb-moduleimport-test.cpp | 2 +- .../SILFunctionExtractor.cpp | 6 +-- .../ModuleAnalyzerNodes.cpp | 2 +- tools/swift-demangle/swift-demangle.cpp | 4 +- tools/swift-ide-test/XMLValidator.cpp | 2 +- tools/swift-refactor/swift-refactor.cpp | 2 +- 102 files changed, 389 insertions(+), 369 deletions(-) diff --git a/include/swift/ABI/TypeIdentity.h b/include/swift/ABI/TypeIdentity.h index 129417b3f36b6..a25b8be2d7ab8 100644 --- a/include/swift/ABI/TypeIdentity.h +++ b/include/swift/ABI/TypeIdentity.h @@ -129,16 +129,16 @@ class TypeImportInfo { value = value.drop_front(1); switch (component) { -#define case_setIfNonEmpty(FIELD) \ - case TypeImportComponent::FIELD: \ - check(!value.empty(), "incoming value of " #FIELD " was empty"); \ - check(FIELD.empty(), #FIELD " was already set"); \ - FIELD = value; \ - return true; \ - - case_setIfNonEmpty(ABIName) - case_setIfNonEmpty(SymbolNamespace) - case_setIfNonEmpty(RelatedEntityName) +#define case_setIfNonEmpty(FIELD) \ + case TypeImportComponent::FIELD: \ + check(!value.empty(), "incoming value of " #FIELD " was empty"); \ + check(FIELD.empty(), #FIELD " was already set"); \ + FIELD = StringType(value); \ + return true; + + case_setIfNonEmpty(ABIName) + case_setIfNonEmpty(SymbolNamespace) + case_setIfNonEmpty(RelatedEntityName) #undef case_setIfNonEmpty #undef check diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h index 05b595d3953eb..e6d1ed4d398ac 100644 --- a/include/swift/AST/Identifier.h +++ b/include/swift/AST/Identifier.h @@ -83,7 +83,9 @@ class Identifier { const char *get() const { return Pointer; } StringRef str() const { return Pointer; } - + + explicit operator std::string() const { return std::string(Pointer); } + unsigned getLength() const { assert(Pointer != nullptr && "Tried getting length of empty identifier"); return ::strlen(Pointer); diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index c125f046281c9..e550ec114d209 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -363,7 +363,7 @@ namespace swift { /// compiler flag. void addCustomConditionalCompilationFlag(StringRef Name) { assert(!Name.empty()); - CustomConditionalCompilationFlags.push_back(Name); + CustomConditionalCompilationFlags.push_back(Name.str()); } /// Determines if a given conditional compilation flag has been set. diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index 3d1af5b91f369..79450a6c9c591 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -384,7 +384,7 @@ class TypeDecoder { } case NodeKind::BuiltinTypeName: { auto mangledName = Demangle::mangleNode(Node); - return Builder.createBuiltinType(Node->getText(), mangledName); + return Builder.createBuiltinType(Node->getText().str(), mangledName); } case NodeKind::Metatype: case NodeKind::ExistentialMetatype: { @@ -683,12 +683,12 @@ class TypeDecoder { auto assocTypeChild = Node->getChild(1); auto member = assocTypeChild->getFirstChild()->getText(); if (assocTypeChild->getNumChildren() < 2) - return Builder.createDependentMemberType(member, base); + return Builder.createDependentMemberType(member.str(), base); auto protocol = decodeMangledProtocolType(assocTypeChild->getChild(1)); if (!protocol) return BuiltType(); - return Builder.createDependentMemberType(member, base, protocol); + return Builder.createDependentMemberType(member.str(), base, protocol); } case NodeKind::DependentAssociatedTypeRef: { if (Node->getNumChildren() < 2) diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index c117a4d15aba5..6fd8a575398e1 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -799,7 +799,7 @@ class MetadataReader { #if SWIFT_OBJC_INTEROP BuiltProtocolDecl objcProtocol(StringRef name) { - return builder.createObjCProtocolDecl(name); + return builder.createObjCProtocolDecl(name.str()); } #endif } resolver{Builder}; diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 12087cac3151b..3cad495b25887 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -678,7 +678,7 @@ class SILFunction void addSemanticsAttr(StringRef Ref) { if (hasSemanticsAttr(Ref)) return; - SemanticsAttrSet.push_back(Ref); + SemanticsAttrSet.push_back(Ref.str()); std::sort(SemanticsAttrSet.begin(), SemanticsAttrSet.end()); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 822901ed7a57f..49f58c521e0af 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1434,7 +1434,7 @@ void ASTContext::addSearchPath(StringRef searchPath, bool isFramework, if (isFramework) SearchPathOpts.FrameworkSearchPaths.push_back({searchPath, isSystem}); else - SearchPathOpts.ImportSearchPaths.push_back(searchPath); + SearchPathOpts.ImportSearchPaths.push_back(searchPath.str()); if (auto *clangLoader = getClangModuleLoader()) clangLoader->addSearchPath(searchPath, isFramework, isSystem); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index eeabdf4de8a65..ae3739661aaa8 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -265,7 +265,7 @@ std::string ASTPrinter::sanitizeUtf8(StringRef Text) { } Data += Step; } - return Builder.str(); + return std::string(Builder); } void ASTPrinter::anchor() {} @@ -4491,7 +4491,7 @@ AnyFunctionType::getParamListAsString(ArrayRef Params, SmallString<16> Scratch; llvm::raw_svector_ostream OS(Scratch); AnyFunctionType::printParams(Params, OS); - return OS.str(); + return std::string(OS.str()); } void LayoutConstraintInfo::print(raw_ostream &OS, diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 56aa08790966a..6825407c765e2 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -989,7 +989,7 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) { while (associatedNotes && *associatedNotes) { SmallString<128> notePath(getDiagnosticDocumentationPath()); llvm::sys::path::append(notePath, *associatedNotes); - educationalNotePaths.push_back(notePath.str()); + educationalNotePaths.push_back(notePath.str().str()); associatedNotes++; } info->EducationalNotePaths = educationalNotePaths; diff --git a/lib/AST/FineGrainedDependencies.cpp b/lib/AST/FineGrainedDependencies.cpp index 69256f1cffc93..b7425b3cad153 100644 --- a/lib/AST/FineGrainedDependencies.cpp +++ b/lib/AST/FineGrainedDependencies.cpp @@ -201,7 +201,7 @@ std::string DependencyKey::humanReadableName() const { return demangleTypeAsContext(context) + "." + name; case NodeKind::externalDepend: case NodeKind::sourceFileProvide: - return llvm::sys::path::filename(name); + return llvm::sys::path::filename(name).str(); case NodeKind::potentialMember: return demangleTypeAsContext(context) + ".*"; case NodeKind::nominal: diff --git a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp index eba5fe33192bb..68ac9c293a2e7 100644 --- a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp +++ b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp @@ -77,11 +77,11 @@ SourceFileDepGraph::loadFromBuffer(llvm::MemoryBuffer &buffer) { //============================================================================== template static std::string getBaseName(const DeclT *decl) { - return decl->getBaseName().userFacingName(); + return decl->getBaseName().userFacingName().str(); } template static std::string getName(const DeclT *decl) { - return DeclBaseName(decl->getName()).userFacingName(); + return DeclBaseName(decl->getName()).userFacingName().str(); } static std::string mangleTypeAsContext(const NominalTypeDecl *NTD) { @@ -376,7 +376,7 @@ std::string DependencyKey::computeNameForProvidedEntity(StringRef swiftDeps) { assert(!swiftDeps.empty()); - return swiftDeps; + return swiftDeps.str(); } template <> @@ -438,28 +438,29 @@ std::string DependencyKey::computeNameForProvidedEntity< template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { - return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", name); + return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", + name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { return DependencyKey(NodeKind::dynamicLookup, DeclAspect::interface, "", - name); + name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { return DependencyKey(NodeKind::externalDepend, DeclAspect::interface, "", - name); + name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef mangledName) { - return DependencyKey(NodeKind::nominal, DeclAspect::interface, mangledName, - ""); + return DependencyKey(NodeKind::nominal, DeclAspect::interface, + mangledName.str(), ""); } DependencyKey DependencyKey::createDependedUponKey(StringRef mangledHolderName, @@ -467,8 +468,8 @@ DependencyKey DependencyKey::createDependedUponKey(StringRef mangledHolderName, const bool isMemberBlank = memberBaseName.empty(); const auto kind = isMemberBlank ? NodeKind::potentialMember : NodeKind::member; - return DependencyKey(kind, DeclAspect::interface, mangledHolderName, - isMemberBlank ? "" : memberBaseName); + return DependencyKey(kind, DeclAspect::interface, mangledHolderName.str(), + isMemberBlank ? "" : memberBaseName.str()); } //============================================================================== @@ -578,11 +579,11 @@ class SourceFileDepGraphConstructor { SourceFileDeclFinder declFinder(SF, includePrivateDeps); std::vector> topLevelDepends; for (const auto &p: SF->getReferencedNameTracker()->getTopLevelNames()) - topLevelDepends.push_back(std::make_pair(p.getFirst().userFacingName(), p.getSecond())); + topLevelDepends.push_back(std::make_pair(p.getFirst().userFacingName().str(), p.getSecond())); std::vector> dynamicLookupDepends; for (const auto &p: SF->getReferencedNameTracker()->getDynamicLookupNames()) - dynamicLookupDepends.push_back(std::make_pair(p.getFirst().userFacingName(), p.getSecond())); + dynamicLookupDepends.push_back(std::make_pair(p.getFirst().userFacingName().str(), p.getSecond())); std::vector, bool>> memberDepends; for (const auto &p: SF->getReferencedNameTracker()->getUsedMembers()) { @@ -592,7 +593,7 @@ class SourceFileDepGraphConstructor { std::make_pair( std::make_tuple( mangleTypeAsContext(p.getFirst().first), - emptyOrUserFacingName, + emptyOrUserFacingName.str(), declIsPrivate(p.getFirst().first)), p.getSecond())); } @@ -906,7 +907,7 @@ static std::vector> getSimpleDepends(ArrayRef simpleNames) { std::vector> result; for (std::string n : simpleNames) - result.push_back({stripPrefix(n), cascades((n))}); + result.push_back({stripPrefix(n).str(), cascades((n))}); return result; } @@ -924,19 +925,18 @@ getCompoundDepends( for (std::string n : simpleNames) { // (On Linux, the compiler needs more verbosity than: // result.push_back({{n, "", false}, cascades(n)}); - result.push_back( - std::make_pair(std::make_tuple(stripPrefix(n), std::string(), false), - cascades(n))); + result.push_back(std::make_pair( + std::make_tuple(stripPrefix(n).str(), std::string(), false), + cascades(n))); } for (auto &p : compoundNames) { // Likewise, for Linux expand the following out: // result.push_back( // {{p.first, p.second, isPrivate(p.second)}, cascades(p.first)}); - result.push_back( - std::make_pair(std::make_tuple(stripPrefix(p.first), - stripPrefix(p.second), - isPrivate(p.second)), - cascades(p.first))); + result.push_back(std::make_pair(std::make_tuple(stripPrefix(p.first).str(), + stripPrefix(p.second).str(), + isPrivate(p.second)), + cascades(p.first))); } return result; } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index b08b2de0ab806..201d3f9f32630 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1914,7 +1914,7 @@ StringRef ModuleEntity::getName() const { std::string ModuleEntity::getFullName() const { assert(!Mod.isNull()); if (auto SwiftMod = Mod.dyn_cast()) - return SwiftMod->getName().str(); + return std::string(SwiftMod->getName()); return getClangModule(Mod)->getFullModuleName(); } diff --git a/lib/AST/SwiftNameTranslation.cpp b/lib/AST/SwiftNameTranslation.cpp index dc4db68081d12..53109c7192277 100644 --- a/lib/AST/SwiftNameTranslation.cpp +++ b/lib/AST/SwiftNameTranslation.cpp @@ -71,7 +71,7 @@ getErrorDomainStringForObjC(const EnumDecl *ED) { outerTypes.push_back(D); } - std::string buffer = ED->getParentModule()->getNameStr(); + std::string buffer = ED->getParentModule()->getNameStr().str(); for (auto D : llvm::reverse(outerTypes)) { buffer += "."; buffer += D->getNameStr(); diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 7f30e930391cb..9148ba8ecbf54 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -214,7 +214,7 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, if (auto ClangD = ClangN.getAsDecl()) { bool Ignore = clang::index::generateUSRForDecl(ClangD, Buffer); if (!Ignore) { - return Buffer.str(); + return std::string(Buffer); } else { return std::string(); } @@ -228,7 +228,7 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, ClangMacroInfo->getDefinitionLoc(), Importer.getClangASTContext().getSourceManager(), Buffer); if (!Ignore) - return Buffer.str(); + return std::string(Buffer); else return std::string(); } @@ -237,7 +237,7 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, if (printObjCUSR(D, OS)) { return std::string(); } else { - return OS.str(); + return std::string(OS.str()); } } diff --git a/lib/ASTSectionImporter/ASTSectionImporter.cpp b/lib/ASTSectionImporter/ASTSectionImporter.cpp index d3797d3020b23..0b0b4b6701eeb 100644 --- a/lib/ASTSectionImporter/ASTSectionImporter.cpp +++ b/lib/ASTSectionImporter/ASTSectionImporter.cpp @@ -47,7 +47,7 @@ bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader, // Register the memory buffer. Loader.registerMemoryBuffer(info.name, std::move(bitstream)); - foundModules.push_back(info.name); + foundModules.push_back(info.name.str()); } } else { llvm::dbgs() << "Unable to load module"; diff --git a/lib/Basic/SourceLoc.cpp b/lib/Basic/SourceLoc.cpp index 76547ff2e91f6..819fd17c260fb 100644 --- a/lib/Basic/SourceLoc.cpp +++ b/lib/Basic/SourceLoc.cpp @@ -105,7 +105,7 @@ bool SourceManager::openVirtualFile(SourceLoc loc, StringRef name, } CharSourceRange range = CharSourceRange(*this, loc, end); - VirtualFiles[end.Value.getPointer()] = { range, name, lineOffset }; + VirtualFiles[end.Value.getPointer()] = {range, name.str(), lineOffset}; CachedVFile = {nullptr, nullptr}; return true; } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index f1c7656773a66..83ca32ac82ff1 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -481,9 +481,8 @@ getNormalInvocationArguments(std::vector &invocationArgStrs, if (!llvm::sys::fs::exists(shimsPath)) { shimsPath = searchPathOpts.SDKPath; llvm::sys::path::append(shimsPath, "usr", "lib", "swift", "shims"); - invocationArgStrs.insert(invocationArgStrs.end(), { - "-isystem", shimsPath.str() - }); + invocationArgStrs.insert(invocationArgStrs.end(), + {"-isystem", std::string(shimsPath)}); } // Construct the invocation arguments for the current target. @@ -638,7 +637,7 @@ getNormalInvocationArguments(std::vector &invocationArgStrs, llvm::sys::path::native(path); invocationArgStrs.push_back("-isystem"); - invocationArgStrs.push_back(path.str()); + invocationArgStrs.push_back(std::string(path)); } else { // On Darwin, Clang uses -isysroot to specify the include // system root. On other targets, it seems to use --sysroot. @@ -747,7 +746,7 @@ addCommonInvocationArguments(std::vector &invocationArgStrs, // Set the Clang resource directory to the path we computed. invocationArgStrs.push_back("-resource-dir"); - invocationArgStrs.push_back(resourceDir.str()); + invocationArgStrs.push_back(std::string(resourceDir)); } else { invocationArgStrs.push_back("-resource-dir"); invocationArgStrs.push_back(overrideResourceDir); @@ -1532,7 +1531,7 @@ ClangImporter::emitBridgingPCH(StringRef headerPath, auto &FrontendOpts = invocation.getFrontendOpts(); FrontendOpts.Inputs = {inputFile}; - FrontendOpts.OutputFile = outputPCHPath; + FrontendOpts.OutputFile = outputPCHPath.str(); FrontendOpts.ProgramAction = clang::frontend::GeneratePCH; auto action = wrapActionForIndexingIfEnabled( @@ -1556,7 +1555,7 @@ bool ClangImporter::emitPrecompiledModule(StringRef moduleMapPath, auto LangOpts = invocation.getLangOpts(); LangOpts->setCompilingModule(clang::LangOptions::CMK_ModuleMap); - LangOpts->ModuleName = moduleName; + LangOpts->ModuleName = moduleName.str(); LangOpts->CurrentModule = LangOpts->ModuleName; auto language = getLanguageFromOptions(LangOpts); @@ -1566,8 +1565,8 @@ bool ClangImporter::emitPrecompiledModule(StringRef moduleMapPath, auto &FrontendOpts = invocation.getFrontendOpts(); FrontendOpts.Inputs = {inputFile}; - FrontendOpts.OriginalModuleMap = moduleMapPath; - FrontendOpts.OutputFile = outputPath; + FrontendOpts.OriginalModuleMap = moduleMapPath.str(); + FrontendOpts.OutputFile = outputPath.str(); FrontendOpts.ProgramAction = clang::frontend::GenerateModule; auto action = wrapActionForIndexingIfEnabled( @@ -1595,7 +1594,7 @@ bool ClangImporter::dumpPrecompiledModule(StringRef modulePath, auto &FrontendOpts = invocation.getFrontendOpts(); FrontendOpts.Inputs = {inputFile}; - FrontendOpts.OutputFile = outputPath; + FrontendOpts.OutputFile = outputPath.str(); auto action = std::make_unique(); dumpInstance->ExecuteAction(*action); diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 94a5247a7063c..67f34a6214292 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -691,7 +691,7 @@ class NodePrinter { auto Label = LabelList->getChild(Index); assert(Label && (Label->getKind() == Node::Kind::Identifier || Label->getKind() == Node::Kind::FirstElementMarker)); - return Label->getKind() == Node::Kind::Identifier ? Label->getText() + return Label->getKind() == Node::Kind::Identifier ? Label->getText().str() : "_"; }; @@ -1121,7 +1121,8 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { return nullptr; case Node::Kind::Suffix: if (Options.DisplayUnmangledSuffix) { - Printer << " with unmangled suffix " << QuotedString(Node->getText()); + Printer << " with unmangled suffix " + << QuotedString(Node->getText().str()); } return nullptr; case Node::Kind::Initializer: diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index 26ed34e4b6abd..2e5dce48aee67 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -48,7 +48,7 @@ namespace { } void setAnonymousContextDiscriminator(StringRef discriminator) { - AnonymousContextDiscriminator = discriminator; + AnonymousContextDiscriminator = discriminator.str(); } std::string takeAnonymousContextDiscriminator() { diff --git a/lib/Driver/CoarseGrainedDependencyGraph.cpp b/lib/Driver/CoarseGrainedDependencyGraph.cpp index 476006f922213..617d0c77ffe7b 100644 --- a/lib/Driver/CoarseGrainedDependencyGraph.cpp +++ b/lib/Driver/CoarseGrainedDependencyGraph.cpp @@ -268,7 +268,7 @@ CoarseGrainedDependencyGraphImpl::loadFromBuffer(const void *node, }); if (iter == provides.end()) - provides.push_back({name, kind}); + provides.push_back({name.str(), kind}); else iter->kindMask |= kind; @@ -276,7 +276,8 @@ CoarseGrainedDependencyGraphImpl::loadFromBuffer(const void *node, }; auto interfaceHashCallback = [this, node](StringRef hash) -> LoadResult { - auto insertResult = InterfaceHashes.insert(std::make_pair(node, hash)); + auto insertResult = + InterfaceHashes.insert(std::make_pair(node, hash.str())); if (insertResult.second) { // Treat a newly-added hash as up-to-date. This includes the initial @@ -286,7 +287,7 @@ CoarseGrainedDependencyGraphImpl::loadFromBuffer(const void *node, auto iter = insertResult.first; if (hash != iter->second) { - iter->second = hash; + iter->second = hash.str(); return LoadResult::AffectsDownstream; } diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 0432e58a6d4d4..2d81975ca0182 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1626,7 +1626,7 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, // REPL mode should always use the REPL module. OI.ModuleName = "REPL"; } else if (const Arg *A = Args.getLastArg(options::OPT_o)) { - OI.ModuleName = llvm::sys::path::stem(A->getValue()); + OI.ModuleName = llvm::sys::path::stem(A->getValue()).str(); if ((OI.LinkAction == LinkKind::DynamicLibrary || OI.LinkAction == LinkKind::StaticLibrary) && !llvm::sys::path::extension(A->getValue()).empty() && @@ -1635,7 +1635,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, OI.ModuleName.erase(0, strlen("lib")); } } else if (Inputs.size() == 1) { - OI.ModuleName = llvm::sys::path::stem(Inputs.front().second->getValue()); + OI.ModuleName = + llvm::sys::path::stem(Inputs.front().second->getValue()).str(); } if (!Lexer::isIdentifier(OI.ModuleName) || @@ -2160,10 +2161,10 @@ bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) { if (const Arg *A = Args.getLastArg(options::OPT_driver_use_frontend_path)) { DriverExecutable = A->getValue(); std::string commandString = - Args.getLastArgValue(options::OPT_driver_use_frontend_path); + Args.getLastArgValue(options::OPT_driver_use_frontend_path).str(); SmallVector commandArgs; StringRef(commandString).split(commandArgs, ';', -1, false); - DriverExecutable = commandArgs[0]; + DriverExecutable = commandArgs[0].str(); DriverExecutableArgs.assign(std::begin(commandArgs) + 1, std::end(commandArgs)); } @@ -2795,26 +2796,29 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA, [] { llvm::outs() << ", "; }); if (!InputActions.empty() && !J->getInputs().empty()) llvm::outs() << ", "; - interleave(J->getInputs().begin(), J->getInputs().end(), - [](const Job *Input) { - auto FileNames = Input->getOutput().getPrimaryOutputFilenames(); - interleave(FileNames.begin(), FileNames.end(), - [](const std::string &FileName) { - llvm::outs() << '"' << FileName << '"'; - }, - [] { llvm::outs() << ", "; }); - }, - [] { llvm::outs() << ", "; }); + interleave( + J->getInputs().begin(), J->getInputs().end(), + [](const Job *Input) { + auto FileNames = Input->getOutput().getPrimaryOutputFilenames(); + interleave( + FileNames.begin(), FileNames.end(), + [](StringRef FileName) { + llvm::outs() << '"' << FileName << '"'; + }, + [] { llvm::outs() << ", "; }); + }, + [] { llvm::outs() << ", "; }); llvm::outs() << "], output: {"; auto OutputFileNames = J->getOutput().getPrimaryOutputFilenames(); StringRef TypeName = file_types::getTypeName(J->getOutput().getPrimaryOutputType()); - interleave(OutputFileNames.begin(), OutputFileNames.end(), - [TypeName](const std::string &FileName) { - llvm::outs() << TypeName << ": \"" << FileName << '"'; - }, - [] { llvm::outs() << ", "; }); + interleave( + OutputFileNames.begin(), OutputFileNames.end(), + [TypeName](StringRef FileName) { + llvm::outs() << TypeName << ": \"" << FileName << '"'; + }, + [] { llvm::outs() << ", "; }); file_types::forAllTypes([&J](file_types::ID Ty) { StringRef AdditionalOutput = diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index 5bda1956f9b4c..78660d9bb4da5 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -54,8 +54,8 @@ ModuleDepGraph::simulateLoad(const Job *cmd, assert(!swiftDeps.empty()); StringRef interfaceHash = swiftDeps; auto sfdg = SourceFileDepGraph::simulateLoad( - swiftDeps, includePrivateDeps, hadCompilationError, interfaceHash, - simpleNames, compoundNames); + swiftDeps.str(), includePrivateDeps, hadCompilationError, + interfaceHash.str(), simpleNames, compoundNames); return loadFromSourceFileDepGraph(cmd, sfdg); } @@ -106,8 +106,8 @@ ModuleDepGraph::Changes ModuleDepGraph::loadFromPath(const Job *Cmd, return None; auto r = loadFromBuffer(Cmd, *buffer.get()); assert(path == getSwiftDeps(Cmd) && "Should be reading the job's swiftdeps"); - assert(!r || !nodeMap[path].empty() && - "Must have a node for the whole file"); + assert(!r || + !nodeMap[path.str()].empty() && "Must have a node for the whole file"); if (emitFineGrainedDependencyDotFileAfterEveryImport) emitDotFileForJob(diags, Cmd); if (verifyFineGrainedDependencyGraphAfterEveryImport) @@ -132,7 +132,7 @@ ModuleDepGraph::Changes ModuleDepGraph::loadFromSourceFileDepGraph( } bool ModuleDepGraph::haveAnyNodesBeenTraversedIn(const Job *cmd) const { - const StringRef swiftDeps = getSwiftDeps(cmd); + std::string swiftDeps = getSwiftDeps(cmd).str(); // optimization const auto fileKey = DependencyKey::createKeyForWholeSourceFile(swiftDeps); @@ -251,7 +251,7 @@ ModuleDepGraph::Changes ModuleDepGraph::integrate(const SourceFileDepGraph &g, FrontendStatsTracer tracer(stats, "fine-grained-dependencies-integrate"); // When done, disappearedNodes contains the nodes which no longer exist. - auto disappearedNodes = nodeMap[swiftDepsOfJob]; + auto disappearedNodes = nodeMap[swiftDepsOfJob.str()]; // When done, changeDependencyKeys contains a list of keys that changed // as a result of this integration. auto changedNodes = std::unordered_set(); @@ -299,7 +299,7 @@ ModuleDepGraph::PreexistingNodeIfAny ModuleDepGraph::findPreexistingMatch( } if (integrand->getIsProvides()) { const auto &preexistingNodeInPlaceIter = - matches->find(swiftDepsOfCompilationToBeIntegrated); + matches->find(swiftDepsOfCompilationToBeIntegrated.str()); if (preexistingNodeInPlaceIter != matches->end()) return std::make_pair(LocationOfPreexistingNode::here, preexistingNodeInPlaceIter->second); @@ -388,7 +388,7 @@ bool ModuleDepGraph::recordWhatUseDependsUpon( usesByDef[def->getKey()].insert(moduleUseNode).second; if (isNewUse && def->getKey().getKind() == NodeKind::externalDepend) { StringRef externalSwiftDeps = def->getKey().getName(); - externalDependencies.insert(externalSwiftDeps); + externalDependencies.insert(externalSwiftDeps.str()); useHasNewExternalDependency = true; } }); @@ -432,7 +432,7 @@ void ModuleDepGraph::forCorrespondingImplementationOfProvidedInterface( const auto &interfaceKey = interfaceNode->getKey(); const DependencyKey implementationKey( interfaceKey.getKind(), DeclAspect::implementation, - interfaceKey.getContext(), interfaceKey.getName()); + interfaceKey.getContext().str(), interfaceKey.getName().str()); if (const auto implementationNode = nodeMap.find(swiftDeps, implementationKey)) fn(implementationNode.getValue()); @@ -463,7 +463,7 @@ void ModuleDepGraph::forEachArc( void ModuleDepGraph::forEachNodeInJob( StringRef swiftDeps, function_ref fn) const { - if (const auto *nodesByKeys = nodeMap.find(swiftDeps).getPtrOrNull()) { + if (const auto *nodesByKeys = nodeMap.find(swiftDeps.str()).getPtrOrNull()) { for (const auto &keyAndNode : *nodesByKeys) fn(keyAndNode.second); } @@ -532,7 +532,7 @@ void ModuleDepGraph::emitDotFileForJob(DiagnosticEngine &diags, } void ModuleDepGraph::emitDotFile(DiagnosticEngine &diags, StringRef baseName) { - unsigned seqNo = dotFileSequenceNumber[baseName]++; + unsigned seqNo = dotFileSequenceNumber[baseName.str()]++; std::string fullName = baseName.str() + "-post-integration." + std::to_string(seqNo) + ".dot"; withOutputFile(diags, fullName, [&](llvm::raw_ostream &out) { @@ -630,7 +630,7 @@ void ModuleDepGraph::verifyNodeIsInRightEntryInNodeMap( void ModuleDepGraph::verifyExternalDependencyUniqueness( const DependencyKey &key) const { assert((key.getKind() != NodeKind::externalDepend || - externalDependencies.count(key.getName()) == 1) && + externalDependencies.count(key.getName().str()) == 1) && "Ensure each external dependency is tracked exactly once"); } diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index c6362335de7d8..85be25f007778 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -67,9 +67,9 @@ void CommandOutput::ensureEntry(StringRef PrimaryInputFile, assert(Type != file_types::TY_Nothing); auto &M = DerivedOutputMap.getOrCreateOutputMapForInput(PrimaryInputFile); if (Overwrite) { - M[Type] = OutputFile; + M[Type] = OutputFile.str(); } else { - auto res = M.insert(std::make_pair(Type, OutputFile)); + auto res = M.insert(std::make_pair(Type, OutputFile.str())); if (res.second) { // New entry, no need to compare. } else { @@ -408,20 +408,16 @@ void Job::printSummary(raw_ostream &os) const { } os << "{" << getSource().getClassName() << ": "; - interleave(Outputs, - [&](const std::string &Arg) { - os << llvm::sys::path::filename(Arg); - }, - [&] { os << ' '; }); + interleave( + Outputs, [&](StringRef Arg) { os << llvm::sys::path::filename(Arg); }, + [&] { os << ' '; }); if (actual_out > limit) { os << " ... " << (actual_out-limit) << " more"; } os << " <= "; - interleave(Inputs, - [&](const std::string &Arg) { - os << llvm::sys::path::filename(Arg); - }, - [&] { os << ' '; }); + interleave( + Inputs, [&](StringRef Arg) { os << llvm::sys::path::filename(Arg); }, + [&] { os << ' '; }); if (actual_in > limit) { os << " ... " << (actual_in-limit) << " more"; } diff --git a/lib/Driver/ParseableOutput.cpp b/lib/Driver/ParseableOutput.cpp index 0b110daad12ec..0277c4c10075b 100644 --- a/lib/Driver/ParseableOutput.cpp +++ b/lib/Driver/ParseableOutput.cpp @@ -48,7 +48,7 @@ namespace json { template <> struct ScalarEnumerationTraits { static void enumeration(Output &out, file_types::ID &value) { file_types::forAllTypes([&](file_types::ID ty) { - std::string typeName = file_types::getTypeName(ty); + std::string typeName = file_types::getTypeName(ty).str(); out.enumCase(value, typeName.c_str(), ty); }); } @@ -125,7 +125,7 @@ class DetailedCommandBasedMessage : public CommandBasedMessage { if (const auto *BJAction = dyn_cast(&Cmd.getSource())) { Inputs.push_back(CommandInput(OutFiles[BJAction->getInputIndex()])); } else { - for (const std::string FileName : OutFiles) { + for (llvm::StringRef FileName : OutFiles) { Inputs.push_back(CommandInput(FileName)); } } @@ -134,8 +134,8 @@ class DetailedCommandBasedMessage : public CommandBasedMessage { // TODO: set up Outputs appropriately. file_types::ID PrimaryOutputType = Cmd.getOutput().getPrimaryOutputType(); if (PrimaryOutputType != file_types::TY_Nothing) { - for (const std::string OutputFileName : Cmd.getOutput(). - getPrimaryOutputFilenames()) { + for (llvm::StringRef OutputFileName : + Cmd.getOutput().getPrimaryOutputFilenames()) { Outputs.push_back(OutputPair(PrimaryOutputType, OutputFileName)); } } diff --git a/lib/Driver/SourceComparator.cpp b/lib/Driver/SourceComparator.cpp index 2fccb91e779b6..4b2d3674036f6 100644 --- a/lib/Driver/SourceComparator.cpp +++ b/lib/Driver/SourceComparator.cpp @@ -70,7 +70,7 @@ SourceComparator::buildEquivalenceClasses() { std::unordered_map> rhsMap; for (auto index = regionsToCompare.start.rhs(); index < regionsToCompare.end.rhs(); ++index) - rhsMap[linesToCompare.rhs()[index]].push_back(index); + rhsMap[linesToCompare.rhs()[index].str()].push_back(index); return rhsMap; } @@ -86,7 +86,7 @@ SourceComparator::buildDAGOfSubsequences( for (auto i = regionsToCompare.start.lhs(); i < regionsToCompare.end.lhs(); ++i) { // What lines in rhs does the ith line in lhs match? - auto iter = rhsMap.find(linesToCompare.lhs()[i]); + auto iter = rhsMap.find(linesToCompare.lhs()[i].str()); if (iter == rhsMap.end()) continue; // no match in rhs auto &res = iter->second; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 7ce44bb05a9c7..c8e0ec762be3e 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1256,13 +1256,13 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibP StringRef SDKPath, bool shared) const { SmallString<128> scratchPath; getResourceDirPath(scratchPath, args, shared); - runtimeLibPaths.push_back(scratchPath.str()); + runtimeLibPaths.push_back(std::string(scratchPath)); // If there's a secondary resource dir, add it too. scratchPath.clear(); getSecondaryResourceDirPath(scratchPath, runtimeLibPaths[0]); if (!scratchPath.empty()) - runtimeLibPaths.push_back(scratchPath.str()); + runtimeLibPaths.push_back(std::string(scratchPath)); if (!SDKPath.empty()) { if (!scratchPath.empty()) { @@ -1271,12 +1271,12 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibP scratchPath = SDKPath; llvm::sys::path::append(scratchPath, "System", "iOSSupport"); llvm::sys::path::append(scratchPath, "usr", "lib", "swift"); - runtimeLibPaths.push_back(scratchPath.str()); + runtimeLibPaths.push_back(std::string(scratchPath)); } scratchPath = SDKPath; llvm::sys::path::append(scratchPath, "usr", "lib", "swift"); - runtimeLibPaths.push_back(scratchPath.str()); + runtimeLibPaths.push_back(std::string(scratchPath)); } } diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 0958d6df7b64d..88802315cb7fc 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -457,7 +457,7 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() { } // In order to pass some tests, must leave ModuleName empty. if (!Opts.InputsAndOutputs.hasInputs()) { - Opts.ModuleName = StringRef(); + Opts.ModuleName = std::string(); // FIXME: This is a bug that should not happen, but does in tests. // The compiler should bail out earlier, where "no frontend action was // selected". @@ -474,7 +474,7 @@ bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() { ? outputFilenames->front() : Opts.InputsAndOutputs.getFilenameOfFirstInput(); - Opts.ModuleName = llvm::sys::path::stem(nameToStem); + Opts.ModuleName = llvm::sys::path::stem(nameToStem).str(); return false; } diff --git a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp index fac378995366f..78b6f728a2c1d 100644 --- a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp @@ -222,7 +222,7 @@ OutputFilesComputer::deriveOutputFileFromParts(StringRef dir, llvm::SmallString<128> path(dir); llvm::sys::path::append(path, base); llvm::sys::path::replace_extension(path, Suffix); - return path.str(); + return std::string(path); } SupplementaryOutputPathsComputer::SupplementaryOutputPathsComputer( @@ -502,11 +502,13 @@ void SupplementaryOutputPathsComputer::deriveModulePathParameters( RequestedAction == FrontendOptions::ActionType::MergeModules || RequestedAction == FrontendOptions::ActionType::EmitModuleOnly || isSIB; - extension = file_types::getExtension( - isSIB ? file_types::TY_SIB : file_types::TY_SwiftModuleFile); + extension = file_types::getExtension(isSIB ? file_types::TY_SIB + : file_types::TY_SwiftModuleFile) + .str(); - mainOutputIfUsable = - canUseMainOutputForModule && !OutputFiles.empty() ? mainOutputFile : ""; + mainOutputIfUsable = canUseMainOutputForModule && !OutputFiles.empty() + ? mainOutputFile.str() + : ""; } static SupplementaryOutputPaths diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 40762133ccb58..08d231305f567 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -56,7 +56,7 @@ void CompilerInvocation::setMainExecutablePath(StringRef Path) { llvm::sys::path::remove_filename(DiagnosticDocsPath); // Remove /bin llvm::sys::path::append(DiagnosticDocsPath, "share", "doc", "swift", "diagnostics"); - DiagnosticOpts.DiagnosticDocumentationPath = DiagnosticDocsPath.str(); + DiagnosticOpts.DiagnosticDocumentationPath = std::string(DiagnosticDocsPath); } /// If we haven't explicitly passed -prebuilt-module-cache-path, set it to @@ -82,7 +82,7 @@ static void setDefaultPrebuiltCacheIfNecessary( platform = getPlatformNameForTriple(triple); } llvm::sys::path::append(defaultPrebuiltPath, platform, "prebuilt-modules"); - frontendOpts.PrebuiltModuleCachePath = defaultPrebuiltPath.str(); + frontendOpts.PrebuiltModuleCachePath = std::string(defaultPrebuiltPath); } static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, @@ -95,7 +95,7 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, llvm::sys::path::append(LibPath, LibSubDir); SearchPathOpts.RuntimeLibraryPaths.clear(); - SearchPathOpts.RuntimeLibraryPaths.push_back(LibPath.str()); + SearchPathOpts.RuntimeLibraryPaths.push_back(std::string(LibPath)); if (Triple.isOSDarwin()) SearchPathOpts.RuntimeLibraryPaths.push_back(DARWIN_OS_LIBRARY_PATH); @@ -109,14 +109,14 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, if (!Triple.isOSDarwin()) llvm::sys::path::append(LibPath, swift::getMajorArchitectureName(Triple)); - SearchPathOpts.RuntimeLibraryImportPaths.push_back(LibPath.str()); + SearchPathOpts.RuntimeLibraryImportPaths.push_back(std::string(LibPath)); if (!SearchPathOpts.SDKPath.empty()) { if (tripleIsMacCatalystEnvironment(Triple)) { LibPath = SearchPathOpts.SDKPath; llvm::sys::path::append(LibPath, "System", "iOSSupport"); llvm::sys::path::append(LibPath, "usr", "lib", "swift"); - SearchPathOpts.RuntimeLibraryImportPaths.push_back(LibPath.str()); + SearchPathOpts.RuntimeLibraryImportPaths.push_back(std::string(LibPath)); } LibPath = SearchPathOpts.SDKPath; @@ -125,7 +125,7 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, llvm::sys::path::append(LibPath, getPlatformNameForTriple(Triple)); llvm::sys::path::append(LibPath, swift::getMajorArchitectureName(Triple)); } - SearchPathOpts.RuntimeLibraryImportPaths.push_back(LibPath.str()); + SearchPathOpts.RuntimeLibraryImportPaths.push_back(std::string(LibPath)); } } @@ -178,7 +178,7 @@ setBridgingHeaderFromFrontendOptions(ClangImporterOptions &ImporterOpts, } void CompilerInvocation::setRuntimeResourcePath(StringRef Path) { - SearchPathOpts.RuntimeResourcePath = Path; + SearchPathOpts.RuntimeResourcePath = Path.str(); updateRuntimeLibraryPaths(SearchPathOpts, LangOpts.Target); } @@ -703,9 +703,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, // Provide a working directory to Clang as well if there are any -Xcc // options, in case some of them are search-related. But do it at the // beginning, so that an explicit -Xcc -working-directory will win. - Opts.ExtraArgs.insert(Opts.ExtraArgs.begin(), { - "-working-directory", workingDirectory - }); + Opts.ExtraArgs.insert(Opts.ExtraArgs.begin(), + {"-working-directory", workingDirectory.str()}); } Opts.InferImportAsMember |= Args.hasArg(OPT_enable_infer_import_as_member); @@ -748,10 +747,10 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, auto resolveSearchPath = [workingDirectory](StringRef searchPath) -> std::string { if (workingDirectory.empty() || path::is_absolute(searchPath)) - return searchPath; + return searchPath.str(); SmallString<64> fullPath{workingDirectory}; path::append(fullPath, searchPath); - return fullPath.str(); + return std::string(fullPath); }; for (const Arg *A : Args.filtered(OPT_I)) { @@ -1142,7 +1141,7 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, // TODO: Should we support -fdebug-compilation-dir? llvm::SmallString<256> cwd; llvm::sys::fs::current_path(cwd); - Opts.DebugCompilationDir = cwd.str(); + Opts.DebugCompilationDir = std::string(cwd); } if (const Arg *A = Args.getLastArg(options::OPT_debug_info_format)) { @@ -1182,7 +1181,7 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, for (const Arg *A : Args.filtered(OPT_Xcc)) { StringRef Opt = A->getValue(); if (Opt.startswith("-D") || Opt.startswith("-U")) - Opts.ClangDefines.push_back(Opt); + Opts.ClangDefines.push_back(Opt.str()); } for (const Arg *A : Args.filtered(OPT_l, OPT_framework)) { @@ -1226,7 +1225,7 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.FunctionSections = Args.hasArg(OPT_function_sections); if (Args.hasArg(OPT_autolink_force_load)) - Opts.ForceLoadSymbolName = Args.getLastArgValue(OPT_module_link_name); + Opts.ForceLoadSymbolName = Args.getLastArgValue(OPT_module_link_name).str(); Opts.ModuleName = FrontendOpts.ModuleName; @@ -1459,8 +1458,8 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, llvm::SmallString<128> authoredDataPath(basePath); llvm::sys::path::append(authoredDataPath, getScriptFileName("overlay", langVer)); // Add authored list first to take higher priority. - Opts.APIDigesterDataStorePaths.push_back(authoredDataPath.str()); - Opts.APIDigesterDataStorePaths.push_back(dataPath.str()); + Opts.APIDigesterDataStorePaths.push_back(std::string(authoredDataPath)); + Opts.APIDigesterDataStorePaths.push_back(std::string(dataPath)); } } @@ -1589,12 +1588,12 @@ CompilerInvocation::loadFromSerializedAST(StringRef data) { LangOpts.EffectiveLanguageVersion = info.compatibilityVersion; setTargetTriple(info.targetTriple); if (!extendedInfo.getSDKPath().empty()) - setSDKPath(extendedInfo.getSDKPath()); + setSDKPath(extendedInfo.getSDKPath().str()); auto &extraClangArgs = getClangImporterOptions().ExtraArgs; - extraClangArgs.insert(extraClangArgs.end(), - extendedInfo.getExtraClangImporterOptions().begin(), - extendedInfo.getExtraClangImporterOptions().end()); + for (StringRef Arg : extendedInfo.getExtraClangImporterOptions()) + extraClangArgs.push_back(Arg.str()); + return info.status; } diff --git a/lib/Frontend/DiagnosticVerifier.cpp b/lib/Frontend/DiagnosticVerifier.cpp index affacf1b309d3..9d0655cf39a30 100644 --- a/lib/Frontend/DiagnosticVerifier.cpp +++ b/lib/Frontend/DiagnosticVerifier.cpp @@ -350,7 +350,7 @@ bool DiagnosticVerifier::verifyFile(unsigned BufferID, llvm::SmallString<256> Buf; Expected.MessageRange = MatchStart.slice(2, End); Expected.MessageStr = - Lexer::getEncodedStringSegment(Expected.MessageRange, Buf); + Lexer::getEncodedStringSegment(Expected.MessageRange, Buf).str(); if (PrevExpectedContinuationLine) Expected.LineNo = PrevExpectedContinuationLine; else diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 96234f6fc0ccd..b7a21176276a7 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -721,7 +721,7 @@ void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage) { } if (shouldImplicityImportSwiftOnoneSupportModule(Invocation)) { Invocation.getFrontendOptions().ImplicitImportModuleNames.push_back( - SWIFT_ONONE_SUPPORT); + SWIFT_ONONE_SUPPORT.str()); } const ImplicitImports implicitImports(*this); diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 2f7a40f255c21..14dd87b51bfe7 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -77,7 +77,7 @@ void ModuleInterfaceBuilder::configureSubInvocationInputsAndOutputs( SOPs.ModuleOutputPath = OutPath.str(); // Pick a primary output path that will cause problems to use. - StringRef MainOut = "/"; + std::string MainOut = "/"; SubFEOpts.InputsAndOutputs .setMainAndSupplementaryOutputs({MainOut}, {SOPs}); } @@ -98,7 +98,7 @@ void ModuleInterfaceBuilder::configureSubInvocation( subInvocation.setModuleName(moduleName); subInvocation.setClangModuleCachePath(moduleCachePath); subInvocation.getFrontendOptions().PrebuiltModuleCachePath = - prebuiltCachePath; + prebuiltCachePath.str(); subInvocation.getFrontendOptions().TrackSystemDeps = trackSystemDependencies; // Respect the detailed-record preprocessor setting of the parent context. @@ -346,7 +346,7 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( // Setup the callbacks for serialization, which can occur during the // optimization pipeline. SerializationOptions SerializationOpts; - std::string OutPathStr = OutPath; + std::string OutPathStr = OutPath.str(); SerializationOpts.OutputPath = OutPathStr.c_str(); SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; SerializationOpts.AutolinkForceLoad = diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 9c925a58cda04..c696d5135cd77 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -46,14 +46,13 @@ std::string swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) { if (!Clang.hasPreprocessor()) return ""; - std::string SpecificModuleCachePath = Clang.getPreprocessor() - .getHeaderSearchInfo() - .getModuleCachePath(); + std::string SpecificModuleCachePath = + Clang.getPreprocessor().getHeaderSearchInfo().getModuleCachePath().str(); // The returned-from-clang module cache path includes a suffix directory // that is specific to the clang version and invocation; we want the // directory above that. - return llvm::sys::path::parent_path(SpecificModuleCachePath); + return llvm::sys::path::parent_path(SpecificModuleCachePath).str(); } #pragma mark - Forwarding Modules @@ -241,7 +240,7 @@ struct ModuleRebuildInfo { for (auto &mod : outOfDateModules) { if (mod.path == path) return mod; } - outOfDateModules.push_back({path, None, ModuleKind::Normal, {}, {}}); + outOfDateModules.push_back({path.str(), None, ModuleKind::Normal, {}, {}}); return outOfDateModules.back(); } @@ -261,14 +260,14 @@ struct ModuleRebuildInfo { /// at \c modulePath. void addOutOfDateDependency(StringRef modulePath, StringRef depPath) { getOrInsertOutOfDateModule(modulePath) - .outOfDateDependencies.push_back(depPath); + .outOfDateDependencies.push_back(depPath.str()); } /// Registers a missing dependency at \c depPath for the module /// at \c modulePath. void addMissingDependency(StringRef modulePath, StringRef depPath) { getOrInsertOutOfDateModule(modulePath) - .missingDependencies.push_back(depPath); + .missingDependencies.push_back(depPath.str()); } /// Determines if we saw the given module path and registered is as out of diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 9b2fc8fc8ff13..43c48110e28b7 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -96,7 +96,7 @@ using namespace swift; static std::string displayName(StringRef MainExecutablePath) { - std::string Name = llvm::sys::path::stem(MainExecutablePath); + std::string Name = llvm::sys::path::stem(MainExecutablePath).str(); Name += " -frontend"; return Name; } @@ -313,21 +313,20 @@ static void computeSwiftModuleTraceInfo( // this is good enough. : buffer.str(); - traceInfo.push_back({ - /*Name=*/ - depMod->getName(), - /*Path=*/ - realDepPath, - // TODO: There is an edge case which is not handled here. - // When we build a framework using -import-underlying-module, or an - // app/test using -import-objc-header, we should look at the direct - // imports of the bridging modules, and mark those as our direct - // imports. - /*IsImportedDirectly=*/ - importedModules.find(depMod) != importedModules.end(), - /*SupportsLibraryEvolution=*/ - depMod->isResilient() - }); + traceInfo.push_back( + {/*Name=*/ + depMod->getName(), + /*Path=*/ + realDepPath.str(), + // TODO: There is an edge case which is not handled here. + // When we build a framework using -import-underlying-module, or an + // app/test using -import-objc-header, we should look at the direct + // imports of the bridging modules, and mark those as our direct + // imports. + /*IsImportedDirectly=*/ + importedModules.find(depMod) != importedModules.end(), + /*SupportsLibraryEvolution=*/ + depMod->isResilient()}); buffer.clear(); continue; @@ -434,9 +433,7 @@ static bool emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule, LoadedModuleTraceFormat trace = { /*version=*/LoadedModuleTraceFormat::CurrentVersion, /*name=*/mainModule->getName(), - /*arch=*/ctxt.LangOpts.Target.getArchName(), - swiftModules - }; + /*arch=*/ctxt.LangOpts.Target.getArchName().str(), swiftModules}; // raw_fd_ostream is unbuffered, and we may have multiple processes writing, // so first write to memory and then dump the buffer to the trace file. @@ -590,7 +587,7 @@ class JSONFixitWriter if (!(FixitAll || shouldTakeFixit(Info))) return; for (const auto &Fix : Info.FixIts) { - AllEdits.push_back({SM, Fix.getRange(), Fix.getText()}); + AllEdits.push_back({SM, Fix.getRange(), Fix.getText().str()}); } } @@ -1703,7 +1700,7 @@ static bool dumpAPI(ModuleDecl *Mod, StringRef OutDir) { SmallString<256> Path = OutDir; StringRef Filename = SF->getFilename(); path::append(Path, path::filename(Filename)); - return Path.str(); + return std::string(Path); }; std::unordered_set Filenames; diff --git a/lib/IDE/APIDigesterData.cpp b/lib/IDE/APIDigesterData.cpp index 97c15e773dde7..83ffc6f6bda35 100644 --- a/lib/IDE/APIDigesterData.cpp +++ b/lib/IDE/APIDigesterData.cpp @@ -87,7 +87,7 @@ CommonDiffItem(SDKNodeKind NodeKind, NodeAnnotation DiffKind, ChildIndex.split(Pieces, ":"); std::transform(Pieces.begin(), Pieces.end(), std::back_inserter(ChildIndexPieces), - [](StringRef Piece) { return std::stoi(Piece); }); + [](StringRef Piece) { return std::stoi(Piece.str()); }); } StringRef swift::ide::api::CommonDiffItem::head() { @@ -319,7 +319,7 @@ static StringRef getScalarString(llvm::yaml::Node *N) { }; static int getScalarInt(llvm::yaml::Node *N) { - return std::stoi(cast(N)->getRawValue()); + return std::stoi(cast(N)->getRawValue().str()); }; static APIDiffItem* diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index f8e20c52b1e38..d924ac3b27eb6 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -5565,7 +5565,7 @@ void CodeCompletionCallbacksImpl::doneParsing() { std::vector AccessPath; for (auto Piece : Path) { - AccessPath.push_back(Piece.Item.str()); + AccessPath.push_back(std::string(Piece.Item)); } StringRef ModuleFilename = TheModule->getModuleFilename(); @@ -5574,15 +5574,17 @@ void CodeCompletionCallbacksImpl::doneParsing() { if (!ModuleFilename.empty()) { auto &Ctx = TheModule->getASTContext(); CodeCompletionCache::Key K{ - ModuleFilename, TheModule->getName().str(), AccessPath, - Request.NeedLeadingDot, - SF.hasTestableOrPrivateImport( - AccessLevel::Internal, TheModule, - SourceFile::ImportQueryKind::TestableOnly), - SF.hasTestableOrPrivateImport( - AccessLevel::Internal, TheModule, - SourceFile::ImportQueryKind::PrivateOnly), - Ctx.LangOpts.CodeCompleteInitsInPostfixExpr}; + ModuleFilename.str(), + std::string(TheModule->getName()), + AccessPath, + Request.NeedLeadingDot, + SF.hasTestableOrPrivateImport( + AccessLevel::Internal, TheModule, + SourceFile::ImportQueryKind::TestableOnly), + SF.hasTestableOrPrivateImport( + AccessLevel::Internal, TheModule, + SourceFile::ImportQueryKind::PrivateOnly), + Ctx.LangOpts.CodeCompleteInitsInPostfixExpr}; using PairType = llvm::DenseSet>::iterator; diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index dd63357194c35..44632bc5b9bbd 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -437,7 +437,7 @@ static std::string getName(StringRef cacheDirectory, llvm::APInt(64, uint64_t(hash)).toStringUnsigned(hashStr, /*Radix*/ 36); OSS << "-" << hashStr << ".completions"; - return name.str(); + return std::string(name); } Optional @@ -490,8 +490,8 @@ OnDiskCodeCompletionCache::getFromFile(StringRef filename) { return None; // Make up a key for readCachedModule. - CodeCompletionCache::Key K{filename, "", {}, false, - false, false, false}; + CodeCompletionCache::Key K{filename.str(), "", {}, false, + false, false, false}; // Read the cached results. auto V = CodeCompletionCache::createValue(); diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index 714116fce3ee1..f0344a4bbc026 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -901,8 +901,9 @@ class CodeFormatter { } if (FC.IsInStringLiteral()) { - return std::make_pair(LineRange(LineIndex, 1), - swift::ide::getTextForLine(LineIndex, Text, /*Trim*/false)); + return std::make_pair( + LineRange(LineIndex, 1), + swift::ide::getTextForLine(LineIndex, Text, /*Trim*/ false).str()); } // Take the current indent position of the outer context, then add another @@ -950,7 +951,7 @@ class CodeFormatter { IndentedLine.assign(ExpandedIndent / FmtOptions.TabWidth, '\t'); else IndentedLine.assign(ExpandedIndent, ' '); - IndentedLine.append(Line); + IndentedLine.append(Line.str()); // Return affected line range, which can later be more than one line. LineRange range = LineRange(LineIndex, 1); diff --git a/lib/IDE/ModuleInterfacePrinting.cpp b/lib/IDE/ModuleInterfacePrinting.cpp index b061bebbfa362..975ea7b7243a4 100644 --- a/lib/IDE/ModuleInterfacePrinting.cpp +++ b/lib/IDE/ModuleInterfacePrinting.cpp @@ -159,7 +159,7 @@ static void printTypeNameToString(Type Ty, std::string &Text) { SmallString<128> Buffer; llvm::raw_svector_ostream OS(Buffer); Ty->print(OS); - Text = OS.str(); + Text = std::string(OS.str()); } bool swift::ide:: diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index 247ddb4d0e473..0ac30c82388ea 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -248,7 +248,7 @@ void REPLCompletions::populate(SourceFile &SF, StringRef EnteredCode) { if (!Tokens.empty()) { Token &LastToken = Tokens.back(); if (LastToken.is(tok::identifier) || LastToken.isKeyword()) { - Prefix = LastToken.getText(); + Prefix = LastToken.getText().str(); unsigned Offset = Ctx.SourceMgr.getLocOffsetInBuffer(LastToken.getLoc(), BufferID); @@ -275,7 +275,7 @@ StringRef REPLCompletions::getRoot() const { return Root.getValue(); } - std::string RootStr = CookedResults[0].InsertableString; + std::string RootStr = CookedResults[0].InsertableString.str(); for (auto R : CookedResults) { if (R.NumBytesToErase != 0) { RootStr.resize(0); diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp index 8ceded06c3da7..22e2aaed29a51 100644 --- a/lib/IDE/Refactoring.cpp +++ b/lib/IDE/Refactoring.cpp @@ -2986,8 +2986,11 @@ static std::string insertUnderscore(StringRef Text) { static void insertUnderscoreInDigits(StringRef Digits, llvm::raw_ostream &OS) { - std::string BeforePoint, AfterPoint; - std::tie(BeforePoint, AfterPoint) = Digits.split('.'); + StringRef BeforePointRef, AfterPointRef; + std::tie(BeforePointRef, AfterPointRef) = Digits.split('.'); + + std::string BeforePoint(BeforePointRef); + std::string AfterPoint(AfterPointRef); // Insert '_' for the part before the decimal point. std::reverse(BeforePoint.begin(), BeforePoint.end()); @@ -3486,7 +3489,7 @@ refactorSwiftModule(ModuleDecl *M, RefactoringOptions Opts, // Use the default name if not specified. if (Opts.PreferredName.empty()) { - Opts.PreferredName = getDefaultPreferredName(Opts.Kind); + Opts.PreferredName = getDefaultPreferredName(Opts.Kind).str(); } switch (Opts.Kind) { diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index a52c6570e178f..1df42ce54e976 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -345,7 +345,7 @@ bool ide::initInvocationByClangArguments(ArrayRef ArgList, llvm::SmallString<64> Str; Str += "-fmodule-name="; Str += ClangInvok->getLangOpts()->CurrentModule; - CCArgs.push_back(Str.str()); + CCArgs.push_back(std::string(Str)); } if (PPOpts.DetailedRecord) { @@ -354,7 +354,7 @@ bool ide::initInvocationByClangArguments(ArrayRef ArgList, if (!ClangInvok->getFrontendOpts().Inputs.empty()) { Invok.getFrontendOptions().ImplicitObjCHeaderPath = - ClangInvok->getFrontendOpts().Inputs[0].getFile(); + ClangInvok->getFrontendOpts().Inputs[0].getFile().str(); } return false; @@ -497,7 +497,7 @@ static std::string getPlistEntry(const llvm::Twine &Path, StringRef KeyName) { std::tie(CurLine, Lines) = Lines.split('\n'); unsigned Begin = CurLine.find("") + strlen(""); unsigned End = CurLine.find(""); - return CurLine.substr(Begin, End-Begin); + return CurLine.substr(Begin, End - Begin).str(); } } @@ -508,7 +508,7 @@ std::string ide::getSDKName(StringRef Path) { std::string Name = getPlistEntry(llvm::Twine(Path)+"/SDKSettings.plist", "CanonicalName"); if (Name.empty() && Path.endswith(".sdk")) { - Name = llvm::sys::path::filename(Path).drop_back(strlen(".sdk")); + Name = llvm::sys::path::filename(Path).drop_back(strlen(".sdk")).str(); } return Name; } @@ -850,7 +850,7 @@ struct swift::ide::SourceEditJsonConsumer::Implementation { } void accept(SourceManager &SM, CharSourceRange Range, llvm::StringRef Text) { - AllEdits.push_back({SM, Range, Text}); + AllEdits.push_back({SM, Range, Text.str()}); } }; diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 392b6c4159f10..87e3eaa4a71fc 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -992,10 +992,10 @@ namespace { abiName = synthesizedTypeAttr->originalTypeName; getMutableImportInfo().RelatedEntityName = - synthesizedTypeAttr->getManglingName(); + std::string(synthesizedTypeAttr->getManglingName()); - // Otherwise, if this was imported from a Clang declaration, use that - // declaration's name as the ABI name. + // Otherwise, if this was imported from a Clang declaration, use that + // declaration's name as the ABI name. } else if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) { abiName = clangDecl->getName(); @@ -1012,7 +1012,7 @@ namespace { // If the ABI name differs from the user-facing name, add it as // an override. if (!abiName.empty() && abiName != UserFacingName) { - getMutableImportInfo().ABIName = abiName; + getMutableImportInfo().ABIName = std::string(abiName); } } diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index 77ce2bedaedf6..90802888dcd1a 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -511,7 +511,7 @@ llvm::Constant *IRGenModule::getAddrOfObjCSelectorRef(SILDeclRef method) { std::string IRGenModule::getObjCSelectorName(SILDeclRef method) { assert(method.isForeign); - return Selector(method).str(); + return Selector(method).str().str(); } static llvm::Value *emitSuperArgument(IRGenFunction &IGF, diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 04b269a990675..aef601ddbdf05 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -1193,7 +1193,7 @@ static std::string getReflectionSectionName(IRGenModule &IGM, OS << "__TEXT,__swift5_" << LongName << ", regular, no_dead_strip"; break; } - return OS.str(); + return std::string(OS.str()); } const char *IRGenModule::getFieldTypeMetadataSectionName() { diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index 19cb5949d15aa..cdb164789cbaa 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -405,7 +405,7 @@ std::string LinkEntity::mangleAsString() const { } case Kind::SILGlobalVariable: - return getSILGlobalVariable()->getName(); + return getSILGlobalVariable()->getName().str(); case Kind::ReflectionBuiltinDescriptor: return mangler.mangleReflectionBuiltinDescriptor(getType()); diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 5b9f33dbb2cd3..fd7296018dfaf 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -300,7 +300,7 @@ llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef( llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(StringRef str, MangledTypeRefRole role){ - return getAddrOfStringForTypeRef(SymbolicMangling{str, {}}, role); + return getAddrOfStringForTypeRef(SymbolicMangling{str.str(), {}}, role); } llvm::Constant *IRGenModule::getAddrOfStringForTypeRef( diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp index 08367ca19c899..c05fcaa6d4a29 100644 --- a/lib/Index/IndexRecord.cpp +++ b/lib/Index/IndexRecord.cpp @@ -337,8 +337,9 @@ recordSourceFile(SourceFile *SF, StringRef indexStorePath, llvm::function_ref callback) { std::string recordFile; bool failed = false; - auto consumer = makeRecordingConsumer(SF->getFilename(), indexStorePath, - &diags, &recordFile, &failed); + auto consumer = + makeRecordingConsumer(SF->getFilename().str(), indexStorePath.str(), + &diags, &recordFile, &failed); indexSourceFile(SF, *consumer); if (!failed && !recordFile.empty()) @@ -407,13 +408,13 @@ static void addModuleDependencies(ArrayRef imports, case FileUnitKind::ClangModule: { auto *LFU = cast(FU); if (auto F = fileMgr.getFile(LFU->getFilename())) { - std::string moduleName = mod->getNameStr(); + std::string moduleName = mod->getNameStr().str(); bool withoutUnitName = true; if (FU->getKind() == FileUnitKind::ClangModule) { withoutUnitName = false; auto clangModUnit = cast(LFU); if (auto clangMod = clangModUnit->getUnderlyingClangModule()) { - moduleName = clangMod->getTopLevelModuleName(); + moduleName = clangMod->getTopLevelModuleName().str(); // FIXME: clang's -Rremarks do not seem to go through Swift's // diagnostic emitter. clang::index::emitIndexDataForModuleFile(clangMod, @@ -455,7 +456,7 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, DiagnosticEngine &diags, IndexUnitWriter &parentUnitWriter) { StringRef filename = module->getModuleFilename(); - std::string moduleName = module->getNameStr(); + std::string moduleName = module->getNameStr().str(); std::string error; auto isUptodateOpt = parentUnitWriter.isUnitUpToDateForOutputFile(/*FilePath=*/filename, @@ -477,7 +478,7 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, if (!module->isStdlibModule()) { std::string recordFile; bool failed = false; - auto consumer = makeRecordingConsumer(filename, indexStorePath, + auto consumer = makeRecordingConsumer(filename.str(), indexStorePath.str(), &diags, &recordFile, &failed); indexModule(module, *consumer); @@ -522,7 +523,9 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, appendGroupNameForFilename(groupName, fileNameWithGroup); std::string outRecordFile; - failed = failed || writeRecord(tracker, fileNameWithGroup.str(), indexStorePath, &diags, outRecordFile); + failed = + failed || writeRecord(tracker, std::string(fileNameWithGroup), + indexStorePath.str(), &diags, outRecordFile); if (failed) return false; records.emplace_back(outRecordFile, moduleName.str()); @@ -538,7 +541,7 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, // FIXME: Get real values for the following. StringRef swiftVersion; StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot; - std::string indexUnitToken = module->getModuleFilename(); + std::string indexUnitToken = module->getModuleFilename().str(); // For indexing serialized modules 'debug compilation' is irrelevant, so // set it to true by default. bool isDebugCompilation = true; diff --git a/lib/LLVMPasses/LLVMInlineTree.cpp b/lib/LLVMPasses/LLVMInlineTree.cpp index f998f6d624c92..5fc584c9fd5a7 100644 --- a/lib/LLVMPasses/LLVMInlineTree.cpp +++ b/lib/LLVMPasses/LLVMInlineTree.cpp @@ -19,17 +19,18 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "llvm-inlinetree" +#include "swift/Basic/Range.h" +#include "swift/Demangling/Demangle.h" #include "swift/LLVMPasses/Passes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Function.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/Pass.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallSet.h" -#include "swift/Demangling/Demangle.h" -#include "swift/Basic/Range.h" using namespace llvm; using namespace swift; diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp index 0cc1870cbd9ff..203a573d49727 100644 --- a/lib/Migrator/APIDiffMigratorPass.cpp +++ b/lib/Migrator/APIDiffMigratorPass.cpp @@ -340,7 +340,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { if (auto CI = dyn_cast(Item)) { if (CI->isRename() && (CI->NodeKind == SDKNodeKind::DeclVar || CI->NodeKind == SDKNodeKind::DeclType)) { - Text = CI->getNewName(); + Text = CI->getNewName().str(); return true; } } @@ -385,7 +385,8 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { SF->getTopLevelDecls(TopDecls); for (auto *D: TopDecls) { if (auto *FD = dyn_cast(D)) { - InsertedFunctions.insert(FD->getBaseName().getIdentifier().str()); + InsertedFunctions.insert( + std::string(FD->getBaseName().getIdentifier())); } } @@ -393,7 +394,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { for (auto &Cur: HelperFuncInfo) { if (Cur.ExpressionToWrap) continue; - auto FuncName = Cur.getFuncName(); + auto FuncName = Cur.getFuncName().str(); // Avoid inserting the helper function if it's already present. if (!InsertedFunctions.count(FuncName)) { Editor.insert(FileEndLoc, Cur.getFuncDef()); @@ -427,7 +428,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { // from type alias to raw-value representable. if (isRecognizedTypeAliasChange(Cur.ExpressionToWrap)) continue; - auto FuncName = Cur.getFuncName(); + auto FuncName = Cur.getFuncName().str(); // Avoid inserting the helper function if it's already present. if (!InsertedFunctions.count(FuncName)) { @@ -937,8 +938,8 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { " {key, value in (key.rawValue, value)})"); break; case NodeAnnotation::SimpleStringRepresentableUpdate: - Segs = {"", "", RawType}; - Segs.push_back(NewType); + Segs = {"", "", RawType.str()}; + Segs.push_back(NewType.str()); Segs.push_back((Twine("\treturn ") + NewType + "(rawValue: input)").str()); Segs.push_back("\treturn input.rawValue"); break; diff --git a/lib/Migrator/EditorAdapter.cpp b/lib/Migrator/EditorAdapter.cpp index ee77d52ecd39b..5e867a3cb1d1b 100644 --- a/lib/Migrator/EditorAdapter.cpp +++ b/lib/Migrator/EditorAdapter.cpp @@ -33,7 +33,7 @@ EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const { return false; unsigned SwiftBufferID, Offset; std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart()); - Replacement R { Offset, Range.getByteLength(), Text }; + Replacement R{Offset, Range.getByteLength(), Text.str()}; if (Replacements.count(R)) { return true; } else { diff --git a/lib/Migrator/FixitApplyDiagnosticConsumer.cpp b/lib/Migrator/FixitApplyDiagnosticConsumer.cpp index 896ee28fa452c..eb250a7ef2c7f 100644 --- a/lib/Migrator/FixitApplyDiagnosticConsumer.cpp +++ b/lib/Migrator/FixitApplyDiagnosticConsumer.cpp @@ -58,7 +58,7 @@ void FixitApplyDiagnosticConsumer::handleDiagnostic( continue; // Ignore pre-applied equivalents. - Replacement R { Offset, Length, Text }; + Replacement R{Offset, Length, Text.str()}; if (Replacements.count(R)) { continue; } else { diff --git a/lib/Migrator/MigrationState.cpp b/lib/Migrator/MigrationState.cpp index b5b28d987edda..5493a29f4742f 100644 --- a/lib/Migrator/MigrationState.cpp +++ b/lib/Migrator/MigrationState.cpp @@ -25,11 +25,11 @@ using namespace swift::migrator; #pragma mark - MigrationState std::string MigrationState::getInputText() const { - return SrcMgr.getEntireTextForBuffer(InputBufferID); + return SrcMgr.getEntireTextForBuffer(InputBufferID).str(); } std::string MigrationState::getOutputText() const { - return SrcMgr.getEntireTextForBuffer(OutputBufferID); + return SrcMgr.getEntireTextForBuffer(OutputBufferID).str(); } static bool quickDumpText(StringRef OutFilename, StringRef Text) { diff --git a/lib/Migrator/Migrator.cpp b/lib/Migrator/Migrator.cpp index 58bee5ab44379..e6ab9f6fa85b2 100644 --- a/lib/Migrator/Migrator.cpp +++ b/lib/Migrator/Migrator.cpp @@ -279,7 +279,8 @@ void printRemap(const StringRef OriginalFilename, assert(!OriginalFilename.empty()); diff_match_patch DMP; - const auto Diffs = DMP.diff_main(InputText, OutputText, /*checkLines=*/false); + const auto Diffs = + DMP.diff_main(InputText.str(), OutputText.str(), /*checkLines=*/false); OS << "["; @@ -354,7 +355,7 @@ void printRemap(const StringRef OriginalFilename, continue; Current.Offset -= 1; Current.Remove += 1; - Current.Text = InputText.substr(Current.Offset, 1); + Current.Text = InputText.substr(Current.Offset, 1).str(); } for (auto Rep = Replacements.begin(); Rep != Replacements.end(); ++Rep) { diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp index 987474fd363fc..a4acee3481aaa 100644 --- a/lib/ParseSIL/ParseSIL.cpp +++ b/lib/ParseSIL/ParseSIL.cpp @@ -1102,7 +1102,7 @@ static bool parseDeclSILOptional(bool *isTransparent, // Drop the double quotes. StringRef rawString = SP.P.Tok.getText().drop_front().drop_back(); - Semantics->push_back(rawString); + Semantics->push_back(rawString.str()); SP.P.consumeToken(tok::string_literal); SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list); diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp index 943a1dad7babe..512cc4e66411c 100644 --- a/lib/RemoteAST/RemoteAST.cpp +++ b/lib/RemoteAST/RemoteAST.cpp @@ -133,7 +133,7 @@ class RemoteASTContextImpl { return getOffsetOfTupleElement(tupleType, optMetadata, memberName); } else { return Result::emplaceFailure(Failure::TypeHasNoSuchMember, - memberName); + memberName.str()); } } @@ -207,7 +207,7 @@ class RemoteASTContextImpl { // Use a specialized diagnostic if we couldn't find any such member. if (!member) { - return fail(Failure::TypeHasNoSuchMember, memberName); + return fail(Failure::TypeHasNoSuchMember, memberName.str()); } return fail(Failure::Unknown); @@ -329,7 +329,7 @@ class RemoteASTContextImpl { unsigned targetIndex; if (memberName.getAsInteger(10, targetIndex) || targetIndex >= type->getNumElements()) - return fail(Failure::TypeHasNoSuchMember, memberName); + return fail(Failure::TypeHasNoSuchMember, memberName.str()); // Fast path: element 0 is always at offset 0. if (targetIndex == 0) diff --git a/lib/SIL/SILConstants.cpp b/lib/SIL/SILConstants.cpp index 093b55ed0af97..d31a35bde86e0 100644 --- a/lib/SIL/SILConstants.cpp +++ b/lib/SIL/SILConstants.cpp @@ -131,7 +131,7 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const { case RK_Closure: { SymbolicClosure *clo = getClosure(); SILFunction *target = clo->getTarget(); - std::string targetName = target->getName(); + std::string targetName = target->getName().str(); os << "closure: target: " << targetName; ArrayRef args = clo->getCaptures(); os << " captures [\n"; diff --git a/lib/SIL/SILCoverageMap.cpp b/lib/SIL/SILCoverageMap.cpp index 449ca98953129..6b4bed71bfecb 100644 --- a/lib/SIL/SILCoverageMap.cpp +++ b/lib/SIL/SILCoverageMap.cpp @@ -34,7 +34,7 @@ SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name, // Store a copy of the names so that we own the lifetime. CM->Filename = M.allocateCopy(Filename); CM->Name = M.allocateCopy(Name); - CM->PGOFuncName = M.allocateCopy(PGOFuncName); + CM->PGOFuncName = M.allocateCopy(PGOFuncName).str(); // Since we have two arrays, we need to manually tail allocate each of them, // rather than relying on the flexible array trick. diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp index b524432785176..d6de976bd5429 100644 --- a/lib/SIL/SILDeclRef.cpp +++ b/lib/SIL/SILDeclRef.cpp @@ -698,7 +698,7 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const { mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext()); return SS.str(); } - return namedClangDecl->getName(); + return namedClangDecl->getName().str(); } } } @@ -732,13 +732,13 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const { if (!NameA->Name.empty() && !isForeignToNativeThunk() && !isNativeToForeignThunk() && !isCurried) { - return NameA->Name; + return NameA->Name.str(); } // Use a given cdecl name for native-to-foreign thunks. if (auto CDeclA = getDecl()->getAttrs().getAttribute()) if (isNativeToForeignThunk()) { - return CDeclA->Name; + return CDeclA->Name.str(); } // Otherwise, fall through into the 'other decl' case. diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index fcdbcffd06c9f..f62c24b0e8a54 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -4884,7 +4884,7 @@ std::string SILGenFunction::getMagicFileString(SourceLoc loc) { auto path = getMagicFilePathString(loc); if (!getASTContext().LangOpts.EnableConcisePoundFile) - return path; + return path.str(); auto value = llvm::sys::path::filename(path).str(); value += " ("; diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index ed9b3c500cbc5..75d13470da839 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -29,7 +29,7 @@ SILGlobalVariable *SILGenModule::getSILGlobalVariable(VarDecl *gDecl, { auto SILGenName = gDecl->getAttrs().getAttribute(); if (SILGenName && !SILGenName->Name.empty()) { - mangledName = SILGenName->Name; + mangledName = SILGenName->Name.str(); } else { Mangle::ASTMangler NewMangler; mangledName = NewMangler.mangleGlobalVariableFull(gDecl); diff --git a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp index d00580b7c4c00..c6f21f5eff6f0 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -509,7 +509,7 @@ static Identifier getBinaryFunction(StringRef Name, SILType IntSILTy, auto IntTy = IntSILTy.castTo(); unsigned NumBits = IntTy->getWidth().getFixedWidth(); // Name is something like: add_Int64 - std::string NameStr = Name; + std::string NameStr(Name); NameStr += "_Int" + llvm::utostr(NumBits); return C.getIdentifier(NameStr); } diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index 1aff133106e81..00ed41f14eb8c 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -351,7 +351,7 @@ DIMemoryObjectInfo::getPathStringToElement(unsigned Element, Result = "self"; else if (ValueDecl *VD = dyn_cast_or_null(getLoc().getAsASTNode())) - Result = VD->getBaseName().getIdentifier().str(); + Result = std::string(VD->getBaseName().getIdentifier()); else Result = ""; diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 1574b966d0e12..7ff49267d79f4 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -2111,7 +2111,7 @@ static Identifier getBinaryFunction(StringRef Name, SILType IntSILTy, auto IntTy = IntSILTy.castTo(); unsigned NumBits = IntTy->getWidth().getFixedWidth(); // Name is something like: add_Int64 - std::string NameStr = Name; + std::string NameStr(Name); NameStr += "_Int" + llvm::utostr(NumBits); return C.getIdentifier(NameStr); diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index ef2e70b71957f..4fb639128dbff 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -738,7 +738,7 @@ void SILPassManager::resetAndRemoveTransformations() { } void SILPassManager::setStageName(llvm::StringRef NextStage) { - StageName = NextStage; + StageName = NextStage.str(); } StringRef SILPassManager::getStageName() const { @@ -940,7 +940,7 @@ namespace llvm { std::string getNodeLabel(const CallGraph::Node *Node, const CallGraph *Graph) { - std::string Label = Node->F->getName(); + std::string Label = Node->F->getName().str(); wrap(Label, Node->NumCallSites); return Label; } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index f16fb16bdbe17..7ee28d115d83d 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -5473,7 +5473,7 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { // comparison with nil is illegal, albeit for different reasons spelled // out by the diagnosis. if (isa(lhs) || isa(rhs)) { - std::string revisedName = name.str(); + std::string revisedName = std::string(name); revisedName.pop_back(); auto loc = binaryOp->getLoc(); @@ -5600,7 +5600,7 @@ bool ArgumentMismatchFailure::diagnoseArchetypeMismatch() const { OS << " '" << decl->getFullName() << "'"; } - return OS.str(); + return std::string(OS.str()); }; emitDiagnostic( diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp index bb38a77300d7c..fd720d702193e 100644 --- a/lib/Sema/CalleeCandidateInfo.cpp +++ b/lib/Sema/CalleeCandidateInfo.cpp @@ -568,7 +568,7 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn, if (auto declRefExpr = dyn_cast(fn)) { auto decl = declRefExpr->getDecl(); candidates.push_back({ decl, skipCurriedSelf(decl) }); - declName = decl->getBaseName().userFacingName(); + declName = decl->getBaseName().userFacingName().str(); return; } @@ -589,7 +589,7 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn, } if (!candidates.empty()) - declName = candidates[0].getDecl()->getBaseName().userFacingName(); + declName = candidates[0].getDecl()->getBaseName().userFacingName().str(); return; } @@ -677,7 +677,7 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn, // base uncurried by one level, and we refer to the name of the member, not to // the name of any base. if (auto UDE = dyn_cast(fn)) { - declName = UDE->getName().getBaseName().userFacingName(); + declName = UDE->getName().getBaseName().userFacingName().str(); hasCurriedSelf = true; // If base is a module or metatype, this is just a simple @@ -738,7 +738,7 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn, if (candidates.empty()) continue; if (declName.empty()) - declName = candidates[0].getDecl()->getBaseName().userFacingName(); + declName = candidates[0].getDecl()->getBaseName().userFacingName().str(); return; } @@ -873,7 +873,7 @@ CalleeCandidateInfo::CalleeCandidateInfo(Type baseType, } if (!candidates.empty()) - declName = candidates[0].getDecl()->getBaseName().userFacingName(); + declName = candidates[0].getDecl()->getBaseName().userFacingName().str(); } CalleeCandidateInfo &CalleeCandidateInfo:: diff --git a/lib/Sema/InstrumenterSupport.cpp b/lib/Sema/InstrumenterSupport.cpp index 9cac1aeb20bd7..1041651892ff2 100644 --- a/lib/Sema/InstrumenterSupport.cpp +++ b/lib/Sema/InstrumenterSupport.cpp @@ -82,7 +82,8 @@ InstrumenterBase::InstrumenterBase(ASTContext &C, DeclContext *DC) const std::string filePrefix = "_pg_file_"; // Setup Module identifier - std::string moduleName = TypeCheckDC->getParentModule()->getName().str(); + std::string moduleName = + std::string(TypeCheckDC->getParentModule()->getName()); Identifier moduleIdentifier = Context.getIdentifier(builtinPrefix + modulePrefix + moduleName); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 483c9db23cb4d..dfc006b48f034 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1048,7 +1048,7 @@ static std::string getDeclNameFromContext(DeclContext *dc, } return result; } else { - return nominal->getName().str(); + return std::string(nominal->getName()); } } diff --git a/lib/Serialization/SerializeDoc.cpp b/lib/Serialization/SerializeDoc.cpp index 5947e1b5c7495..3fa8c010b81cb 100644 --- a/lib/Serialization/SerializeDoc.cpp +++ b/lib/Serialization/SerializeDoc.cpp @@ -64,7 +64,7 @@ class YamlGroupInputParser { if (!ParentName.empty()) { CombinedName = (llvm::Twine(ParentName) + Separator + GroupName).str(); } else { - CombinedName = GroupName; + CombinedName = GroupName.str(); } for (llvm::yaml::Node &Entry : *Value) { @@ -75,7 +75,7 @@ class YamlGroupInputParser { GroupNameAndFileName.append(CombinedName); GroupNameAndFileName.append(Separator); GroupNameAndFileName.append(llvm::sys::path::stem(FileName)); - Map[FileName] = GroupNameAndFileName.str(); + Map[FileName] = std::string(GroupNameAndFileName); } else if (Entry.getType() == llvm::yaml::Node::NodeKind::NK_Mapping) { if (parseRoot(Map, &Entry, CombinedName)) return true; diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 1e9594f75ed15..8cd863cde09ba 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -433,7 +433,7 @@ std::string SerializedModuleBaseName::getName(file_types::ID fileTy) const { result += '.'; result += file_types::getExtension(fileTy); - return result.str(); + return std::string(result); } bool diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index 675c9d2a3faea..7c5607e908600 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -282,7 +282,7 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdPrevious(StringRef name, if (!IntroVer.hasValue()) continue; auto PlatformNumber = getLinkerPlatformId(Ver); - auto It = previousInstallNameMap->find(Ver.ModuleName); + auto It = previousInstallNameMap->find(Ver.ModuleName.str()); if (It == previousInstallNameMap->end()) { Ctx.Diags.diagnose(SourceLoc(), diag::cannot_find_install_name, Ver.ModuleName, getLinkerPlatformName(Ver)); diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp index b2e2a7d27afbd..84f1226c95e87 100644 --- a/stdlib/public/Reflection/TypeRefBuilder.cpp +++ b/stdlib/public/Reflection/TypeRefBuilder.cpp @@ -88,7 +88,7 @@ TypeRefBuilder::normalizeReflectionName(RemoteRef reflectionName) { } // Fall back to the raw string. - return getTypeRefString(reflectionName); + return getTypeRefString(reflectionName).str(); } /// Determine whether the given reflection protocol name matches. @@ -106,7 +106,7 @@ lookupTypeWitness(const std::string &MangledTypeName, TypeRefID key; key.addString(MangledTypeName); key.addString(Member); - key.addString(Protocol); + key.addString(Protocol.str()); auto found = AssociatedTypeCache.find(key); if (found != AssociatedTypeCache.end()) return found->second; @@ -128,7 +128,8 @@ lookupTypeWitness(const std::string &MangledTypeName, for (auto &AssocTyRef : *AssocTyDescriptor.getLocalBuffer()) { auto AssocTy = AssocTyDescriptor.getField(AssocTyRef); if (Member.compare( - getTypeRefString(readTypeRef(AssocTy, AssocTy->Name))) != 0) + getTypeRefString(readTypeRef(AssocTy, AssocTy->Name)).str()) != + 0) continue; auto SubstitutedTypeName = readTypeRef(AssocTy, @@ -218,7 +219,7 @@ bool TypeRefBuilder::getFieldTypeRefs( // Empty cases of enums do not have a type if (FD->isEnum() && !Field->hasMangledTypeName()) { - Fields.push_back(FieldTypeInfo::forEmptyCase(FieldName)); + Fields.push_back(FieldTypeInfo::forEmptyCase(FieldName.str())); continue; } @@ -230,11 +231,12 @@ bool TypeRefBuilder::getFieldTypeRefs( auto Substituted = Unsubstituted->subst(*this, *Subs); if (FD->isEnum() && Field->isIndirectCase()) { - Fields.push_back(FieldTypeInfo::forIndirectCase(FieldName, Substituted)); + Fields.push_back( + FieldTypeInfo::forIndirectCase(FieldName.str(), Substituted)); continue; } - Fields.push_back(FieldTypeInfo::forField(FieldName, Substituted)); + Fields.push_back(FieldTypeInfo::forField(FieldName.str(), Substituted)); } return true; } @@ -320,7 +322,7 @@ TypeRefBuilder::getClosureContextInfo(RemoteRef CD) { if (MSR->hasMangledMetadataSource()) { auto MangledMetadataSource = getTypeRefString(readTypeRef(MSR, MSR->MangledMetadataSource)); - MS = MetadataSource::decode(MSB, MangledMetadataSource); + MS = MetadataSource::decode(MSB, MangledMetadataSource.str()); } Info.MetadataSources.push_back({TR, MS}); @@ -391,9 +393,10 @@ void TypeRefBuilder::dumpAssociatedTypeSection(FILE *file) { for (const auto &associatedTypeRef : *descriptor.getLocalBuffer()) { auto associatedType = descriptor.getField(associatedTypeRef); - - std::string name = getTypeRefString( - readTypeRef(associatedType, associatedType->Name)); + + std::string name = + getTypeRefString(readTypeRef(associatedType, associatedType->Name)) + .str(); fprintf(file, "typealias %s = ", name.c_str()); dumpTypeRef( readTypeRef(associatedType, associatedType->SubstitutedTypeName), file); diff --git a/tools/SourceKit/include/SourceKit/Support/Logging.h b/tools/SourceKit/include/SourceKit/Support/Logging.h index 662577be9f320..0421e319a167a 100644 --- a/tools/SourceKit/include/SourceKit/Support/Logging.h +++ b/tools/SourceKit/include/SourceKit/Support/Logging.h @@ -67,7 +67,7 @@ class Logger : public llvm::RefCountedBase { return LoggingLevel >= LogLevel; } static void enableLogging(StringRef Name, Level LogLevel) { - LoggerName = Name; + LoggerName = Name.str(); LoggingLevel = LogLevel; } diff --git a/tools/SourceKit/lib/Core/NotificationCenter.cpp b/tools/SourceKit/lib/Core/NotificationCenter.cpp index e7e2e163a7ffc..c6fdfac609e21 100644 --- a/tools/SourceKit/lib/Core/NotificationCenter.cpp +++ b/tools/SourceKit/lib/Core/NotificationCenter.cpp @@ -34,8 +34,8 @@ void NotificationCenter::postDocumentUpdateNotification( { llvm::sys::ScopedLock L(Mtx); recvs = DocUpdReceivers; - } - std::string docName = DocumentName; + } + std::string docName = DocumentName.str(); auto sendNote = [recvs, docName]{ for (auto &Fn : recvs) Fn(docName); diff --git a/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp b/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp index 69e9725b7f455..460ef667f8a16 100644 --- a/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp +++ b/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp @@ -124,7 +124,7 @@ bool ImmutableTextSnapshot::foreachReplaceUntil( static std::atomic Generation{ 0 }; EditableTextBuffer::EditableTextBuffer(StringRef Filename, StringRef Text) { - this->Filename = Filename; + this->Filename = Filename.str(); Root = new ImmutableTextBuffer(Filename, Text, ++Generation); CurrUpd = Root; } diff --git a/tools/SourceKit/lib/Support/UIDRegistry.cpp b/tools/SourceKit/lib/Support/UIDRegistry.cpp index 023268de3caf6..a6f0a057c768f 100644 --- a/tools/SourceKit/lib/Support/UIDRegistry.cpp +++ b/tools/SourceKit/lib/Support/UIDRegistry.cpp @@ -10,9 +10,10 @@ // //===----------------------------------------------------------------------===// -#include "SourceKit/Support/UIdent.h" #include "SourceKit/Support/Concurrency.h" +#include "SourceKit/Support/UIdent.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index f07046c625cff..0ed7876b1739a 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -396,15 +396,15 @@ static StringRef copyString(llvm::BumpPtrAllocator &allocator, StringRef str) { static std::unique_ptr make_group(StringRef name) { auto g = std::make_unique(); - g->name = name; - g->description = name; + g->name = name.str(); + g->description = name.str(); return g; } static std::unique_ptr make_result(Completion *result) { auto r = std::make_unique(result); - r->name = result->getName(); - r->description = result->getDescription(); + r->name = result->getName().str(); + r->description = result->getDescription().str(); return r; } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 1e2b1fd10a211..9448f5abef40f 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -461,7 +461,7 @@ static FrontendInputsAndOutputs resolveSymbolicLinksInInputs( llvm::SmallString<64> Err; llvm::raw_svector_ostream OS(Err); OS << "'" << PrimaryFile << "' is not part of the input files"; - Error = OS.str(); + Error = std::string(OS.str()); return replacementInputsAndOutputs; } @@ -501,7 +501,7 @@ bool SwiftASTManager::initCompilerInvocation( Diags.removeConsumer(DiagConsumer); if (HadError) { - Error = ErrOS.str(); + Error = std::string(ErrOS.str()); return true; } @@ -683,7 +683,7 @@ static FileContent getFileContentFromSnap(ImmutableTextSnapshotRef Snap, bool IsPrimary, StringRef FilePath) { auto Buf = llvm::MemoryBuffer::getMemBufferCopy( Snap->getBuffer()->getText(), FilePath); - return FileContent(Snap, FilePath, std::move(Buf), IsPrimary, + return FileContent(Snap, FilePath.str(), std::move(Buf), IsPrimary, Snap->getStamp()); } @@ -699,8 +699,8 @@ FileContent SwiftASTManager::Implementation::getFileContent( // FIXME: Is there a way to get timestamp and buffer for a file atomically ? auto Stamp = getBufferStamp(FilePath, FileSystem); auto Buffer = getMemoryBuffer(FilePath, FileSystem, Error); - return FileContent(nullptr, UnresolvedPath, std::move(Buffer), IsPrimary, - Stamp); + return FileContent(nullptr, UnresolvedPath.str(), std::move(Buffer), + IsPrimary, Stamp); } BufferStamp SwiftASTManager::Implementation::getBufferStamp( @@ -902,7 +902,7 @@ static void collectModuleDependencies(ModuleDecl *TopMod, // getModuleFilename() (by returning an empty path). Note that such modules // may be heterogeneous. { - std::string Path = Mod->getModuleFilename(); + std::string Path = Mod->getModuleFilename().str(); if (Path.empty() || Path == TopMod->getModuleFilename()) continue; // this is a submodule. Filenames.push_back(std::move(Path)); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index f5a716ad61775..d63acacb0a14e 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -1064,7 +1064,7 @@ static void transformAndForwardResults( }); auto *inputBuf = session->getBuffer(); - std::string str = inputBuf->getBuffer().slice(0, offset); + std::string str = inputBuf->getBuffer().slice(0, offset).str(); { llvm::raw_string_ostream OSS(str); SwiftToSourceKitCompletionAdapter::getResultSourceText( diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp index 9e7616216ddab..943998dbe32e1 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp @@ -274,7 +274,7 @@ static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) { if (GP->getDecl()->isImplicit()) continue; DocGenericParam Param; - Param.Name = GP->getName().str(); + Param.Name = std::string(GP->getName()); Info.GenericParams.push_back(Param); } @@ -959,7 +959,7 @@ static bool getModuleInterfaceInfo(ASTContext &Ctx, StringRef ModuleName, AnnotatingPrinter Printer(OS); printModuleInterface(M, None, TraversalOptions, Printer, Options, true); - Info.Text = OS.str(); + Info.Text = std::string(OS.str()); Info.TopEntities = std::move(Printer.TopEntities); Info.References = std::move(Printer.References); return false; @@ -1080,7 +1080,7 @@ static bool getSourceTextInfo(CompilerInstance &CI, Walker.walk(*CI.getMainModule()); CharSourceRange FullRange = SM.getRangeForBuffer(BufID); - Info.Text = SM.extractText(FullRange); + Info.Text = SM.extractText(FullRange).str(); Info.TopEntities = std::move(Walker.TopEntities); Info.References = std::move(Walker.References); return false; @@ -1168,8 +1168,8 @@ class RequestRefactoringEditConsumer::Implementation { R.StartLine, R.StartColumn, R.EndLine, R.EndColumn, R.ArgIndex }; }); - return {Start.first, Start.second, End.first, End.second, R.Text, - std::move(SubRanges)}; + return {Start.first, Start.second, End.first, + End.second, R.Text.str(), std::move(SubRanges)}; }); unsigned End = AllEdits.size(); StartEnds.emplace_back(Start, End); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 8914b992bcc22..b24d9183ec249 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -108,7 +108,7 @@ void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString, Info.FormatArgs); } - SKInfo.Description = Text.str(); + SKInfo.Description = std::string(Text); Optional BufferIDOpt; if (Info.Loc.isValid()) { @@ -148,7 +148,7 @@ void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, SKInfo.Offset = SM.getLocOffsetInBuffer(Info.Loc, BufferID); std::tie(SKInfo.Line, SKInfo.Column) = SM.getLineAndColumn(Info.Loc, BufferID); - SKInfo.Filename = SM.getDisplayNameForLoc(Info.Loc); + SKInfo.Filename = SM.getDisplayNameForLoc(Info.Loc).str(); for (auto R : Info.Ranges) { if (R.isInvalid() || SM.findBufferContainingLoc(R.getStart()) != BufferID) @@ -165,7 +165,7 @@ void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, unsigned Offset = SM.getLocOffsetInBuffer(F.getRange().getStart(), BufferID); unsigned Length = F.getRange().getByteLength(); - SKInfo.Fixits.push_back({Offset, Length, F.getText()}); + SKInfo.Fixits.push_back({Offset, Length, F.getText().str()}); } } else { SKInfo.Filename = ""; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp index 475629e4a22db..7275933fb6b2c 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp @@ -137,7 +137,7 @@ class AnnotatingPrinter : public StreamPrinter { llvm::raw_svector_ostream OS(Buf); auto TargetNTD = Target.getBaseNominal(); if (!SwiftLangSupport::printUSR(TargetNTD, OS)) { - TargetUSR = OS.str(); + TargetUSR = std::string(OS.str()); } } @@ -336,7 +336,7 @@ static bool getModuleInterfaceInfo(ASTContext &Ctx, Printer, Options, Group.hasValue() && SynthesizedExtensions); - Info.Text = OS.str(); + Info.Text = std::string(OS.str()); return false; } @@ -356,7 +356,7 @@ static bool getHeaderInterfaceInfo(ASTContext &Ctx, AnnotatingPrinter Printer(Info, OS); printHeaderInterface(HeaderName, Ctx, Printer, Options); - Info.Text = OS.str(); + Info.Text = std::string(OS.str()); return false; } @@ -367,9 +367,9 @@ SwiftInterfaceGenContext::createForSwiftSource(StringRef DocumentName, CompilerInvocation Invocation, std::string &ErrMsg) { SwiftInterfaceGenContextRef IFaceGenCtx{ new SwiftInterfaceGenContext() }; - IFaceGenCtx->Impl.DocumentName = DocumentName; + IFaceGenCtx->Impl.DocumentName = DocumentName.str(); IFaceGenCtx->Impl.IsModule = true; - IFaceGenCtx->Impl.ModuleOrHeaderName = SourceFileName; + IFaceGenCtx->Impl.ModuleOrHeaderName = SourceFileName.str(); IFaceGenCtx->Impl.AstUnit = AstUnit; PrintOptions Options = PrintOptions::printSwiftFileInterface(); @@ -377,7 +377,7 @@ SwiftInterfaceGenContext::createForSwiftSource(StringRef DocumentName, llvm::raw_svector_ostream OS(Text); AnnotatingPrinter Printer(IFaceGenCtx->Impl.Info, OS); printSwiftSourceInterface(AstUnit->getPrimarySourceFile(), Printer, Options); - IFaceGenCtx->Impl.Info.Text = OS.str(); + IFaceGenCtx->Impl.Info.Text = std::string(OS.str()); if (makeParserAST(IFaceGenCtx->Impl.TextCI, IFaceGenCtx->Impl.Info.Text, Invocation)) { ErrMsg = "Error during syntactic parsing"; @@ -396,9 +396,9 @@ SwiftInterfaceGenContext::create(StringRef DocumentName, bool SynthesizedExtensions, Optional InterestedUSR) { SwiftInterfaceGenContextRef IFaceGenCtx{ new SwiftInterfaceGenContext() }; - IFaceGenCtx->Impl.DocumentName = DocumentName; + IFaceGenCtx->Impl.DocumentName = DocumentName.str(); IFaceGenCtx->Impl.IsModule = IsModule; - IFaceGenCtx->Impl.ModuleOrHeaderName = ModuleOrHeaderName; + IFaceGenCtx->Impl.ModuleOrHeaderName = ModuleOrHeaderName.str(); IFaceGenCtx->Impl.Invocation = Invocation; CompilerInstance &CI = IFaceGenCtx->Impl.Instance; @@ -457,7 +457,7 @@ SwiftInterfaceGenContext::createForTypeInterface(CompilerInvocation Invocation, std::string &ErrorMsg) { SwiftInterfaceGenContextRef IFaceGenCtx{ new SwiftInterfaceGenContext() }; IFaceGenCtx->Impl.IsModule = false; - IFaceGenCtx->Impl.ModuleOrHeaderName = TypeUSR; + IFaceGenCtx->Impl.ModuleOrHeaderName = TypeUSR.str(); IFaceGenCtx->Impl.Invocation = Invocation; CompilerInstance &CI = IFaceGenCtx->Impl.Instance; SourceTextInfo &Info = IFaceGenCtx->Impl.Info; @@ -491,7 +491,7 @@ SwiftInterfaceGenContext::createForTypeInterface(CompilerInvocation Invocation, if (ide::printTypeInterface(Module, TypeUSR, Printer, IFaceGenCtx->Impl.DocumentName, ErrorMsg)) return nullptr; - IFaceGenCtx->Impl.Info.Text = OS.str(); + IFaceGenCtx->Impl.Info.Text = std::string(OS.str()); if (makeParserAST(IFaceGenCtx->Impl.TextCI, IFaceGenCtx->Impl.Info.Text, Invocation)) { ErrorMsg = "Error during syntactic parsing"; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp index 8c74396273932..95279377493a0 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp @@ -217,7 +217,7 @@ static void initTraceInfoImpl(trace::SwiftInvocation &SwiftArgs, ArrayRef Args) { llvm::raw_string_ostream OS(SwiftArgs.Args.Arguments); interleave(Args, [&OS](StringRef arg) { OS << arg; }, [&OS] { OS << ' '; }); - SwiftArgs.Args.PrimaryFile = InputFile; + SwiftArgs.Args.PrimaryFile = InputFile.str(); } void trace::initTraceInfo(trace::SwiftInvocation &SwiftArgs, diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp index 6ae23afd709ce..4feb051df26e7 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp @@ -262,7 +262,7 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) CCCache(new SwiftCompletionCache) { llvm::SmallString<128> LibPath(SKCtx.getRuntimeLibPath()); llvm::sys::path::append(LibPath, "swift"); - RuntimeResourcePath = LibPath.str(); + RuntimeResourcePath = std::string(LibPath); Stats = std::make_shared(); EditorDocuments = std::make_shared(); @@ -897,11 +897,11 @@ void SwiftLangSupport::printMemberDeclDescription(const swift::ValueDecl *VD, } std::string SwiftLangSupport::resolvePathSymlinks(StringRef FilePath) { - std::string InputPath = FilePath; + std::string InputPath = FilePath.str(); llvm::SmallString<256> output; if (llvm::sys::fs::real_path(InputPath, output)) return InputPath; - return output.str(); + return std::string(output); } void SwiftLangSupport::getStatistics(StatisticsReceiver receiver) { diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp index 92db039a37e85..1813dafadc3fc 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp @@ -631,7 +631,7 @@ static bool passCursorInfoForModule(ModuleEntity Mod, SwiftInterfaceGenMap &IFaceGenContexts, const CompilerInvocation &Invok, std::function &)> Receiver) { - std::string Name = Mod.getName(); + std::string Name = Mod.getName().str(); std::string FullName = Mod.getFullName(); CursorInfoData Info; Info.Kind = SwiftLangSupport::getUIDForModuleRef(); @@ -916,7 +916,7 @@ static bool passCursorInfoForDecl(SourceFile* SF, if (ClangMod) ModuleName = ClangMod->getFullModuleName(); } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) { - ModuleName = VD->getModuleContext()->getName().str(); + ModuleName = std::string(VD->getModuleContext()->getName()); } StringRef ModuleInterfaceName; if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok)) @@ -2165,7 +2165,7 @@ semanticRefactoring(StringRef Filename, SemanticRefactoringInfo Info, Opts.Range.Line = Info.Line; Opts.Range.Column = Info.Column; Opts.Range.Length = Info.Length; - Opts.PreferredName = Info.PreferredName; + Opts.PreferredName = Info.PreferredName.str(); RequestRefactoringEditConsumer EditConsumer(Receiver); refactorSwiftModule(MainModule, Opts, EditConsumer, EditConsumer); diff --git a/tools/SourceKit/tools/complete-test/complete-test.cpp b/tools/SourceKit/tools/complete-test/complete-test.cpp index 3579a813e3112..7bab09ad673b8 100644 --- a/tools/SourceKit/tools/complete-test/complete-test.cpp +++ b/tools/SourceKit/tools/complete-test/complete-test.cpp @@ -253,7 +253,7 @@ static bool parseOptions(ArrayRef args, TestOptions &options, } options.showTopNonLiteral = uval; } else if (opt == "module-cache-path") { - options.moduleCachePath = value; + options.moduleCachePath = value.str(); } } @@ -403,7 +403,7 @@ removeCodeCompletionTokens(StringRef Input, StringRef TokenName, StringRef next = StringRef(fullMatch).split(',').second; while (next != "") { auto split = next.split(','); - prefixes.push_back(split.first); + prefixes.push_back(split.first.str()); next = split.second; } } @@ -695,7 +695,7 @@ static bool codeCompleteRequest(sourcekitd_uid_t requestUID, const char *name, static bool readPopularAPIList(StringRef filename, std::vector &result) { - std::ifstream in(filename); + std::ifstream in(filename.str()); if (!in.is_open()) { llvm::errs() << "error opening '" << filename << "'\n"; return true; diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp index 2188f711a48dc..d326c98491b8f 100644 --- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp +++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp @@ -290,7 +290,7 @@ static inline std::string getInterfaceGenDocumentName() { llvm::SmallString<64> path = llvm::StringRef("/"); llvm::sys::fs::make_absolute(path); llvm::sys::path::native(path); - return path.str(); + return std::string(path); } static int printAnnotations(); @@ -305,7 +305,7 @@ static void addCodeCompleteOptions(sourcekitd_object_t Req, TestOptions &Opts) { for (auto &Opt : Opts.RequestOptions) { auto KeyValue = StringRef(Opt).split('='); std::string KeyStr("key.codecomplete."); - KeyStr.append(KeyValue.first); + KeyStr.append(KeyValue.first.str()); sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str()); // FIXME: more robust way to determine the option type. @@ -326,7 +326,7 @@ static void addCodeCompleteOptions(sourcekitd_object_t Req, TestOptions &Opts) { static bool readPopularAPIList(StringRef filename, std::vector &result) { - std::ifstream in(filename); + std::ifstream in(filename.str()); if (!in.is_open()) { llvm::errs() << "error opening '" << filename << "'\n"; return true; @@ -441,7 +441,7 @@ static int setExpectedTypes(const sourcekitd_test::TestOptions &Opts, auto typenames = sourcekitd_request_array_create(nullptr, 0); for (auto &name : expectedTypeNames) { - std::string n = name; + std::string n = name.str(); sourcekitd_request_array_set_string(typenames, SOURCEKITD_ARRAY_APPEND, n.c_str()); } sourcekitd_request_dictionary_set_value(Req, KeyExpectedTypes, typenames); @@ -489,13 +489,13 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) { AbsSourceFile += SourceFile; llvm::sys::fs::make_absolute(AbsSourceFile); llvm::sys::path::native(AbsSourceFile); - SourceFile = AbsSourceFile.str(); + SourceFile = std::string(AbsSourceFile); } std::string SemaName = !Opts.Name.empty() ? Opts.Name : SourceFile; if (!Opts.TextInputFile.empty()) { auto Buf = getBufferForFilename(Opts.TextInputFile, Opts.VFSFiles); - Opts.SourceText = Buf->getBuffer(); + Opts.SourceText = Buf->getBuffer().str(); } std::unique_ptr SourceBuf; @@ -755,13 +755,13 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) { return 1; } if (!BaseName.empty()) { - std::string S = BaseName; + std::string S = BaseName.str(); sourcekitd_request_dictionary_set_string(Req, KeyBaseName, S.c_str()); } if (!ArgPieces.empty()) { sourcekitd_object_t Arr = sourcekitd_request_array_create(nullptr, 0); for (StringRef A : ArgPieces) { - std::string S = A; + std::string S = A.str(); sourcekitd_request_array_set_string(Arr, SOURCEKITD_ARRAY_APPEND, S.c_str()); } @@ -1278,7 +1278,7 @@ static bool handleResponse(sourcekitd_response_t Resp, const TestOptions &Opts, for (auto &FmtOpt : Opts.RequestOptions) { auto KeyValue = StringRef(FmtOpt).split('='); std::string KeyStr("key.editor.format."); - KeyStr.append(KeyValue.first); + KeyStr.append(KeyValue.first.str()); sourcekitd_uid_t Key = sourcekitd_uid_get_from_cstr(KeyStr.c_str()); int64_t Value = 0; KeyValue.second.getAsInteger(0, Value); @@ -1476,10 +1476,10 @@ static void printCursorInfo(sourcekitd_variant_t Info, StringRef FilenameIn, return; } - std::string Filename = FilenameIn; + std::string Filename = FilenameIn.str(); llvm::SmallString<256> output; if (!llvm::sys::fs::real_path(Filename, output)) - Filename = output.str(); + Filename = std::string(output); const char *Kind = sourcekitd_uid_get_string_ptr(KindUID); const char *USR = sourcekitd_variant_dictionary_get_string(Info, KeyUSR); @@ -1648,10 +1648,10 @@ static void printRangeInfo(sourcekitd_variant_t Info, StringRef FilenameIn, return; } - std::string Filename = FilenameIn; + std::string Filename = FilenameIn.str(); llvm::SmallString<256> output; if (llvm::sys::fs::real_path(Filename, output)) - Filename = output.str(); + Filename = std::string(output); sourcekitd_variant_t OffsetObj = sourcekitd_variant_dictionary_get_value(Info, KeyOffset); diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp index 67d1e8cc72872..3afed31e7c9ca 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp @@ -101,7 +101,7 @@ std::string sourcekitd::getRuntimeLibPath() { llvm_unreachable("Call to dladdr() failed"); // We now have the path to the shared lib, move to the parent 'lib' path. - return llvm::sys::path::parent_path(info.dli_fname); + return llvm::sys::path::parent_path(info.dli_fname).str(); #endif } diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp index 9c80853ae2f6b..c14c0b248fc46 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp @@ -204,7 +204,7 @@ std::string sourcekitd::getRuntimeLibPath() { StringRef Path = MainExePath; for (unsigned i = 0; i < MainExeLibNestingLevel; ++i) Path = llvm::sys::path::parent_path(Path); - return Path; + return Path.str(); } static void sourcekitdServer_peer_event_handler(xpc_connection_t peer, diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp index bd8faa51058ab..63b622d4986d8 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp @@ -193,10 +193,10 @@ void DocStructureArrayBuilder::beginSubStructure( BodyLength, DocOffset, DocLength, - DisplayName, - TypeName, - RuntimeName, - SelectorName, + DisplayName.str(), + TypeName.str(), + RuntimeName.str(), + SelectorName.str(), impl.addInheritedTypes(InheritedTypes), impl.addAttrs(Attrs), {}, // elements diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index 483a2ac2998a0..a665c4e22d988 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -701,7 +701,7 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) { std::string swiftVer; Optional swiftVerValStr = Req.getString(KeySwiftVersion); if (swiftVerValStr.hasValue()) { - swiftVer = swiftVerValStr.getValue(); + swiftVer = swiftVerValStr.getValue().str(); } else { Optional swiftVerVal = Req.getOptionalInt64(KeySwiftVersion); if (swiftVerVal.hasValue()) @@ -833,7 +833,7 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) { err = createErrorRequestInvalid("missing 'key.name'"); return true; } - CCInfo.Name = *Name; + CCInfo.Name = (*Name).str(); sourcekitd_uid_t Kind = dict.getUID(KeyKind); if (!Kind) { @@ -1271,7 +1271,7 @@ static sourcekitd_response_t indexSource(StringRef Filename, } void SKIndexingConsumer::failed(StringRef ErrDescription) { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } bool SKIndexingConsumer::startDependency(UIdent Kind, @@ -1581,7 +1581,7 @@ void SKDocConsumer::addDocEntityInfoToDict(const DocEntityInfo &Info, } void SKDocConsumer::failed(StringRef ErrDescription) { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } bool SKDocConsumer::handleSourceText(StringRef Text) { @@ -1952,7 +1952,7 @@ codeComplete(llvm::MemoryBuffer *InputBuf, int64_t Offset, } void SKCodeCompletionConsumer::failed(StringRef ErrDescription) { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } void SKCodeCompletionConsumer::setCompletionKind(UIdent kind) { @@ -2131,7 +2131,7 @@ codeCompleteUpdate(StringRef name, int64_t offset, } void SKGroupedCodeCompletionConsumer::failed(StringRef ErrDescription) { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } bool SKGroupedCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) { @@ -2247,7 +2247,7 @@ static sourcekitd_response_t typeContextInfo(llvm::MemoryBuffer *InputBuf, } void failed(StringRef ErrDescription) override { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } bool isError() const { return ErrorDescription.hasValue(); } @@ -2300,7 +2300,7 @@ conformingMethodList(llvm::MemoryBuffer *InputBuf, int64_t Offset, } void failed(StringRef ErrDescription) override { - ErrorDescription = ErrDescription; + ErrorDescription = ErrDescription.str(); } bool isError() const { return ErrorDescription.hasValue(); } diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp index 7b0cd6eefb05e..3bf9d8894761c 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-Common.cpp @@ -786,7 +786,7 @@ bool YAMLRequestParser::parseArray(sourcekitd_object_t Array, void YAMLRequestParser::initError(StringRef Desc, llvm::yaml::Node *Node, std::string &Error) { - Error = Desc; + Error = Desc.str(); Error += " at: "; llvm::SMRange Range = Node->getSourceRange(); StringRef Text(Range.Start.getPointer(), diff --git a/tools/driver/autolink_extract_main.cpp b/tools/driver/autolink_extract_main.cpp index d025564f8e0de..76825313eb3f1 100644 --- a/tools/driver/autolink_extract_main.cpp +++ b/tools/driver/autolink_extract_main.cpp @@ -80,7 +80,8 @@ class AutolinkExtractInvocation { } if (ParsedArgs.getLastArg(OPT_help)) { - std::string ExecutableName = llvm::sys::path::stem(MainExecutablePath); + std::string ExecutableName = + llvm::sys::path::stem(MainExecutablePath).str(); Table->PrintHelp(llvm::outs(), ExecutableName.c_str(), "Swift Autolink Extract", options::AutolinkExtractOption, 0, /*ShowAllAliases*/false); @@ -138,7 +139,7 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile, SectionData->split(SplitFlags, llvm::StringRef("\0", 1), -1, /*KeepEmpty=*/false); for (const auto &Flag : SplitFlags) - LinkerFlags.push_back(Flag); + LinkerFlags.push_back(Flag.str()); } } return false; diff --git a/tools/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp index 57e4f64996613..adcaf542ff69a 100644 --- a/tools/driver/modulewrap_main.cpp +++ b/tools/driver/modulewrap_main.cpp @@ -90,7 +90,8 @@ class ModuleWrapInvocation { } if (ParsedArgs.getLastArg(OPT_help)) { - std::string ExecutableName = llvm::sys::path::stem(MainExecutablePath); + std::string ExecutableName = + llvm::sys::path::stem(MainExecutablePath).str(); Table->PrintHelp(llvm::outs(), ExecutableName.c_str(), "Swift Module Wrapper", options::ModuleWrapOption, 0, /*ShowAllAliases*/false); @@ -159,7 +160,7 @@ int modulewrap_main(ArrayRef Args, const char *Argv0, SmallString<128> RuntimeResourcePath; CompilerInvocation::computeRuntimeResourcePathFromExecutablePath( MainExecutablePath, RuntimeResourcePath); - SearchPathOpts.RuntimeResourcePath = RuntimeResourcePath.str(); + SearchPathOpts.RuntimeResourcePath = std::string(RuntimeResourcePath); SourceManager SrcMgr; TypeCheckerOptions TypeCheckOpts; diff --git a/tools/driver/swift_indent_main.cpp b/tools/driver/swift_indent_main.cpp index bb44ea8a085b4..d5280177a0ab7 100644 --- a/tools/driver/swift_indent_main.cpp +++ b/tools/driver/swift_indent_main.cpp @@ -147,7 +147,8 @@ class SwiftIndentInvocation { } if (ParsedArgs.getLastArg(OPT_help)) { - std::string ExecutableName = llvm::sys::path::stem(MainExecutablePath); + std::string ExecutableName = + llvm::sys::path::stem(MainExecutablePath).str(); Table->PrintHelp(llvm::outs(), ExecutableName.c_str(), "Swift Format Tool", options::SwiftIndentOption, 0, /*ShowAllAliases*/false); @@ -183,7 +184,7 @@ class SwiftIndentInvocation { LineRanges.push_back("1:" + std::to_string(UINT_MAX)); } - std::string Output = Doc.memBuffer().getBuffer(); + std::string Output = Doc.memBuffer().getBuffer().str(); for (unsigned Range = 0; Range < LineRanges.size(); ++Range) { unsigned FromLine; unsigned ToLine; diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp index e3dc90678712f..4523df82f1f42 100644 --- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp +++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp @@ -293,7 +293,7 @@ int main(int argc, char **argv) { // Infer SDK and Target triple from the module. if (!extendedInfo.getSDKPath().empty()) - Invocation.setSDKPath(extendedInfo.getSDKPath()); + Invocation.setSDKPath(extendedInfo.getSDKPath().str()); Invocation.setTargetTriple(info.targetTriple); Invocation.setModuleName("lldbtest"); diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp index 33d0082c8b352..43c0dcd0b25bd 100644 --- a/tools/sil-func-extractor/SILFunctionExtractor.cpp +++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp @@ -142,7 +142,7 @@ static void getFunctionNames(std::vector &Names) { if (Token.empty()) { break; } - Names.push_back(Token); + Names.push_back(Token.str()); Buffer = NewBuffer; } } @@ -153,12 +153,12 @@ static bool stringInSortedArray( llvm::function_ref &&cmp) { if (list.empty()) return false; - auto iter = std::lower_bound(list.begin(), list.end(), str, cmp); + auto iter = std::lower_bound(list.begin(), list.end(), str.str(), cmp); // If we didn't find str, return false. if (list.end() == iter) return false; - return !cmp(str, *iter); + return !cmp(str.str(), *iter); } void removeUnwantedFunctions(SILModule *M, ArrayRef MangledNames, diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp index 3f5fea81e5244..0174384085815 100644 --- a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp +++ b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp @@ -592,7 +592,7 @@ SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx, }; static auto getAsInt = [&](llvm::yaml::Node *N) -> int { - return std::stoi(cast(N)->getRawValue()); + return std::stoi(cast(N)->getRawValue().str()); }; static auto getAsBool = [&](llvm::yaml::Node *N) -> bool { auto txt = cast(N)->getRawValue(); diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index 3c71f54cd91fc..f6468b7366a59 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -125,7 +125,7 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name, // the old mangling scheme. // This makes it easier to share the same database between the // mangling and demangling tests. - remangled = name; + remangled = name.str(); } else { remangled = swift::Demangle::mangleNode(pointer); unsigned prefixLen = swift::Demangle::getManglingPrefixLength(remangled); @@ -148,7 +148,7 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name, llvm::outs() << remangled; return; } else if (RemangleRtMode) { - std::string remangled = name; + std::string remangled = name.str(); if (pointer) { remangled = swift::Demangle::mangleNodeOld(pointer); } diff --git a/tools/swift-ide-test/XMLValidator.cpp b/tools/swift-ide-test/XMLValidator.cpp index 48637acd0af2f..24f8985a3fef5 100644 --- a/tools/swift-ide-test/XMLValidator.cpp +++ b/tools/swift-ide-test/XMLValidator.cpp @@ -39,7 +39,7 @@ XMLValidator::~XMLValidator() { delete Impl; } void XMLValidator::setSchema(StringRef FileName) { assert(Impl->SchemaFileName.empty()); - Impl->SchemaFileName = FileName; + Impl->SchemaFileName = FileName.str(); } XMLValidator::Status XMLValidator::validate(const std::string &XML) { diff --git a/tools/swift-refactor/swift-refactor.cpp b/tools/swift-refactor/swift-refactor.cpp index 22c885b97c2cb..690e16c23eabf 100644 --- a/tools/swift-refactor/swift-refactor.cpp +++ b/tools/swift-refactor/swift-refactor.cpp @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) { SourceManager &SM = SF->getASTContext().SourceMgr; unsigned BufferID = SF->getBufferID().getValue(); - std::string Buffer = SM.getRangeForBuffer(BufferID).str(); + std::string Buffer = SM.getRangeForBuffer(BufferID).str().str(); auto Start = getLocsByLabelOrPosition(options::LineColumnPair, Buffer); if (Start.empty()) { From 1fa3a310131845ddf5169ec606500371f5904c7d Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Tue, 4 Feb 2020 18:02:35 -0800 Subject: [PATCH 014/625] [SourceKit] Adjust for LLVM StringRef change (#29625) StringRef needs an explicit conversion to std::string now. --- .../tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp | 2 +- .../tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp index 3afed31e7c9ca..13c8a7c245168 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp @@ -93,7 +93,7 @@ std::string sourcekitd::getRuntimeLibPath() { llvm_unreachable("call to GetModuleFileNameA failed"); libPath = llvm::sys::path::parent_path(llvm::sys::path::parent_path(path)); llvm::sys::path::append(libPath, "lib"); - return libPath.str(); + return libPath.str().str(); #else // This silly cast below avoids a C++ warning. Dl_info info; diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp index fe93d733c538b..a1324125c6019 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-InProc.cpp @@ -633,7 +633,7 @@ void ResponseBuilder::Dictionary::set(UIdent Key, const char *Str) { void ResponseBuilder::Dictionary::set(UIdent Key, StringRef Str) { static_cast(Impl)->set(SKDUIDFromUIdent(Key), - new SKDString(Str)); + new SKDString(std::string(Str))); } void ResponseBuilder::Dictionary::set(UIdent Key, const std::string &Str) { @@ -649,7 +649,7 @@ void ResponseBuilder::Dictionary::set(SourceKit::UIdent Key, ArrayRef Strs) { auto ArrayObject = new SKDArray(); for (auto Str : Strs) { - ArrayObject->set(SOURCEKITD_ARRAY_APPEND, new SKDString(Str)); + ArrayObject->set(SOURCEKITD_ARRAY_APPEND, new SKDString(std::string(Str))); } static_cast(Impl)->set(SKDUIDFromUIdent(Key), ArrayObject); } From 3d3e19223b58abc4eaab1576ff3f82d9024216f3 Mon Sep 17 00:00:00 2001 From: Puyan Lotfi Date: Mon, 10 Feb 2020 18:23:20 -0500 Subject: [PATCH 015/625] Handling strict conversion criteria for StringRef to std::string from TOT llvm. --- lib/Frontend/ModuleInterfaceBuilder.cpp | 2 +- tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 83a89487ea32f..b276ecd961cd9 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -346,7 +346,7 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( // Setup the callbacks for serialization, which can occur during the // optimization pipeline. SerializationOptions SerializationOpts; - std::string OutPathStr = OutPath; + std::string OutPathStr = OutPath.str(); SerializationOpts.EnableNestedTypeLookupTable = FEOpts.EnableSerializationNestedTypeLookupTable; SerializationOpts.OutputPath = OutPathStr.c_str(); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp index 2daa27f7efcc0..5020459797e34 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp @@ -916,7 +916,7 @@ static bool passCursorInfoForDecl(SourceFile* SF, if (ClangMod) ModuleName = ClangMod->getFullModuleName(); } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) { - ModuleName = VD->getModuleContext()->getName().str(); + ModuleName = VD->getModuleContext()->getName().str().str(); } StringRef ModuleInterfaceName; if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok)) From 728e8a1bde9b5e2ae219427dca70ff689e2f200a Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Fri, 14 Feb 2020 13:52:26 +0100 Subject: [PATCH 016/625] Adapt to API change that moved Sysroot attribute to CompileUnit Commit 7b30370e5bcf569fcdc15204d4c592163fd78cb3 changed the Sysroot attribute to the CompileUnit which broke the build. --- lib/IRGen/IRGenDebugInfo.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 6363398bdf82c..c65f43d5b8e5b 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -659,10 +659,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } } - StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; llvm::DIModule *M = - DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath, - Sysroot); + DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); return M; } @@ -1692,6 +1690,7 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts, DBuilder.createFile(DebugPrefixMap.remapPath(SourcePath), DebugPrefixMap.remapPath(Opts.DebugCompilationDir)); + StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; TheCU = DBuilder.createCompileUnit( Lang, MainFile, Producer, Opts.shouldOptimize(), Opts.getDebugFlags(PD), @@ -1702,7 +1701,7 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts, /* DWOId */ 0, /* SplitDebugInlining */ true, /* DebugInfoForProfiling */ false, llvm::DICompileUnit::DebugNameTableKind::Default, - /* RangesBaseAddress */ false); + /* RangesBaseAddress */ false, Sysroot); // Because the swift compiler relies on Clang to setup the Module, // the clang CU is always created first. Several dwarf-reading From 4469a6819e041d1bd58dbc5a6ca2cc19b7767b23 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 17 Feb 2020 09:51:58 -0800 Subject: [PATCH 017/625] [IRGen] Adjust for upstream API change --- lib/IRGen/IRGenDebugInfo.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 6363398bdf82c..bc1f52f4bc3c0 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -659,10 +659,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } } - StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath; llvm::DIModule *M = - DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath, - Sysroot); + DBuilder.createModule(Parent, Name, ConfigMacros, RemappedIncludePath); DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)}); return M; } From ccd9ed2aaa3f77065578677c83252754c61c7eec Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 17 Feb 2020 10:05:30 -0800 Subject: [PATCH 018/625] Resolve master -> master-next Merge Conflicts (#29884) * [Stdlib] Eagerly realize EmptyDictionarySingleton and EmptySetSingleton. These objects can escape into ObjC without their class being realized first, which can cause a crash if the unrealized class gets passed into the ObjC runtime. rdar://problem/59295395 * Reorganization of SourceFileDepGraph building and mocking. * Further reorganization. * [ConstraintSystem] Removing check related to ArgumentMismatch in CSDiag. * [docs] Updating TypeChecker.rst * hash templates for linux * Fix string memory bug * SILCombine: fix a miscompile in the alloc_stack optimization which causes a use-after-free. A "copy_addr [take] %src to [initialization] %alloc_stack" is replaced by a "destroy_addr %src" if the alloc_stack is otherwise dead. This is okay as long as the "moved" object is kept alive otherwise. This can break if a retain of %src is moved after the copy_addr. It cannot happen with OSSA. So as soon as we have OSSA, we can remove the check again. rdar://problem/59509229 Co-authored-by: Mike Ash Co-authored-by: David Ungar Co-authored-by: Luciano Almeida Co-authored-by: eeckstein Co-authored-by: Pavel Yaskevich --- docs/TypeChecker.rst | 1 - include/swift/AST/FineGrainedDependencies.h | 95 +- .../swift/AST/SourceFileDepGraphConstructor.h | 172 +++ .../Driver/FineGrainedDependencyDriverGraph.h | 16 +- lib/AST/FineGrainedDependencies.cpp | 42 +- lib/AST/SourceFileDepGraphConstructor.cpp | 1191 +++++++++-------- .../FineGrainedDependencyDriverGraph.cpp | 72 +- .../SILCombiner/SILCombinerMiscVisitors.cpp | 48 +- lib/Sema/ConstraintSystem.cpp | 15 +- stdlib/public/core/DictionaryStorage.swift | 1 + stdlib/public/core/SetStorage.swift | 1 + test/SILOptimizer/sil_combine.sil | 101 ++ .../sil_combine_alloc_stack.swift | 43 + .../EmptyCollectionSingletonRealization.swift | 48 + unittests/Driver/CMakeLists.txt | 1 + .../FineGrainedDependencyGraphTests.cpp | 578 ++++---- .../MockingFineGrainedDependencyGraphs.cpp | 89 ++ .../MockingFineGrainedDependencyGraphs.h | 103 ++ ...peBodyFingerprintsDependencyGraphTests.cpp | 619 +++++---- 19 files changed, 1943 insertions(+), 1293 deletions(-) create mode 100644 include/swift/AST/SourceFileDepGraphConstructor.h create mode 100644 test/SILOptimizer/sil_combine_alloc_stack.swift create mode 100644 test/stdlib/EmptyCollectionSingletonRealization.swift create mode 100644 unittests/Driver/MockingFineGrainedDependencyGraphs.cpp create mode 100644 unittests/Driver/MockingFineGrainedDependencyGraphs.h diff --git a/docs/TypeChecker.rst b/docs/TypeChecker.rst index b41381b24d1de..1deeaeb8441e5 100644 --- a/docs/TypeChecker.rst +++ b/docs/TypeChecker.rst @@ -985,4 +985,3 @@ The things in the queue yet to be ported are: - Missing explicit ``Self.`` and ``self.`` - Logic related to overload candidate ranking (``CalleeCandidateInfo``) - - ``diagnoseParameterErrors`` diff --git a/include/swift/AST/FineGrainedDependencies.h b/include/swift/AST/FineGrainedDependencies.h index 5f3424a189e84..6163e829191d7 100644 --- a/include/swift/AST/FineGrainedDependencies.h +++ b/include/swift/AST/FineGrainedDependencies.h @@ -93,14 +93,20 @@ template class Memoizer { public: Memoizer() = default; + Optional findExisting(KeyT key) { + auto iter = memos.find(key); + if (iter != memos.end()) + return iter->second; + return None; + } + /// \p createFn must create a \ref ValueT that corresponds to the \ref KeyT /// passed into it. ValueT findExistingOrCreateIfNew(KeyT key, function_ref createFn) { - auto iter = memos.find(key); - if (iter != memos.end()) - return iter->second; + if (auto existing = findExisting(key)) + return existing.getValue(); ValueT v = createFn(key); (void)insert(key, v); return v; @@ -372,6 +378,7 @@ const std::string NodeKindNames[]{ "topLevel", "nominal", "potentialMember", "member", "dynamicLookup", "externalDepend", "sourceFileProvide"}; + /// Instead of the status quo scheme of two kinds of "Depends", cascading and /// non-cascading this code represents each entity ("Provides" in the status /// quo), by a pair of nodes. One node represents the "implementation." If the @@ -391,6 +398,7 @@ template void forEachAspect(FnT fn) { fn(DeclAspect(i)); } + /// A pair of nodes that represent the two aspects of a given entity. /// Templated in order to serve for either SourceFileDepGraphNodes or /// ModuleDepGraphNodes. @@ -499,10 +507,23 @@ class DependencyKey { } bool isInterface() const { return getAspect() == DeclAspect::interface; } + /// Create just the interface half of the keys for a provided Decl or Decl + /// pair + template + static DependencyKey createForProvidedEntityInterface(Entity); + /// Given some type of provided entity compute the context field of the key. template static std::string computeContextForProvidedEntity(Entity); + DependencyKey correspondingImplementation() const { + return withAspect(DeclAspect::implementation); + } + + DependencyKey withAspect(DeclAspect aspect) const { + return DependencyKey(kind, aspect, context, name); + } + /// Given some type of provided entity compute the name field of the key. template static std::string computeNameForProvidedEntity(Entity); @@ -514,7 +535,8 @@ class DependencyKey { template static DependencyKey createDependedUponKey(StringRef); - static DependencyKey createKeyForWholeSourceFile(StringRef swiftDeps); + static DependencyKey createKeyForWholeSourceFile(DeclAspect, + StringRef swiftDeps); std::string humanReadableName() const; @@ -555,6 +577,14 @@ struct std::hash { return size_t(aspect); } }; +template <> +struct std::hash { + size_t + operator()(const swift::fine_grained_dependencies::NodeKind kind) const { + return size_t(kind); + } +}; + namespace swift { namespace fine_grained_dependencies { @@ -616,6 +646,10 @@ class DepGraphNode { /// See SourceFileDepGraphNode::SourceFileDepGraphNode(...) and /// ModuleDepGraphNode::ModuleDepGraphNode(...) Don't set swiftDeps on /// creation because this field can change if a node is moved. + DepGraphNode(DependencyKey key, Optional fingerprint) + : DepGraphNode(key, fingerprint ? fingerprint->str() + : Optional()) {} + DepGraphNode(DependencyKey key, Optional fingerprint) : key(key), fingerprint(fingerprint) {} DepGraphNode(const DepGraphNode &other) = default; @@ -627,8 +661,12 @@ class DepGraphNode { const DependencyKey &getKey() const { return key; } - const Optional &getFingerprint() const { return fingerprint; } - + const Optional getFingerprint() const { + if (fingerprint) { + return StringRef(fingerprint.getValue()); + } + return None; + } /// When driver reads a SourceFileDepGraphNode, it may be a node that was /// created to represent a name-lookup (a.k.a a "depend") in the frontend. In /// that case, the node represents an entity that resides in some other file @@ -637,7 +675,9 @@ class DepGraphNode { /// (someday) have a fingerprint. In order to preserve the /// ModuleDepGraphNode's identity but bring its fingerprint up to date, it /// needs to set the fingerprint *after* the node has been created. - void setFingerprint(Optional fp) { fingerprint = fp; } + void setFingerprint(Optional fp) { + fingerprint = fp ? fp->str() : Optional(); + } SWIFT_DEBUG_DUMP; void dump(llvm::raw_ostream &os) const; @@ -684,7 +724,7 @@ class SourceFileDepGraphNode : public DepGraphNode { SourceFileDepGraphNode() : DepGraphNode(), sequenceNumber(~0) {} /// Used by the frontend to build nodes. - SourceFileDepGraphNode(DependencyKey key, Optional fingerprint, + SourceFileDepGraphNode(DependencyKey key, Optional fingerprint, bool isProvides) : DepGraphNode(key, fingerprint), isProvides(isProvides) { assert(key.verify()); @@ -780,34 +820,6 @@ class SourceFileDepGraph { SourceFileDepGraph(const SourceFileDepGraph &g) = delete; SourceFileDepGraph(SourceFileDepGraph &&g) = default; - /// Simulate loading for unit testing: - /// \param swiftDepsFileName The name of the swiftdeps file of the phony job - /// \param includePrivateDeps Whether the graph includes intra-file arcs - /// \param hadCompilationError Simulate a compilation error - /// \param interfaceHash The interface hash of the simulated graph - /// \param simpleNamesByRDK A map of vectors of names keyed by reference - /// dependency key \param compoundNamesByRDK A map of (mangledHolder, - /// baseName) pairs keyed by reference dependency key. For single-name - /// dependencies, an initial underscore indicates that the name does not - /// cascade. For compound names, it is the first name, the holder which - /// indicates non-cascading. For member names, an initial underscore indicates - /// file-privacy. - static SourceFileDepGraph - simulateLoad(std::string swiftDepsFileName, const bool includePrivateDeps, - const bool hadCompilationError, std::string interfaceHash, - llvm::StringMap> simpleNamesByRDK, - llvm::StringMap>> - compoundNamesByRDK); - - static constexpr char noncascadingOrPrivatePrefix = '#'; - static constexpr char nameFingerprintSeparator = ','; - - static std::string noncascading(std::string name); - - LLVM_ATTRIBUTE_UNUSED - static std::string privatize(std::string name); - - /// Nodes are owned by the graph. ~SourceFileDepGraph() { forEachNode([&](SourceFileDepGraphNode *n) { delete n; }); @@ -851,12 +863,15 @@ class SourceFileDepGraph { /// The frontend creates a pair of nodes for every tracked Decl and the source /// file itself. InterfaceAndImplementationPair - findExistingNodePairOrCreateAndAddIfNew( - NodeKind k, const ContextNameFingerprint &contextNameFingerprint); + findExistingNodePairOrCreateAndAddIfNew(const DependencyKey &interfaceKey, + Optional fingerprint); + + NullablePtr + findExistingNode(const DependencyKey &key); SourceFileDepGraphNode * - findExistingNodeOrCreateIfNew(DependencyKey key, - const Optional &fingerprint, + findExistingNodeOrCreateIfNew(const DependencyKey &key, + const Optional fingerprint, bool isProvides); /// \p Use is the Node that must be rebuilt when \p def changes. diff --git a/include/swift/AST/SourceFileDepGraphConstructor.h b/include/swift/AST/SourceFileDepGraphConstructor.h new file mode 100644 index 0000000000000..3598b40bc9e89 --- /dev/null +++ b/include/swift/AST/SourceFileDepGraphConstructor.h @@ -0,0 +1,172 @@ +//===----- SourceFileDepGraphConstructor.h ----------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H +#define SWIFT_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H + +#include + +namespace swift { +namespace fine_grained_dependencies { +/// Abstract class for building a \c SourceFileDepGraph from either a real +/// \c SourceFile or a unit test +class SourceFileDepGraphConstructor { +protected: + /// To match the existing system, set this to false. + /// To include even private entities and get intra-file info, set to true. + const bool includePrivateDeps; + + /// If there was an error, cannot get accurate info. + const bool hadCompilationError; + + /// The name of the swiftDeps file. + const std::string swiftDeps; + + /// The fingerprint of the whole file + const std::string fileFingerprint; + + /// For debugging + const bool emitDotFileAfterConstruction; + + DiagnosticEngine &diags; + + /// Graph under construction + SourceFileDepGraph g; + +public: + /// Expose this layer to enable faking up a constructor for testing. + /// See the instance variable comments for explanation. + SourceFileDepGraphConstructor(bool includePrivateDeps, + bool hadCompilationError, StringRef swiftDeps, + StringRef fileFingerprint, + bool emitDotFileAfterConstruction, + DiagnosticEngine &diags); + + virtual ~SourceFileDepGraphConstructor() = default; + + /// Create a SourceFileDepGraph. + SourceFileDepGraph construct(); + +private: + void addSourceFileNodesToGraph(); + + /// Add the "provides" nodes when mocking up a graph + virtual void addAllDefinedDecls() = 0; + + /// Add the "depends" nodes and arcs when mocking a graph + virtual void addAllUsedDecls() = 0; + +protected: + /// Add an pair of interface, implementation nodes to the graph, which + /// represent some \c Decl defined in this source file. \param key the + /// interface key of the pair + void addADefinedDecl(const DependencyKey &key, + Optional fingerprint); + + void addAUsedDecl(const DependencyKey &def, const DependencyKey &use); +}; + +/// Constructs a SourceFileDepGraph from a *real* \c SourceFile +/// Reads the information provided by the frontend and builds the +/// SourceFileDepGraph + +class RealSourceFileDepGraphConstructor : public SourceFileDepGraphConstructor { + SourceFile *const SF; + const DependencyTracker &depTracker; + +public: + RealSourceFileDepGraphConstructor(SourceFile *SF, StringRef outputPath, + const DependencyTracker &depTracker, + bool alsoEmitDotFile); + + ~RealSourceFileDepGraphConstructor() override = default; + +private: + static std::string getFingerprint(SourceFile *SF); + + static bool computeIncludePrivateDeps(SourceFile *SF); + static std::string getInterfaceHash(SourceFile *SF); + + void addAllDefinedDecls() override; + void addAllUsedDecls() override; + + /// Given an array of Decls or pairs of them in \p declsOrPairs + /// create node pairs for context and name + template + void addAllDefinedDeclsOfAGivenType(std::vector &contentsVec); + + /// At present, only nominals, protocols, and extensions have (body) + /// fingerprints + static Optional + getFingerprintIfAny(std::pair); + static Optional getFingerprintIfAny(const Decl *d); +}; + +using DependencyDescriptions = + std::unordered_multimap>; + +class MockSourceFileDepGraphConstructor : public SourceFileDepGraphConstructor { + const DependencyDescriptions dependencyDescriptions; + +public: + MockSourceFileDepGraphConstructor( + bool includePrivateDeps, bool hadCompilationError, StringRef swiftDeps, + StringRef fileFingerprint, bool emitDotFileAfterConstruction, + const DependencyDescriptions &dependencyDescriptions, + DiagnosticEngine &diags) + : SourceFileDepGraphConstructor(includePrivateDeps, hadCompilationError, + swiftDeps, fileFingerprint, + emitDotFileAfterConstruction, diags), + dependencyDescriptions(dependencyDescriptions) {} + + ~MockSourceFileDepGraphConstructor() override = default; + +private: + void addAllDefinedDecls() override; + void addAllUsedDecls() override; + + /// For brevity, unit tests specify dependencies by NodeKind, + /// but for processing, the kind is needed for each entry. + void forEachEntry(function_ref fn); + + static const char *defUseSeparator; + static bool isADefinedDecl(StringRef s); + + void addADefinedDecl(StringRef s, NodeKind kind); + void addAUsedDecl(StringRef s, NodeKind kind); + + Optional> parseAUsedDecl(StringRef s, + NodeKind); + + /// Parse and return an interface \c DependencyKey + Optional parseADefinedDecl(StringRef s, NodeKind, DeclAspect); + + DependencyKey computeUseKey(StringRef s, bool isCascadingUse); + + /// Return true if when the name appears in a unit test, it represents a + /// context, not a baseName. Return false if a single name is a baseName, + /// without context Return None if there shoud be two names + static Optional singleNameIsContext(NodeKind kind); + + static constexpr char nameContextSeparator = ','; + + static constexpr char fingerprintSeparator = '@'; + + static std::string parseContext(const StringRef s, const NodeKind kind); + + static std::string parseName(const StringRef s, const NodeKind kind); +}; + +} // namespace fine_grained_dependencies +} // namespace swift + +#endif // SWIFT_AST_SOURCE_FILE_DEP_GRAPH_CONSTRUCTOR_H diff --git a/include/swift/Driver/FineGrainedDependencyDriverGraph.h b/include/swift/Driver/FineGrainedDependencyDriverGraph.h index 36ab089d6c029..71ecc27c506b6 100644 --- a/include/swift/Driver/FineGrainedDependencyDriverGraph.h +++ b/include/swift/Driver/FineGrainedDependencyDriverGraph.h @@ -57,8 +57,7 @@ class ModuleDepGraphNode : public DepGraphNode { bool hasBeenTracedAsADependent = false; public: - ModuleDepGraphNode(const DependencyKey &key, - Optional fingerprint, + ModuleDepGraphNode(const DependencyKey &key, Optional fingerprint, Optional swiftDeps) : DepGraphNode(key, fingerprint), swiftDeps(swiftDeps) {} @@ -187,11 +186,13 @@ class ModuleDepGraph { /// files for the same name distinct, keep a sequence number for each name. std::unordered_map dotFileSequenceNumber; +public: const bool verifyFineGrainedDependencyGraphAfterEveryImport; const bool emitFineGrainedDependencyDotFileAfterEveryImport; const bool EnableTypeFingerprints; +private: /// If tracing dependencies, holds a vector used to hold the current path /// def - use/def - use/def - ... Optional> currentPathIfTracing; @@ -336,15 +337,6 @@ class ModuleDepGraph { const SourceFileDepGraph &, DiagnosticEngine &); - /// Also for unit tests - Changes - simulateLoad(const driver::Job *cmd, - llvm::StringMap> simpleNames, - llvm::StringMap>> - compoundNames = {}, - const bool includePrivateDeps = false, - const bool hadCompilationError = false); - private: /// Read a SourceFileDepGraph belonging to \p job from \p buffer @@ -515,6 +507,8 @@ class ModuleDepGraph { /// Record a new (to this graph) Job. void registerJob(const driver::Job *); + std::vector getAllJobs() const; + /// Find jobs that were previously not known to need compilation but that /// depend on \c externalDependency. std::vector diff --git a/lib/AST/FineGrainedDependencies.cpp b/lib/AST/FineGrainedDependencies.cpp index 62c57a4d25900..b3f9c752b0e80 100644 --- a/lib/AST/FineGrainedDependencies.cpp +++ b/lib/AST/FineGrainedDependencies.cpp @@ -103,17 +103,20 @@ void SourceFileDepGraph::forEachArc( InterfaceAndImplementationPair SourceFileDepGraph::findExistingNodePairOrCreateAndAddIfNew( - NodeKind k, const ContextNameFingerprint &contextNameFingerprint) { - const std::string &context = std::get<0>(contextNameFingerprint); - const std::string &name = std::get<1>(contextNameFingerprint); - const Optional &fingerprint = - std::get<2>(contextNameFingerprint); - auto *interfaceNode = findExistingNodeOrCreateIfNew( - DependencyKey(k, DeclAspect::interface, context, name), fingerprint, - true /* = isProvides */); + const DependencyKey &interfaceKey, Optional fingerprint) { + + // Optimization for whole-file users: + if (interfaceKey.getKind() == NodeKind::sourceFileProvide && + !allNodes.empty()) + return getSourceFileNodePair(); + + assert(interfaceKey.isInterface()); + const DependencyKey implementationKey = + interfaceKey.correspondingImplementation(); + auto *interfaceNode = findExistingNodeOrCreateIfNew(interfaceKey, fingerprint, + true /* = isProvides */); auto *implementationNode = findExistingNodeOrCreateIfNew( - DependencyKey(k, DeclAspect::implementation, context, name), fingerprint, - true /* = isProvides */); + implementationKey, fingerprint, true /* = isProvides */); InterfaceAndImplementationPair nodePair{ interfaceNode, implementationNode}; @@ -136,7 +139,7 @@ SourceFileDepGraph::findExistingNodePairOrCreateAndAddIfNew( } SourceFileDepGraphNode *SourceFileDepGraph::findExistingNodeOrCreateIfNew( - DependencyKey key, const Optional &fingerprint, + const DependencyKey &key, const Optional fingerprint, const bool isProvides) { SourceFileDepGraphNode *result = memoizedNodes.findExistingOrCreateIfNew( key, [&](DependencyKey key) -> SourceFileDepGraphNode * { @@ -164,20 +167,25 @@ SourceFileDepGraphNode *SourceFileDepGraph::findExistingNodeOrCreateIfNew( return result; } +NullablePtr +SourceFileDepGraph::findExistingNode(const DependencyKey &key) { + auto existing = memoizedNodes.findExisting(key); + return existing ? existing.getValue() : NullablePtr(); +} + std::string DependencyKey::demangleTypeAsContext(StringRef s) { return swift::Demangle::demangleTypeAsString(s.str()); } -DependencyKey -DependencyKey::createKeyForWholeSourceFile(const StringRef swiftDeps) { +DependencyKey DependencyKey::createKeyForWholeSourceFile(DeclAspect aspect, + StringRef swiftDeps) { assert(!swiftDeps.empty()); - const auto context = DependencyKey::computeContextForProvidedEntity< + const std::string context = DependencyKey::computeContextForProvidedEntity< NodeKind::sourceFileProvide>(swiftDeps); - const auto name = + const std::string name = DependencyKey::computeNameForProvidedEntity( swiftDeps); - return DependencyKey(NodeKind::sourceFileProvide, DeclAspect::interface, - context, name); + return DependencyKey(NodeKind::sourceFileProvide, aspect, context, name); } //============================================================================== diff --git a/lib/AST/SourceFileDepGraphConstructor.cpp b/lib/AST/SourceFileDepGraphConstructor.cpp index 7019e224edca7..3c9894b669391 100644 --- a/lib/AST/SourceFileDepGraphConstructor.cpp +++ b/lib/AST/SourceFileDepGraphConstructor.cpp @@ -25,6 +25,7 @@ #include "swift/AST/ModuleLoader.h" #include "swift/AST/NameLookup.h" #include "swift/AST/SourceFile.h" +#include "swift/AST/SourceFileDepGraphConstructor.h" #include "swift/AST/Types.h" #include "swift/Basic/FileSystem.h" #include "swift/Basic/LLVM.h" @@ -46,16 +47,78 @@ using namespace swift; using namespace fine_grained_dependencies; +//============================================================================== +// MARK: SourceFileDepGraphConstructor - client interface +//============================================================================== + +SourceFileDepGraphConstructor::SourceFileDepGraphConstructor( + bool includePrivateDeps, bool hadCompilationError, StringRef swiftDeps, + StringRef fileFingerprint, bool emitDotFileAfterConstruction, + DiagnosticEngine &diags) + : includePrivateDeps(includePrivateDeps), + hadCompilationError(hadCompilationError), swiftDeps(swiftDeps.str()), + fileFingerprint(fileFingerprint.str()), + emitDotFileAfterConstruction(emitDotFileAfterConstruction), diags(diags) { +} + +SourceFileDepGraph SourceFileDepGraphConstructor::construct() { + addSourceFileNodesToGraph(); + if (!hadCompilationError) { + addAllDefinedDecls(); + addAllUsedDecls(); + } + assert(g.verify()); + if (emitDotFileAfterConstruction) + g.emitDotFile(swiftDeps, diags); + return std::move(g); +} + +//============================================================================== +// MARK: SourceFileDepGraphConstructor - adding a defined or used Decl +//============================================================================== +void SourceFileDepGraphConstructor::addSourceFileNodesToGraph() { + g.findExistingNodePairOrCreateAndAddIfNew( + DependencyKey::createKeyForWholeSourceFile(DeclAspect::interface, + swiftDeps), + StringRef(fileFingerprint)); +} + +void SourceFileDepGraphConstructor::addADefinedDecl( + const DependencyKey &interfaceKey, Optional fingerprint) { + + auto nodePair = + g.findExistingNodePairOrCreateAndAddIfNew(interfaceKey, fingerprint); + // Since the current type fingerprints only include tokens in the body, + // when the interface hash changes, it is possible that the type in the + // file has changed. + g.addArc(g.getSourceFileNodePair().getInterface(), nodePair.getInterface()); +} + +void SourceFileDepGraphConstructor::addAUsedDecl(const DependencyKey &defKey, + const DependencyKey &useKey) { + auto *defNode = + g.findExistingNodeOrCreateIfNew(defKey, None, false /* = !isProvides */); + auto nullableUse = g.findExistingNode(useKey); + assert(nullableUse.isNonNull() && "Use must be an already-added provides"); + auto *useNode = nullableUse.get(); + assert(useNode->getIsProvides() && "Use (using node) must be a provides"); + g.addArc(defNode, useNode); +} + +//============================================================================== +// MARK: Constructing from a SourceFile +//============================================================================== + //============================================================================== // MARK: Helpers for key construction that must be in frontend //============================================================================== template static std::string getBaseName(const DeclT *decl) { - return decl->getBaseName().userFacingName().str(); + return decl->getBaseName().userFacingName(); } template static std::string getName(const DeclT *decl) { - return DeclBaseName(decl->getName()).userFacingName().str(); + return DeclBaseName(decl->getName()).userFacingName(); } static std::string mangleTypeAsContext(const NominalTypeDecl *NTD) { @@ -135,6 +198,239 @@ static bool allInheritedProtocolsArePrivate(const ExtensionDecl *ED) { extendedTypeIsPrivate); } +//============================================================================== +// MARK: DependencyKey - creation for Decls +//============================================================================== + +template +DependencyKey DependencyKey::createForProvidedEntityInterface(Entity entity) { + return DependencyKey( + kindArg, DeclAspect::interface, + DependencyKey::computeContextForProvidedEntity(entity), + DependencyKey::computeNameForProvidedEntity(entity)); +} + +//============================================================================== +// MARK: computeContextForProvidedEntity +//============================================================================== + +template +std::string DependencyKey::computeContextForProvidedEntity(Entity) { + // Context field is not used for most kinds + return ""; +} + +// \ref nominal dependencies are created from a Decl and use the context field. +template <> +std::string DependencyKey::computeContextForProvidedEntity< + NodeKind::nominal, NominalTypeDecl const *>(NominalTypeDecl const *D) { + return mangleTypeAsContext(D); +} + +/// \ref potentialMember dependencies are created from a Decl and use the +/// context field. +template <> +std::string +DependencyKey::computeContextForProvidedEntity( + const NominalTypeDecl *D) { + return mangleTypeAsContext(D); +} + +template <> +std::string DependencyKey::computeContextForProvidedEntity< + NodeKind::member, const NominalTypeDecl *>(const NominalTypeDecl *holder) { + return mangleTypeAsContext(holder); +} + +/// \ref member dependencies are created from a pair and use the context field. +template <> +std::string DependencyKey::computeContextForProvidedEntity< + NodeKind::member, std::pair>( + std::pair holderAndMember) { + return computeContextForProvidedEntity( + holderAndMember.first); +} + +// Linux compiler requires the following: +template std::string + DependencyKey::computeContextForProvidedEntity(StringRef); + +//============================================================================== +// MARK: computeNameForProvidedEntity +//============================================================================== + +template <> +std::string +DependencyKey::computeNameForProvidedEntity(StringRef swiftDeps) { + assert(!swiftDeps.empty()); + return swiftDeps; +} + +template <> +std::string +DependencyKey::computeNameForProvidedEntity( + const PrecedenceGroupDecl *D) { + return ::getName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::topLevel, FuncDecl const *>(const FuncDecl *D) { + return ::getName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::topLevel, OperatorDecl const *>(const OperatorDecl *D) { + return ::getName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::topLevel, NominalTypeDecl const *>(const NominalTypeDecl *D) { + return ::getName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::topLevel, ValueDecl const *>(const ValueDecl *D) { + return getBaseName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::dynamicLookup, ValueDecl const *>(const ValueDecl *D) { + return getBaseName(D); +} +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::nominal, NominalTypeDecl const *>(const NominalTypeDecl *D) { + return ""; +} +template <> +std::string +DependencyKey::computeNameForProvidedEntity( + const NominalTypeDecl *D) { + return ""; +} + +template <> +std::string DependencyKey::computeNameForProvidedEntity< + NodeKind::member, std::pair>( + std::pair holderAndMember) { + return getBaseName(holderAndMember.second); +} + +//============================================================================== +// MARK: createDependedUponKey +//============================================================================== + +template <> +DependencyKey +DependencyKey::createDependedUponKey(StringRef name) { + return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", name); +} + +template <> +DependencyKey +DependencyKey::createDependedUponKey(StringRef name) { + return DependencyKey(NodeKind::dynamicLookup, DeclAspect::interface, "", + name); +} + +template <> +DependencyKey +DependencyKey::createDependedUponKey(StringRef name) { + return DependencyKey(NodeKind::externalDepend, DeclAspect::interface, "", + name); +} + +template <> +DependencyKey +DependencyKey::createDependedUponKey(StringRef mangledName) { + return DependencyKey(NodeKind::nominal, DeclAspect::interface, mangledName, + ""); +} + +DependencyKey DependencyKey::createDependedUponKey(StringRef mangledHolderName, + StringRef memberBaseName) { + const bool isMemberBlank = memberBaseName.empty(); + const auto kind = + isMemberBlank ? NodeKind::potentialMember : NodeKind::member; + return DependencyKey(kind, DeclAspect::interface, mangledHolderName, + isMemberBlank ? "" : memberBaseName); +} + +//============================================================================== +// MARK: Entry point into frontend graph construction +//============================================================================== + +bool fine_grained_dependencies::emitReferenceDependencies( + DiagnosticEngine &diags, SourceFile *const SF, + const DependencyTracker &depTracker, StringRef outputPath, + const bool alsoEmitDotFile) { + + // Before writing to the dependencies file path, preserve any previous file + // that may have been there. No error handling -- this is just a nicety, it + // doesn't matter if it fails. + llvm::sys::fs::rename(outputPath, outputPath + "~"); + + SourceFileDepGraph g = RealSourceFileDepGraphConstructor( + SF, outputPath, depTracker, alsoEmitDotFile) + .construct(); + + const bool hadError = + withOutputFile(diags, outputPath, [&](llvm::raw_pwrite_stream &out) { + out << g.yamlProlog(SF->getASTContext().hadError()); + llvm::yaml::Output yamlWriter(out); + yamlWriter << g; + return false; + }); + + // If path is stdout, cannot read it back, so check for "-" + assert(outputPath == "-" || g.verifyReadsWhatIsWritten(outputPath)); + + if (alsoEmitDotFile) + g.emitDotFile(outputPath, diags); + + return hadError; +} + +//============================================================================== +// MARK: RealSourceFileDepGraphConstructor +//============================================================================== + +RealSourceFileDepGraphConstructor::RealSourceFileDepGraphConstructor( + SourceFile *SF, StringRef outputPath, const DependencyTracker &depTracker, + const bool alsoEmitDotFile) + : SourceFileDepGraphConstructor(computeIncludePrivateDeps(SF), + SF->getASTContext().hadError(), outputPath, + getInterfaceHash(SF), alsoEmitDotFile, + SF->getASTContext().Diags), + SF(SF), depTracker(depTracker) {} + +bool RealSourceFileDepGraphConstructor::computeIncludePrivateDeps( + SourceFile *SF) { + // Since, when fingerprints are enabled, + // the parser diverts token hashing into per-body fingerprints + // before it can know if a difference is in a private type, + // in order to be able to test the changed fingerprints + // we force the inclusion of private declarations when fingerprints + // are enabled. + return SF->getASTContext() + .LangOpts.FineGrainedDependenciesIncludeIntrafileOnes || + SF->getASTContext().LangOpts.EnableTypeFingerprints; +} + +/// Centralize the invariant that the fingerprint of the whole file is the +/// interface hash +std::string RealSourceFileDepGraphConstructor::getFingerprint(SourceFile *SF) { + return getInterfaceHash(SF); +} + +//============================================================================== +// MARK: RealSourceFileDepGraphConstructor - adding collections of defined Decls +//============================================================================== //============================================================================== // MARK: SourceFileDeclFinder //============================================================================== @@ -300,653 +596,360 @@ struct SourceFileDeclFinder { }; } // namespace -//============================================================================== -// MARK: computeContextForProvidedEntity -//============================================================================== - -template -std::string DependencyKey::computeContextForProvidedEntity(Entity) { - // Context field is not used for most kinds - return ""; -} - -// \ref nominal dependencies are created from a Decl and use the context field. -template <> -std::string DependencyKey::computeContextForProvidedEntity< - NodeKind::nominal, NominalTypeDecl const *>(NominalTypeDecl const *D) { - return mangleTypeAsContext(D); -} - -/// \ref potentialMember dependencies are created from a Decl and use the -/// context field. -template <> -std::string -DependencyKey::computeContextForProvidedEntity( - const NominalTypeDecl *D) { - return mangleTypeAsContext(D); -} - -/// \ref member dependencies are created from a pair and use the context field. -template <> -std::string DependencyKey::computeContextForProvidedEntity< - NodeKind::member, std::pair>( - std::pair holderAndMember) { - return mangleTypeAsContext(holderAndMember.first); -} - -// Linux compiler requires the following: -template -std::string -DependencyKey::computeContextForProvidedEntity(StringRef); - -//============================================================================== -// MARK: computeNameForProvidedEntity -//============================================================================== +void RealSourceFileDepGraphConstructor::addAllDefinedDecls() { + // TODO: express the multiple provides and depends streams with variadic + // templates -template <> -std::string -DependencyKey::computeNameForProvidedEntity(StringRef swiftDeps) { - assert(!swiftDeps.empty()); - return swiftDeps.str(); -} + // Many kinds of Decls become top-level depends. -template <> -std::string -DependencyKey::computeNameForProvidedEntity( - const PrecedenceGroupDecl *D) { - return ::getName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::topLevel, FuncDecl const *>(const FuncDecl *D) { - return ::getName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::topLevel, OperatorDecl const *>(const OperatorDecl *D) { - return ::getName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::topLevel, NominalTypeDecl const *>(const NominalTypeDecl *D) { - return ::getName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::topLevel, ValueDecl const *>(const ValueDecl *D) { - return getBaseName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::dynamicLookup, ValueDecl const *>(const ValueDecl *D) { - return getBaseName(D); -} -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::nominal, NominalTypeDecl const *>(const NominalTypeDecl *D) { - return ""; -} -template <> -std::string -DependencyKey::computeNameForProvidedEntity( - const NominalTypeDecl *D) { - return ""; -} + SourceFileDeclFinder declFinder(SF, includePrivateDeps); -template <> -std::string DependencyKey::computeNameForProvidedEntity< - NodeKind::member, std::pair>( - std::pair holderAndMember) { - return getBaseName(holderAndMember.second); + addAllDefinedDeclsOfAGivenType( + declFinder.precedenceGroups); + addAllDefinedDeclsOfAGivenType( + declFinder.memberOperatorDecls); + addAllDefinedDeclsOfAGivenType(declFinder.operators); + addAllDefinedDeclsOfAGivenType(declFinder.topNominals); + addAllDefinedDeclsOfAGivenType(declFinder.topValues); + addAllDefinedDeclsOfAGivenType(declFinder.allNominals); + addAllDefinedDeclsOfAGivenType( + declFinder.potentialMemberHolders); + addAllDefinedDeclsOfAGivenType( + declFinder.valuesInExtensions); + addAllDefinedDeclsOfAGivenType( + declFinder.classMembers); +} + +/// Given an array of Decls or pairs of them in \p declsOrPairs +/// create node pairs for context and name +template +void RealSourceFileDepGraphConstructor::addAllDefinedDeclsOfAGivenType( + std::vector &contentsVec) { + for (const auto declOrPair : contentsVec) { + Optional fp = getFingerprintIfAny(declOrPair); + addADefinedDecl( + DependencyKey::createForProvidedEntityInterface(declOrPair), + fp ? StringRef(fp.getValue()) : Optional()); + } } //============================================================================== -// MARK: createDependedUponKey +// MARK: RealSourceFileDepGraphConstructor - adding collections of used Decls //============================================================================== -template <> -DependencyKey -DependencyKey::createDependedUponKey(StringRef name) { - return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", - name.str()); -} - -template <> -DependencyKey -DependencyKey::createDependedUponKey(StringRef name) { - return DependencyKey(NodeKind::dynamicLookup, DeclAspect::interface, "", - name.str()); -} - -template <> -DependencyKey -DependencyKey::createDependedUponKey(StringRef name) { - return DependencyKey(NodeKind::externalDepend, DeclAspect::interface, "", - name.str()); -} - -template <> -DependencyKey -DependencyKey::createDependedUponKey(StringRef mangledName) { - return DependencyKey(NodeKind::nominal, DeclAspect::interface, - mangledName.str(), ""); -} - -DependencyKey DependencyKey::createDependedUponKey(StringRef mangledHolderName, - StringRef memberBaseName) { - const bool isMemberBlank = memberBaseName.empty(); - const auto kind = - isMemberBlank ? NodeKind::potentialMember : NodeKind::member; - return DependencyKey(kind, DeclAspect::interface, mangledHolderName.str(), - isMemberBlank ? "" : memberBaseName.str()); -} +namespace { +/// Extracts uses out of a SourceFile +class UsedDeclEnumerator { + SourceFile *SF; + const DependencyTracker &depTracker; + StringRef swiftDeps; -//============================================================================== -// MARK: SourceFileDepGraphConstructor -//============================================================================== + /// Cache these for efficiency + const DependencyKey sourceFileInterface; + const DependencyKey sourceFileImplementation; -namespace { + const bool includeIntrafileDeps; -/// Reads the information provided by the frontend and builds the -/// SourceFileDepGraph -class SourceFileDepGraphConstructor { - /// Name of the swiftDeps file, for inclusion in the constructed graph. - StringRef swiftDeps; // TODO rm? - - /// To match the existing system, set this to false. - /// To include even private entities and get intra-file info, set to true. - const bool includePrivateDeps; - - /// If there was an error, cannot get accurate info. - const bool hadCompilationError; - - /// Functions as the fingerprint of the entire file - const std::string interfaceHash; - - /// Top-level base names of decls that are depended-upon and a flag indicating - /// if the dependency "cascades" - const std::vector> topLevelDepends; - - /// A mangled nominal name and the member base name that are depended-upon, - /// a flag indicating if the member is private to its enclosing file, and - /// a flag indicating if the dependency cascades. - const std::vector, bool>> - dependsWithContexts; - - /// The base name of a class member depended-upon for dynamic lookup, and a - /// cascades flag. - const std::vector> dynamicLookupDepends; - - /// The paths of swiftdeps files of other modules that are depended-upon. - const std::vector externalDependencies; - - /// Provided names - std::vector precedenceGroups; - std::vector memberOperatorDecls; - std::vector operators; - std::vector topNominals; - std::vector topValues; - std::vector allNominals; - std::vector potentialMemberHolders; - std::vector valuesInExtensions; - std::vector classMembers; - - /// Graph under construction - SourceFileDepGraph g; + function_ref createDefUse; public: - /// Expose this layer to enable faking up a constructor for testing. - /// See the instance variable comments for explanation. - // clang-format off - SourceFileDepGraphConstructor( - StringRef swiftDeps, - bool includePrivateDeps, - bool hadCompilationError, - const std::string &interfaceHash, - ArrayRef> topLevelDepends, - ArrayRef, bool>> - dependsWithContexts, - ArrayRef> dynamicLookupDepends, - ArrayRef externalDependencies, - - ArrayRef precedenceGroups, - ArrayRef memberOperatorDecls, - ArrayRef operators, - ArrayRef topNominals, - ArrayRef topValues, - ArrayRef allNominals, - ArrayRef potentialMemberHolders, - ArrayRef valuesInExtensions, - ArrayRef classMembers - ) : - swiftDeps(swiftDeps), - includePrivateDeps(includePrivateDeps), - hadCompilationError(hadCompilationError), - - interfaceHash(interfaceHash), - topLevelDepends(topLevelDepends), - dependsWithContexts(dependsWithContexts), - dynamicLookupDepends(dynamicLookupDepends), - externalDependencies(externalDependencies), - - precedenceGroups(precedenceGroups), - memberOperatorDecls(memberOperatorDecls), - operators(operators), - topNominals(topNominals), - topValues(topValues), - allNominals(allNominals), - potentialMemberHolders(potentialMemberHolders), - valuesInExtensions(valuesInExtensions), - classMembers(classMembers) - {} - -// clang-format off -static SourceFileDepGraphConstructor -forSourceFile( - SourceFile *SF, - const DependencyTracker &depTracker, - StringRef swiftDeps, - const bool includePrivateDeps, - const bool hadCompilationError) { -// clang-format on - - SourceFileDeclFinder declFinder(SF, includePrivateDeps); - std::vector> topLevelDepends; - for (const auto &p: SF->getReferencedNameTracker()->getTopLevelNames()) - topLevelDepends.push_back(std::make_pair(p.getFirst().userFacingName().str(), p.getSecond())); - - std::vector> dynamicLookupDepends; - for (const auto &p: SF->getReferencedNameTracker()->getDynamicLookupNames()) - dynamicLookupDepends.push_back(std::make_pair(p.getFirst().userFacingName().str(), p.getSecond())); - - std::vector, bool>> dependsWithContexts; - for (const auto &p: SF->getReferencedNameTracker()->getUsedMembers()) { - const auto &member = p.getFirst().second; - StringRef emptyOrUserFacingName = member.empty() ? "" : member.userFacingName(); - dependsWithContexts.push_back( - std::make_pair( - std::make_tuple( - mangleTypeAsContext(p.getFirst().first), - emptyOrUserFacingName.str(), - declIsPrivate(p.getFirst().first)), - p.getSecond())); - } + UsedDeclEnumerator( + SourceFile *SF, const DependencyTracker &depTracker, StringRef swiftDeps, + bool includeIntrafileDeps, + function_ref + createDefUse) + : SF(SF), depTracker(depTracker), swiftDeps(swiftDeps), + sourceFileInterface(DependencyKey::createKeyForWholeSourceFile( + DeclAspect::interface, swiftDeps)), + sourceFileImplementation(DependencyKey::createKeyForWholeSourceFile( + DeclAspect::implementation, swiftDeps)), + includeIntrafileDeps(includeIntrafileDeps), createDefUse(createDefUse) { + } - return SourceFileDepGraphConstructor( - swiftDeps, - includePrivateDeps, - hadCompilationError, - - getInterfaceHash(SF), - topLevelDepends, - dependsWithContexts, - dynamicLookupDepends, - depTracker.getDependencies(), - - namesForProvidersOfAGivenType(declFinder.precedenceGroups), - namesForProvidersOfAGivenType(declFinder.memberOperatorDecls), - namesForProvidersOfAGivenType(declFinder.operators), - namesForProvidersOfAGivenType(declFinder.topNominals), - namesForProvidersOfAGivenType(declFinder.topValues), - namesForProvidersOfAGivenType(declFinder.allNominals), - namesForProvidersOfAGivenType(declFinder.potentialMemberHolders), - namesForProvidersOfAGivenType(declFinder.valuesInExtensions), - namesForProvidersOfAGivenType(declFinder.classMembers) - ); - } - // clang-format on - - /// Construct the graph and return it. - SourceFileDepGraph construct() { - // Order matters here, each function adds state used by the next one. - addSourceFileNodesToGraph(); - if (!hadCompilationError) { - addProviderNodesToGraph(); - addDependencyArcsToGraph(); - } - assert(g.verify()); - return std::move(g); +public: + void enumerateAllUses() { + enumerateSimpleUses( + SF->getReferencedNameTracker()->getTopLevelNames()); + enumerateSimpleUses( + SF->getReferencedNameTracker()->getDynamicLookupNames()); + enumerateExternalUses(); + enumerateCompoundUses(); } private: - std::string getSourceFileFingerprint() const { return interfaceHash; } - - static std::string getInterfaceHash(SourceFile *SF) { - llvm::SmallString<32> interfaceHash; - SF->getInterfaceHash(interfaceHash); - return interfaceHash.str().str(); - } - - /// Also sets sourceFileNodes - void addSourceFileNodesToGraph(); - /// Uses sourceFileNodes - void addProviderNodesToGraph(); - /// Uses provides nodes for intra-graph dependences - void addDependencyArcsToGraph(); - - /// Given an array of Decls or pairs of them in \p declsOrPairs - /// create string pairs for context and name - template - static std::vector - namesForProvidersOfAGivenType(std::vector &contentsVec) { - std::vector result; - for (const auto declOrPair : contentsVec) - result.push_back( - std::make_tuple( - DependencyKey::computeContextForProvidedEntity(declOrPair), - DependencyKey::computeNameForProvidedEntity(declOrPair), - getFingerprintIfAny(declOrPair))); - return result; + void enumerateUse(NodeKind kind, StringRef context, StringRef name, + bool isCascadingUse) { + // Assume that what is depended-upon is the interface + createDefUse(DependencyKey(kind, DeclAspect::interface, context, name), + isCascadingUse ? sourceFileInterface + : sourceFileImplementation); } - - static Optional - getFingerprintIfAny(std::pair) { - return None; + template + void enumerateSimpleUses(llvm::DenseMap cascadesByName) { + for (const auto &p : cascadesByName) + enumerateUse(kind, "", p.getFirst().userFacingName(), p.getSecond()); } - static Optional getFingerprintIfAny(const Decl *d) { - if (const auto *idc = dyn_cast(d)) - return idc->getBodyFingerprint(); - return None; + + void enumerateCompoundUses() { + enumerateNominalUses(std::move(computeHoldersOfCascadingMembers())); + enumerateMemberUses(); } - template - void addAllProviderNodesOfAGivenType( - ArrayRef contextNameFingerprints) { - for (const auto &contextNameFingerprint : contextNameFingerprints) { - auto p = g.findExistingNodePairOrCreateAndAddIfNew( - kind, contextNameFingerprint); - // Since the current type fingerprints only include tokens in the body, - // when the interface hash changes, it is possible that the type in the - // file has changed. - g.addArc(g.getSourceFileNodePair().getInterface(), p.getInterface()); + std::unordered_set computeHoldersOfCascadingMembers() { + std::unordered_set holdersOfCascadingMembers; + for (const auto &p : SF->getReferencedNameTracker()->getUsedMembers()) { + { + bool isPrivate = declIsPrivate(p.getFirst().first); + if (isPrivate && !includeIntrafileDeps) + continue; + } + std::string context = + DependencyKey::computeContextForProvidedEntity( + p.getFirst().first); + bool isCascading = p.getSecond(); + if (isCascading) + holdersOfCascadingMembers.insert(context); } + return holdersOfCascadingMembers; } - /// Given a map of names and isCascades, add the resulting dependencies to the - /// graph. - template - void addAllDependenciesFrom(ArrayRef> names) { - for (const auto &p : names) - recordThatThisWholeFileDependsOn( - DependencyKey::createDependedUponKey(p.first), p.second); - } - - /// Given a map of holder-and-member-names and isCascades, add the resulting - /// dependencies to the graph. - void addAllDependenciesFrom( - ArrayRef, bool>>); - - /// Given an array of external swiftDeps files, add the resulting external - /// dependencies to the graph. - void addAllDependenciesFrom(ArrayRef externals) { - for (const auto &s : externals) - recordThatThisWholeFileDependsOn( - DependencyKey::createDependedUponKey(s), - true); - } - - /// In the status quo, we don't get to know which provided entities are - /// affected by a particular dependency; we only get to know that the whole - /// file must be recompiled if said def changes. However if \p cascades is - /// true, then every other file that depends upon something provided here must - /// be recompiled, too. - void recordThatThisWholeFileDependsOn(const DependencyKey &, bool cascades); -}; -} // namespace + void enumerateNominalUses( + const std::unordered_set &&holdersOfCascadingMembers) { + for (const auto &p : SF->getReferencedNameTracker()->getUsedMembers()) { + { + bool isPrivate = declIsPrivate(p.getFirst().first); + if (isPrivate && !includeIntrafileDeps) + continue; + } + const NominalTypeDecl *nominal = p.getFirst().first; -void SourceFileDepGraphConstructor::addAllDependenciesFrom( - ArrayRef, bool>> - members) { + std::string context = + DependencyKey::computeContextForProvidedEntity( + nominal); + const bool isCascadingUse = holdersOfCascadingMembers.count(context) != 0; + enumerateUse(NodeKind::nominal, context, "", isCascadingUse); + } + } - llvm::StringSet<> holdersOfCascadingMembers; - for (const auto &entry : members) { - if (!includePrivateDeps && std::get<2>(entry.first)) - continue; - if (entry.second) - holdersOfCascadingMembers.insert(std::get<0>(entry.first)); + void enumerateMemberUses() { + for (const auto &p : SF->getReferencedNameTracker()->getUsedMembers()) { + const NominalTypeDecl *nominal = p.getFirst().first; + const auto rawName = p.getFirst().second; + const bool isPotentialMember = rawName.empty(); + const bool isCascadingUse = p.getSecond(); + if (isPotentialMember) { + std::string context = DependencyKey::computeContextForProvidedEntity< + NodeKind::potentialMember>(nominal); + enumerateUse(NodeKind::potentialMember, context, "", isCascadingUse); + } else { + std::string context = + DependencyKey::computeContextForProvidedEntity( + nominal); + StringRef name = rawName.userFacingName(); + enumerateUse(NodeKind::member, context, name, isCascadingUse); + } + } } - for (const auto &entry : members) { - if (!includePrivateDeps && std::get<2>(entry.first)) - continue; - recordThatThisWholeFileDependsOn( - DependencyKey::createDependedUponKey( - std::get<0>(entry.first)), - holdersOfCascadingMembers.count(std::get<0>(entry.first)) != 0); - recordThatThisWholeFileDependsOn( - DependencyKey::createDependedUponKey(std::get<0>(entry.first), - std::get<1>(entry.first)), - entry.second); + + void enumerateExternalUses() { + // external dependencies always cascade + for (StringRef s : depTracker.getDependencies()) + enumerateUse(NodeKind::externalDepend, "", s, true); } +}; +} // end namespace + +void RealSourceFileDepGraphConstructor::addAllUsedDecls() { + UsedDeclEnumerator(SF, depTracker, swiftDeps, includePrivateDeps, + [&](const DependencyKey &def, const DependencyKey &use) { + addAUsedDecl(def, use); + }) + .enumerateAllUses(); } //============================================================================== -// MARK: SourceFileDepGraphConstructor: Adding nodes to the graph +// MARK: RealSourceFileDepGraphConstructor - adding individual defined Decls //============================================================================== -void SourceFileDepGraphConstructor::addSourceFileNodesToGraph() { - g.findExistingNodePairOrCreateAndAddIfNew( - NodeKind::sourceFileProvide, - ContextNameFingerprint(DependencyKey::computeContextForProvidedEntity< - NodeKind::sourceFileProvide>(swiftDeps), - DependencyKey::computeNameForProvidedEntity< - NodeKind::sourceFileProvide>(swiftDeps), - getSourceFileFingerprint())); +std::string +RealSourceFileDepGraphConstructor::getInterfaceHash(SourceFile *SF) { + llvm::SmallString<32> interfaceHash; + SF->getInterfaceHash(interfaceHash); + return interfaceHash.str().str(); +} + +/// At present, only nominals, protocols, and extensions have (body) +/// fingerprints +Optional RealSourceFileDepGraphConstructor::getFingerprintIfAny( + std::pair) { + return None; +} +Optional +RealSourceFileDepGraphConstructor::getFingerprintIfAny(const Decl *d) { + if (const auto *idc = dyn_cast(d)) { + auto result = idc->getBodyFingerprint(); + assert((!result || !result->empty()) && + "Fingerprint should never be empty"); + return result; + } + return None; } -void SourceFileDepGraphConstructor::addProviderNodesToGraph() { - // TODO: express the multiple provides and depends streams with variadic - // templates - - // Many kinds of Decls become top-level depends. - addAllProviderNodesOfAGivenType(precedenceGroups); - addAllProviderNodesOfAGivenType(memberOperatorDecls); - addAllProviderNodesOfAGivenType(operators); - addAllProviderNodesOfAGivenType(topNominals); - addAllProviderNodesOfAGivenType(topValues); - - addAllProviderNodesOfAGivenType(allNominals); - - addAllProviderNodesOfAGivenType( - potentialMemberHolders); - addAllProviderNodesOfAGivenType(valuesInExtensions); +//============================================================================== +// MARK: MockSourceFileDepGraphConstructor - adding collections of Decls +//============================================================================== - addAllProviderNodesOfAGivenType(classMembers); +void MockSourceFileDepGraphConstructor::forEachEntry( + function_ref fn) { + for (const auto &kindAndEntries : dependencyDescriptions) { + for (StringRef s : kindAndEntries.second) + fn(kindAndEntries.first, s); + } } -void SourceFileDepGraphConstructor::addDependencyArcsToGraph() { - // TODO: express the multiple provides and depends streams with variadic - // templates - addAllDependenciesFrom(topLevelDepends); - addAllDependenciesFrom(dependsWithContexts); - addAllDependenciesFrom(dynamicLookupDepends); - addAllDependenciesFrom(externalDependencies); +void MockSourceFileDepGraphConstructor::addAllDefinedDecls() { + forEachEntry([&](NodeKind kind, StringRef s) { + if (isADefinedDecl(s)) + addADefinedDecl(s, kind); + }); } -void SourceFileDepGraphConstructor::recordThatThisWholeFileDependsOn( - const DependencyKey &key, bool cascades) { - SourceFileDepGraphNode *def = - g.findExistingNodeOrCreateIfNew(key, None, false /* = !isProvides */); - g.addArc(def, g.getSourceFileNodePair().useDependingOnCascading(cascades)); -} +void MockSourceFileDepGraphConstructor::addAllUsedDecls() { + forEachEntry([&](NodeKind kind, StringRef s) { + if (!isADefinedDecl(s)) + addAUsedDecl(s, kind); + }); +}; //============================================================================== -// Entry point from the Frontend to this whole system +// MARK: MockSourceFileDepGraphConstructor - adding individual Decls //============================================================================== -bool fine_grained_dependencies::emitReferenceDependencies( - DiagnosticEngine &diags, SourceFile *const SF, - const DependencyTracker &depTracker, StringRef outputPath, - const bool alsoEmitDotFile) { - - // Before writing to the dependencies file path, preserve any previous file - // that may have been there. No error handling -- this is just a nicety, it - // doesn't matter if it fails. - llvm::sys::fs::rename(outputPath, outputPath + "~"); - // Since, when fingerprints are enabled, - // the parser diverts token hashing into per-body fingerprints - // before it can know if a difference is in a private type, - // in order to be able to test the changed fingerprints - // we force the inclusion of private declarations when fingerprints - // are enabled. - const bool includeIntrafileDeps = - SF->getASTContext() - .LangOpts.FineGrainedDependenciesIncludeIntrafileOnes || - SF->getASTContext().LangOpts.EnableTypeFingerprints; - const bool hadCompilationError = SF->getASTContext().hadError(); - auto gc = SourceFileDepGraphConstructor::forSourceFile( - SF, depTracker, outputPath, includeIntrafileDeps, hadCompilationError); - SourceFileDepGraph g = gc.construct(); +void MockSourceFileDepGraphConstructor::addADefinedDecl(StringRef s, + const NodeKind kind) { + const Optional key = + parseADefinedDecl(s, kind, DeclAspect::interface); + if (!key) + return; + StringRef fingerprintString = s.split(fingerprintSeparator).second; + const Optional fingerprint = fingerprintString.empty() + ? Optional() + : StringRef(fingerprintString); + + SourceFileDepGraphConstructor::addADefinedDecl(key.getValue(), fingerprint); + } - const bool hadError = - withOutputFile(diags, outputPath, [&](llvm::raw_pwrite_stream &out) { - out << g.yamlProlog(hadCompilationError); - llvm::yaml::Output yamlWriter(out); - yamlWriter << g; - return false; - }); + void MockSourceFileDepGraphConstructor::addAUsedDecl(const StringRef s, + const NodeKind kind) { + const auto defAndUseKeys = parseAUsedDecl(s, kind); + if (defAndUseKeys) { + SourceFileDepGraphConstructor::addAUsedDecl(defAndUseKeys->first, + defAndUseKeys->second); + } + } - // If path is stdout, cannot read it back, so check for "-" - assert(outputPath == "-" || g.verifyReadsWhatIsWritten(outputPath)); + DependencyKey + MockSourceFileDepGraphConstructor::computeUseKey(StringRef s, + const bool isCascadingUse) { + // For now, in unit tests, mock uses are always nominal + static const NodeKind kindOfUse = NodeKind::nominal; + const DeclAspect aspectOfUse = + isCascadingUse ? DeclAspect::interface : DeclAspect::implementation; + + if (!s.empty()) + return parseADefinedDecl(s, kindOfUse, aspectOfUse).getValue(); + StringRef swiftDepsRef(swiftDeps); + return DependencyKey(NodeKind::sourceFileProvide, aspectOfUse, + DependencyKey::computeContextForProvidedEntity< + NodeKind::sourceFileProvide>(swiftDepsRef), + DependencyKey::computeNameForProvidedEntity< + NodeKind::sourceFileProvide>(swiftDepsRef)); + } - if (alsoEmitDotFile) - g.emitDotFile(outputPath, diags); + //============================================================================== + // MARK: SourceFileDepGraphConstructor - parsing + //============================================================================== - return hadError; -} + const char *MockSourceFileDepGraphConstructor::defUseSeparator = "->"; -//============================================================================== -// Entry point from the unit tests -//============================================================================== -static StringRef stripPrefix(const StringRef name) { - return name.ltrim(SourceFileDepGraph::noncascadingOrPrivatePrefix); -} -static StringRef stripFingerprint(const StringRef nameAndFingerprint) { - return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) - .first; -} -static StringRef stripName(const StringRef nameAndFingerprint) { - return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) - .second; -} -static std::string extractName(const StringRef prefixNameFingerprint) { - return stripFingerprint(stripPrefix(prefixNameFingerprint)).str(); -} -static Optional extractFingerprint( - const StringRef prefixNameFingerprint) { - const auto fp = stripName(stripPrefix(prefixNameFingerprint)); - return fp.empty() ? None : Optional(fp.str()); -} - -static std::vector -getBaseNameProvides(ArrayRef simpleNames) { - std::vector result; - for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint("", extractName(n), - extractFingerprint(n))); - return result; -} + bool MockSourceFileDepGraphConstructor::isADefinedDecl(StringRef s) { + return s.find(defUseSeparator) == StringRef::npos; + } -static std::vector -getMangledHolderProvides(ArrayRef simpleNames) { - std::vector result; - for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint(extractName(n), "", - extractFingerprint(n))); - return result; -} + Optional MockSourceFileDepGraphConstructor::parseADefinedDecl( + StringRef s, const NodeKind kind, const DeclAspect aspect) { + static const char *privatePrefix = "#"; -static std::vector getCompoundProvides( - ArrayRef> compoundNames) { - std::vector result; - for (const auto &p : compoundNames) - result.push_back(ContextNameFingerprint(extractName(p.first), - extractName(p.second), - extractFingerprint(p.second))); - return result; -} + const bool isPrivate = s.consume_front(privatePrefix); + if (isPrivate && !includePrivateDeps) + return None; + const std::string context = + parseContext(s.split(fingerprintSeparator).first, kind); + std::string name = parseName(s.split(fingerprintSeparator).first, kind); -static bool cascades(const std::string &s) { - return s.empty() || s[0] != SourceFileDepGraph::noncascadingOrPrivatePrefix; -} - -// Use '_' as a prefix for a file-private member -static bool isPrivate(const std::string &s) { - return !s.empty() && s[0] == SourceFileDepGraph::noncascadingOrPrivatePrefix; -} + return DependencyKey(kind, aspect, context, name); + } -static std::vector> -getSimpleDepends(ArrayRef simpleNames) { - std::vector> result; - for (std::string n : simpleNames) - result.push_back({stripPrefix(n).str(), cascades((n))}); - return result; -} + Optional> + MockSourceFileDepGraphConstructor::parseAUsedDecl(const StringRef argString, + const NodeKind kind) { + static const char *noncascadingPrefix = "#"; + static const char *privateHolderPrefix = "~"; + + StringRef s = argString; + const bool isCascadingUse = !s.consume_front(noncascadingPrefix); + // Someday, we might differentiate. + const DeclAspect aspectOfDefUsed = DeclAspect::interface; + + const bool isHolderPrivate = s.consume_front(privateHolderPrefix); + if (!includePrivateDeps && isHolderPrivate) + return None; + const auto defUseStrings = s.split(defUseSeparator); + const auto context = parseContext(defUseStrings.first, kind); + const auto name = parseName(defUseStrings.first, kind); + + const DependencyKey defKey = + DependencyKey(kind, aspectOfDefUsed, context, name); + + return std::make_pair(defKey, + computeUseKey(defUseStrings.second, isCascadingUse)); + } -static std::vector -getExternalDepends(ArrayRef simpleNames) { - return simpleNames; -} -static std::vector, bool>> -getCompoundDepends( - ArrayRef simpleNames, - ArrayRef> compoundNames) { - std::vector, bool>> - result; - for (std::string n : simpleNames) { - // (On Linux, the compiler needs more verbosity than: - // result.push_back({{n, "", false}, cascades(n)}); - result.push_back(std::make_pair( - std::make_tuple(stripPrefix(n).str(), std::string(), false), - cascades(n))); - } - for (auto &p : compoundNames) { - // Likewise, for Linux expand the following out: - // result.push_back( - // {{p.first, p.second, isPrivate(p.second)}, cascades(p.first)}); - result.push_back(std::make_pair(std::make_tuple(stripPrefix(p.first).str(), - stripPrefix(p.second).str(), - isPrivate(p.second)), - cascades(p.first))); + Optional + MockSourceFileDepGraphConstructor::singleNameIsContext(const NodeKind kind) { + switch (kind) { + case NodeKind::nominal: + case NodeKind::potentialMember: + return true; + case NodeKind::topLevel: + case NodeKind::dynamicLookup: + case NodeKind::externalDepend: + case NodeKind::sourceFileProvide: + return false; + case NodeKind::member: + return None; + case NodeKind::kindCount: + llvm_unreachable("impossible case"); + } } - return result; -} - -SourceFileDepGraph SourceFileDepGraph::simulateLoad( - std::string swiftDepsFilename, const bool includePrivateDeps, - const bool hadCompilationError, std::string interfaceHash, - llvm::StringMap> simpleNamesByRDK, - llvm::StringMap>> - compoundNamesByRDK) { - using namespace reference_dependency_keys; + std::string + MockSourceFileDepGraphConstructor::parseContext(const StringRef s, + const NodeKind kind) { + return !singleNameIsContext(kind) + ? s.split(nameContextSeparator).first.str() + : singleNameIsContext(kind).getValue() ? s.str() : ""; + } - // clang-format off - SourceFileDepGraphConstructor c( - swiftDepsFilename, - includePrivateDeps, - hadCompilationError, - interfaceHash, - getSimpleDepends(simpleNamesByRDK[dependsTopLevel]), - getCompoundDepends(simpleNamesByRDK[dependsNominal], - compoundNamesByRDK[dependsMember]), - getSimpleDepends(simpleNamesByRDK[dependsDynamicLookup]), - getExternalDepends(simpleNamesByRDK[dependsExternal]), - {}, // precedence groups - {}, // memberOperatorDecls - {}, // operators - {}, // topNominals - getBaseNameProvides(simpleNamesByRDK[providesTopLevel]), // topValues - getMangledHolderProvides(simpleNamesByRDK[providesNominal]), // allNominals - getMangledHolderProvides(simpleNamesByRDK[providesNominal]), // potentialMemberHolders - getCompoundProvides(compoundNamesByRDK[providesMember]), // valuesInExtensions - getBaseNameProvides(simpleNamesByRDK[providesDynamicLookup]) // classMembers - ); - // clang-format on - return c.construct(); -} + std::string + MockSourceFileDepGraphConstructor::parseName(const StringRef s, + const NodeKind kind) { + const std::string name = + !singleNameIsContext(kind) + ? s.split(nameContextSeparator).second.str() + : singleNameIsContext(kind).getValue() ? "" : s.str(); + assert(kind != NodeKind::member || + !name.empty() && "Should be a potentialMember"); + return name; + } diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index 97902d396c356..f44e3c7d3aa58 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -43,44 +43,6 @@ using namespace swift::driver; //============================================================================== // MARK: Affordances to unit tests //============================================================================== -/// Initial underscore makes non-cascading, on member means private. - ModuleDepGraph::Changes -ModuleDepGraph::simulateLoad(const Job *cmd, - llvm::StringMap> simpleNames, - llvm::StringMap>> - compoundNames, - const bool includePrivateDeps, - const bool hadCompilationError) { - StringRef swiftDeps = - cmd->getOutput().getAdditionalOutputForType(file_types::TY_SwiftDeps); - assert(!swiftDeps.empty()); - StringRef interfaceHash = swiftDeps; - auto sfdg = SourceFileDepGraph::simulateLoad( - swiftDeps.str(), includePrivateDeps, hadCompilationError, - interfaceHash.str(), simpleNames, compoundNames); - - SourceManager sm; - DiagnosticEngine diags(sm); - // help for debugging: emit imported file, too - if (emitFineGrainedDependencyDotFileAfterEveryImport) { - sfdg.emitDotFile(swiftDeps, diags); - } - - return loadFromSourceFileDepGraph(cmd, sfdg, diags); -} - -std::string SourceFileDepGraph::noncascading(std::string name) { - std::string s{SourceFileDepGraph::noncascadingOrPrivatePrefix}; - s += name; - return s; -} - -LLVM_ATTRIBUTE_UNUSED -std::string SourceFileDepGraph::privatize(std::string name) { - std::string s{SourceFileDepGraph::noncascadingOrPrivatePrefix}; - s += name; - return s; -} LLVM_ATTRIBUTE_UNUSED std::vector @@ -115,12 +77,8 @@ ModuleDepGraph::Changes ModuleDepGraph::loadFromPath(const Job *Cmd, return None; auto r = loadFromBuffer(Cmd, *buffer.get(), diags); assert(path == getSwiftDeps(Cmd) && "Should be reading the job's swiftdeps"); - assert(!r || - !nodeMap[path.str()].empty() && "Must have a node for the whole file"); - if (emitFineGrainedDependencyDotFileAfterEveryImport) - emitDotFileForJob(diags, Cmd); - if (verifyFineGrainedDependencyGraphAfterEveryImport) - verify(); + assert(!r || !nodeMap[path].empty() && + "Must have a node for the whole file"); return r; } @@ -149,10 +107,11 @@ ModuleDepGraph::Changes ModuleDepGraph::loadFromSourceFileDepGraph( } bool ModuleDepGraph::haveAnyNodesBeenTraversedIn(const Job *cmd) const { - std::string swiftDeps = getSwiftDeps(cmd).str(); + const StringRef swiftDeps = getSwiftDeps(cmd); // optimization - const auto fileKey = DependencyKey::createKeyForWholeSourceFile(swiftDeps); + const auto fileKey = DependencyKey::createKeyForWholeSourceFile( + DeclAspect::interface, swiftDeps); if (const auto fileNode = nodeMap.find(swiftDeps, fileKey)) { if (fileNode && fileNode.getValue()->getHasBeenTraced()) return true; @@ -222,6 +181,13 @@ void ModuleDepGraph::registerJob(const Job *job) { jobsBySwiftDeps.insert(std::make_pair(getSwiftDeps(job), job)); } +std::vector ModuleDepGraph::getAllJobs() const { + std::vector jobs; + for (auto const &entry : jobsBySwiftDeps) + jobs.push_back(entry.second); + return jobs; +} + std::vector ModuleDepGraph::getExternalDependencies() const { return std::vector(externalDependencies.begin(), externalDependencies.end()); @@ -268,7 +234,7 @@ ModuleDepGraph::Changes ModuleDepGraph::integrate(const SourceFileDepGraph &g, FrontendStatsTracer tracer(stats, "fine-grained-dependencies-integrate"); // When done, disappearedNodes contains the nodes which no longer exist. - auto disappearedNodes = nodeMap[swiftDepsOfJob.str()]; + auto disappearedNodes = nodeMap[swiftDepsOfJob]; // When done, changeDependencyKeys contains a list of keys that changed // as a result of this integration. // Or if the integration failed, None. @@ -324,7 +290,7 @@ ModuleDepGraph::PreexistingNodeIfAny ModuleDepGraph::findPreexistingMatch( } if (integrand->getIsProvides()) { const auto &preexistingNodeInPlaceIter = - matches->find(swiftDepsOfCompilationToBeIntegrated.str()); + matches->find(swiftDepsOfCompilationToBeIntegrated); if (preexistingNodeInPlaceIter != matches->end()) return std::make_pair(LocationOfPreexistingNode::here, preexistingNodeInPlaceIter->second); @@ -420,7 +386,7 @@ bool ModuleDepGraph::recordWhatUseDependsUpon( usesByDef[def->getKey()].insert(moduleUseNode).second; if (isNewUse && def->getKey().getKind() == NodeKind::externalDepend) { StringRef externalSwiftDeps = def->getKey().getName(); - externalDependencies.insert(externalSwiftDeps.str()); + externalDependencies.insert(externalSwiftDeps); useHasNewExternalDependency = true; } }); @@ -464,7 +430,7 @@ void ModuleDepGraph::forCorrespondingImplementationOfProvidedInterface( const auto &interfaceKey = interfaceNode->getKey(); const DependencyKey implementationKey( interfaceKey.getKind(), DeclAspect::implementation, - interfaceKey.getContext().str(), interfaceKey.getName().str()); + interfaceKey.getContext(), interfaceKey.getName()); if (const auto implementationNode = nodeMap.find(swiftDeps, implementationKey)) fn(implementationNode.getValue()); @@ -495,7 +461,7 @@ void ModuleDepGraph::forEachArc( void ModuleDepGraph::forEachNodeInJob( StringRef swiftDeps, function_ref fn) const { - if (const auto *nodesByKeys = nodeMap.find(swiftDeps.str()).getPtrOrNull()) { + if (const auto *nodesByKeys = nodeMap.find(swiftDeps).getPtrOrNull()) { for (const auto &keyAndNode : *nodesByKeys) fn(keyAndNode.second); } @@ -564,7 +530,7 @@ void ModuleDepGraph::emitDotFileForJob(DiagnosticEngine &diags, } void ModuleDepGraph::emitDotFile(DiagnosticEngine &diags, StringRef baseName) { - unsigned seqNo = dotFileSequenceNumber[baseName.str()]++; + unsigned seqNo = dotFileSequenceNumber[baseName]++; std::string fullName = baseName.str() + "-post-integration." + std::to_string(seqNo) + ".dot"; withOutputFile(diags, fullName, [&](llvm::raw_ostream &out) { @@ -670,7 +636,7 @@ void ModuleDepGraph::verifyNodeIsInRightEntryInNodeMap( void ModuleDepGraph::verifyExternalDependencyUniqueness( const DependencyKey &key) const { assert((key.getKind() != NodeKind::externalDepend || - externalDependencies.count(key.getName().str()) == 1) && + externalDependencies.count(key.getName()) == 1) && "Ensure each external dependency is tracked exactly once"); } diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index 194c0b8181e5a..4a4742e6c49cd 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -417,6 +417,36 @@ struct AllocStackAnalyzer : SILInstructionVisitor { } // end anonymous namespace +/// Returns true if there is a retain instruction between \p from and the +/// destroy or deallocation of \p alloc. +static bool somethingIsRetained(SILInstruction *from, AllocStackInst *alloc) { + llvm::SmallVector workList; + llvm::SmallPtrSet handled; + workList.push_back(from); + while (!workList.empty()) { + SILInstruction *start = workList.pop_back_val(); + for (auto iter = start->getIterator(), end = start->getParent()->end(); + iter != end; + ++iter) { + SILInstruction *inst = &*iter; + if (isa(inst) || isa(inst)) { + return true; + } + if ((isa(inst) || isa(inst)) && + inst->getOperand(0) == alloc) { + break; + } + if (isa(inst)) { + for (SILBasicBlock *succ : start->getParent()->getSuccessors()) { + if (handled.insert(succ).second) + workList.push_back(&*succ->begin()); + } + } + } + } + return false; +} + SILInstruction *SILCombiner::visitAllocStackInst(AllocStackInst *AS) { // If we are testing SILCombine and we are asked not to eliminate // alloc_stacks, just return. @@ -477,6 +507,7 @@ SILInstruction *SILCombiner::visitAllocStackInst(AllocStackInst *AS) { // // TODO: Do we not remove purely dead live ranges here? Seems like we should. SmallPtrSet ToDelete; + SmallVector takingCopies; for (auto *Op : AS->getUses()) { // Replace a copy_addr [take] %src ... by a destroy_addr %src if %src is @@ -484,8 +515,7 @@ SILInstruction *SILCombiner::visitAllocStackInst(AllocStackInst *AS) { // Otherwise, just delete the copy_addr. if (auto *CopyAddr = dyn_cast(Op->getUser())) { if (CopyAddr->isTakeOfSrc() && CopyAddr->getSrc() != AS) { - Builder.setInsertionPoint(CopyAddr); - Builder.createDestroyAddr(CopyAddr->getLoc(), CopyAddr->getSrc()); + takingCopies.push_back(CopyAddr); } } @@ -506,6 +536,20 @@ SILInstruction *SILCombiner::visitAllocStackInst(AllocStackInst *AS) { ToDelete.insert(Op->getUser()); } + // Check if a retain is moved after the copy_addr. If the retained object + // happens to be the source of the copy_addr it might be only kept alive by + // the stack location. This cannot happen with OSSA. + // TODO: remove this check once we have OSSA. + for (CopyAddrInst *copy : takingCopies) { + if (somethingIsRetained(copy, AS)) + return nullptr; + } + + for (CopyAddrInst *copy : takingCopies) { + SILBuilderWithScope destroyBuilder(copy, Builder.getBuilderContext()); + destroyBuilder.createDestroyAddr(copy->getLoc(), copy->getSrc()); + } + // Erase the 'live-range' for (auto *Inst : ToDelete) { Inst->replaceAllUsesOfAllResultsWithUndef(); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index dcba5942accd3..5146536179cb9 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -3743,19 +3743,10 @@ ConstraintSystem::getFunctionArgApplyInfo(ConstraintLocator *locator) { } else { // If we didn't resolve an overload for the callee, we should be dealing // with a call of an arbitrary function expr. - if (auto *call = dyn_cast(anchor)) { - assert(!shouldHaveDirectCalleeOverload(call) && + auto *call = cast(anchor); + assert(!shouldHaveDirectCalleeOverload(call) && "Should we have resolved a callee for this?"); - rawFnType = getType(call->getFn()); - } else if (auto *apply = dyn_cast(anchor)) { - // FIXME: ArgumentMismatchFailure is currently used from CSDiag, meaning - // we can end up a BinaryExpr here with an unresolved callee. It should be - // possible to remove this once we've gotten rid of the old CSDiag logic - // and just assert that we have a CallExpr. - rawFnType = getType(apply->getFn()); - } else { - return None; - } + rawFnType = getType(call->getFn()); } // Try to resolve the function type by loading lvalues and looking through diff --git a/stdlib/public/core/DictionaryStorage.swift b/stdlib/public/core/DictionaryStorage.swift index ac931fd2ed51c..bd5c9d583036d 100644 --- a/stdlib/public/core/DictionaryStorage.swift +++ b/stdlib/public/core/DictionaryStorage.swift @@ -117,6 +117,7 @@ internal class __RawDictionaryStorage: __SwiftNativeNSDictionary { // renamed. The old name must not be used in the new runtime. @_fixed_layout @usableFromInline +@_objc_non_lazy_realization internal class __EmptyDictionarySingleton: __RawDictionaryStorage { @nonobjc internal override init(_doNotCallMe: ()) { diff --git a/stdlib/public/core/SetStorage.swift b/stdlib/public/core/SetStorage.swift index 44936c806e1c2..f5c889ce93c1b 100644 --- a/stdlib/public/core/SetStorage.swift +++ b/stdlib/public/core/SetStorage.swift @@ -112,6 +112,7 @@ internal class __RawSetStorage: __SwiftNativeNSSet { // The old names must not be used in the new runtime. @_fixed_layout @usableFromInline +@_objc_non_lazy_realization internal class __EmptySetSingleton: __RawSetStorage { @nonobjc override internal init(_doNotCallMe: ()) { diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil index 7ff913b806830..627b0da622557 100644 --- a/test/SILOptimizer/sil_combine.sil +++ b/test/SILOptimizer/sil_combine.sil @@ -2640,6 +2640,107 @@ bb0(%0 : $*B): return %4 : $() } +// CHECK-LABEL: sil @moved_retain_prevents_alloc_stack_deletion1 +// CHECK: copy_addr +// CHECK: strong_retain +// CHECK: destroy_addr +// CHECK: } // end sil function 'moved_retain_prevents_alloc_stack_deletion1' +sil @moved_retain_prevents_alloc_stack_deletion1 : $@convention(thin) (@guaranteed B) -> () { +bb0(%0 : $B): + %3 = alloc_stack $B + %4 = alloc_stack $B + store %0 to %4 : $*B + copy_addr [take] %4 to [initialization] %3 : $*B + dealloc_stack %4 : $*B + strong_retain %0 : $B + destroy_addr %3 : $*B + dealloc_stack %3 : $*B + %14 = tuple () + return %14 : $() +} + +// CHECK-LABEL: sil @moved_retain_prevents_alloc_stack_deletion2 +// CHECK: copy_addr +// CHECK: bb1: +// CHECK: strong_retain +// CHECK: destroy_addr +// CHECK: bb2: +// CHECK: strong_retain +// CHECK: destroy_addr +// CHECK: } // end sil function 'moved_retain_prevents_alloc_stack_deletion2' +sil @moved_retain_prevents_alloc_stack_deletion2 : $@convention(thin) (@guaranteed B) -> () { +bb0(%0 : $B): + %3 = alloc_stack $B + %4 = alloc_stack $B + store %0 to %4 : $*B + copy_addr [take] %4 to [initialization] %3 : $*B + dealloc_stack %4 : $*B + cond_br undef, bb1, bb2 +bb1: + strong_retain %0 : $B + destroy_addr %3 : $*B + dealloc_stack %3 : $*B + br bb3 +bb2: + strong_retain %0 : $B + destroy_addr %3 : $*B + dealloc_stack %3 : $*B + br bb3 +bb3: + %14 = tuple () + return %14 : $() +} + +// CHECK-LABEL: sil @retain_is_after_stack_location +// CHECK-NOT: copy_addr +// CHECK: } // end sil function 'retain_is_after_stack_location' +sil @retain_is_after_stack_location : $@convention(thin) (@guaranteed B) -> () { +bb0(%0 : $B): + %3 = alloc_stack $B + %4 = alloc_stack $B + store %0 to %4 : $*B + copy_addr [take] %4 to [initialization] %3 : $*B + dealloc_stack %4 : $*B + cond_br undef, bb1, bb2 +bb1: + destroy_addr %3 : $*B + strong_retain %0 : $B + dealloc_stack %3 : $*B + br bb3 +bb2: + destroy_addr %3 : $*B + strong_retain %0 : $B + dealloc_stack %3 : $*B + br bb3 +bb3: + %14 = tuple () + return %14 : $() +} + +// CHECK-LABEL: sil @moved_retain_prevents_alloc_stack_deletion3 +// CHECK: copy_addr +// CHECK: bb2: +// CHECK: strong_retain +// CHECK: destroy_addr +// CHECK: } // end sil function 'moved_retain_prevents_alloc_stack_deletion3' +sil @moved_retain_prevents_alloc_stack_deletion3 : $@convention(thin) (@guaranteed B) -> () { +bb0(%0 : $B): + %3 = alloc_stack $B + %4 = alloc_stack $B + store %0 to %4 : $*B + copy_addr [take] %4 to [initialization] %3 : $*B + dealloc_stack %4 : $*B + br bb1 +bb1: + cond_br undef, bb1, bb2 +bb2: + strong_retain %0 : $B + destroy_addr %3 : $*B + dealloc_stack %3 : $*B + %14 = tuple () + return %14 : $() +} + protocol someProtocol { var i: Int { get } } diff --git a/test/SILOptimizer/sil_combine_alloc_stack.swift b/test/SILOptimizer/sil_combine_alloc_stack.swift new file mode 100644 index 0000000000000..134a1e7f51916 --- /dev/null +++ b/test/SILOptimizer/sil_combine_alloc_stack.swift @@ -0,0 +1,43 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -O %s -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s + +protocol E { + func f() -> Bool +} + +final class K { + deinit { + print("deinit") + } +} + + +struct X : E { + var x: K + func f() -> Bool { return true } +} + +func g(_ x : T) -> Bool { + if let y = x as? E { return y.f() } + return false +} + +// CHECK that there is no use-after-free in this function. +@inline(never) +func foo(_ x: X) -> Bool { + return g(x) +} + +@inline(never) +func testit() { + let x = X(x: K()) + _ = foo(x) + print(x) +} + +// CHECK: X(x: a.K) +// CHECK: deinit +testit() + + diff --git a/test/stdlib/EmptyCollectionSingletonRealization.swift b/test/stdlib/EmptyCollectionSingletonRealization.swift new file mode 100644 index 0000000000000..2993262622a6c --- /dev/null +++ b/test/stdlib/EmptyCollectionSingletonRealization.swift @@ -0,0 +1,48 @@ +// 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 +// +//===----------------------------------------------------------------------===// +// +// RUN: %target-run-simple-swift | %FileCheck %s +// REQUIRES: executable_test +// REQUIRES: objc_interop + +import Foundation + +// Test to make sure that empty collections don't cause a crash if we smuggle +// them into the ObjC runtime without doing anything that would trigger +// realization. The ObjC runtime expects all classes to have been realized +// (i.e. runtime data structures initialized, triggered the first time a class +// is accessed or used) before being queried in any way. +// +// Note: this test deliberately avoids StdlibUnittest to make sure +// no other code runs that might inadvertently trigger realization behind our +// back. + +@objc protocol P {} + +do { + let d: [NSObject: NSObject] = [:] + let c: AnyClass? = object_getClass(d) + let conforms = class_conformsToProtocol(c, P.self) + print("Dictionary: ", conforms) // CHECK: Dictionary: false +} + +do { + let a: [NSObject] = [] + let c: AnyClass? = object_getClass(a) + let p = objc_getProtocol("NSObject") + let conforms = class_conformsToProtocol(c, p) + print("Array:", conforms) // CHECK: Array: false +} + +do { + let s: Set = [] + let c: AnyClass? = object_getClass(s) + let p = objc_getProtocol("NSObject") + let conforms = class_conformsToProtocol(c, p) + print("Set:", conforms) // CHECK: Set: false +} \ No newline at end of file diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt index 586053c4d71b7..18ccbdcd14b6e 100644 --- a/unittests/Driver/CMakeLists.txt +++ b/unittests/Driver/CMakeLists.txt @@ -1,6 +1,7 @@ add_swift_unittest(SwiftDriverTests CoarseGrainedDependencyGraphTests.cpp FineGrainedDependencyGraphTests.cpp + MockingFineGrainedDependencyGraphs.cpp TypeBodyFingerprintsDependencyGraphTests.cpp ) diff --git a/unittests/Driver/FineGrainedDependencyGraphTests.cpp b/unittests/Driver/FineGrainedDependencyGraphTests.cpp index 28e8286866d9e..40b98ca1adff4 100644 --- a/unittests/Driver/FineGrainedDependencyGraphTests.cpp +++ b/unittests/Driver/FineGrainedDependencyGraphTests.cpp @@ -1,23 +1,21 @@ +#include "MockingFineGrainedDependencyGraphs.h" #include "swift/Basic/ReferenceDependencyKeys.h" #include "swift/Driver/CoarseGrainedDependencyGraph.h" #include "swift/Driver/FineGrainedDependencyDriverGraph.h" #include "swift/Driver/Job.h" #include "gtest/gtest.h" -// This file adapts the unit tests from the older, coarse-grained, dependency -// graph to the new fine-grained graph. - -// \c findJobsToRecompileWhenWholeJobChanges and \c -// findExternallyDependentUntracedJobs may include jobs in their result that -// would be excluded in the coarse-grained graph. But since these will be jobs -// that have already been scheduled, downstream mechanisms will filter them out. +// A version of \c ModuleDepGraphTests.cpp that tests things with +// type-body fingerprints disabled. +// +// In order to get the test macros to work right, it seems that the tests +// must be copied-and-pasted, sigh. using namespace swift; -using namespace reference_dependency_keys; using namespace fine_grained_dependencies; +using namespace mocking_fine_grained_dependency_graphs; using Job = driver::Job; - static OutputFileMap OFM; static Job @@ -41,39 +39,31 @@ static bool contains(const Range &range, const T &value) { std::end(range); } -TEST(ModuleDepGraph, BasicLoad) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); - - EXPECT_TRUE(graph.simulateLoad( &job0, {{dependsTopLevel, {"a", "b"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"c", "d"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{providesTopLevel, {"e", "f"}}})); - EXPECT_TRUE(graph.simulateLoad( &job3, {{providesNominal, {"g", "h"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job4, {{providesDynamicLookup, {"i", "j"}}})); - EXPECT_TRUE(graph.simulateLoad( &job5, {{dependsDynamicLookup, {"k", "l"}}})); - EXPECT_TRUE(graph.simulateLoad( &job6, {}, - {{providesMember, {{"m", "mm"}, {"n", "nn"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job7, {}, - {{dependsMember, {{"o", "oo"}, {"p", "pp"}}}})); - EXPECT_TRUE( - graph.simulateLoad( &job8, {{dependsExternal, {"/foo", "/bar"}}})); - - EXPECT_TRUE(graph.simulateLoad( &job9, - {{providesNominal, {"a", "b"}}, - {providesTopLevel, {"b", "c"}}, - {dependsNominal, {"c", "d"}}, - {dependsTopLevel, {"d", "a"}}})); -} - -TEST(ModuleDepGraph, IndependentNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); - - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsTopLevel, {"a"}}, {providesTopLevel, {"a0"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"b0"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job2, {{dependsTopLevel, {"c"}}, {providesTopLevel, {"c0"}}})); +TEST(ModuleDepGraphWithoutFingerprints, BasicLoad) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"c->", "d->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"e", "f"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"g", "h"}}}); + simulateLoad(graph, &job4, {{NodeKind::dynamicLookup, {"i", "j"}}}); + simulateLoad(graph, &job5, {{NodeKind::dynamicLookup, {"k->", "l->"}}}); + simulateLoad(graph, &job6, {{NodeKind::member, {"m,mm", "n,nn"}}}); + simulateLoad(graph, &job7, {{NodeKind::member, {"o,oo->", "p,pp->"}}}); + simulateLoad(graph, &job8, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); + + simulateLoad(graph, &job9, + {{NodeKind::nominal, {"a", "b", "c->", "d->"}}, + {NodeKind::topLevel, {"b", "c", "d->", "a->"}}}); +} + +TEST(ModuleDepGraphWithoutFingerprints, IndependentNodes) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a0", "a->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b0", "b->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"c0", "c->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -97,41 +87,36 @@ TEST(ModuleDepGraph, IndependentNodes) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, IndependentDepKinds) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "a->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a", "b->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, IndependentDepKinds2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a->", "b"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b->", "a"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job1).size()); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, IndependentMembers) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, IndependentMembers) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {}, {{providesMember, {{"a", "aa"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {}, {{dependsMember, {{"a", "bb"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {}, {{dependsMember, {{"a", ""}}}})); - EXPECT_TRUE(graph.simulateLoad( &job3, {}, {{dependsMember, {{"b", "aa"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job4, {}, {{dependsMember, {{"b", "bb"}}}})); + simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa"}}}); + simulateLoad(graph, &job1, {{NodeKind::member, {"a,bb->"}}}); + simulateLoad(graph, &job2, {{NodeKind::potentialMember, {"a"}}}); + simulateLoad(graph, &job3, {{NodeKind::member, {"b,aa->"}}}); + simulateLoad(graph, &job4, {{NodeKind::member, {"b,bb->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -141,12 +126,11 @@ TEST(ModuleDepGraph, IndependentMembers) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job4)); } -TEST(ModuleDepGraph, SimpleDependent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_EQ(2u, jobs.size()); @@ -160,17 +144,16 @@ TEST(ModuleDepGraph, SimpleDependent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependentReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentReverse) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{dependsTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {{providesTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->", "c->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x", "b", "z"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(2u, jobs.size()); - EXPECT_EQ(&job0, jobs.front()); + EXPECT_TRUE(contains(jobs, &job0)); } EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -184,11 +167,11 @@ TEST(ModuleDepGraph, SimpleDependentReverse) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependent2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -203,12 +186,12 @@ TEST(ModuleDepGraph, SimpleDependent2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependent3) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent3) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{providesNominal, {"a"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); + simulateLoad(graph, &job0, + {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -223,12 +206,12 @@ TEST(ModuleDepGraph, SimpleDependent3) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependent4) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent4) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {dependsTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, + {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -243,13 +226,13 @@ TEST(ModuleDepGraph, SimpleDependent4) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependent5) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent5) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{providesNominal, {"a"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {dependsTopLevel, {"a"}}})); + simulateLoad(graph, &job0, + {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad(graph, &job1, + {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -265,13 +248,12 @@ TEST(ModuleDepGraph, SimpleDependent5) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependent6) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent6) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesDynamicLookup, {"a", "b", "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {{dependsDynamicLookup, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::dynamicLookup, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, + {{NodeKind::dynamicLookup, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_EQ(2u, jobs.size()); @@ -285,15 +267,12 @@ TEST(ModuleDepGraph, SimpleDependent6) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleDependentMember) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentMember) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {}, - {{providesMember, {{"a", "aa"}, {"b", "bb"}, {"c", "cc"}}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {}, - {{dependsMember, {{"x", "xx"}, {"b", "bb"}, {"z", "zz"}}}})); + simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa", "b,bb", "c,cc"}}}); + simulateLoad(graph, &job1, + {{NodeKind::member, {"x,xx->", "b,bb->", "z,zz->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -308,12 +287,12 @@ TEST(ModuleDepGraph, SimpleDependentMember) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, MultipleDependentsSame) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsSame) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"q", "b", "s"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"q->", "b->", "s->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -331,12 +310,12 @@ TEST(ModuleDepGraph, MultipleDependentsSame) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, MultipleDependentsDifferent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsDifferent) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"q", "r", "c"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"q->", "r->", "c->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -354,13 +333,12 @@ TEST(ModuleDepGraph, MultipleDependentsDifferent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, ChainedDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedDependents) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"x", "b"}}, {providesNominal, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"z"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -378,13 +356,12 @@ TEST(ModuleDepGraph, ChainedDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, ChainedNoncascadingDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"x", "b"}}, {providesNominal, {SourceFileDepGraph::noncascading("z")}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {SourceFileDepGraph::noncascading("z")}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "#z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"#z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -402,15 +379,14 @@ TEST(ModuleDepGraph, ChainedNoncascadingDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, ChainedNoncascadingDependents2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", SourceFileDepGraph::noncascading("b"), "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, - {{dependsTopLevel, {"x", SourceFileDepGraph::noncascading("b")}}, {providesNominal, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::topLevel, {"x->", "#b->"}}, {NodeKind::nominal, {"z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -422,19 +398,15 @@ TEST(ModuleDepGraph, ChainedNoncascadingDependents2) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, MarkTwoNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkTwoNodes) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"a"}}, {providesTopLevel, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsTopLevel, {"z"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job10, - {{providesTopLevel, {"y", "z"}}, {dependsTopLevel, {"q"}}})); - EXPECT_TRUE(graph.simulateLoad( &job11, {{dependsTopLevel, {"y"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job12, {{dependsTopLevel, {"q"}}, {providesTopLevel, {"q"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "z"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"z->"}}}); + simulateLoad(graph, &job10, {{NodeKind::topLevel, {"y", "z", "q->"}}}); + simulateLoad(graph, &job11, {{NodeKind::topLevel, {"y->"}}}); + simulateLoad(graph, &job12, {{NodeKind::topLevel, {"q->", "q"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -464,12 +436,12 @@ TEST(ModuleDepGraph, MarkTwoNodes) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job12)); } -TEST(ModuleDepGraph, MarkOneNodeTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -480,11 +452,8 @@ TEST(ModuleDepGraph, MarkOneNodeTwice) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 0. - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"b"}}})); - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"b"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job2)); } @@ -493,12 +462,12 @@ TEST(ModuleDepGraph, MarkOneNodeTwice) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, MarkOneNodeTwice2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -509,11 +478,8 @@ TEST(ModuleDepGraph, MarkOneNodeTwice2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 0. - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b"}}})); - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"a", "b"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job2)); } @@ -522,12 +488,12 @@ TEST(ModuleDepGraph, MarkOneNodeTwice2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, ReloadDetectsChange) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ReloadDetectsChange) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(1u, jobs.size()); @@ -537,41 +503,27 @@ TEST(ModuleDepGraph, ReloadDetectsChange) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 1. - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - // Re-mark 1. { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + auto jobs = + simulateReload(graph, &job1, {{NodeKind::nominal, {"b", "a->"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job1)); EXPECT_TRUE(contains(jobs, &job2)); } - - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); + EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, NotTransitiveOnceMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, NotTransitiveOnceMarked) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(1u, jobs.size()); EXPECT_TRUE(contains(jobs, &job1)); } @@ -579,41 +531,25 @@ TEST(ModuleDepGraph, NotTransitiveOnceMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 1. - EXPECT_TRUE(graph.simulateLoad( &job1, - {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - // Re-mark 1. - { - auto found = graph.findJobsToRecompileWhenWholeJobChanges(&job1); - EXPECT_EQ(2u, found.size()); - EXPECT_TRUE(contains(found, &job1)); - EXPECT_TRUE(contains(found, &job2)); + const auto jobs = + simulateReload(graph, &job1, {{NodeKind::nominal, {"b", "a->"}}}); + EXPECT_EQ(2u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); + EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, DependencyLoops) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, DependencyLoops) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, - {{providesTopLevel, {"a", "b", "c"}}, {dependsTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, - {{providesTopLevel, {"x"}}, {dependsTopLevel, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsTopLevel, {"x"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c", "a->"}}}); + simulateLoad(graph, &job1, + {{NodeKind::topLevel, {"x", "x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"x->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -634,12 +570,11 @@ TEST(ModuleDepGraph, DependencyLoops) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraph, MarkIntransitive) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitive) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -653,23 +588,21 @@ TEST(ModuleDepGraph, MarkIntransitive) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, MarkIntransitiveTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveTwice) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, MarkIntransitiveThenIndirect) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveThenIndirect) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -684,11 +617,11 @@ TEST(ModuleDepGraph, MarkIntransitiveThenIndirect) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, SimpleExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{dependsExternal, {"/foo", "/bar"}}})); + simulateLoad(graph, &job0, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/foo")); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/bar")); @@ -705,11 +638,11 @@ TEST(ModuleDepGraph, SimpleExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraph, SimpleExternal2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{dependsExternal, {"/foo", "/bar"}}})); + simulateLoad(graph, &job0, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); EXPECT_EQ(1u, graph.findExternallyDependentUntracedJobs("/bar").size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -718,13 +651,15 @@ TEST(ModuleDepGraph, SimpleExternal2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraph, ChainedExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedExternal) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/foo")); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/bar")); @@ -746,13 +681,15 @@ TEST(ModuleDepGraph, ChainedExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, ChainedExternalReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalReverse) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findExternallyDependentUntracedJobs("/bar"); @@ -769,19 +706,21 @@ TEST(ModuleDepGraph, ChainedExternalReverse) { { auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); EXPECT_EQ(1u, jobs.size()); - EXPECT_EQ(&job0, jobs.front()); + EXPECT_TRUE(contains(jobs, &job0)); } EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraph, ChainedExternalPreMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalPreMarked) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); @@ -793,34 +732,105 @@ TEST(ModuleDepGraph, ChainedExternalPreMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } - -TEST(ModuleDepGraph, MutualInterfaceHash) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); - graph.simulateLoad( &job0, { - {providesTopLevel, {"a"}}, - {dependsTopLevel, {"b"}} - }); - graph.simulateLoad( &job1, { - {dependsTopLevel, {"a"}}, - {providesTopLevel, {"b"}} - }); +TEST(ModuleDepGraphWithoutFingerprints, MutualInterfaceHash) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "b"}}}); const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } -TEST(ModuleDepGraph, DisabledTypeBodyFingerprints) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); +TEST(ModuleDepGraphWithoutFingerprints, DisabledTypeBodyFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); - graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); - graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"B2->"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "B2"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B1->"}}}); { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); - EXPECT_EQ(3u, jobs.size()); + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + } +} + +TEST(ModuleDepGraphWithoutFingerprints, BaselineForPrintsAndCrossType) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + + // Because when A1 changes, B1 and not B2 is affected, only jobs1 and job2 + // should be recompiled, except type fingerprints is off! + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "A1->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"C1", "A2->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"D1"}}}); + + { + const auto jobs = simulateReload( + graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}, "changed"); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job3)); + } +} + +TEST(ModuleDepGraphWithoutFingerprints, LoadFailsWithFingerprint) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + EXPECT_FALSE( + getChangesForSimulatedLoad(graph, &job0, {{NodeKind::nominal, {"A@1"}}})); +} + +TEST(ModuleDepGraphWithoutFingerprints, IgnoreFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "A1->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"C1", "A2->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"D1"}}}); + + { + const auto jobs = + simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); + EXPECT_EQ(4u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_TRUE(contains(jobs, &job3)); + } +} + +TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependencyBaseline) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B", "C", "A->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C->"}}}); + + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job0)); EXPECT_TRUE(contains(jobs, &job1)); EXPECT_TRUE(contains(jobs, &job2)); - } + EXPECT_TRUE(contains(jobs, &job3)); +} + +TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependency) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); + // Because of the cross-type dependency, A->B, + // when A changes, only B is dirtied in job1. + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B", "C", "A->B"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C->"}}}); + + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job3)); } diff --git a/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp b/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp new file mode 100644 index 0000000000000..f9d1caaa14e72 --- /dev/null +++ b/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp @@ -0,0 +1,89 @@ +//===--------------- MockingFineGraonedDependencyGraphs.cpp ---------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "MockingFineGrainedDependencyGraphs.h" +#include "swift/AST/DiagnosticEngine.h" +#include "swift/AST/SourceFileDepGraphConstructor.h" +#include "swift/Basic/ReferenceDependencyKeys.h" +#include "swift/Basic/SourceManager.h" + +#include +#include + +using namespace swift; +using namespace fine_grained_dependencies; +using namespace mocking_fine_grained_dependency_graphs; + +void mocking_fine_grained_dependency_graphs::simulateLoad( + ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty, const bool includePrivateDeps, + const bool hadCompilationError) { + const auto changes = getChangesForSimulatedLoad( + g, cmd, dependencyDescriptions, interfaceHashIfNonEmpty, + includePrivateDeps, hadCompilationError); + assert(changes && "simulated load should always succeed"); +} + +ModuleDepGraph::Changes +mocking_fine_grained_dependency_graphs::getChangesForSimulatedLoad( + ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty, const bool includePrivateDeps, + const bool hadCompilationError) { + StringRef swiftDeps = + cmd->getOutput().getAdditionalOutputForType(file_types::TY_SwiftDeps); + assert(!swiftDeps.empty()); + StringRef interfaceHash = + interfaceHashIfNonEmpty.empty() ? swiftDeps : interfaceHashIfNonEmpty; + + SourceManager sm; + DiagnosticEngine diags(sm); + + auto sfdg = + MockSourceFileDepGraphConstructor( + includePrivateDeps, hadCompilationError, swiftDeps, interfaceHash, + g.emitFineGrainedDependencyDotFileAfterEveryImport, + dependencyDescriptions, diags) + .construct(); + + return g.loadFromSourceFileDepGraph(cmd, sfdg, diags); +} + +std::vector +mocking_fine_grained_dependency_graphs::simulateReload( + ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty, const bool includePrivateDeps, + const bool hadCompilationError) { + const auto changedNodes = getChangesForSimulatedLoad( + g, cmd, dependencyDescriptions, interfaceHashIfNonEmpty, + includePrivateDeps, hadCompilationError); + if (!changedNodes) + return g.getAllJobs(); + return g.findJobsToRecompileWhenNodesChange(changedNodes.getValue()); +} + +LLVM_ATTRIBUTE_UNUSED +std::vector +mocking_fine_grained_dependency_graphs::printJobsForDebugging( + const std::vector &jobs) { + llvm::errs() << "\nprintForDebugging: "; + for (auto *j : jobs) { + const auto swiftDeps = + j->getOutput().getAdditionalOutputForType(file_types::TY_SwiftDeps); + assert(!swiftDeps.empty()); + llvm::errs() << "job" << swiftDeps << " "; + } + llvm::errs() << "\n"; + return jobs; +} diff --git a/unittests/Driver/MockingFineGrainedDependencyGraphs.h b/unittests/Driver/MockingFineGrainedDependencyGraphs.h new file mode 100644 index 0000000000000..72cb3e6018241 --- /dev/null +++ b/unittests/Driver/MockingFineGrainedDependencyGraphs.h @@ -0,0 +1,103 @@ +//===----------- MockingFineGrainedDependencyGraphs.h -----------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef MOCKING_FINE_GRAINED_DEPENDENCY_GRAPHS_H +#define MOCKING_FINE_GRAINED_DEPENDENCY_GRAPHS_H + +#include "swift/AST/FineGrainedDependencies.h" +#include "swift/AST/SourceFileDepGraphConstructor.h" +#include "swift/Driver/FineGrainedDependencyDriverGraph.h" + +namespace swift { +namespace fine_grained_dependencies { + +/// Affordances for testing the \c SourceFileDepGraph and \c ModuleFileDepGraph +/// +/// Because fine-grained swiftdeps files are somewhat verbose, this file +/// provides affordances to mock them up in a concise fashion. + +namespace mocking_fine_grained_dependency_graphs { + +/// Simulate loading for unit testing, as if the driver is reading the swiftdeps +/// file for the first time. +/// +/// \param g The graph to load into. +/// \param cmd The \c Job whose dependency info will be loaded. +/// \param dependencyDescriptions Dependency info, see below +/// \param interfaceHashIfNonEmpty If non-empty, overrides the default simulated +/// interface hash \param includePrivateDeps Include file-private declarations +/// in the dependency information. \param hadCompilationError Simulate a +/// compilation error. +/// +/// Fails an assertion if the information is not valid (for instance a +/// fingerprint where it should not be). +/// +/// *Dependency info format:* +/// A list of entries, each of which is keyed by a \c NodeKind and contains a +/// list of dependency nodes. +/// +/// *Dependency node format:* +/// Each node here is either a "provides" (i.e. a declaration provided by the +/// file) or a "depends" (i.e. a declaration that is depended upon). +/// +/// For "provides" (i.e. declarations provided by the source file): +/// = [#][@], +/// where the '#' prefix indicates that the declaration is file-private. +/// +/// = | , +/// where is a mangled type name, and is a base-name. +/// +/// For "depends" (i.e. uses of declarations in the source file): +/// [#][~]->[] +/// where the '#' prefix indicates that the use does not cascade, +/// the '~' prefix indicates that the holder is private, +/// is the depended-upon declaration and the optional +/// is the dependent declaration if known. If not known, the +/// use will be the entire file. + +void simulateLoad(ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty = StringRef(), + const bool includePrivateDeps = true, + const bool hadCompilationError = false); + +/// Same as \ref simulateLoad, but returns the specifically changed nodes or +/// None if the load failed. + +ModuleDepGraph::Changes +getChangesForSimulatedLoad(ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty = StringRef(), + const bool includePrivateDeps = true, + const bool hadCompilationError = false); + +/// Simulates the driver reloading a swiftdeps file after a job has run. +/// Returns the jobs that must now be run, possibly redundantly including \p +/// cmd. +/// +/// See \ref simulateLoad for a parameter description. + +std::vector +simulateReload(ModuleDepGraph &g, const driver::Job *cmd, + const DependencyDescriptions &dependencyDescriptions, + StringRef interfaceHashIfNonEmpty = StringRef(), + const bool includePrivateDeps = true, + const bool hadCompilationError = false); + +std::vector +printJobsForDebugging(const std::vector &jobs); + +} // end namespace mocking_fine_grained_dependency_graphs +} // namespace fine_grained_dependencies +} // end namespace swift + +#endif /* MOCKING_FINE_GRAINED_DEPENDENCY_GRAPHS_H */ diff --git a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp index 041cc9c2ee416..c19fd1313457f 100644 --- a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp +++ b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp @@ -1,3 +1,4 @@ +#include "MockingFineGrainedDependencyGraphs.h" #include "swift/Basic/ReferenceDependencyKeys.h" #include "swift/Driver/CoarseGrainedDependencyGraph.h" #include "swift/Driver/FineGrainedDependencyDriverGraph.h" @@ -7,17 +8,22 @@ // This file adapts the unit tests from the older, coarse-grained, dependency // graph to the new fine-grained graph. -// \c findJobsToRecompileWhenWholeJobChanges and \c -// findExternallyDependentUntracedJobs may include jobs in their result that +// \c findJobsToRecompileWhenWholeJobChanges, +// \c findExternallyDependentUntracedJobs, and \c simulateReload +// may include jobs in their result that // would be excluded in the coarse-grained graph. But since these will be jobs // that have already been scheduled, downstream mechanisms will filter them out. +// To debug a test, create the \c ModuleDepGraph and pass true as the second +// argument to the constructor, then find the dot files in the directory +// where the tests run, +// and inspect them with, e.g. OmniGraffle. + using namespace swift; -using namespace reference_dependency_keys; using namespace fine_grained_dependencies; +using namespace mocking_fine_grained_dependency_graphs; using Job = driver::Job; - static OutputFileMap OFM; static Job @@ -41,39 +47,31 @@ static bool contains(const Range &range, const T &value) { std::end(range); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, BasicLoad) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, BasicLoad) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{dependsTopLevel, {"a", "b"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"c", "d"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{providesTopLevel, {"e", "f"}}})); - EXPECT_TRUE(graph.simulateLoad( &job3, {{providesNominal, {"g", "h"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job4, {{providesDynamicLookup, {"i", "j"}}})); - EXPECT_TRUE(graph.simulateLoad( &job5, {{dependsDynamicLookup, {"k", "l"}}})); - EXPECT_TRUE(graph.simulateLoad( &job6, {}, - {{providesMember, {{"m", "mm"}, {"n", "nn"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job7, {}, - {{dependsMember, {{"o", "oo"}, {"p", "pp"}}}})); - EXPECT_TRUE( - graph.simulateLoad( &job8, {{dependsExternal, {"/foo", "/bar"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"c->", "d->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"e", "f"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"g", "h"}}}); + simulateLoad(graph, &job4, {{NodeKind::dynamicLookup, {"i", "j"}}}); + simulateLoad(graph, &job5, {{NodeKind::dynamicLookup, {"k->", "l->"}}}); + simulateLoad(graph, &job6, {{NodeKind::member, {"m,mm", "n,nn"}}}); + simulateLoad(graph, &job7, {{NodeKind::member, {"o,oo->", "p,pp->"}}}); + simulateLoad(graph, &job8, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); - EXPECT_TRUE(graph.simulateLoad( &job9, - {{providesNominal, {"a", "b"}}, - {providesTopLevel, {"b", "c"}}, - {dependsNominal, {"c", "d"}}, - {dependsTopLevel, {"d", "a"}}})); + simulateLoad(graph, &job9, + {{NodeKind::nominal, {"a", "b", "c->", "d->"}}, + {NodeKind::topLevel, {"b", "c", "d->", "a->"}}}); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, IndependentNodes) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsTopLevel, {"a"}}, {providesTopLevel, {"a0"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"b0"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job2, {{dependsTopLevel, {"c"}}, {providesTopLevel, {"c0"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a0", "a->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b0", "b->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"c0", "c->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -97,41 +95,36 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentNodes) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentDepKinds) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, IndependentDepKinds) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "a->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a", "b->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentDepKinds2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, IndependentDepKinds2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"b"}}, {providesTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a->", "b"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b->", "a"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job1).size()); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentMembers) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, IndependentMembers) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {}, {{providesMember, {{"a", "aa"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {}, {{dependsMember, {{"a", "bb"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {}, {{dependsMember, {{"a", ""}}}})); - EXPECT_TRUE(graph.simulateLoad( &job3, {}, {{dependsMember, {{"b", "aa"}}}})); - EXPECT_TRUE(graph.simulateLoad( &job4, {}, {{dependsMember, {{"b", "bb"}}}})); + simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa"}}}); + simulateLoad(graph, &job1, {{NodeKind::member, {"a,bb->"}}}); + simulateLoad(graph, &job2, {{NodeKind::potentialMember, {"a"}}}); + simulateLoad(graph, &job3, {{NodeKind::member, {"b,aa->"}}}); + simulateLoad(graph, &job4, {{NodeKind::member, {"b,bb->"}}}); EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -141,12 +134,11 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, IndependentMembers) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job4)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_EQ(2u, jobs.size()); @@ -160,17 +152,16 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependentReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependentReverse) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{dependsTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {{providesTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->", "c->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x", "b", "z"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(2u, jobs.size()); - EXPECT_EQ(&job0, jobs.front()); + EXPECT_TRUE(contains(jobs, &job0)); } EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -184,11 +175,11 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependentReverse) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -203,12 +194,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent3) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent3) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{providesNominal, {"a"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); + simulateLoad(graph, &job0, + {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -223,12 +214,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent3) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent4) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent4) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {dependsTopLevel, {"a"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, + {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -243,13 +234,13 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent4) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent5) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent5) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{providesNominal, {"a"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {dependsTopLevel, {"a"}}})); + simulateLoad(graph, &job0, + {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad(graph, &job1, + {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -265,13 +256,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent5) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent6) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependent6) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesDynamicLookup, {"a", "b", "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {{dependsDynamicLookup, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::dynamicLookup, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, + {{NodeKind::dynamicLookup, {"x->", "b->", "z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_EQ(2u, jobs.size()); @@ -285,15 +275,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependent6) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependentMember) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleDependentMember) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {}, - {{providesMember, {{"a", "aa"}, {"b", "bb"}, {"c", "cc"}}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, {}, - {{dependsMember, {{"x", "xx"}, {"b", "bb"}, {"z", "zz"}}}})); + simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa", "b,bb", "c,cc"}}}); + simulateLoad(graph, &job1, + {{NodeKind::member, {"x,xx->", "b,bb->", "z,zz->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -308,12 +295,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleDependentMember) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MultipleDependentsSame) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MultipleDependentsSame) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"q", "b", "s"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"q->", "b->", "s->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -331,12 +318,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MultipleDependentsSame) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MultipleDependentsDifferent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MultipleDependentsDifferent) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"q", "r", "c"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"q->", "r->", "c->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -354,13 +341,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MultipleDependentsDifferent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedDependents) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"x", "b"}}, {providesNominal, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"z"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -378,13 +364,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedNoncascadingDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedNoncascadingDependents) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"x", "b"}}, {providesNominal, {SourceFileDepGraph::noncascading("z")}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {SourceFileDepGraph::noncascading("z")}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "#z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"#z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -402,15 +387,14 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedNoncascadingDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedNoncascadingDependents2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedNoncascadingDependents2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", SourceFileDepGraph::noncascading("b"), "c"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job1, - {{dependsTopLevel, {"x", SourceFileDepGraph::noncascading("b")}}, {providesNominal, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::topLevel, {"x->", "#b->"}}, {NodeKind::nominal, {"z"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"z->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -422,19 +406,15 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedNoncascadingDependents2) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkTwoNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkTwoNodes) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsTopLevel, {"a"}}, {providesTopLevel, {"z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsTopLevel, {"z"}}})); - EXPECT_TRUE( - graph.simulateLoad( &job10, - {{providesTopLevel, {"y", "z"}}, {dependsTopLevel, {"q"}}})); - EXPECT_TRUE(graph.simulateLoad( &job11, {{dependsTopLevel, {"y"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job12, {{dependsTopLevel, {"q"}}, {providesTopLevel, {"q"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "z"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"z->"}}}); + simulateLoad(graph, &job10, {{NodeKind::topLevel, {"y", "z", "q->"}}}); + simulateLoad(graph, &job11, {{NodeKind::topLevel, {"y->"}}}); + simulateLoad(graph, &job12, {{NodeKind::topLevel, {"q->", "q"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -464,12 +444,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkTwoNodes) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job12)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkOneNodeTwice) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -480,11 +460,8 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 0. - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"b"}}})); - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"b"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job2)); } @@ -493,12 +470,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkOneNodeTwice2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -509,11 +486,8 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 0. - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a", "b"}}})); - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"a", "b"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job2)); } @@ -522,12 +496,12 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkOneNodeTwice2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ReloadDetectsChange) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ReloadDetectsChange) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(1u, jobs.size()); @@ -537,41 +511,27 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ReloadDetectsChange) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 1. - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - // Re-mark 1. { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + auto jobs = + simulateReload(graph, &job1, {{NodeKind::nominal, {"b", "a->"}}}); EXPECT_EQ(2u, jobs.size()); EXPECT_TRUE(contains(jobs, &job1)); EXPECT_TRUE(contains(jobs, &job2)); } - - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); + EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, NotTransitiveOnceMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, NotTransitiveOnceMarked) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( &job0, {{providesNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsNominal, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsNominal, {"b"}}})); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); EXPECT_EQ(1u, jobs.size()); EXPECT_TRUE(contains(jobs, &job1)); } @@ -579,41 +539,25 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, NotTransitiveOnceMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - // Reload 1. - EXPECT_TRUE(graph.simulateLoad( &job1, - {{dependsNominal, {"a"}}, {providesNominal, {"b"}}})); - - { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - // Re-mark 1. { - auto found = graph.findJobsToRecompileWhenWholeJobChanges(&job1); - EXPECT_EQ(2u, found.size()); - EXPECT_TRUE(contains(found, &job1)); - EXPECT_TRUE(contains(found, &job2)); + const auto jobs = + simulateReload(graph, &job1, {{NodeKind::nominal, {"b", "a->"}}}); + EXPECT_EQ(2u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); + EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, DependencyLoops) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, DependencyLoops) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, - {{providesTopLevel, {"a", "b", "c"}}, {dependsTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, - {{providesTopLevel, {"x"}}, {dependsTopLevel, {"x", "b", "z"}}})); - EXPECT_TRUE(graph.simulateLoad( &job2, {{dependsTopLevel, {"x"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c", "a->"}}}); + simulateLoad(graph, &job1, + {{NodeKind::topLevel, {"x", "x->", "b->", "z->"}}}); + simulateLoad(graph, &job2, {{NodeKind::topLevel, {"x->"}}}); { auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); @@ -634,12 +578,11 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, DependencyLoops) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkIntransitive) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkIntransitive) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -653,23 +596,21 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkIntransitive) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkIntransitiveTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkIntransitiveTwice) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkIntransitiveThenIndirect) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, MarkIntransitiveThenIndirect) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{providesTopLevel, {"a", "b", "c"}}})); - EXPECT_TRUE(graph.simulateLoad( &job1, {{dependsTopLevel, {"x", "b", "z"}}})); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); @@ -684,11 +625,11 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MarkIntransitiveThenIndirect) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleExternal) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{dependsExternal, {"/foo", "/bar"}}})); + simulateLoad(graph, &job0, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/foo")); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/bar")); @@ -705,11 +646,11 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleExternal2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, SimpleExternal2) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE( - graph.simulateLoad( &job0, {{dependsExternal, {"/foo", "/bar"}}})); + simulateLoad(graph, &job0, + {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); EXPECT_EQ(1u, graph.findExternallyDependentUntracedJobs("/bar").size()); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); @@ -718,13 +659,15 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, SimpleExternal2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedExternal) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/foo")); EXPECT_TRUE(contains(graph.getExternalDependencies(), "/bar")); @@ -746,13 +689,15 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternalReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedExternalReverse) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findExternallyDependentUntracedJobs("/bar"); @@ -769,19 +714,21 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternalReverse) { { auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); EXPECT_EQ(1u, jobs.size()); - EXPECT_EQ(&job0, jobs.front()); + EXPECT_TRUE(contains(jobs, &job0)); } EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternalPreMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); +TEST(ModuleDepGraph, ChainedExternalPreMarked) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - EXPECT_TRUE(graph.simulateLoad( - &job0, {{dependsExternal, {"/foo"}}, {providesTopLevel, {"a"}}})); - EXPECT_TRUE(graph.simulateLoad( - &job1, {{dependsExternal, {"/bar"}}, {dependsTopLevel, {"a"}}})); + simulateLoad( + graph, &job0, + {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); + simulateLoad( + graph, &job1, + {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); { auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); @@ -793,39 +740,153 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, ChainedExternalPreMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } - -TEST(ModuleDepGraphWithTypeBodyFingerprints, MutualInterfaceHash) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); - graph.simulateLoad( &job0, { - {providesTopLevel, {"a"}}, - {dependsTopLevel, {"b"}} - }); - graph.simulateLoad( &job1, { - {dependsTopLevel, {"a"}}, - {providesTopLevel, {"b"}} - }); +TEST(ModuleDepGraph, MutualInterfaceHash) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b->"}}}); + simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "b"}}}); const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } TEST(ModuleDepGraph, EnabledTypeBodyFingerprints) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"B2->"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "B2"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B1->"}}}); + + { + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + } +} - graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); - graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); - graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); +TEST(ModuleDepGraph, BaselineForPrintsAndCrossType) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + // Because when A1 changes, B1 and not B2 is affected, only jobs1 and job2 + // should be recompiled, except type fingerprints is off! + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "A1->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"C1", "A2->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"D1"}}}); - const DependencyKey k = DependencyKey(NodeKind::nominal, - DeclAspect::interface, "B1", ""); - std::vector changedNodes; - graph.forEachMatchingNode( - k, - [&](ModuleDepGraphNode* n) {changedNodes.push_back(n);}); { - const auto jobs = graph.findJobsToRecompileWhenNodesChange(changedNodes); + const auto jobs = simulateReload( + graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}, "changed"); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); EXPECT_TRUE(contains(jobs, &job2)); - EXPECT_FALSE(contains(jobs, &job0)); - } + EXPECT_FALSE(contains(jobs, &job3)); + } +} + +TEST(ModuleDepGraph, LoadPassesWithFingerprint) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + EXPECT_TRUE( + getChangesForSimulatedLoad(graph, &job0, {{NodeKind::nominal, {"A@1"}}})); +} + +TEST(ModuleDepGraph, UseFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + + // Because when A1 changes, B1 and not B2 is affected, only jobs1 and job2 + // should be recompiled, except type fingerprints is off! + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1@1", "A2@2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "A1->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"C1", "A2->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"D1"}}}); + + { + const auto jobs = + simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); + EXPECT_EQ(2u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_FALSE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job3)); + } +} + +TEST(ModuleDepGraph, CrossTypeDependencyBaseline) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B", "C", "A->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C->"}}}); + + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_TRUE(contains(jobs, &job3)); +} + +TEST(ModuleDepGraph, CrossTypeDependency) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + // Because of the cross-type dependency, A->B, + // when A changes, only B is dirtied in job1. + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B", "C", "A->B"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C->"}}}); + + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job3)); +} + +TEST(ModuleDepGraph, CrossTypeDependencyBaselineWithFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1@1", "A2@2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "C1", "A1->"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B1->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C1->"}}}); + simulateLoad(graph, &job4, {{NodeKind::nominal, {"B2", "C2", "A2->"}}}); + simulateLoad(graph, &job5, {{NodeKind::nominal, {"B2->"}}}); + simulateLoad(graph, &job6, {{NodeKind::nominal, {"C2->"}}}); + + const auto jobs = + simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_TRUE(contains(jobs, &job3)); + EXPECT_FALSE(contains(jobs, &job4)); + EXPECT_FALSE(contains(jobs, &job5)); + EXPECT_FALSE(contains(jobs, &job6)); +} + +TEST(ModuleDepGraph, CrossTypeDependencyWithFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); + // Because of the cross-type dependency, A->B, + // when A changes, only B is dirtied in job1. + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1@1", "A2@2"}}}); + simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "C1", "A1->B1"}}}); + simulateLoad(graph, &job2, {{NodeKind::nominal, {"B1->"}}}); + simulateLoad(graph, &job3, {{NodeKind::nominal, {"C1->"}}}); + simulateLoad(graph, &job4, {{NodeKind::nominal, {"B2", "C2", "A2->B2"}}}); + simulateLoad(graph, &job5, {{NodeKind::nominal, {"B2->"}}}); + simulateLoad(graph, &job6, {{NodeKind::nominal, {"C2->"}}}); + + const auto jobs = + simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job3)); + EXPECT_FALSE(contains(jobs, &job4)); + EXPECT_FALSE(contains(jobs, &job5)); + EXPECT_FALSE(contains(jobs, &job6)); } From 3dedcce62011587e1abeb49249dd1176948c526a Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 17 Feb 2020 18:41:59 -0800 Subject: [PATCH 019/625] Add missing StringRef -> std::string conversions (#29892) --- lib/AST/SourceFileDepGraphConstructor.cpp | 20 +++++++++---------- .../FineGrainedDependencyDriverGraph.cpp | 18 ++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/AST/SourceFileDepGraphConstructor.cpp b/lib/AST/SourceFileDepGraphConstructor.cpp index 3c9894b669391..79c86de59a663 100644 --- a/lib/AST/SourceFileDepGraphConstructor.cpp +++ b/lib/AST/SourceFileDepGraphConstructor.cpp @@ -114,11 +114,11 @@ void SourceFileDepGraphConstructor::addAUsedDecl(const DependencyKey &defKey, //============================================================================== template static std::string getBaseName(const DeclT *decl) { - return decl->getBaseName().userFacingName(); + return decl->getBaseName().userFacingName().str(); } template static std::string getName(const DeclT *decl) { - return DeclBaseName(decl->getName()).userFacingName(); + return DeclBaseName(decl->getName()).userFacingName().str(); } static std::string mangleTypeAsContext(const NominalTypeDecl *NTD) { @@ -266,7 +266,7 @@ std::string DependencyKey::computeNameForProvidedEntity(StringRef swiftDeps) { assert(!swiftDeps.empty()); - return swiftDeps; + return swiftDeps.str(); } template <> @@ -328,27 +328,27 @@ std::string DependencyKey::computeNameForProvidedEntity< template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { - return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", name); + return DependencyKey(NodeKind::topLevel, DeclAspect::interface, "", name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { return DependencyKey(NodeKind::dynamicLookup, DeclAspect::interface, "", - name); + name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef name) { return DependencyKey(NodeKind::externalDepend, DeclAspect::interface, "", - name); + name.str()); } template <> DependencyKey DependencyKey::createDependedUponKey(StringRef mangledName) { - return DependencyKey(NodeKind::nominal, DeclAspect::interface, mangledName, + return DependencyKey(NodeKind::nominal, DeclAspect::interface, mangledName.str(), ""); } @@ -357,8 +357,8 @@ DependencyKey DependencyKey::createDependedUponKey(StringRef mangledHolderName, const bool isMemberBlank = memberBaseName.empty(); const auto kind = isMemberBlank ? NodeKind::potentialMember : NodeKind::member; - return DependencyKey(kind, DeclAspect::interface, mangledHolderName, - isMemberBlank ? "" : memberBaseName); + return DependencyKey(kind, DeclAspect::interface, mangledHolderName.str(), + isMemberBlank ? "" : memberBaseName.str()); } //============================================================================== @@ -680,7 +680,7 @@ class UsedDeclEnumerator { void enumerateUse(NodeKind kind, StringRef context, StringRef name, bool isCascadingUse) { // Assume that what is depended-upon is the interface - createDefUse(DependencyKey(kind, DeclAspect::interface, context, name), + createDefUse(DependencyKey(kind, DeclAspect::interface, context.str(), name.str()), isCascadingUse ? sourceFileInterface : sourceFileImplementation); } diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index f44e3c7d3aa58..cac4636591c65 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -77,7 +77,7 @@ ModuleDepGraph::Changes ModuleDepGraph::loadFromPath(const Job *Cmd, return None; auto r = loadFromBuffer(Cmd, *buffer.get(), diags); assert(path == getSwiftDeps(Cmd) && "Should be reading the job's swiftdeps"); - assert(!r || !nodeMap[path].empty() && + assert(!r || !nodeMap[path.str()].empty() && "Must have a node for the whole file"); return r; } @@ -112,7 +112,7 @@ bool ModuleDepGraph::haveAnyNodesBeenTraversedIn(const Job *cmd) const { // optimization const auto fileKey = DependencyKey::createKeyForWholeSourceFile( DeclAspect::interface, swiftDeps); - if (const auto fileNode = nodeMap.find(swiftDeps, fileKey)) { + if (const auto fileNode = nodeMap.find(swiftDeps.str(), fileKey)) { if (fileNode && fileNode.getValue()->getHasBeenTraced()) return true; } @@ -234,7 +234,7 @@ ModuleDepGraph::Changes ModuleDepGraph::integrate(const SourceFileDepGraph &g, FrontendStatsTracer tracer(stats, "fine-grained-dependencies-integrate"); // When done, disappearedNodes contains the nodes which no longer exist. - auto disappearedNodes = nodeMap[swiftDepsOfJob]; + auto disappearedNodes = nodeMap[swiftDepsOfJob.str()]; // When done, changeDependencyKeys contains a list of keys that changed // as a result of this integration. // Or if the integration failed, None. @@ -290,7 +290,7 @@ ModuleDepGraph::PreexistingNodeIfAny ModuleDepGraph::findPreexistingMatch( } if (integrand->getIsProvides()) { const auto &preexistingNodeInPlaceIter = - matches->find(swiftDepsOfCompilationToBeIntegrated); + matches->find(swiftDepsOfCompilationToBeIntegrated.str()); if (preexistingNodeInPlaceIter != matches->end()) return std::make_pair(LocationOfPreexistingNode::here, preexistingNodeInPlaceIter->second); @@ -386,7 +386,7 @@ bool ModuleDepGraph::recordWhatUseDependsUpon( usesByDef[def->getKey()].insert(moduleUseNode).second; if (isNewUse && def->getKey().getKind() == NodeKind::externalDepend) { StringRef externalSwiftDeps = def->getKey().getName(); - externalDependencies.insert(externalSwiftDeps); + externalDependencies.insert(externalSwiftDeps.str()); useHasNewExternalDependency = true; } }); @@ -430,7 +430,7 @@ void ModuleDepGraph::forCorrespondingImplementationOfProvidedInterface( const auto &interfaceKey = interfaceNode->getKey(); const DependencyKey implementationKey( interfaceKey.getKind(), DeclAspect::implementation, - interfaceKey.getContext(), interfaceKey.getName()); + interfaceKey.getContext().str(), interfaceKey.getName().str()); if (const auto implementationNode = nodeMap.find(swiftDeps, implementationKey)) fn(implementationNode.getValue()); @@ -461,7 +461,7 @@ void ModuleDepGraph::forEachArc( void ModuleDepGraph::forEachNodeInJob( StringRef swiftDeps, function_ref fn) const { - if (const auto *nodesByKeys = nodeMap.find(swiftDeps).getPtrOrNull()) { + if (const auto *nodesByKeys = nodeMap.find(swiftDeps.str()).getPtrOrNull()) { for (const auto &keyAndNode : *nodesByKeys) fn(keyAndNode.second); } @@ -530,7 +530,7 @@ void ModuleDepGraph::emitDotFileForJob(DiagnosticEngine &diags, } void ModuleDepGraph::emitDotFile(DiagnosticEngine &diags, StringRef baseName) { - unsigned seqNo = dotFileSequenceNumber[baseName]++; + unsigned seqNo = dotFileSequenceNumber[baseName.str()]++; std::string fullName = baseName.str() + "-post-integration." + std::to_string(seqNo) + ".dot"; withOutputFile(diags, fullName, [&](llvm::raw_ostream &out) { @@ -636,7 +636,7 @@ void ModuleDepGraph::verifyNodeIsInRightEntryInNodeMap( void ModuleDepGraph::verifyExternalDependencyUniqueness( const DependencyKey &key) const { assert((key.getKind() != NodeKind::externalDepend || - externalDependencies.count(key.getName()) == 1) && + externalDependencies.count(key.getName().str()) == 1) && "Ensure each external dependency is tracked exactly once"); } From 487fbddfdb10967ad87aab310b1180b26911277c Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Fri, 21 Feb 2020 13:07:51 +0100 Subject: [PATCH 020/625] Fix compilation error after removal of implicit StringRef -> std::string conversion --- lib/AST/FrontendSourceFileDepGraphFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AST/FrontendSourceFileDepGraphFactory.cpp b/lib/AST/FrontendSourceFileDepGraphFactory.cpp index 0ccb1e9d27f24..eabbbe319d27f 100644 --- a/lib/AST/FrontendSourceFileDepGraphFactory.cpp +++ b/lib/AST/FrontendSourceFileDepGraphFactory.cpp @@ -688,7 +688,7 @@ class UsedDeclEnumerator { std::string context = DependencyKey::computeContextForProvidedEntity( nominal); - std::string name = rawName.userFacingName(); + std::string name = rawName.userFacingName().str(); enumerateUse(NodeKind::member, context, name, isCascadingUse); } } From ea4204244ccfea2133973d6531282d7a48675595 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:33:57 -0800 Subject: [PATCH 021/625] Adjust for LLVM commit 21390eab4c05 SCCIterator::hasLoop was renamed SCCIterator::hasCycle --- lib/SILOptimizer/IPO/GlobalOpt.cpp | 2 +- lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index b338a12522244..54a7fdcfeef06 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -284,7 +284,7 @@ bool SILGlobalOpt::isInLoop(SILBasicBlock *CurBB) { if (LoopCheckedFunctions.insert(F).second) { for (auto I = scc_begin(F); !I.isAtEnd(); ++I) { - if (I.hasLoop()) + if (I.hasCycle()) for (SILBasicBlock *BB : *I) LoopBlocks.insert(BB); } diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp index 8aadfb4ce1f93..bf6e4a5f0743c 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp @@ -1020,7 +1020,7 @@ static bool mergeAccesses( info.id = 0; for (auto sccIt = scc_begin(F); !sccIt.isAtEnd(); ++sccIt) { ++info.id; - info.hasLoop = sccIt.hasLoop(); + info.hasLoop = sccIt.hasCycle(); for (auto *bb : *sccIt) { blockToSCCMap.insert(std::make_pair(bb, info)); } From 17b25bad5de1890a89726fa478cd881f2c340413 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:36:09 -0800 Subject: [PATCH 022/625] Include clang SourceManager header where needed These files were using clang::SourceManager with only a forward declaration. Most likely another header was previously including the SourceManager header so that these files got the header included transitively. --- lib/AST/ASTPrinter.cpp | 1 + lib/IDE/SwiftSourceDocInfo.cpp | 1 + lib/PrintAsObjC/DeclAndTypePrinter.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 060e51630fe59..74dcd70486fdc 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -46,6 +46,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp index a60e6ab70e276..5b48f6499153f 100644 --- a/lib/IDE/SwiftSourceDocInfo.cpp +++ b/lib/IDE/SwiftSourceDocInfo.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" #include "clang/Basic/CharInfo.h" diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.cpp b/lib/PrintAsObjC/DeclAndTypePrinter.cpp index 0b609510f66c7..6b0e8154940a0 100644 --- a/lib/PrintAsObjC/DeclAndTypePrinter.cpp +++ b/lib/PrintAsObjC/DeclAndTypePrinter.cpp @@ -32,6 +32,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/SourceManager.h" using namespace swift; using namespace swift::objc_translation; From 030f70b7034e0ef72ece702e8c7ead7b82e00ef7 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:38:47 -0800 Subject: [PATCH 023/625] Include llvm Debug header where used Most likely another header was including the header so TypeLayout.h got it transitively. --- lib/IRGen/TypeLayout.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/IRGen/TypeLayout.h b/lib/IRGen/TypeLayout.h index 04543d146190d..0427b31475521 100644 --- a/lib/IRGen/TypeLayout.h +++ b/lib/IRGen/TypeLayout.h @@ -16,6 +16,7 @@ #include "TypeInfo.h" #include "swift/SIL/SILType.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Debug.h" namespace swift { namespace irgen { From 69ae40eada1401f12cee3083930ebc9024642c20 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:39:50 -0800 Subject: [PATCH 024/625] Include llvm StringMap header where used Most likely another header was previously including StringMap.h so FrontendInputsAndOutputs.h got it transitively. --- include/swift/Frontend/FrontendInputsAndOutputs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/Frontend/FrontendInputsAndOutputs.h b/include/swift/Frontend/FrontendInputsAndOutputs.h index b1bbeb0129457..aee55c70b3104 100644 --- a/include/swift/Frontend/FrontendInputsAndOutputs.h +++ b/include/swift/Frontend/FrontendInputsAndOutputs.h @@ -18,6 +18,7 @@ #include "swift/Frontend/InputFile.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" #include #include From 4a004de39da438fc0103ff86350b8f9f259df286 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:40:54 -0800 Subject: [PATCH 025/625] Include llvm Error header where used Most likely another header was including Error.h so SimpleRequest.h got the header transitively. --- include/swift/AST/SimpleRequest.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h index 018163f541630..6058c38b3a6ba 100644 --- a/include/swift/AST/SimpleRequest.h +++ b/include/swift/AST/SimpleRequest.h @@ -24,6 +24,7 @@ #include "swift/Basic/TypeID.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Error.h" #include #include From 9c99dd39d563cb47519f6be16375ff1da6e2628f Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:41:43 -0800 Subject: [PATCH 026/625] Include llvm PointerLikeTypeTraits header where used Most likely another header was including this so SILNode.h was getting the header transitively. --- include/swift/SIL/SILNode.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h index c5820ef1e59b9..70f77db7ff815 100644 --- a/include/swift/SIL/SILNode.h +++ b/include/swift/SIL/SILNode.h @@ -19,6 +19,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/PointerLikeTypeTraits.h" #include "swift/Basic/InlineBitfield.h" #include "swift/Basic/LLVM.h" #include From ef9ecd87b43f520d0a545c5d7a9721cc08cdc3b4 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:42:42 -0800 Subject: [PATCH 027/625] More explicit StringRef to std::string conversions --- lib/AST/ReferencedNameTracker.cpp | 2 +- lib/Frontend/PrintingDiagnosticConsumer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/ReferencedNameTracker.cpp b/lib/AST/ReferencedNameTracker.cpp index 74494ae53f8f6..8bd4922802f4b 100644 --- a/lib/AST/ReferencedNameTracker.cpp +++ b/lib/AST/ReferencedNameTracker.cpp @@ -136,7 +136,7 @@ void ReferencedNameTracker::enumerateMemberUses( std::string context = DependencyKey::computeContextForProvidedEntity( nominal); - std::string name = rawName.userFacingName(); + std::string name = std::string(rawName.userFacingName()); enumerateUsedDecl(NodeKind::member, context, name, isCascadingUse); } } diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index 929b5b13d166a..0aeb195247e32 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -254,7 +254,7 @@ namespace { void addMessage(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, StringRef Message) { - Messages.push_back({lineByteOffsetForLoc(SM, Loc), Kind, Message}); + Messages.push_back({lineByteOffsetForLoc(SM, Loc), Kind, std::string(Message)}); } void addHighlight(SourceManager &SM, CharSourceRange Range) { @@ -264,7 +264,7 @@ namespace { void addFixIt(SourceManager &SM, CharSourceRange Range, StringRef Text) { FixIts.push_back({lineByteOffsetForLoc(SM, Range.getStart()), - lineByteOffsetForLoc(SM, Range.getEnd()), Text}); + lineByteOffsetForLoc(SM, Range.getEnd()), std::string(Text)}); } void render(unsigned LineNumberIndent, raw_ostream &Out) { From a489c40fd7c3dd52c140c9f4d3d5858fbcc25838 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 12:44:50 -0800 Subject: [PATCH 028/625] Adjust for LLVM commit dd1ea9de2e3e3 --- lib/IRGen/GenCoverage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/IRGen/GenCoverage.cpp b/lib/IRGen/GenCoverage.cpp index 239e507177074..12dbdfb718c0d 100644 --- a/lib/IRGen/GenCoverage.cpp +++ b/lib/IRGen/GenCoverage.cpp @@ -145,6 +145,7 @@ void IRGenModule::emitCoverageMapping() { auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords); // Create the coverage data header. + const unsigned NRecords = 0; llvm::Type *CovDataHeaderTypes[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" From 224c612fc01677a01aaf5846189a5cfd5de472b0 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Tue, 3 Mar 2020 14:14:59 -0800 Subject: [PATCH 029/625] Follow-up change to PR30186 `std::string(...)` -> `.str()` --- lib/AST/ReferencedNameTracker.cpp | 2 +- lib/Frontend/PrintingDiagnosticConsumer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/ReferencedNameTracker.cpp b/lib/AST/ReferencedNameTracker.cpp index 8bd4922802f4b..601a69710f691 100644 --- a/lib/AST/ReferencedNameTracker.cpp +++ b/lib/AST/ReferencedNameTracker.cpp @@ -136,7 +136,7 @@ void ReferencedNameTracker::enumerateMemberUses( std::string context = DependencyKey::computeContextForProvidedEntity( nominal); - std::string name = std::string(rawName.userFacingName()); + std::string name = rawName.userFacingName().str(); enumerateUsedDecl(NodeKind::member, context, name, isCascadingUse); } } diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index 0aeb195247e32..2bf880ab6039c 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -254,7 +254,7 @@ namespace { void addMessage(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, StringRef Message) { - Messages.push_back({lineByteOffsetForLoc(SM, Loc), Kind, std::string(Message)}); + Messages.push_back({lineByteOffsetForLoc(SM, Loc), Kind, Message.str()}); } void addHighlight(SourceManager &SM, CharSourceRange Range) { @@ -264,7 +264,7 @@ namespace { void addFixIt(SourceManager &SM, CharSourceRange Range, StringRef Text) { FixIts.push_back({lineByteOffsetForLoc(SM, Range.getStart()), - lineByteOffsetForLoc(SM, Range.getEnd()), std::string(Text)}); + lineByteOffsetForLoc(SM, Range.getEnd()), Text.str()}); } void render(unsigned LineNumberIndent, raw_ostream &Out) { From 61f4c32bc89f48f97339e95de3b8f9176e6268d2 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 3 Mar 2020 14:58:20 -0800 Subject: [PATCH 030/625] [Coverage] Port GenCoverage to the new format Totally untested, as tests are not really close to building on master-next at the moment. --- lib/IRGen/GenCoverage.cpp | 144 ++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 74 deletions(-) diff --git a/lib/IRGen/GenCoverage.cpp b/lib/IRGen/GenCoverage.cpp index 12dbdfb718c0d..93432458d897c 100644 --- a/lib/IRGen/GenCoverage.cpp +++ b/lib/IRGen/GenCoverage.cpp @@ -22,19 +22,23 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/FileSystem.h" +// This selects the coverage mapping format defined when `InstrProfData.inc` +// is textually included. +#define COVMAP_V3 + using namespace swift; using namespace irgen; -using llvm::coverage::CovMapVersion; using llvm::coverage::CounterMappingRegion; +using llvm::coverage::CovMapVersion; -static std::string getCoverageSection(IRGenModule &IGM) { - return llvm::getInstrProfSectionName(llvm::IPSK_covmap, - IGM.Triple.getObjectFormat()); +static std::string getInstrProfSection(IRGenModule &IGM, + llvm::InstrProfSectKind SK) { + return llvm::getInstrProfSectionName(SK, IGM.Triple.getObjectFormat()); } void IRGenModule::emitCoverageMapping() { @@ -61,8 +65,6 @@ void IRGenModule::emitCoverageMapping() { Files.push_back(M->getFile()); // Awkwardly munge absolute filenames into a vector of StringRefs. - // TODO: This is heinous - the same thing is happening in clang, but the API - // really needs to be cleaned up for both. llvm::SmallVector FilenameStrs; llvm::SmallVector FilenameRefs; for (StringRef Name : Files) { @@ -72,33 +74,31 @@ void IRGenModule::emitCoverageMapping() { FilenameRefs.push_back(FilenameStrs.back()); } - // Encode the filenames first. - std::string FilenamesAndCoverageMappings; - llvm::raw_string_ostream OS(FilenamesAndCoverageMappings); - llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS); - size_t FilenamesSize = OS.str().size(); - size_t CurrentSize, PrevSize = FilenamesSize; - - // Now we need to build up the list of function records. + // Encode the filenames. + std::string Filenames; llvm::LLVMContext &Ctx = LLVMContext; - auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); + { + llvm::raw_string_ostream OS(Filenames); + llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS); + } + auto *FilenamesVal = + llvm::ConstantDataArray::getString(Ctx, Filenames, false); + const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames); + const size_t FilenamesSize = Filenames.size(); - llvm::Type *FunctionRecordTypes[] = { -#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, -#include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_FUNC_RECORD - }; + // Emit the function records. + auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); + for (const auto &M : Mappings) { + StringRef NameValue = M->getPGOFuncName(); + assert(!NameValue.empty() && "Expected a named record"); + uint64_t FuncHash = M->getHash(); - auto FunctionRecordTy = - llvm::StructType::get(Ctx, llvm::makeArrayRef(FunctionRecordTypes), - /*isPacked=*/true); + const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue); + std::string FuncRecordName = "__covrec_" + llvm::utohexstr(NameHash); - std::vector FunctionRecords; - std::vector Regions; - for (const auto &M : Mappings) { unsigned FileID = std::find(Files.begin(), Files.end(), M->getFile()) - Files.begin(); - Regions.clear(); + std::vector Regions; for (const auto &MR : M->getMappedRegions()) Regions.emplace_back(CounterMappingRegion::makeRegion( MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine, @@ -107,74 +107,70 @@ void IRGenModule::emitCoverageMapping() { ArrayRef VirtualFileMapping(FileID); llvm::coverage::CoverageMappingWriter W(VirtualFileMapping, M->getExpressions(), Regions); - W.write(OS); - - CurrentSize = OS.str().size(); - unsigned MappingLen = CurrentSize - PrevSize; - StringRef CoverageMapping(OS.str().c_str() + PrevSize, MappingLen); + std::string CoverageMapping; + { + llvm::raw_string_ostream OS(CoverageMapping); + W.write(OS); + } - StringRef NameValue = M->getPGOFuncName(); - assert(!NameValue.empty() && "Expected a named record"); - uint64_t FuncHash = M->getHash(); +#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, + llvm::Type *FunctionRecordTypes[] = { +#include "llvm/ProfileData/InstrProfData.inc" + }; + auto *FunctionRecordTy = + llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), + /*isPacked=*/true); - // Create a record for this function. - llvm::Constant *FunctionRecordVals[] = { + // Create the function record constant. #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, + llvm::Constant *FunctionRecordVals[] = { #include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_FUNC_RECORD }; - - FunctionRecords.push_back(llvm::ConstantStruct::get( - FunctionRecordTy, makeArrayRef(FunctionRecordVals))); - PrevSize = CurrentSize; - } - size_t CoverageMappingSize = PrevSize - FilenamesSize; - - // Append extra zeroes if necessary to ensure that the size of the filenames - // and coverage mappings is a multiple of 8. - if (size_t Rem = OS.str().size() % 8) { - CoverageMappingSize += 8 - Rem; - for (size_t I = 0, S = 8 - Rem; I < S; ++I) - OS << '\0'; + auto *FuncRecordConstant = llvm::ConstantStruct::get( + FunctionRecordTy, makeArrayRef(FunctionRecordVals)); + + // Create the function record global. + auto *FuncRecord = new llvm::GlobalVariable( + *getModule(), FunctionRecordTy, /*isConstant=*/true, + llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant, + FuncRecordName); + FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility); + FuncRecord->setSection(getInstrProfSection(*this, llvm::IPSK_covfun)); + FuncRecord->setAlignment(llvm::Align(8)); + if (Triple.supportsCOMDAT()) + FuncRecord->setComdat(getModule()->getOrInsertComdat(FuncRecordName)); + + // Make sure the data doesn't get deleted. + addUsedGlobal(FuncRecord); } - auto *FilenamesAndMappingsVal = - llvm::ConstantDataArray::getString(Ctx, OS.str(), false); - - auto *RecordsTy = - llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size()); - auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords); // Create the coverage data header. const unsigned NRecords = 0; + const unsigned CoverageMappingSize = 0; llvm::Type *CovDataHeaderTypes[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_HEADER }; - auto *CovDataHeaderTy = + auto CovDataHeaderTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes)); llvm::Constant *CovDataHeaderVals[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" -#undef COVMAP_HEADER }; - auto *CovDataHeaderVal = llvm::ConstantStruct::get( + auto CovDataHeaderVal = llvm::ConstantStruct::get( CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); - // Combine the header, function records, and mappings together. - llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy, - FilenamesAndMappingsVal->getType()}; - auto *CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes)); - llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal, - FilenamesAndMappingsVal}; - auto *CovDataVal = + // Create the coverage data record + llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()}; + auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes)); + llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal}; + auto CovDataVal = llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals)); - auto CovData = new llvm::GlobalVariable( - *getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage, + *getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage, CovDataVal, llvm::getCoverageMappingVarName()); - std::string CovSection = getCoverageSection(*this); - CovData->setSection(CovSection); - CovData->setAlignment(llvm::MaybeAlign(8)); + + CovData->setSection(getInstrProfSection(*this, llvm::IPSK_covmap)); + CovData->setAlignment(llvm::Align(8)); addUsedGlobal(CovData); } From b29f7cd2c10e9ddc4abe4b1fb587a97bc6d65c98 Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Wed, 4 Mar 2020 14:43:49 +0100 Subject: [PATCH 031/625] Fix build breaks for master-next against llvm.org. StringRef conversion to std::string needs to be explicit now. --- unittests/Basic/PrefixMapTest.cpp | 4 ++-- unittests/ClangImporter/ClangImporterTests.cpp | 2 +- unittests/FrontendTool/ModuleLoadingTests.cpp | 2 +- unittests/IDE/Placeholders.cpp | 4 ++-- unittests/SourceKit/SwiftLang/CursorInfoTest.cpp | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/unittests/Basic/PrefixMapTest.cpp b/unittests/Basic/PrefixMapTest.cpp index 75b0dcdee0db6..aea324e273391 100644 --- a/unittests/Basic/PrefixMapTest.cpp +++ b/unittests/Basic/PrefixMapTest.cpp @@ -40,7 +40,7 @@ struct Tester { // Performs an insert operation and tests that the result matches what // we get from the std::map. void insert(StringRef key, int value) { - auto stdmapResult = StdMap.insert({key, value}); + auto stdmapResult = StdMap.insert({key.str(), value}); auto premapResult = PreMap.insert(asArray(key), value); // Whether or not we modified the map should be the same in both @@ -57,7 +57,7 @@ struct Tester { // Tests that the result of a findPrefix matches what we expect from // the std::map. void find(StringRef key) { - auto stdmapResult = StdMap.lower_bound(key); + auto stdmapResult = StdMap.lower_bound(key.str()); while (stdmapResult == StdMap.end() || !key.startswith(stdmapResult->first)) { if (stdmapResult == StdMap.begin()) { diff --git a/unittests/ClangImporter/ClangImporterTests.cpp b/unittests/ClangImporter/ClangImporterTests.cpp index 94d021452a1c1..e353fba57745f 100644 --- a/unittests/ClangImporter/ClangImporterTests.cpp +++ b/unittests/ClangImporter/ClangImporterTests.cpp @@ -25,7 +25,7 @@ static bool emitFileWithContents(StringRef path, StringRef contents, if (llvm::sys::fs::openFileForWrite(path, FD)) return true; if (pathOut) - *pathOut = path; + *pathOut = path.str(); llvm::raw_fd_ostream file(FD, /*shouldClose=*/true); file << contents; return false; diff --git a/unittests/FrontendTool/ModuleLoadingTests.cpp b/unittests/FrontendTool/ModuleLoadingTests.cpp index 0ad89a65878b5..7e343aaeeeab1 100644 --- a/unittests/FrontendTool/ModuleLoadingTests.cpp +++ b/unittests/FrontendTool/ModuleLoadingTests.cpp @@ -33,7 +33,7 @@ static bool emitFileWithContents(StringRef path, StringRef contents, if (llvm::sys::fs::openFileForWrite(path, fd)) return true; if (pathOut) - *pathOut = path; + *pathOut = path.str(); llvm::raw_fd_ostream file(fd, /*shouldClose=*/true); file << contents; return false; diff --git a/unittests/IDE/Placeholders.cpp b/unittests/IDE/Placeholders.cpp index b7ad0efdb458c..8e7913cc67f35 100644 --- a/unittests/IDE/Placeholders.cpp +++ b/unittests/IDE/Placeholders.cpp @@ -11,7 +11,7 @@ static std::string replaceFromString(const std::string &S, auto Buf = llvm::MemoryBuffer::getMemBufferCopy(S, ""); Buf = ide::replacePlaceholders(std::move(Buf), HadPH); - return Buf->getBuffer(); + return Buf->getBuffer().str(); } TEST(Placeholders, Replace) { @@ -83,6 +83,6 @@ TEST(Placeholders, TooShort) { Source += "<##>\n"; } std::string Out = replaceFromString(Source); - std::string Last = StringRef(Out).substr(Out.size()-15); + std::string Last(StringRef(Out).substr(Out.size()-15)); EXPECT_EQ("$_99\n$___\n$___\n", Last); } diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp index 193c8fcd4fad9..2a6841ab7d97a 100644 --- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp +++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp @@ -151,14 +151,14 @@ class CursorInfoTest : public ::testing::Test { [&](const RequestResult &Result) { assert(!Result.isCancelled()); if (Result.isError()) { - TestInfo.Error = Result.getError(); + TestInfo.Error = Result.getError().str(); sema.signal(); return; } const CursorInfoData &Info = Result.value(); - TestInfo.Name = Info.Name; - TestInfo.Typename = Info.TypeName; - TestInfo.Filename = Info.Filename; + TestInfo.Name = Info.Name.str(); + TestInfo.Typename = Info.TypeName.str(); + TestInfo.Filename = Info.Filename.str(); TestInfo.DeclarationLoc = Info.DeclarationLoc; sema.signal(); }); From 8c2aeb387cead9a6b0f4dda7e804713a58846329 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 6 Mar 2020 13:51:15 -0800 Subject: [PATCH 032/625] Patch up runConstructors() change in Immediate.cpp --- lib/Immediate/Immediate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Immediate/Immediate.cpp b/lib/Immediate/Immediate.cpp index 964cf561f4674..ba1025563c6e3 100644 --- a/lib/Immediate/Immediate.cpp +++ b/lib/Immediate/Immediate.cpp @@ -350,7 +350,7 @@ int swift::RunImmediately(CompilerInstance &CI, using MainFnTy = int(*)(int, char*[]); - if (auto Err = JIT->runConstructors()) { + if (auto Err = JIT->initialize(JIT->getMainJITDylib())) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), ""); return -1; } @@ -364,7 +364,7 @@ int swift::RunImmediately(CompilerInstance &CI, } LLVM_DEBUG(llvm::dbgs() << "Running static constructors\n"); - if (auto Err = JIT->runConstructors()) { + if (auto Err = JIT->initialize(JIT->getMainJITDylib())) { logAllUnhandledErrors(std::move(Err), llvm::errs(), ""); return -1; } From 5da2adb6b1b823a5ca3ea0ae7b28c1783e9c6f22 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 10 Mar 2020 10:11:55 -0700 Subject: [PATCH 033/625] Disable SourceKit/CursorInfo/use-swift-source-info.swift rdar://60096971 --- test/SourceKit/CursorInfo/use-swift-source-info.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/SourceKit/CursorInfo/use-swift-source-info.swift b/test/SourceKit/CursorInfo/use-swift-source-info.swift index 7f905f4cf52ca..a255c6f3dc8c1 100644 --- a/test/SourceKit/CursorInfo/use-swift-source-info.swift +++ b/test/SourceKit/CursorInfo/use-swift-source-info.swift @@ -3,6 +3,8 @@ func bar() { foo() } +// FIXME: Rmove XFAIL rdar://problem/60096971 +// XFAIL: * // RUN: %empty-directory(%t) // RUN: echo "/// Some doc" >> %t/Foo.swift // RUN: echo "public func foo() { }" >> %t/Foo.swift From 1bd6a0a3719a5fe7cfb9f7611e443895cfab0bf9 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 11 Mar 2020 15:45:25 -0700 Subject: [PATCH 034/625] Adapt to upstream header file reshuffling in c915cb957dc37275ce1ca1a0b993239c82f12692. --- include/swift/ClangImporter/ClangModule.h | 6 +++--- lib/ClangImporter/ClangImporter.cpp | 2 +- lib/IRGen/IRGenDebugInfo.cpp | 2 +- lib/PrintAsObjC/ModuleContentsWriter.cpp | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/swift/ClangImporter/ClangModule.h b/include/swift/ClangImporter/ClangModule.h index 90cc2c97c9166..f1f15794a0c76 100644 --- a/include/swift/ClangImporter/ClangModule.h +++ b/include/swift/ClangImporter/ClangModule.h @@ -19,6 +19,7 @@ #include "swift/AST/FileUnit.h" #include "swift/ClangImporter/ClangImporter.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/Module.h" namespace clang { class ASTContext; @@ -37,7 +38,7 @@ class ClangModuleUnit final : public LoadedFile { llvm::PointerIntPair overlayModule; mutable Optional> importedModulesForLookup; /// The metadata of the underlying Clang module. - clang::ExternalASTSource::ASTSourceDescriptor ASTSourceDescriptor; + clang::ASTSourceDescriptor ASTSourceDescriptor; public: /// True if the given Module contains an imported Clang module unit. @@ -115,8 +116,7 @@ class ClangModuleUnit final : public LoadedFile { /// Returns the ASTSourceDescriptor of the associated Clang module if one /// exists. - Optional - getASTSourceDescriptor() const; + Optional getASTSourceDescriptor() const; virtual StringRef getModuleDefiningPath() const override; diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 4af873767bd1e..8c73c7cd89cb5 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3316,7 +3316,7 @@ StringRef ClangModuleUnit::getModuleDefiningPath() const { return clangSourceMgr.getFilename(clangModule->DefinitionLoc); } -Optional +Optional ClangModuleUnit::getASTSourceDescriptor() const { if (clangModule) { assert(ASTSourceDescriptor.getModuleOrNull() == clangModule); diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 88e0907553f6c..85a3c2e03ab03 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -665,7 +665,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { return M; } - using ASTSourceDescriptor = clang::ExternalASTSource::ASTSourceDescriptor; + using ASTSourceDescriptor = clang::ASTSourceDescriptor; /// Create a DIModule from a clang module or PCH. /// The clang::Module pointer is passed separately because the recursive case /// needs to fudge the AST descriptor. diff --git a/lib/PrintAsObjC/ModuleContentsWriter.cpp b/lib/PrintAsObjC/ModuleContentsWriter.cpp index a1653028bfdc2..eaba01e51d901 100644 --- a/lib/PrintAsObjC/ModuleContentsWriter.cpp +++ b/lib/PrintAsObjC/ModuleContentsWriter.cpp @@ -22,6 +22,7 @@ #include "swift/ClangImporter/ClangImporter.h" #include "clang/AST/Decl.h" +#include "clang/Basic/Module.h" #include "llvm/Support/raw_ostream.h" From 41f76322d2687c114cff491461a0127467cea8d0 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 12 Mar 2020 10:23:47 -0700 Subject: [PATCH 035/625] Adapt to upstream header file reshuffling --- lib/AST/ClangTypeConverter.cpp | 1 + lib/ClangImporter/ImportDecl.cpp | 10 ++++++---- lib/FrontendTool/FrontendTool.cpp | 2 +- lib/IDE/Utils.cpp | 3 ++- lib/Sema/NameBinding.cpp | 1 + lib/Serialization/SerializedModuleLoader.cpp | 4 +++- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index aa141e1454ea9..a535950cf82bb 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -34,6 +34,7 @@ #include "swift/Basic/LLVM.h" #include "clang/AST/ASTContext.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Sema.h" using namespace swift; diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 21b1e5b3f074a..fbacdbe2c2fea 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -16,7 +16,6 @@ #include "CFTypeInfo.h" #include "ImporterImpl.h" -#include "swift/Strings.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ASTMangler.h" #include "swift/AST/Attr.h" @@ -36,17 +35,20 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/Stmt.h" -#include "swift/AST/Types.h" #include "swift/AST/TypeCheckRequests.h" +#include "swift/AST/Types.h" #include "swift/Basic/Defer.h" #include "swift/Basic/PrettyStackTrace.h" +#include "swift/Basic/Statistic.h" #include "swift/ClangImporter/ClangModule.h" -#include "swift/Parse/Lexer.h" #include "swift/Config.h" +#include "swift/Parse/Lexer.h" +#include "swift/Strings.h" + #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/Basic/CharInfo.h" -#include "swift/Basic/Statistic.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 3186dd600aaae..54a2c0762d05d 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1178,7 +1178,7 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs( llvm::SmallString<32> Buffer(*opts.BridgingHeaderDirForPrint); llvm::sys::path::append(Buffer, llvm::sys::path::filename(opts.ImplicitObjCHeaderPath)); - BridgingHeaderPathForPrint = Buffer.str(); + BridgingHeaderPathForPrint = (std::string)Buffer; } else { // By default, include the given bridging header path directly. BridgingHeaderPathForPrint = opts.ImplicitObjCHeaderPath; diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index 843dcf79bb9dd..58dd3a5969dff 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -19,12 +19,13 @@ #include "swift/Subsystems.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/PreprocessorOptions.h" -#include "clang/Serialization/ASTReader.h" #include "clang/Rewrite/Core/RewriteBuffer.h" +#include "clang/Serialization/ASTReader.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/lib/Sema/NameBinding.cpp b/lib/Sema/NameBinding.cpp index c699aaf0e7060..bc7f152a2b64e 100644 --- a/lib/Sema/NameBinding.cpp +++ b/lib/Sema/NameBinding.cpp @@ -33,6 +33,7 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 65eadf33e2c5e..3a93c663b889a 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -20,12 +20,14 @@ #include "swift/Basic/STLExtras.h" #include "swift/Basic/SourceManager.h" #include "swift/Basic/Version.h" + #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -#include "llvm/Support/Debug.h" #include using namespace swift; From 2576ee91f3e7c6a6aa7ac783c2b87f124dbd07e5 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 12 Mar 2020 14:54:02 -0700 Subject: [PATCH 036/625] Add missing include --- unittests/AST/TestContext.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittests/AST/TestContext.h b/unittests/AST/TestContext.h index 46aa8d985b62b..6736edef7dc0c 100644 --- a/unittests/AST/TestContext.h +++ b/unittests/AST/TestContext.h @@ -17,6 +17,8 @@ #include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" +#include "llvm/Support/Host.h" + namespace swift { namespace unittest { From 562afc6e97610eb8ca0420a7065805be1dd35048 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 12 Mar 2020 15:09:34 -0700 Subject: [PATCH 037/625] Update testcases for upstream changes. rdar://problem/60280545 --- test/DebugInfo/inlinescopes.swift | 8 ++++++-- test/DebugInfo/transparent.swift | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/DebugInfo/inlinescopes.swift b/test/DebugInfo/inlinescopes.swift index 6c4a3a4fefc3d..4b40340d49a28 100644 --- a/test/DebugInfo/inlinescopes.swift +++ b/test/DebugInfo/inlinescopes.swift @@ -6,13 +6,17 @@ // RUN: %FileCheck %s -check-prefix=TRANSPARENT-CHECK < %t.ll // CHECK: define{{( dllexport)?}}{{( protected)?( signext)?}} i32 @main{{.*}} -// CHECK: call swiftcc i64 @"$s4main8noinlineys5Int64VADF"(i64 %{{.*}}), !dbg ![[CALL:.*]] +// CHECK: call swiftcc i64 @"$s4main8noinlineys5Int64VADF"(i64 %{{.*}}) +// CHECK-SAME: !dbg ![[CALL:.*]] // CHECK-DAG: ![[TOPLEVEL:.*]] = !DIFile(filename: "{{.*}}inlinescopes.swift" import FooBar @inline(never) -func noinline(_ x: Int64) -> Int64 { return x } +func use(_ x: Int64) -> Int64 { return x } + +@inline(never) +func noinline(_ x: Int64) -> Int64 { return use(x) } @_transparent func transparent(_ x: Int64) -> Int64 { return noinline(x) } diff --git a/test/DebugInfo/transparent.swift b/test/DebugInfo/transparent.swift index 5bfd301c65ca6..b951b4a19e012 100644 --- a/test/DebugInfo/transparent.swift +++ b/test/DebugInfo/transparent.swift @@ -19,7 +19,6 @@ use(z) // CHECK-SAME: !dbg ![[SP:[0-9]+]] // CHECK-NEXT: entry: // CHECK-NEXT: !dbg ![[ZERO:[0-9]+]] -// CHECK-NEXT: !dbg ![[ZERO]] // CHECK-NEXT: } // CHECK: ![[FILE:[0-9]+]] = {{.*}}"" From 6fb3b15c17187294dc80793451050f0e87d6450c Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Fri, 13 Mar 2020 10:21:57 -0700 Subject: [PATCH 038/625] XFAIL two tests failing on master-next https://bugs.swift.org/browse/SR-12362 https://bugs.swift.org/browse/SR-12363 --- test/Driver/bad_tmpdir.swift | 3 +++ test/Serialization/load-target-normalization.swift | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test/Driver/bad_tmpdir.swift b/test/Driver/bad_tmpdir.swift index bf0565ef89439..50be890aee355 100644 --- a/test/Driver/bad_tmpdir.swift +++ b/test/Driver/bad_tmpdir.swift @@ -6,6 +6,9 @@ // // REQUIRES: OS=macosx +// SR-12362: This test is failing on master-next. +// XFAIL: * + // RUN: env TMP="%t/fake/" TMPDIR="%t/fake/" not %target-build-swift -c -driver-filelist-threshold=0 %s 2>&1 | %FileCheck -check-prefix=CHECK-SOURCES %s // CHECK-SOURCES: - unable to create list of input sources diff --git a/test/Serialization/load-target-normalization.swift b/test/Serialization/load-target-normalization.swift index 21040c0c2aab8..d4b6301568122 100644 --- a/test/Serialization/load-target-normalization.swift +++ b/test/Serialization/load-target-normalization.swift @@ -1,6 +1,9 @@ // RUN: %empty-directory(%t/ForeignModule.swiftmodule) // RUN: touch %t/ForeignModule.swiftmodule/garbage-garbage-garbage.swiftmodule +// SR-12363: This test crashes on master-next. +// XFAIL: * + // Test format: We try to import ForeignModule with architectures besides // garbage-garbage-garbage and check the target triple listed in the error // message to make sure it was normalized correctly. This works in lieu of a From cc8653d86eb27abc1e0202bc6fb617c2443335e2 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 18 Mar 2020 16:19:34 -0700 Subject: [PATCH 039/625] Adjust to llvm change ac1d23ed7de01fb3a18b340536842a419b504d86 --- tools/swift-llvm-opt/LLVMOpt.cpp | 80 +++++++++++++++++--------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp index 900fe57e18364..e04693d64b177 100644 --- a/tools/swift-llvm-opt/LLVMOpt.cpp +++ b/tools/swift-llvm-opt/LLVMOpt.cpp @@ -37,7 +37,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeWriterPass.h" -#include "llvm/CodeGen/CommandFlags.inc" +#include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" @@ -69,6 +69,8 @@ using namespace swift; +static llvm::codegen::RegisterCodeGenFlags CGF; + //===----------------------------------------------------------------------===// // Option Declarations //===----------------------------------------------------------------------===// @@ -97,19 +99,19 @@ static llvm::cl::opt PrintStats("print-stats", llvm::cl::desc("Should LLVM Statistics be printed")); -static cl::opt InputFilename(cl::Positional, - cl::desc(""), - cl::init("-"), - cl::value_desc("filename")); +static llvm::cl::opt InputFilename(llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::init("-"), + llvm::cl::value_desc("filename")); -static cl::opt OutputFilename("o", - cl::desc("Override output filename"), - cl::value_desc("filename")); +static llvm::cl::opt + OutputFilename("o", llvm::cl::desc("Override output filename"), + llvm::cl::value_desc("filename")); -static cl::opt DefaultDataLayout( +static llvm::cl::opt DefaultDataLayout( "default-data-layout", - cl::desc("data layout string to use if not specified by module"), - cl::value_desc("layout-string"), cl::init("")); + llvm::cl::desc("data layout string to use if not specified by module"), + llvm::cl::value_desc("layout-string"), llvm::cl::init("")); //===----------------------------------------------------------------------===// // Helper Methods @@ -118,8 +120,8 @@ static cl::opt DefaultDataLayout( static llvm::CodeGenOpt::Level GetCodeGenOptLevel() { // TODO: Is this the right thing to do here? if (Optimized) - return CodeGenOpt::Default; - return CodeGenOpt::None; + return llvm::CodeGenOpt::Default; + return llvm::CodeGenOpt::None; } // Returns the TargetMachine instance or zero if no triple is provided. @@ -127,8 +129,8 @@ static llvm::TargetMachine * getTargetMachine(llvm::Triple TheTriple, StringRef CPUStr, StringRef FeaturesStr, const llvm::TargetOptions &Options) { std::string Error; - const auto *TheTarget = - llvm::TargetRegistry::lookupTarget(MArch, TheTriple, Error); + const auto *TheTarget = llvm::TargetRegistry::lookupTarget( + llvm::codegen::getMArch(), TheTriple, Error); // Some modules don't specify a triple, and this is okay. if (!TheTarget) { return nullptr; @@ -136,12 +138,13 @@ getTargetMachine(llvm::Triple TheTriple, StringRef CPUStr, return TheTarget->createTargetMachine( TheTriple.getTriple(), CPUStr, FeaturesStr, Options, - Optional(RelocModel), getCodeModel(), GetCodeGenOptLevel()); + Optional(llvm::codegen::getExplicitRelocModel()), + llvm::codegen::getExplicitCodeModel(), GetCodeGenOptLevel()); } static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) { // For now just always dump assembly. - legacy::PassManager EmitPasses; + llvm::legacy::PassManager EmitPasses; EmitPasses.add(createPrintModulePass(os)); EmitPasses.run(M); } @@ -153,11 +156,12 @@ static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) { // without being given the address of a function in the main executable). void anchorForGetMainExecutable() {} -static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { +static inline void addPass(llvm::legacy::PassManagerBase &PM, llvm::Pass *P) { // Add the pass to the pass manager... PM.add(P); if (P->getPassID() == &SwiftAAWrapperPass::ID) { - PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) { + PM.add(llvm::createExternalAAWrapperPass([](llvm::Pass &P, llvm::Function &, + llvm::AAResults &AAR) { if (auto *WrapperPass = P.getAnalysisIfAvailable()) AAR.addAAResult(WrapperPass->getResult()); })); @@ -165,7 +169,7 @@ static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { // If we are verifying all of the intermediate steps, add the verifier... if (VerifyEach) - PM.add(createVerifierPass()); + PM.add(llvm::createVerifierPass()); } static void runSpecificPasses(StringRef Binary, llvm::Module *M, @@ -173,7 +177,7 @@ static void runSpecificPasses(StringRef Binary, llvm::Module *M, llvm::Triple &ModuleTriple) { llvm::legacy::PassManager Passes; llvm::TargetLibraryInfoImpl TLII(ModuleTriple); - Passes.add(new TargetLibraryInfoWrapperPass(TLII)); + Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII)); const llvm::DataLayout &DL = M->getDataLayout(); if (DL.isDefault() && !DefaultDataLayout.empty()) { @@ -181,13 +185,13 @@ static void runSpecificPasses(StringRef Binary, llvm::Module *M, } // Add internal analysis passes from the target machine. - Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() - : TargetIRAnalysis())); + Passes.add(createTargetTransformInfoWrapperPass( + TM ? TM->getTargetIRAnalysis() : llvm::TargetIRAnalysis())); if (TM) { // FIXME: We should dyn_cast this when supported. - auto <M = static_cast(*TM); - Pass *TPC = LTM.createPassConfig(Passes); + auto <M = static_cast(*TM); + llvm::Pass *TPC = LTM.createPassConfig(Passes); Passes.add(TPC); } @@ -196,8 +200,9 @@ static void runSpecificPasses(StringRef Binary, llvm::Module *M, if (PassInfo->getNormalCtor()) P = PassInfo->getNormalCtor()(); else - errs() << Binary << ": cannot create pass: " << PassInfo->getPassName() - << "\n"; + llvm::errs() << Binary + << ": cannot create pass: " << PassInfo->getPassName() + << "\n"; if (P) { addPass(Passes, P); } @@ -216,7 +221,7 @@ int main(int argc, char **argv) { INITIALIZE_LLVM(); // Initialize passes - PassRegistry &Registry = *PassRegistry::getPassRegistry(); + llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); @@ -252,16 +257,16 @@ int main(int argc, char **argv) { llvm::SMDiagnostic Err; // Load the input module... - std::unique_ptr M = + std::unique_ptr M = parseIRFile(InputFilename, Err, getGlobalLLVMContext()); if (!M) { - Err.print(argv[0], errs()); + Err.print(argv[0], llvm::errs()); return 1; } - if (verifyModule(*M, &errs())) { - errs() << argv[0] << ": " << InputFilename + if (verifyModule(*M, &llvm::errs())) { + llvm::errs() << argv[0] << ": " << InputFilename << ": error: input module is broken!\n"; return 1; } @@ -280,18 +285,19 @@ int main(int argc, char **argv) { Out.reset( new llvm::ToolOutputFile(OutputFilename, EC, llvm::sys::fs::F_None)); if (EC) { - errs() << EC.message() << '\n'; + llvm::errs() << EC.message() << '\n'; return 1; } llvm::Triple ModuleTriple(M->getTargetTriple()); std::string CPUStr, FeaturesStr; llvm::TargetMachine *Machine = nullptr; - const llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + const llvm::TargetOptions Options = + llvm::codegen::InitTargetOptionsFromCodeGenFlags(); if (ModuleTriple.getArch()) { - CPUStr = getCPUStr(); - FeaturesStr = getFeaturesStr(); + CPUStr = llvm::codegen::getCPUStr(); + FeaturesStr = llvm::codegen::getFeaturesStr(); Machine = getTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options); } @@ -299,7 +305,7 @@ int main(int argc, char **argv) { // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. - setFunctionAttributes(CPUStr, FeaturesStr, *M); + llvm::codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M); if (Optimized) { IRGenOptions Opts; From 95d98249ce239c34f496b05222c6de814b8e98c8 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Sun, 22 Mar 2020 18:04:04 -0700 Subject: [PATCH 040/625] Handle flaky SourceKit/CursorInfo/use-swift-source-info.swift This test was XFAILed on master-next in https://github.com/apple/swift/pull/30330, but it is now passing again. Change the XFAIL to a failing REQUIRES instead. --- test/SourceKit/CursorInfo/use-swift-source-info.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/SourceKit/CursorInfo/use-swift-source-info.swift b/test/SourceKit/CursorInfo/use-swift-source-info.swift index a255c6f3dc8c1..05a391ee5c8b6 100644 --- a/test/SourceKit/CursorInfo/use-swift-source-info.swift +++ b/test/SourceKit/CursorInfo/use-swift-source-info.swift @@ -3,8 +3,9 @@ func bar() { foo() } -// FIXME: Rmove XFAIL rdar://problem/60096971 -// XFAIL: * +// FIXME: Rmove REQUIRES rdar://problem/60096971 +// REQUIRES: rdar60096971 + // RUN: %empty-directory(%t) // RUN: echo "/// Some doc" >> %t/Foo.swift // RUN: echo "public func foo() { }" >> %t/Foo.swift From afafae4148c8413bb15a681d1155f722ef3f548d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 23 Mar 2020 10:39:03 -0700 Subject: [PATCH 041/625] Disable irgen test on linux rdar://60752860 --- test/IRGen/pic.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/test/IRGen/pic.swift b/test/IRGen/pic.swift index 8afc50ec49846..6f7b9a8eaf1c3 100644 --- a/test/IRGen/pic.swift +++ b/test/IRGen/pic.swift @@ -3,6 +3,7 @@ // SR-12194 // XFAIL: OS=linux-android, CPU=aarch64 +// UNSUPPORTED: OS=linux-gnu // RUN: %target-swift-frontend %s -module-name main -S -o - | %FileCheck -check-prefix=%target-cpu -check-prefix=%target-cpu-%target-sdk-name %s From f7cf5bde468e29ebe8239fbea53af39e7ecf4f5d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 23 Mar 2020 18:06:18 -0700 Subject: [PATCH 042/625] Adapt test to upstream readobj output change --- test/DebugInfo/modulecache.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/DebugInfo/modulecache.swift b/test/DebugInfo/modulecache.swift index c4eb24e70c66c..f3bb46b58f200 100644 --- a/test/DebugInfo/modulecache.swift +++ b/test/DebugInfo/modulecache.swift @@ -16,7 +16,7 @@ import ClangModule // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -c -g -o %t.o -module-cache-path %t -I %S/Inputs // RUN: llvm-readobj -h %t/*/ClangModule-*.pcm | %FileCheck %s -// CHECK: Format: {{(Mach-O|ELF|COFF)}} +// CHECK: Format: {{(Mach-O|ELF|elf64|COFF)}} // 3. Test that swift-ide-check will not share swiftc's module cache. From 886e25ac1c5666c59f5599b550e7f5bd42299db9 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 23 Mar 2020 18:09:17 -0700 Subject: [PATCH 043/625] Update test for upstream codegen changes --- test/DebugInfo/top_level_code.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/DebugInfo/top_level_code.swift b/test/DebugInfo/top_level_code.swift index 790f5dffbdf84..6693d78863fb4 100644 --- a/test/DebugInfo/top_level_code.swift +++ b/test/DebugInfo/top_level_code.swift @@ -2,7 +2,7 @@ func markUsed(_ t: T) {} // CHECK: {{_?}}main: -// CHECK-NEXT: Lfunc_begin0: +// CHECK: Lfunc_begin0: // Verify that the top-level function (main) begins at line 0 and then // proceeds to the first line. // CHECK: .loc {{[0-9]}} 0 {{[0-9]}} From dfcd6611afc14356e9c908bb61119b0d0f34b168 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Fri, 27 Mar 2020 13:42:17 -0700 Subject: [PATCH 044/625] Handle clang::TargetInfo::HexagonBuiltinVaList --- lib/ClangImporter/ImportDecl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 906ad9f86dfb7..c879e5e1550b3 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -379,6 +379,7 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D, case clang::TargetInfo::VoidPtrBuiltinVaList: case clang::TargetInfo::PowerABIBuiltinVaList: case clang::TargetInfo::AAPCSABIBuiltinVaList: + case clang::TargetInfo::HexagonBuiltinVaList: assert(ClangCtx.getTypeSize(ClangCtx.VoidPtrTy) == ClangTypeSize && "expected va_list type to be sizeof(void *)"); break; From c04b6b6e329b6017f6297243da1cab70e5435b72 Mon Sep 17 00:00:00 2001 From: Alex Langford Date: Fri, 27 Mar 2020 14:04:22 -0700 Subject: [PATCH 045/625] More StringRef -> std::string explicit conversions --- lib/Serialization/ModuleFile.cpp | 2 +- lib/Serialization/Serialization.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index f1fab8d01fcee..1c08abf40c60d 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -949,7 +949,7 @@ class ModuleFile::DerivativeFunctionConfigTableInfo { while (data < limit) { DeclID genSigId = endian::readNext(data); int32_t nameLength = endian::readNext(data); - StringRef mangledName(reinterpret_cast(data), nameLength); + std::string mangledName(reinterpret_cast(data), nameLength); data += nameLength; result.push_back({mangledName, genSigId}); } diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index a24206eaa28df..37515d87a4a85 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5126,7 +5126,7 @@ void Serializer::writeAST(ModuleOrSourceFile DC) { DerivativeFunctionConfigTable derivativeConfigs; for (auto entry : uniquedDerivativeConfigs) { for (auto config : entry.second) { - auto paramIndices = config.first.str(); + std::string paramIndices = config.first.str().str(); auto genSigID = addGenericSignatureRef(config.second); derivativeConfigs[entry.first].push_back({paramIndices, genSigID}); } From 9f9668327c7b1e34c3cd1ba5240a3c31a2832657 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Mon, 30 Mar 2020 11:51:32 -0700 Subject: [PATCH 046/625] Add OMPArrayShaping to a few switch statements --- lib/ClangImporter/ClangAdapter.cpp | 1 + lib/ClangImporter/ImportType.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index eddac5d46b3bf..6428b38c31609 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -446,6 +446,7 @@ OmissionTypeName importer::getClangTypeNameForOmission(clang::ASTContext &ctx, // OpenMP types that don't have Swift equivalents. case clang::BuiltinType::OMPArraySection: + case clang::BuiltinType::OMPArrayShaping: return OmissionTypeName(); // SVE builtin types that don't have Swift equivalents. diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 3d067ef2fdab5..91e1985282b90 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -320,6 +320,7 @@ namespace { // OpenMP types that don't have Swift equivalents. case clang::BuiltinType::OMPArraySection: + case clang::BuiltinType::OMPArrayShaping: return Type(); // SVE builtin types that don't have Swift equivalents. From a162bd5ea85c843bfb09c9dc1d7b0b1cc8e1c34b Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Fri, 3 Apr 2020 14:52:33 -0700 Subject: [PATCH 047/625] Add OMPIterator to a few switch cases OMPIterator was recently added to upstream clang and thus a few switch statements need to account for this addition. --- lib/ClangImporter/ClangAdapter.cpp | 1 + lib/ClangImporter/ImportType.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index 6428b38c31609..daf1a5c91288a 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -447,6 +447,7 @@ OmissionTypeName importer::getClangTypeNameForOmission(clang::ASTContext &ctx, // OpenMP types that don't have Swift equivalents. case clang::BuiltinType::OMPArraySection: case clang::BuiltinType::OMPArrayShaping: + case clang::BuiltinType::OMPIterator: return OmissionTypeName(); // SVE builtin types that don't have Swift equivalents. diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 91e1985282b90..94dca10d3dfe2 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -321,6 +321,7 @@ namespace { // OpenMP types that don't have Swift equivalents. case clang::BuiltinType::OMPArraySection: case clang::BuiltinType::OMPArrayShaping: + case clang::BuiltinType::OMPIterator: return Type(); // SVE builtin types that don't have Swift equivalents. From a49bceeedf2875c6542812b0dc03ae7e382246e1 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Fri, 3 Apr 2020 16:36:26 -0700 Subject: [PATCH 048/625] Convert a clang::Module to non-const to account for a clang API change An upstream clang changed ASTSourceDescriptor to not have a const Module pointer. const_cast here to make this agree. --- lib/ClangImporter/ClangImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index cc5a374c245d1..2ff697bb48a21 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3305,7 +3305,7 @@ ClangModuleUnit::ClangModuleUnit(ModuleDecl &M, clangModule(clangModule) { // Capture the file metadata before it goes away. if (clangModule) - ASTSourceDescriptor = {*clangModule}; + ASTSourceDescriptor = {*const_cast(clangModule)}; } StringRef ClangModuleUnit::getModuleDefiningPath() const { From 249299d7bb5242a6761f853e9740e5103cb323e3 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 13 Apr 2020 13:58:33 -0700 Subject: [PATCH 049/625] Tighten-up a Foundation Deserialization Test CocoaError.Code.fileReadUnknown conflicts with the CHECK-NOT line here. We should be checking more specifically for UnknownBlock and UnknownCode anyways. rdar://53284293 --- test/SIL/Serialization/deserialize_foundation.sil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SIL/Serialization/deserialize_foundation.sil b/test/SIL/Serialization/deserialize_foundation.sil index 845b1cf97d083..1a9de216aba26 100644 --- a/test/SIL/Serialization/deserialize_foundation.sil +++ b/test/SIL/Serialization/deserialize_foundation.sil @@ -4,4 +4,4 @@ // REQUIRES: objc_interop -// CHECK-NOT: Unknown +// CHECK-NOT: Unknown{{Code|Block}} From 9c7624cdaa2b6a10ee700ad56a0b9fc3ebc7f2d4 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Sat, 18 Apr 2020 16:04:02 +0200 Subject: [PATCH 050/625] Removes redundant buffer zeroing in _persistCString func --- stdlib/public/Darwin/Foundation/NSStringAPI.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/public/Darwin/Foundation/NSStringAPI.swift b/stdlib/public/Darwin/Foundation/NSStringAPI.swift index 512a06182b288..d19675dfb4f83 100644 --- a/stdlib/public/Darwin/Foundation/NSStringAPI.swift +++ b/stdlib/public/Darwin/Foundation/NSStringAPI.swift @@ -73,10 +73,10 @@ internal func _persistCString(_ p: UnsafePointer?) -> [CChar]? { guard let cString = p else { return nil } - let len = UTF8._nullCodeUnitOffset(in: cString) - var result = [CChar](repeating: 0, count: len + 1) - for i in 0.. Date: Fri, 17 Apr 2020 16:57:17 +0200 Subject: [PATCH 051/625] Call the new BinaryOperator factory function The constructor is not public any more. This fixes the master-next build. --- lib/ClangImporter/ImportDecl.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 09448575c5fd0..bef2145b5acfa 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -1223,15 +1223,16 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl, fieldType, clang::VK_RValue, clang::SourceLocation()); - - auto cSetterExpr = new (Ctx) clang::BinaryOperator(cSetterMemberExpr, - cSetterValueExpr, - clang::BO_Assign, - fieldType, - clang::VK_RValue, - clang::OK_Ordinary, - clang::SourceLocation(), - clang::FPOptions()); + + auto cSetterExpr = clang::BinaryOperator::Create(Ctx, + cSetterMemberExpr, + cSetterValueExpr, + clang::BO_Assign, + fieldType, + clang::VK_RValue, + clang::OK_Ordinary, + clang::SourceLocation(), + clang::FPOptions()); cSetterDecl->setBody(cSetterExpr); } From 36279e2b6e2600dd45ea5f4ca8c657c46a880ab2 Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Fri, 17 Apr 2020 16:57:17 +0200 Subject: [PATCH 052/625] Use LLVM version of combineHashValue This fixes the master-next build. --- include/swift/AST/SourceFile.h | 8 +++++--- lib/IRGen/LocalTypeDataKind.h | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index b3fcb9ac66973..7c6b0ed45251f 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -734,9 +734,11 @@ struct DenseMapInfo { StringRefDMI::getTombstoneKey()); } static inline unsigned getHashValue(const ImportedModuleDesc &import) { - return combineHashValue(ImportedModuleDMI::getHashValue(import.module), - combineHashValue(ImportOptionsDMI::getHashValue(import.importOptions), - StringRefDMI::getHashValue(import.filename))); + return detail::combineHashValue( + ImportedModuleDMI::getHashValue(import.module), + detail::combineHashValue( + ImportOptionsDMI::getHashValue(import.importOptions), + StringRefDMI::getHashValue(import.filename))); } static bool isEqual(const ImportedModuleDesc &a, const ImportedModuleDesc &b) { diff --git a/lib/IRGen/LocalTypeDataKind.h b/lib/IRGen/LocalTypeDataKind.h index f45aa30cb1755..1f8215f60eab5 100644 --- a/lib/IRGen/LocalTypeDataKind.h +++ b/lib/IRGen/LocalTypeDataKind.h @@ -211,8 +211,8 @@ template <> struct DenseMapInfo { swift::irgen::LocalTypeDataKind::forFormalTypeMetadata() }; } static unsigned getHashValue(const LocalTypeDataKey &key) { - return combineHashValue(CanTypeInfo::getHashValue(key.Type), - key.Kind.getRawValue()); + return detail::combineHashValue(CanTypeInfo::getHashValue(key.Type), + key.Kind.getRawValue()); } static bool isEqual(const LocalTypeDataKey &a, const LocalTypeDataKey &b) { return a == b; From 7b345931d55cc6153757967c0448e1dea0107154 Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Fri, 17 Apr 2020 12:45:24 +0200 Subject: [PATCH 053/625] Remove Swift's copy of llvm::interleave This is only needed on the master branch, which doesn't have LLVM's copy, yet. --- include/swift/Basic/STLExtras.h | 43 --------------------------------- 1 file changed, 43 deletions(-) diff --git a/include/swift/Basic/STLExtras.h b/include/swift/Basic/STLExtras.h index 14d48f5bafbe5..7a8264ca50cce 100644 --- a/include/swift/Basic/STLExtras.h +++ b/include/swift/Basic/STLExtras.h @@ -69,49 +69,6 @@ struct function_traits { using argument_types = std::tuple; }; -} // end namespace swift - -namespace llvm { - -/// @{ - -/// An STL-style algorithm similar to std::for_each that applies a second -/// functor between every pair of elements. -/// -/// This provides the control flow logic to, for example, print a -/// comma-separated list: -/// \code -/// interleave(names.begin(), names.end(), -/// [&](StringRef name) { OS << name; }, -/// [&] { OS << ", "; }); -/// \endcode -template -inline void interleave(ForwardIterator begin, ForwardIterator end, - UnaryFunctor each_fn, - NullaryFunctor between_fn) { - if (begin == end) - return; - each_fn(*begin); - ++begin; - for (; begin != end; ++begin) { - between_fn(); - each_fn(*begin); - } -} - -template -inline void interleave(const Container &c, UnaryFunctor each_fn, - NullaryFunctor between_fn) { - interleave(c.begin(), c.end(), each_fn, between_fn); -} - -/// @} - -} // end namespace llvm - -namespace swift { - /// @{ /// The equivalent of std::for_each, but for two lists at once. From bcf0afd57af27b5fafee2ab7d2641e51d82b175e Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Mon, 20 Apr 2020 11:45:11 +0200 Subject: [PATCH 054/625] Ignore ExtInt for C interop and IRGen This feature was introduced here: https://github.com/apple/llvm-project/commit/61ba1481e200b5b35baa81ffcff81acb678e8508 --- lib/ClangImporter/ImportType.cpp | 5 +++++ lib/IRGen/GenCall.cpp | 3 +++ 2 files changed, 8 insertions(+) diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 313ce962aadda..790b1fd665328 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -341,6 +341,11 @@ namespace { llvm_unreachable("Invalid BuiltinType."); } + ImportResult VisitExtIntType(const clang::ExtIntType *) { + // ExtInt is not supported in Swift. + return Type(); + } + ImportResult VisitPipeType(const clang::PipeType *) { // OpenCL types are not supported in Swift. return Type(); diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 92d57820cf640..33a9fabd6a728 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -724,6 +724,9 @@ namespace { case clang::Type::Pipe: llvm_unreachable("OpenCL type in ABI lowering?"); + case clang::Type::ExtInt: + llvm_unreachable("ExtInt type in ABI lowering?"); + case clang::Type::ConstantArray: { auto array = Ctx.getAsConstantArrayType(type); auto elt = Ctx.getCanonicalType(array->getElementType()); From 21adecc9c27ce43271ba462f6f245751a64af4b6 Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Tue, 21 Apr 2020 06:28:30 +0200 Subject: [PATCH 055/625] Another StringRef -> std::string conversion fix. This is needed to make this code compile on master-next. --- tools/swift-api-digester/swift-api-digester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp index 9b145860f67ed..dbf90c1601339 100644 --- a/tools/swift-api-digester/swift-api-digester.cpp +++ b/tools/swift-api-digester/swift-api-digester.cpp @@ -2774,7 +2774,7 @@ static std::string getJsonOutputFilePath(llvm::Triple Triple, bool ABI) { exit(1); } llvm::sys::path::append(OutputPath, getBaselineFilename(Triple)); - return OutputPath.str(); + return OutputPath.str().str(); } llvm::errs() << "Unable to decide output file path\n"; exit(1); From 01096b6a61ea32ea577e37a2bb48242e1beaf3a8 Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Fri, 24 Apr 2020 06:36:20 +0200 Subject: [PATCH 056/625] Fix the master-next build --- lib/ClangImporter/ClangAdapter.cpp | 2 +- lib/IRGen/IRGenDebugInfo.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index daf1a5c91288a..351f8b6788f36 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -81,7 +81,7 @@ const clang::Decl * importer::getFirstNonLocalDecl(const clang::Decl *D) { D = D->getCanonicalDecl(); auto iter = llvm::find_if(D->redecls(), [](const clang::Decl *next) -> bool { - return !next->isLexicallyWithinFunctionOrMethod(); + return !next->isInLocalScope(); }); if (iter == D->redecls_end()) return nullptr; diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 72e84361ee5d2..7e28353538b97 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -1014,7 +1014,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { SmallVector TemplateParams; for (auto Param : BGT->getGenericArgs()) { TemplateParams.push_back(DBuilder.createTemplateTypeParameter( - TheCU, "", getOrCreateType(DebugTypeInfo::getForwardDecl(Param)))); + TheCU, "", getOrCreateType(DebugTypeInfo::getForwardDecl(Param)), + false)); } return DBuilder.getOrCreateArray(TemplateParams); } From b59ffe0edf8c89892faed8ce728b37b8a433f628 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Wed, 29 Apr 2020 15:20:04 -0700 Subject: [PATCH 057/625] [ClangImporter] Adjust for LLVM changes https://github.com/llvm/llvm-project/commit/9721fbf85b83 refactors the enum; adjust Swift accordingly. --- lib/ClangImporter/ImportDecl.cpp | 11 ++++++----- lib/ClangImporter/ImportType.cpp | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index cb08947a154b0..356f342cfe1a3 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -47,6 +47,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/DeclObjCCommon.h" #include "clang/Basic/CharInfo.h" #include "swift/Basic/Statistic.h" #include "clang/Basic/TargetInfo.h" @@ -2085,7 +2086,7 @@ classImplementsProtocol(const clang::ObjCInterfaceDecl *constInterface, static void applyPropertyOwnership(VarDecl *prop, - clang::ObjCPropertyDecl::PropertyAttributeKind attrs) { + clang::ObjCPropertyAttribute::Kind attrs) { Type ty = prop->getInterfaceType(); if (auto innerTy = ty->getOptionalObjectType()) ty = innerTy; @@ -2093,19 +2094,19 @@ applyPropertyOwnership(VarDecl *prop, return; ASTContext &ctx = prop->getASTContext(); - if (attrs & clang::ObjCPropertyDecl::OBJC_PR_copy) { + if (attrs & clang::ObjCPropertyAttribute::kind_copy) { prop->getAttrs().add(new (ctx) NSCopyingAttr(false)); return; } - if (attrs & clang::ObjCPropertyDecl::OBJC_PR_weak) { + if (attrs & clang::ObjCPropertyAttribute::kind_weak) { prop->getAttrs().add(new (ctx) ReferenceOwnershipAttr(ReferenceOwnership::Weak)); prop->setInterfaceType(WeakStorageType::get( prop->getInterfaceType(), ctx)); return; } - if ((attrs & clang::ObjCPropertyDecl::OBJC_PR_assign) || - (attrs & clang::ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) { + if ((attrs & clang::ObjCPropertyAttribute::kind_assign) || + (attrs & clang::ObjCPropertyAttribute::kind_unsafe_unretained)) { prop->getAttrs().add( new (ctx) ReferenceOwnershipAttr(ReferenceOwnership::Unmanaged)); prop->setInterfaceType(UnmanagedStorageType::get( diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 790b1fd665328..9b94b93c93247 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -32,6 +32,7 @@ #include "swift/Parse/Token.h" #include "swift/Strings.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjCCommon.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Lex/Preprocessor.h" @@ -1556,8 +1557,8 @@ bool ClangImporter::Implementation::shouldAllowNSUIntegerAsInt( ImportedType ClangImporter::Implementation::importPropertyType( const clang::ObjCPropertyDecl *decl, bool isFromSystemModule) { const auto assignOrUnsafeUnretained = - clang::ObjCPropertyDecl::OBJC_PR_assign | - clang::ObjCPropertyDecl::OBJC_PR_unsafe_unretained; + clang::ObjCPropertyAttribute::kind_assign | + clang::ObjCPropertyAttribute::kind_unsafe_unretained; ImportTypeKind importKind; // HACK: Certain decls are always imported using bridged types, From b91c475bfb29d64ec5647e0524ac4f3a466d8310 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Wed, 29 Apr 2020 23:54:23 -0700 Subject: [PATCH 058/625] [runtime] Adjust LLVMSupport for SmallVectorBase change https://github.com/llvm/llvm-project/commit/dda3c19a3618 makes SmallVectorBase templated. Adjust our copy accordingly and add explicit instantiations for the types in question. Note that for an explicit instantiation, the hidden visibility attribute has to be on the instantiation itself and not the template to have an effect. --- stdlib/public/runtime/LLVMSupport.cpp | 40 ++++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/stdlib/public/runtime/LLVMSupport.cpp b/stdlib/public/runtime/LLVMSupport.cpp index ce8d2838d7387..720d165075fbf 100644 --- a/stdlib/public/runtime/LLVMSupport.cpp +++ b/stdlib/public/runtime/LLVMSupport.cpp @@ -39,19 +39,25 @@ report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {} /// grow_pod - This is an implementation of the grow() method which only works /// on POD-like datatypes and is out of line to reduce code duplication. -void -#if !defined(_WIN32) -__attribute__((__weak__, __visibility__("hidden"))) -#endif -llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, - size_t TSize) { - // Ensure we can fit the new capacity in 32 bits. - if (MinCapacity > UINT32_MAX) +template +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize) { + // Ensure we can fit the new capacity. + // This is only going to be applicable when the capacity is 32 bit. + if (MinCapacity > SizeTypeMax()) report_bad_alloc_error("SmallVector capacity overflow during allocation"); + // Ensure we can meet the guarantee of space for at least one more element. + // The above check alone will not catch the case where grow is called with a + // default MinCapacity of 0, but the current capacity cannot be increased. + // This is only going to be applicable when the capacity is 32 bit. + if (capacity() == SizeTypeMax()) + report_bad_alloc_error("SmallVector capacity unable to grow"); + + // In theory 2*capacity can overflow if the capacity is 64 bit, but the + // original capacity would never be large enough for this to be a problem. size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = - std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX)); + NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); void *NewElts; if (BeginX == FirstEl) { @@ -68,5 +74,19 @@ llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, this->Capacity = NewCapacity; } +template +#if !defined(_WIN32) +__attribute__((__weak__, __visibility__("hidden"))) +#endif +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize); + +template +#if !defined(_WIN32) +__attribute__((__weak__, __visibility__("hidden"))) +#endif +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize); + } // end namespace llvm #endif // defined(swiftCore_EXPORTS) From 78b444d1f0993803d14975a529deec84472afb10 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Wed, 29 Apr 2020 23:57:16 -0700 Subject: [PATCH 059/625] [runtime] Adjust LLVMSupport for upstream 7aaff8fd2da2 https://github.com/llvm/llvm-project/commit/7aaff8fd2da2 moves allocate_buffer and deallocate_buffer out of line, so we have to follow suit. --- stdlib/public/runtime/LLVMSupport.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/stdlib/public/runtime/LLVMSupport.cpp b/stdlib/public/runtime/LLVMSupport.cpp index 720d165075fbf..7b34557ee0e46 100644 --- a/stdlib/public/runtime/LLVMSupport.cpp +++ b/stdlib/public/runtime/LLVMSupport.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemAlloc.h" // ADT uses report_bad_alloc_error to report an error when it can't allocate // elements for a data structure. The swift runtime uses ADT without linking @@ -88,5 +89,31 @@ __attribute__((__weak__, __visibility__("hidden"))) void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); +// The same for allocate_buffer and deallocate_buffer, which are used by +// DenseMap and unique_function. This is a hack. This implementation is copied +// from llvm/lib/Support/MemAlloc.cpp and has to stay in sync with it. +LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * +llvm::allocate_buffer(size_t Size, size_t Alignment) { + return ::operator new(Size +#ifdef __cpp_aligned_new + , + std::align_val_t(Alignment) +#endif + ); +} + +void llvm::deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) { + ::operator delete(Ptr +#ifdef __cpp_sized_deallocation + , + Size +#endif +#ifdef __cpp_aligned_new + , + std::align_val_t(Alignment) +#endif + ); +} + } // end namespace llvm #endif // defined(swiftCore_EXPORTS) From 8637bdab631147fa02f86b7b645251b99fdd9ecc Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 30 Apr 2020 14:33:12 -0700 Subject: [PATCH 060/625] Merge llvm:master; fix SmallVectorBase in the swift runtime. --- stdlib/public/runtime/LLVMSupport.cpp | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/stdlib/public/runtime/LLVMSupport.cpp b/stdlib/public/runtime/LLVMSupport.cpp index ce8d2838d7387..f977cecfa6f23 100644 --- a/stdlib/public/runtime/LLVMSupport.cpp +++ b/stdlib/public/runtime/LLVMSupport.cpp @@ -37,21 +37,30 @@ report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {} // TODO: This is a hack. This implementaiton is copied from LLVM and has to stay // in sync with it. -/// grow_pod - This is an implementation of the grow() method which only works -/// on POD-like datatypes and is out of line to reduce code duplication. +// Note: Moving this function into the header may cause performance regression. +template void #if !defined(_WIN32) __attribute__((__weak__, __visibility__("hidden"))) #endif -llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, - size_t TSize) { - // Ensure we can fit the new capacity in 32 bits. - if (MinCapacity > UINT32_MAX) +SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize) { + // Ensure we can fit the new capacity. + // This is only going to be applicable when the capacity is 32 bit. + if (MinCapacity > SizeTypeMax()) report_bad_alloc_error("SmallVector capacity overflow during allocation"); + // Ensure we can meet the guarantee of space for at least one more element. + // The above check alone will not catch the case where grow is called with a + // default MinCapacity of 0, but the current capacity cannot be increased. + // This is only going to be applicable when the capacity is 32 bit. + if (capacity() == SizeTypeMax()) + report_bad_alloc_error("SmallVector capacity unable to grow"); + + // In theory 2*capacity can overflow if the capacity is 64 bit, but the + // original capacity would never be large enough for this to be a problem. size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = - std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX)); + NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); void *NewElts; if (BeginX == FirstEl) { @@ -68,5 +77,8 @@ llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, this->Capacity = NewCapacity; } +template class llvm::SmallVectorBase; +template class llvm::SmallVectorBase; + } // end namespace llvm #endif // defined(swiftCore_EXPORTS) From d38f436a5f7f0e9dc96218eb6c286a3c4a068d06 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 30 Apr 2020 14:47:43 -0700 Subject: [PATCH 061/625] Revert "Merge llvm:master; fix SmallVectorBase in the swift runtime." --- stdlib/public/runtime/LLVMSupport.cpp | 28 ++++++++------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/stdlib/public/runtime/LLVMSupport.cpp b/stdlib/public/runtime/LLVMSupport.cpp index f977cecfa6f23..ce8d2838d7387 100644 --- a/stdlib/public/runtime/LLVMSupport.cpp +++ b/stdlib/public/runtime/LLVMSupport.cpp @@ -37,30 +37,21 @@ report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {} // TODO: This is a hack. This implementaiton is copied from LLVM and has to stay // in sync with it. -// Note: Moving this function into the header may cause performance regression. -template +/// grow_pod - This is an implementation of the grow() method which only works +/// on POD-like datatypes and is out of line to reduce code duplication. void #if !defined(_WIN32) __attribute__((__weak__, __visibility__("hidden"))) #endif -SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, - size_t TSize) { - // Ensure we can fit the new capacity. - // This is only going to be applicable when the capacity is 32 bit. - if (MinCapacity > SizeTypeMax()) +llvm::SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize) { + // Ensure we can fit the new capacity in 32 bits. + if (MinCapacity > UINT32_MAX) report_bad_alloc_error("SmallVector capacity overflow during allocation"); - // Ensure we can meet the guarantee of space for at least one more element. - // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. - // This is only going to be applicable when the capacity is 32 bit. - if (capacity() == SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); - - // In theory 2*capacity can overflow if the capacity is 64 bit, but the - // original capacity would never be large enough for this to be a problem. size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); + NewCapacity = + std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX)); void *NewElts; if (BeginX == FirstEl) { @@ -77,8 +68,5 @@ SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, this->Capacity = NewCapacity; } -template class llvm::SmallVectorBase; -template class llvm::SmallVectorBase; - } // end namespace llvm #endif // defined(swiftCore_EXPORTS) From c6cc769a64c58cc820ce76699275cae5e9dd6e95 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 1 May 2020 13:50:04 -0700 Subject: [PATCH 062/625] build: default the lld/gold enabling as per reality Rather than defaulting both of these to true, enable gold by default only on ELFish targets, and enable LLD by default for Windows on non-Windows hosts. --- CMakeLists.txt | 14 ++++++++++++-- cmake/modules/AddSwift.cmake | 18 ++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c334534250777..015c0e0fe2085 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,12 +147,22 @@ set(CLANG_COMPILER_VERSION "" CACHE STRING "The internal version of the Clang compiler") # Indicate whether Swift should attempt to use the lld linker. -set(SWIFT_ENABLE_LLD_LINKER TRUE CACHE BOOL +if(CMAKE_SYSTEM_NAME STREQUAL Windows AND NOT CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) + set(SWIFT_ENABLE_LLD_LINKER_default TRUE) +else() + set(SWIFT_ENABLE_LLD_LINKER_default FALSE) +endif() +set(SWIFT_ENABLE_LLD_LINKER ${SWIFT_ENABLE_LLD_LINKER_default} CACHE BOOL "Enable using the lld linker when available") # Indicate whether Swift should attempt to use the gold linker. # This is not used on Darwin. -set(SWIFT_ENABLE_GOLD_LINKER TRUE CACHE BOOL +if(CMAKE_SYSTEM_NAME STREQUAL Darwin OR CMAKE_SYSTEM_NAME STREQUAL Windows) + set(SWIFT_ENABLE_GOLD_LINKER_default FALSE) +else() + set(SWIFT_ENABLE_GOLD_LINKER_default TRUE) +endif() +set(SWIFT_ENABLE_GOLD_LINKER ${SWIFT_ENABLE_GOLD_LINKER_default} CACHE BOOL "Enable using the gold linker when available") set(SWIFT_TOOLS_ENABLE_LTO OFF CACHE STRING "Build Swift tools with LTO. One diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index e8747c21b6c8f..cebc0f1a5a7fa 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -403,18 +403,12 @@ function(_add_host_variant_link_flags target) endif() if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - # FIXME: On Apple platforms, find_program needs to look for "ld64.lld" - find_program(LDLLD_PATH "ld.lld") - if((SWIFT_ENABLE_LLD_LINKER AND LDLLD_PATH AND NOT APPLE) OR - (SWIFT_HOST_VARIANT_SDK STREQUAL WINDOWS AND NOT CMAKE_SYSTEM_NAME STREQUAL WINDOWS)) - target_link_options(${target} PRIVATE -fuse-ld=lld) - elseif(SWIFT_ENABLE_GOLD_LINKER AND - "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_OBJECT_FORMAT}" STREQUAL "ELF") - if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) - target_link_options(${target} PRIVATE -fuse-ld=gold.exe) - else() - target_link_options(${target} PRIVATE -fuse-ld=gold) - endif() + if(SWIFT_ENABLE_LLD_LINKER) + target_link_options(${target} PRIVATE + -fuse-ld=lld$<$:.exe>) + elseif(SWIFT_ENABLE_GOLD_LINKER) + target_link_options(${target} PRIVATE + -fuse-ld=gold$<$:.exe>) endif() endif() From cc798552652c9dad62fb5124898618148b08cd1c Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Wed, 6 May 2020 13:31:44 -0400 Subject: [PATCH 063/625] [Runtime] Fix ConcurrentMapBase::destroyNode to pass the new alignment parameter to MallocAllocator. rdar://problem/62860159 --- include/swift/Runtime/Concurrent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Runtime/Concurrent.h b/include/swift/Runtime/Concurrent.h index 003088c485fbf..4d2f040db8805 100644 --- a/include/swift/Runtime/Concurrent.h +++ b/include/swift/Runtime/Concurrent.h @@ -203,7 +203,7 @@ class ConcurrentMapBase : protected Allocator { // Deallocate the node. The static_cast here is required // because LLVM's allocator API is insane. - this->Deallocate(static_cast(node), allocSize); + this->Deallocate(static_cast(node), allocSize, alignof(Node)); } }; From f8107fbe85e7a6873aafcbfd12c767b2650d99b7 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Thu, 7 May 2020 11:25:11 -0400 Subject: [PATCH 064/625] [Runtime] Add an alignment parameter to MetadataAllocator::Deallocate to match LLVM. rdar://problem/62975124 --- stdlib/public/runtime/Metadata.cpp | 3 ++- stdlib/public/runtime/MetadataCache.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 2c224d3765875..1e7ac996fe645 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -5504,7 +5504,8 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) { } } -void MetadataAllocator::Deallocate(const void *allocation, size_t size) { +void MetadataAllocator::Deallocate(const void *allocation, size_t size, + size_t alignment) { __asan_poison_memory_region(allocation, size); if (size > PoolRange::MaxPoolAllocationSize) { diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h index 41d838e630378..77960dc890461 100644 --- a/stdlib/public/runtime/MetadataCache.h +++ b/stdlib/public/runtime/MetadataCache.h @@ -33,7 +33,7 @@ class MetadataAllocator : public llvm::AllocatorBase { LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t size, size_t alignment); using AllocatorBase::Allocate; - void Deallocate(const void *Ptr, size_t size); + void Deallocate(const void *Ptr, size_t size, size_t alignment); using AllocatorBase::Deallocate; void PrintStats() const {} From a195733336ffc51c09a8de0a39ba6df50a17c07d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Thu, 7 May 2020 10:43:02 -0700 Subject: [PATCH 065/625] [master-next] Fix compile error ParsedRawSyntaxNode and SwiftLangSupport --- include/swift/Parse/ParsedRawSyntaxNode.h | 4 ++-- tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/swift/Parse/ParsedRawSyntaxNode.h b/include/swift/Parse/ParsedRawSyntaxNode.h index 00a1dc93381af..340684556c56f 100644 --- a/include/swift/Parse/ParsedRawSyntaxNode.h +++ b/include/swift/Parse/ParsedRawSyntaxNode.h @@ -99,8 +99,8 @@ class ParsedRawSyntaxNode { assert(DeferredToken.NumTrailingTrivia == numTrailingTrivia && "numLeadingTrivia is too large value!"); } - ParsedRawSyntaxNode(ParsedRawSyntaxNode &other) = delete; - ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &other) = delete; + ParsedRawSyntaxNode(const ParsedRawSyntaxNode &other) = delete; + ParsedRawSyntaxNode &operator=(const ParsedRawSyntaxNode &other) = delete; public: ParsedRawSyntaxNode() diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp index 8fea7e661c542..a6eb8ca6fcbe1 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp @@ -270,7 +270,7 @@ SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) llvm::SmallString<128> LibPath(SKCtx.getRuntimeLibPath()); llvm::sys::path::append(LibPath, "swift"); RuntimeResourcePath = std::string(LibPath.str()); - DiagnosticDocumentationPath = SKCtx.getDiagnosticDocumentationPath(); + DiagnosticDocumentationPath = SKCtx.getDiagnosticDocumentationPath().str(); Stats = std::make_shared(); EditorDocuments = std::make_shared(); From 342836892af8f8111b7561e0356aec0b103eb216 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Mon, 11 May 2020 12:36:21 +0200 Subject: [PATCH 066/625] Using initialize instead of assign --- stdlib/public/Darwin/Foundation/NSStringAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/Darwin/Foundation/NSStringAPI.swift b/stdlib/public/Darwin/Foundation/NSStringAPI.swift index d19675dfb4f83..cdedb10f00a10 100644 --- a/stdlib/public/Darwin/Foundation/NSStringAPI.swift +++ b/stdlib/public/Darwin/Foundation/NSStringAPI.swift @@ -75,7 +75,7 @@ internal func _persistCString(_ p: UnsafePointer?) -> [CChar]? { } let bytesToCopy = UTF8._nullCodeUnitOffset(in: cString) + 1 // +1 for the terminating NUL let result = [CChar](unsafeUninitializedCapacity: bytesToCopy) { buffer, initializedCount in - buffer.baseAddress!.assign(from: cString, count: bytesToCopy) + buffer.baseAddress!.initialize(from: cString, count: bytesToCopy) initializedCount = bytesToCopy } return result From 63c0ded8c90f670f886dd213f3148bdb352b60ea Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 11 May 2020 10:59:45 -0700 Subject: [PATCH 067/625] Include llvm/Support/Debug.h in AdjointValue.h --- include/swift/SILOptimizer/Differentiation/AdjointValue.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/SILOptimizer/Differentiation/AdjointValue.h b/include/swift/SILOptimizer/Differentiation/AdjointValue.h index 104a3f0bc699f..4b316835518f7 100644 --- a/include/swift/SILOptimizer/Differentiation/AdjointValue.h +++ b/include/swift/SILOptimizer/Differentiation/AdjointValue.h @@ -21,6 +21,7 @@ #include "swift/AST/Decl.h" #include "swift/SIL/SILValue.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Debug.h" namespace swift { namespace autodiff { From fd98ce10c7f709a9d62914fb10f597388e439060 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 25 Mar 2020 07:22:26 -0700 Subject: [PATCH 068/625] 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 7eec685b074bbd356272c9af7ad9501742f1c663 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 12 May 2020 08:13:29 -0700 Subject: [PATCH 069/625] ClangImporter: Ignore matrix types for now --- lib/ClangImporter/ImportType.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 9b94b93c93247..3ad13c1cd555f 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -352,6 +352,11 @@ namespace { return Type(); } + ImportResult VisitMatrixType(const clang::MatrixType *ty) { + // Matrix types are not supported in Swift. + return Type(); + } + ImportResult VisitComplexType(const clang::ComplexType *type) { // FIXME: Implement once Complex is in the library. return Type(); From a7f3d2bae391e888ce804ff9d7ebf0a2dca8d4c0 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 12 May 2020 08:18:23 -0700 Subject: [PATCH 070/625] Adjust to new ElementCount type for vector operations --- lib/IRGen/GenConstant.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/IRGen/GenConstant.cpp b/lib/IRGen/GenConstant.cpp index 6855b0ccadf94..6c498276def14 100644 --- a/lib/IRGen/GenConstant.cpp +++ b/lib/IRGen/GenConstant.cpp @@ -85,7 +85,8 @@ llvm::Constant *irgen::emitConstantZero(IRGenModule &IGM, BuiltinInst *BI) { if (auto vector = BI->getType().getAs()) { auto zero = helper(vector.getElementType()); - return llvm::ConstantVector::getSplat(vector->getNumElements(), zero); + return llvm::ConstantVector::getSplat( + llvm::ElementCount(vector->getNumElements(), /*scalable*/ false), zero); } return helper(BI->getType().getASTType()); From eab0fe2ff7cb4a31366345e17032d155a9567518 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 12 May 2020 08:22:22 -0700 Subject: [PATCH 071/625] IRGen: Adjust to added Matrix type ignore for now --- lib/IRGen/GenCall.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index eafd9e15b0303..ed01996f0bc47 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -730,6 +730,10 @@ namespace { case clang::Type::ExtInt: llvm_unreachable("ExtInt type in ABI lowering?"); + case clang::Type::ConstantMatrix: { + llvm_unreachable("ConstantMatrix type in ABI lowering?"); + } + case clang::Type::ConstantArray: { auto array = Ctx.getAsConstantArrayType(type); auto elt = Ctx.getCanonicalType(array->getElementType()); From f00953c62d36c0d89b8dd8d4e0afb22bd7c07fef Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sat, 18 Apr 2020 11:12:32 -0700 Subject: [PATCH 072/625] [Diags-Experimental-Formatting] Fixes for printing diagnostics when #sourceLocation is used - Always use the line number in the actual source file when extracting excerpts and adding highlights/fix-its - Always use the display name when printing excerpt titles - Don't print surrounding lines when an annotated line is in a virtual file This reverts commit f919e047834eddf8863723b9db1fcb8d344d2006. --- include/swift/Basic/SourceManager.h | 5 ++ lib/Frontend/PrintingDiagnosticConsumer.cpp | 81 ++++++++++++------- ...y-printed-source-loc-directive-diags.swift | 77 ++++++++++++++++++ 3 files changed, 136 insertions(+), 27 deletions(-) create mode 100644 test/diagnostics/pretty-printed-source-loc-directive-diags.swift diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index d05e8c9e66f81..d503772799b38 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -268,6 +268,11 @@ class SourceManager { else return 0; } + +public: + bool isLocInVirtualFile(SourceLoc Loc) const { + return getVirtualFile(Loc) != nullptr; + } }; } // end namespace swift diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index b7f2a9ea60d8f..229b49e4b9ae4 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -381,6 +381,9 @@ namespace { }; unsigned LineNumber; + // The line number displayed to the user. This may differ from the actual + // line number if #sourceLocation is used. + unsigned DisplayLineNumber; std::string LineText; SmallVector Messages; SmallVector Highlights; @@ -448,8 +451,10 @@ namespace { } public: - AnnotatedLine(unsigned LineNumber, StringRef LineText) - : LineNumber(LineNumber), LineText(LineText) {} + AnnotatedLine(unsigned LineNumber, unsigned DisplayLineNumber, + StringRef LineText) + : LineNumber(LineNumber), DisplayLineNumber(DisplayLineNumber), + LineText(LineText) {} unsigned getLineNumber() { return LineNumber; } @@ -469,7 +474,7 @@ namespace { } void render(unsigned LineNumberIndent, raw_ostream &Out) { - printNumberedGutter(LineNumber, LineNumberIndent, Out); + printNumberedGutter(DisplayLineNumber, LineNumberIndent, Out); // Determine if the line is all-ASCII. This will determine a number of // later formatting decisions. @@ -628,14 +633,17 @@ namespace { /// diagnostic message. This is printed alongside the file path so it can be /// parsed by editors and other tooling. SourceLoc PrimaryLoc; + /// Whether the excerpt is from a virtual file (e.g. one introduced using + /// #sourceLocation). + bool FromVirtualFile; std::vector AnnotatedLines; /// Return the AnnotatedLine for a given SourceLoc, creating it if it /// doesn't already exist. AnnotatedLine &lineForLoc(SourceLoc Loc) { - // FIXME: This call to `getLineAndColumn` is expensive. - unsigned lineNo = SM.getLineAndColumn(Loc).first; - AnnotatedLine newLine(lineNo, ""); + // FIXME: This call to `getLineNumber` is expensive. + unsigned lineNo = SM.getLineNumber(Loc); + AnnotatedLine newLine(lineNo, 0, ""); auto iter = std::lower_bound(AnnotatedLines.begin(), AnnotatedLines.end(), newLine, [](AnnotatedLine l1, AnnotatedLine l2) { @@ -643,6 +651,7 @@ namespace { }); if (iter == AnnotatedLines.end() || iter->getLineNumber() != lineNo) { newLine.LineText = SM.getLineString(BufferID, lineNo); + newLine.DisplayLineNumber = SM.getLineAndColumn(Loc).first; return *AnnotatedLines.insert(iter, newLine); } else { return *iter; @@ -658,10 +667,8 @@ namespace { void lineRangesForRange(CharSourceRange Range, SmallVectorImpl &LineRanges) { - // FIXME: The calls to `getLineAndColumn` and `getLocForLineCol` are - // expensive. - unsigned startLineNo = SM.getLineAndColumn(Range.getStart()).first; - unsigned endLineNo = SM.getLineAndColumn(Range.getEnd()).first; + unsigned startLineNo = SM.getLineNumber(Range.getStart()); + unsigned endLineNo = SM.getLineNumber(Range.getEnd()); if (startLineNo == endLineNo) { LineRanges.push_back(Range); @@ -687,10 +694,19 @@ namespace { LineRanges.push_back(CharSourceRange(SM, lastLineStart, Range.getEnd())); } + void printLineEllipsis(raw_ostream &Out) { + Out.changeColor(ColoredStream::Colors::CYAN, true); + Out << llvm::formatv("{0}...\n", + llvm::fmt_repeat(" ", getLineNumberIndent())); + Out.resetColor(); + } + public: AnnotatedFileExcerpt(SourceManager &SM, unsigned BufferID, SourceLoc PrimaryLoc) - : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) {} + : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) { + FromVirtualFile = SM.isLocInVirtualFile(PrimaryLoc); + } unsigned getPreferredLineNumberIndent() { // The lines are already in sorted ascending order, and we render one line @@ -734,13 +750,14 @@ namespace { auto primaryLineAndColumn = SM.getLineAndColumn(PrimaryLoc); Out.changeColor(ColoredStream::Colors::CYAN); Out << std::string(lineNumberIndent + 1, '=') << " " - << SM.getIdentifierForBuffer(BufferID) << ":" + << SM.getDisplayNameForLoc(PrimaryLoc) << ":" << primaryLineAndColumn.first << ":" << primaryLineAndColumn.second << " " << std::string(lineNumberIndent + 1, '=') << "\n"; Out.resetColor(); - // Print one extra line at the top for context. - if (AnnotatedLines.front().getLineNumber() > 1) + // Print one extra line at the top for context, so long as this isn't an + // excerpt from a virtual file. + if (AnnotatedLines.front().getLineNumber() > 1 && !FromVirtualFile) printNumberedLine(SM, BufferID, AnnotatedLines.front().getLineNumber() - 1, lineNumberIndent, Out); @@ -754,14 +771,18 @@ namespace { for (auto line = AnnotatedLines.begin() + 1; line != AnnotatedLines.end(); ++line) { unsigned lineNumber = line->getLineNumber(); - if (lineNumber - lastLineNumber > maxIntermediateLines) { + if (FromVirtualFile) { + // Don't print intermediate lines in virtual files, as they may not + // make sense in context. Instead, just print an ellipsis between them + // if they're not consecutive in the actual source file. + if (lineNumber - lastLineNumber > 1) { + printLineEllipsis(Out); + } + } else if (lineNumber - lastLineNumber > maxIntermediateLines) { // Use an ellipsis to denote an ommitted part of the file. printNumberedLine(SM, BufferID, lastLineNumber + 1, lineNumberIndent, Out); - Out.changeColor(ColoredStream::Colors::CYAN); - Out << llvm::formatv("{0}...\n", - llvm::fmt_repeat(" ", lineNumberIndent)); - Out.resetColor(); + printLineEllipsis(Out); printNumberedLine(SM, BufferID, lineNumber - 1, lineNumberIndent, Out); } else { @@ -774,11 +795,14 @@ namespace { line->render(lineNumberIndent, Out); lastLineNumber = lineNumber; } - // Print one extra line at the bottom for context. - printNumberedLine( - SM, BufferID, - AnnotatedLines[AnnotatedLines.size() - 1].getLineNumber() + 1, - lineNumberIndent, Out); + // Print one extra line at the bottom for context, so long as the excerpt + // isn't from a virtual file. + if (!FromVirtualFile) { + printNumberedLine( + SM, BufferID, + AnnotatedLines[AnnotatedLines.size() - 1].getLineNumber() + 1, + lineNumberIndent, Out); + } } }; } // end anonymous namespace @@ -788,14 +812,17 @@ namespace swift { /// complete diagnostic message. class AnnotatedSourceSnippet { SourceManager &SM; - std::map FileExcerpts; + std::map FileExcerpts; SmallVector, 1> UnknownLocationMessages; AnnotatedFileExcerpt &excerptForLoc(SourceLoc Loc) { + StringRef bufName = SM.getDisplayNameForLoc(Loc); unsigned bufID = SM.findBufferContainingLoc(Loc); - FileExcerpts.emplace(bufID, AnnotatedFileExcerpt(SM, bufID, Loc)); - return FileExcerpts.find(bufID)->second; + // Use the buffer display name as the key in the excerpt map instead of the + // buffer identifier to respect #sourceLocation directives. + FileExcerpts.emplace(bufName, AnnotatedFileExcerpt(SM, bufID, Loc)); + return FileExcerpts.find(bufName)->second; } public: diff --git a/test/diagnostics/pretty-printed-source-loc-directive-diags.swift b/test/diagnostics/pretty-printed-source-loc-directive-diags.swift new file mode 100644 index 0000000000000..cebc5a22884bb --- /dev/null +++ b/test/diagnostics/pretty-printed-source-loc-directive-diags.swift @@ -0,0 +1,77 @@ +// RUN: not %target-swift-frontend -enable-experimental-diagnostic-formatting -typecheck %s 2>&1 | %FileCheck %s + +// Error split between the real file and a virtual one. +#sourceLocation(file: "abc.swift", line: 9) +let x = 1 +#sourceLocation() +let x = 2 + +// Error split between two virtual files. +#sourceLocation(file: "abc.swift", line: 4) +let y = 1 +#sourceLocation(file: "xyz.swift", line: 18) +let y = 2 +#sourceLocation() + +// Error within a virtual file on non-consecutive lines. +#sourceLocation(file: "abc.swift", line: 1) +let z = 1 +// space +let z = 2 +#sourceLocation() + +// Error with note location placed in the same virtual file via a separate #sourceLocation block. +#sourceLocation(file: "abc.swift", line: 1) +let a = 1 +#sourceLocation() + + +#sourceLocation(file: "abc.swift", line: 10) +let a = 2 +#sourceLocation() + +// Error at the beginning of a virtual file. +#sourceLocation(file: "abc.swift", line: 1) +let any: Any = "" +let zz: Int = any +#sourceLocation() + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-source-loc-directive-diags.swift:[[#LINE:]]:5 +// CHECK: [[#LINE-1]] | #sourceLocation() +// CHECK: [[#LINE]] | let x = 2 +// CHECK: | ^ error: invalid redeclaration of 'x' +// CHECK: [[#LINE+1]] | +// CHECK: abc.swift:9:5 +// CHECK: 9 | let x = 1 +// CHECK: | ^ note: 'x' previously declared here + + +// CHECK: abc.swift:4:5 +// CHECK: 4 | let y = 1 +// CHECK: | ^ note: 'y' previously declared here +// CHECK: xyz.swift:18:5 +// CHECK: 18 | let y = 2 +// CHECK: | ^ error: invalid redeclaration of 'y' + + +// CHECK: abc.swift:3:5 +// CHECK: 1 | let z = 1 +// CHECK: | ^ note: 'z' previously declared here +// CHECK: ... +// CHECK: 3 | let z = 2 +// CHECK: | ^ error: invalid redeclaration of 'z' + + +// CHECK: abc.swift:10:5 +// CHECK: 1 | let a = 1 +// CHECK: | ^ note: 'a' previously declared here +// CHECK: ... +// CHECK: 10 | let a = 2 +// CHECK: | ^ error: invalid redeclaration of 'a' + + +// CHECK: abc.swift:2:15 +// CHECK: 2 | let zz: Int = any as! Int +// CHECK: | ~~~++++++++ +// CHECK: | ^ error: cannot convert value of type 'Any' to specified type 'Int' [insert ' as! Int'] + From 96696c88231bebe3ed65ce164bd59bf8c94f9432 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Mon, 20 Apr 2020 10:07:45 -0700 Subject: [PATCH 073/625] [Diag-Experimental-Formatting] Add a formatting test for Swift diags emitted in clang virtual files --- lib/Frontend/PrintingDiagnosticConsumer.cpp | 2 +- test/diagnostics/Inputs/RenamedObjc.h | 9 +++++++++ test/diagnostics/Inputs/module.map | 4 ++++ ...pretty-printed-diags-in-clang-buffer.swift | 20 +++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/diagnostics/Inputs/RenamedObjc.h create mode 100644 test/diagnostics/Inputs/module.map create mode 100644 test/diagnostics/pretty-printed-diags-in-clang-buffer.swift diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index 229b49e4b9ae4..ab4937d448b8b 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -697,7 +697,7 @@ namespace { void printLineEllipsis(raw_ostream &Out) { Out.changeColor(ColoredStream::Colors::CYAN, true); Out << llvm::formatv("{0}...\n", - llvm::fmt_repeat(" ", getLineNumberIndent())); + llvm::fmt_repeat(" ", getPreferredLineNumberIndent())); Out.resetColor(); } diff --git a/test/diagnostics/Inputs/RenamedObjc.h b/test/diagnostics/Inputs/RenamedObjc.h new file mode 100644 index 0000000000000..a4ed605ce18e4 --- /dev/null +++ b/test/diagnostics/Inputs/RenamedObjc.h @@ -0,0 +1,9 @@ +@import Foundation; + +#define SWIFT_NAME(X) __attribute__((swift_name(#X))) + +#pragma clang assume_nonnull begin +@interface SwiftNameTest : NSObject ++ (instancetype)g:(id)x outParam:(int *)foo SWIFT_NAME(init(g:)); +@end +#pragma clang assume_nonnull end diff --git a/test/diagnostics/Inputs/module.map b/test/diagnostics/Inputs/module.map new file mode 100644 index 0000000000000..02eaefab7c2e1 --- /dev/null +++ b/test/diagnostics/Inputs/module.map @@ -0,0 +1,4 @@ +module RenamedObjc { + header "RenamedObjc.h" + export * +} diff --git a/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift b/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift new file mode 100644 index 0000000000000..049ca95278278 --- /dev/null +++ b/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t.mcp) +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-diagnostic-formatting -I %S/Inputs/ -typecheck %s -module-cache-path %t.mcp 2>&1 | %FileCheck %s + +// REQUIRES: objc_interop + +import RenamedObjc + +let foo = SwiftNameTest(g: "") + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}Inputs{{[/\]+}}RenamedObjc.h:7:1 +// CHECK: 7 | + (instancetype)g:(id)x outParam:(int *)foo SWIFT_NAME(init(g:)); +// CHECK: | ^ warning: too few parameters in swift_name attribute (expected 2; got 1) +// CHECK: | ^ note: please report this issue to the owners of 'RenamedObjc' + + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diags-in-clang-buffer.swift:8:28 +// CHECK: 7 | +// CHECK: 8 | let foo = SwiftNameTest(g: "") +// CHECK: | ~~ +// CHECK: | ^ error: argument passed to call that takes no arguments From 622fee54a7996d835c525291926f90ef0dda2e73 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 13 May 2020 07:35:11 -0700 Subject: [PATCH 074/625] Another std::string StringRef assignment. --- lib/Frontend/ModuleInterfaceLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 0770cbecd2883..9e2494b67678c 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1105,7 +1105,7 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( if (CompRe.match(SB, &CompMatches)) { assert(CompMatches.size() == 2); - CompilerVersion = SubArgSaver.save(CompMatches[1]); + CompilerVersion = SubArgSaver.save(CompMatches[1]).str(); } else { // Don't diagnose; handwritten module interfaces don't include this field. From 803414cea7f3ad5e60cfb300f3a32f38fd23c28d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 15 May 2020 06:40:37 -0700 Subject: [PATCH 075/625] Adjust to MaybeAlign -> Align change in LoadInst api --- lib/IRGen/IRBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index 69ecb3de278bb..445bb5730edf5 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -125,7 +125,7 @@ class IRBuilder : public IRBuilderBase { llvm::LoadInst *CreateLoad(llvm::Value *addr, Alignment align, const llvm::Twine &name = "") { llvm::LoadInst *load = IRBuilderBase::CreateLoad(addr, name); - load->setAlignment(llvm::MaybeAlign(align.getValue())); + load->setAlignment(llvm::Align(align.getValue())); return load; } llvm::LoadInst *CreateLoad(Address addr, const llvm::Twine &name = "") { From 0792b12eed45f5269df6557058eb805f58b73c77 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 15 May 2020 06:54:53 -0700 Subject: [PATCH 076/625] Make sure we get a valid llvm::Align value --- lib/IRGen/IRBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index 445bb5730edf5..c7b875b2b2179 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -125,7 +125,7 @@ class IRBuilder : public IRBuilderBase { llvm::LoadInst *CreateLoad(llvm::Value *addr, Alignment align, const llvm::Twine &name = "") { llvm::LoadInst *load = IRBuilderBase::CreateLoad(addr, name); - load->setAlignment(llvm::Align(align.getValue())); + load->setAlignment(llvm::MaybeAlign(align.getValue()).valueOrOne()); return load; } llvm::LoadInst *CreateLoad(Address addr, const llvm::Twine &name = "") { From 40759df737166167422824d2d2ea678247a1a25d Mon Sep 17 00:00:00 2001 From: David Goldman Date: Fri, 15 May 2020 17:16:30 -0400 Subject: [PATCH 077/625] [SourceKit] Include operation kind in compile notifications - Compile will start / did finish now includes the operation kind (perform sema or code complete). - See also https://forums.swift.org/t/sourcekit-lsp-file-status-ux/35947 --- .../CompileNotifications/arg-parsing.swift | 4 ++++ .../code-completion.swift | 2 ++ .../CompileNotifications/cursor-info.swift | 2 ++ .../CompileNotifications/edits.swift | 8 ++++++++ .../tools/sourcekitd/lib/API/Requests.cpp | 19 ++++++++++++++++++- utils/gyb_sourcekit_support/UIDs.py | 1 + 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/test/SourceKit/CompileNotifications/arg-parsing.swift b/test/SourceKit/CompileNotifications/arg-parsing.swift index 67bfc0cd20928..069915854726e 100644 --- a/test/SourceKit/CompileNotifications/arg-parsing.swift +++ b/test/SourceKit/CompileNotifications/arg-parsing.swift @@ -4,6 +4,7 @@ // ARG_PARSE_0: key.notification: source.notification.compile-will-start // ARG_PARSE_0: key.compileid: [[CID1:".*"]] // ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg" +// ARG_PARSE_0: key.compileoperation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0: { // ARG_PARSE_0: key.notification: source.notification.compile-did-finish @@ -15,6 +16,7 @@ // ARG_PARSE_0: } // ARG_PARSE_0: ] // ARG_PARSE_0: key.compileid: [[CID1]] +// ARG_PARSE_0: key.compileoperation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0-NOT: compile-will-start // ARG_PARSE_0-NOT: compile-did-finish @@ -25,6 +27,7 @@ // ARG_PARSE_1: key.notification: source.notification.compile-will-start // ARG_PARSE_1: key.compileid: [[CID1:".*"]] // ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg" +// ARG_PARSE_1: key.compileoperation: source.compile.operation.perform-sema // ARG_PARSE_1: } // ARG_PARSE_1: { // ARG_PARSE_1: key.notification: source.notification.compile-did-finish @@ -36,6 +39,7 @@ // ARG_PARSE_1: } // ARG_PARSE_1: ] // ARG_PARSE_1: key.compileid: [[CID1]] +// ARG_PARSE_1: key.compileoperation: source.compile.operation.perform-sema // ARG_PARSE_1: } // ARG_PARSE_1-NOT: compile-will-start // ARG_PARSE_1-NOT: compile-did-finish diff --git a/test/SourceKit/CompileNotifications/code-completion.swift b/test/SourceKit/CompileNotifications/code-completion.swift index 53dbb2084d6b9..50335818ae69b 100644 --- a/test/SourceKit/CompileNotifications/code-completion.swift +++ b/test/SourceKit/CompileNotifications/code-completion.swift @@ -3,10 +3,12 @@ // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.filepath: "{{.*}}SOURCE_DIR{{.*}}code-completion.swift", // COMPILE_1: key.compileid: [[CID1:".*"]] +// COMPILE_1: key.compileoperation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] +// COMPILE_1: key.compileoperation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1-NOT: compile-will-start // COMPILE_1-NOT: compile-did-finish \ No newline at end of file diff --git a/test/SourceKit/CompileNotifications/cursor-info.swift b/test/SourceKit/CompileNotifications/cursor-info.swift index 45840c2422f5b..7c592b9937be1 100644 --- a/test/SourceKit/CompileNotifications/cursor-info.swift +++ b/test/SourceKit/CompileNotifications/cursor-info.swift @@ -3,10 +3,12 @@ // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.filepath: "SOURCE_DIR{{.*}}cursor-info.swift", // COMPILE_1: key.compileid: [[CID1:".*"]] +// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] +// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: // COMPILE_1-NOT: compile-will-start diff --git a/test/SourceKit/CompileNotifications/edits.swift b/test/SourceKit/CompileNotifications/edits.swift index 23045d716739f..b130d25e785ae 100644 --- a/test/SourceKit/CompileNotifications/edits.swift +++ b/test/SourceKit/CompileNotifications/edits.swift @@ -4,10 +4,12 @@ // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.compileid: [[CID1:".*"]] +// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] +// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1-NOT: compile-will-start // COMPILE_1-NOT: compile-did-finish @@ -19,26 +21,32 @@ // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID1:".*"]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID1]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID2:".*"]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID2]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID3:".*"]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID3]] +// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3-NOT: compile-will-start // COMPILE_3-NOT: compile-did-finish diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index cdc17f6009e97..7e2426aef19a9 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -3181,6 +3181,22 @@ class CompileTrackingConsumer final : public trace::TraceConsumer { }; } // end anonymous namespace +static UIdent getUIDForOperationKind(trace::OperationKind OpKind) { + static UIdent CompileOperationPerformSema("source.compile.operation.perform-sema"); + static UIdent CompileOperationIndexSource("source.compile.operation.index-source"); + static UIdent CompileOperationCodeCompletion("source.compile.operation.code-completion"); + switch (OpKind) { + case trace::OperationKind::PerformSema: + return CompileOperationPerformSema; + case trace::OperationKind::IndexSource: + return CompileOperationIndexSource; + case trace::OperationKind::CodeCompletion: + return CompileOperationCodeCompletion; + case trace::OperationKind::All: + return CompileOperationPerformSema; + } +} + void CompileTrackingConsumer::operationStarted( uint64_t OpId, trace::OperationKind OpKind, const trace::SwiftInvocation &Inv, const trace::StringPairs &OpArgs) { @@ -3193,7 +3209,7 @@ void CompileTrackingConsumer::operationStarted( Dict.set(KeyNotification, CompileWillStartUID); Dict.set(KeyCompileID, std::to_string(OpId)); Dict.set(KeyFilePath, Inv.Args.PrimaryFile); - // FIXME: OperationKind + Dict.set(KeyCompileOperation, getUIDForOperationKind(OpKind)); Dict.set(KeyCompilerArgsString, Inv.Args.Arguments); sourcekitd::postNotification(RespBuilder.createResponse()); } @@ -3209,6 +3225,7 @@ void CompileTrackingConsumer::operationFinished( auto Dict = RespBuilder.getDictionary(); Dict.set(KeyNotification, CompileDidFinishUID); Dict.set(KeyCompileID, std::to_string(OpId)); + Dict.set(KeyCompileOperation, getUIDForOperationKind(OpKind)); auto DiagArray = Dict.setArray(KeyDiagnostics); for (const auto &DiagInfo : Diagnostics) { fillDictionaryForDiagnosticInfo(DiagArray.appendDictionary(), DiagInfo); diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py index 33b80673032c5..e5114e55dd5d9 100644 --- a/utils/gyb_sourcekit_support/UIDs.py +++ b/utils/gyb_sourcekit_support/UIDs.py @@ -182,6 +182,7 @@ def __init__(self, internal_name, external_name): KEY('CompletionCheckDependencyInterval', 'key.completion_check_dependency_interval'), KEY('AnnotatedTypename', 'key.annotated.typename'), + KEY('CompileOperation', 'key.compileoperation'), ] From 95c16fc9e1d1caa0f586a7bdf7675647e3eb9ec9 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Sat, 16 May 2020 08:06:53 +0300 Subject: [PATCH 078/625] [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 3ffd0da30d23a8ddf29fe0521435ac4efa989678 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 18 May 2020 15:10:23 +0300 Subject: [PATCH 079/625] [NFC] AST: Push up a fast path in TypeBase::getContextSubstitutions --- lib/AST/Type.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index abdc06e298980..439392df88976 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3949,16 +3949,16 @@ TypeBase::getContextSubstitutions(const DeclContext *dc, return substitutions; } + const auto genericSig = dc->getGenericSignatureOfContext(); + if (!genericSig) + return substitutions; + // Find the superclass type with the context matching that of the member. auto *ownerNominal = dc->getSelfNominalTypeDecl(); if (auto *ownerClass = dyn_cast(ownerNominal)) baseTy = baseTy->getSuperclassForDecl(ownerClass); // Gather all of the substitutions for all levels of generic arguments. - auto genericSig = dc->getGenericSignatureOfContext(); - if (!genericSig) - return substitutions; - auto params = genericSig->getGenericParams(); unsigned n = params.size(); From 5372afeb98cf7a4523ed3a5cd7582800cd2b7a1a Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 18 May 2020 06:16:38 -0700 Subject: [PATCH 080/625] Adjust to MaybeAlign -> Align change in llvm::StoreInst api --- lib/IRGen/IRBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index c7b875b2b2179..4eaa167b26f49 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -135,7 +135,7 @@ class IRBuilder : public IRBuilderBase { llvm::StoreInst *CreateStore(llvm::Value *value, llvm::Value *addr, Alignment align) { llvm::StoreInst *store = IRBuilderBase::CreateStore(value, addr); - store->setAlignment(llvm::MaybeAlign(align.getValue())); + store->setAlignment(llvm::MaybeAlign(align.getValue()).valueOrOne()); return store; } llvm::StoreInst *CreateStore(llvm::Value *value, Address addr) { From 67a2fe494a0eb4827bfe4e14116b521c4293eb97 Mon Sep 17 00:00:00 2001 From: David Goldman Date: Mon, 18 May 2020 13:18:40 -0400 Subject: [PATCH 081/625] Fix up compile operation kind - `key.compile_operation` instead of `key.compileoperation` - Make the operation kind optional (nothing emitted for perform sema) --- .../CompileNotifications/arg-parsing.swift | 6 ++---- .../CompileNotifications/code-completion.swift | 4 ++-- .../CompileNotifications/cursor-info.swift | 2 -- test/SourceKit/CompileNotifications/edits.swift | 8 -------- .../tools/sourcekitd/lib/API/Requests.cpp | 15 +++++++++------ utils/gyb_sourcekit_support/UIDs.py | 2 +- 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/test/SourceKit/CompileNotifications/arg-parsing.swift b/test/SourceKit/CompileNotifications/arg-parsing.swift index 069915854726e..7dc654d7d5ac5 100644 --- a/test/SourceKit/CompileNotifications/arg-parsing.swift +++ b/test/SourceKit/CompileNotifications/arg-parsing.swift @@ -4,7 +4,7 @@ // ARG_PARSE_0: key.notification: source.notification.compile-will-start // ARG_PARSE_0: key.compileid: [[CID1:".*"]] // ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg" -// ARG_PARSE_0: key.compileoperation: source.compile.operation.code-completion +// ARG_PARSE_0: key.compile_operation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0: { // ARG_PARSE_0: key.notification: source.notification.compile-did-finish @@ -16,7 +16,7 @@ // ARG_PARSE_0: } // ARG_PARSE_0: ] // ARG_PARSE_0: key.compileid: [[CID1]] -// ARG_PARSE_0: key.compileoperation: source.compile.operation.code-completion +// ARG_PARSE_0: key.compile_operation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0-NOT: compile-will-start // ARG_PARSE_0-NOT: compile-did-finish @@ -27,7 +27,6 @@ // ARG_PARSE_1: key.notification: source.notification.compile-will-start // ARG_PARSE_1: key.compileid: [[CID1:".*"]] // ARG_PARSE_1: key.compilerargs-string: "{{.*}}.swift -no-such-arg" -// ARG_PARSE_1: key.compileoperation: source.compile.operation.perform-sema // ARG_PARSE_1: } // ARG_PARSE_1: { // ARG_PARSE_1: key.notification: source.notification.compile-did-finish @@ -39,7 +38,6 @@ // ARG_PARSE_1: } // ARG_PARSE_1: ] // ARG_PARSE_1: key.compileid: [[CID1]] -// ARG_PARSE_1: key.compileoperation: source.compile.operation.perform-sema // ARG_PARSE_1: } // ARG_PARSE_1-NOT: compile-will-start // ARG_PARSE_1-NOT: compile-did-finish diff --git a/test/SourceKit/CompileNotifications/code-completion.swift b/test/SourceKit/CompileNotifications/code-completion.swift index 50335818ae69b..8ec32210e6e0e 100644 --- a/test/SourceKit/CompileNotifications/code-completion.swift +++ b/test/SourceKit/CompileNotifications/code-completion.swift @@ -3,12 +3,12 @@ // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.filepath: "{{.*}}SOURCE_DIR{{.*}}code-completion.swift", // COMPILE_1: key.compileid: [[CID1:".*"]] -// COMPILE_1: key.compileoperation: source.compile.operation.code-completion +// COMPILE_1: key.compile_operation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] -// COMPILE_1: key.compileoperation: source.compile.operation.code-completion +// COMPILE_1: key.compile_operation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1-NOT: compile-will-start // COMPILE_1-NOT: compile-did-finish \ No newline at end of file diff --git a/test/SourceKit/CompileNotifications/cursor-info.swift b/test/SourceKit/CompileNotifications/cursor-info.swift index 7c592b9937be1..45840c2422f5b 100644 --- a/test/SourceKit/CompileNotifications/cursor-info.swift +++ b/test/SourceKit/CompileNotifications/cursor-info.swift @@ -3,12 +3,10 @@ // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.filepath: "SOURCE_DIR{{.*}}cursor-info.swift", // COMPILE_1: key.compileid: [[CID1:".*"]] -// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] -// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: // COMPILE_1-NOT: compile-will-start diff --git a/test/SourceKit/CompileNotifications/edits.swift b/test/SourceKit/CompileNotifications/edits.swift index b130d25e785ae..23045d716739f 100644 --- a/test/SourceKit/CompileNotifications/edits.swift +++ b/test/SourceKit/CompileNotifications/edits.swift @@ -4,12 +4,10 @@ // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.compileid: [[CID1:".*"]] -// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] -// COMPILE_1: key.compileoperation: source.compile.operation.perform-sema // COMPILE_1: } // COMPILE_1-NOT: compile-will-start // COMPILE_1-NOT: compile-did-finish @@ -21,32 +19,26 @@ // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID1:".*"]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID1]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID2:".*"]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID2]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-will-start, // COMPILE_3: key.compileid: [[CID3:".*"]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3: { // COMPILE_3: key.notification: source.notification.compile-did-finish, // COMPILE_3: key.compileid: [[CID3]] -// COMPILE_3: key.compileoperation: source.compile.operation.perform-sema // COMPILE_3: } // COMPILE_3-NOT: compile-will-start // COMPILE_3-NOT: compile-did-finish diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index 7e2426aef19a9..c6a728171c403 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -3181,19 +3181,18 @@ class CompileTrackingConsumer final : public trace::TraceConsumer { }; } // end anonymous namespace -static UIdent getUIDForOperationKind(trace::OperationKind OpKind) { - static UIdent CompileOperationPerformSema("source.compile.operation.perform-sema"); +static Optional getUIDForOperationKind(trace::OperationKind OpKind) { static UIdent CompileOperationIndexSource("source.compile.operation.index-source"); static UIdent CompileOperationCodeCompletion("source.compile.operation.code-completion"); switch (OpKind) { case trace::OperationKind::PerformSema: - return CompileOperationPerformSema; + return None; case trace::OperationKind::IndexSource: return CompileOperationIndexSource; case trace::OperationKind::CodeCompletion: return CompileOperationCodeCompletion; case trace::OperationKind::All: - return CompileOperationPerformSema; + return None; } } @@ -3209,7 +3208,9 @@ void CompileTrackingConsumer::operationStarted( Dict.set(KeyNotification, CompileWillStartUID); Dict.set(KeyCompileID, std::to_string(OpId)); Dict.set(KeyFilePath, Inv.Args.PrimaryFile); - Dict.set(KeyCompileOperation, getUIDForOperationKind(OpKind)); + if (auto OperationUID = getUIDForOperationKind(OpKind)) { + Dict.set(KeyCompileOperation, OperationUID.getValue()); + } Dict.set(KeyCompilerArgsString, Inv.Args.Arguments); sourcekitd::postNotification(RespBuilder.createResponse()); } @@ -3225,7 +3226,9 @@ void CompileTrackingConsumer::operationFinished( auto Dict = RespBuilder.getDictionary(); Dict.set(KeyNotification, CompileDidFinishUID); Dict.set(KeyCompileID, std::to_string(OpId)); - Dict.set(KeyCompileOperation, getUIDForOperationKind(OpKind)); + if (auto OperationUID = getUIDForOperationKind(OpKind)) { + Dict.set(KeyCompileOperation, OperationUID.getValue()); + } auto DiagArray = Dict.setArray(KeyDiagnostics); for (const auto &DiagInfo : Diagnostics) { fillDictionaryForDiagnosticInfo(DiagArray.appendDictionary(), DiagInfo); diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py index e5114e55dd5d9..974544dbbb111 100644 --- a/utils/gyb_sourcekit_support/UIDs.py +++ b/utils/gyb_sourcekit_support/UIDs.py @@ -182,7 +182,7 @@ def __init__(self, internal_name, external_name): KEY('CompletionCheckDependencyInterval', 'key.completion_check_dependency_interval'), KEY('AnnotatedTypename', 'key.annotated.typename'), - KEY('CompileOperation', 'key.compileoperation'), + KEY('CompileOperation', 'key.compile_operation'), ] From 3e9e253acb038c32a4b9f43789bf2a49a371142a Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 18 May 2020 13:08:16 -0700 Subject: [PATCH 082/625] [ConstraintSystem] Add a new locator element - `argument attribute` `ArgumentAttribute` points to a particular attribute associated with one of the arguments e.g. `inout` or its type e.g. `@escaping`. This is very useful when dealing with argument-to-parameter failures because it allows to express in the locator kind of a problem. --- lib/Sema/ConstraintLocator.cpp | 21 +++++++++++++++++++++ lib/Sema/ConstraintLocator.h | 26 ++++++++++++++++++++++++++ lib/Sema/ConstraintLocatorPathElts.def | 8 ++++++++ 3 files changed, 55 insertions(+) diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index 3d866168d063e..10a76299ef8f9 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -57,6 +57,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, ASTNode anchor, id.AddPointer(elt.castTo().getPattern()); break; + case ArgumentAttribute: case GenericArgument: case NamedTupleElement: case TupleElement: @@ -125,6 +126,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::ImplicitCallAsFunction: case ConstraintLocator::TernaryBranch: case ConstraintLocator::PatternMatch: + case ConstraintLocator::ArgumentAttribute: return 0; case ConstraintLocator::FunctionArgument: @@ -500,6 +502,25 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const { case PatternMatch: out << "pattern match"; break; + + case ArgumentAttribute: { + using AttrLoc = LocatorPathElt::ArgumentAttribute; + + auto attrElt = elt.castTo(); + out << "argument attribute: "; + + switch (attrElt.getAttr()) { + case AttrLoc::Attribute::InOut: + out << "inout"; + break; + + case AttrLoc::Attribute::Escaping: + out << "@escaping"; + break; + } + + break; + } } } out << ']'; diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h index 625f47cab4dbb..211fe8e06ae54 100644 --- a/lib/Sema/ConstraintLocator.h +++ b/lib/Sema/ConstraintLocator.h @@ -86,6 +86,7 @@ class ConstraintLocator : public llvm::FoldingSetNode { case SynthesizedArgument: case KeyPathDynamicMember: case TernaryBranch: + case ArgumentAttribute: return 1; case TypeParameterRequirement: @@ -847,6 +848,31 @@ class LocatorPathElt::PatternMatch final : public LocatorPathElt { } }; +class LocatorPathElt::ArgumentAttribute final : public LocatorPathElt { +public: + enum Attribute : uint8_t { InOut, Escaping }; + +private: + ArgumentAttribute(Attribute attr) + : LocatorPathElt(ConstraintLocator::ArgumentAttribute, + static_cast(attr)) {} + +public: + Attribute getAttr() const { return static_cast(getValue(0)); } + + static ArgumentAttribute forInOut() { + return ArgumentAttribute(Attribute::InOut); + } + + static ArgumentAttribute forEscaping() { + return ArgumentAttribute(Attribute::Escaping); + } + + static bool classof(const LocatorPathElt *elt) { + return elt->getKind() == ConstraintLocator::ArgumentAttribute; + } +}; + /// A simple stack-only builder object that constructs a /// constraint locator without allocating memory. /// diff --git a/lib/Sema/ConstraintLocatorPathElts.def b/lib/Sema/ConstraintLocatorPathElts.def index 3cb6923cf8265..856b13bac83e5 100644 --- a/lib/Sema/ConstraintLocatorPathElts.def +++ b/lib/Sema/ConstraintLocatorPathElts.def @@ -181,6 +181,14 @@ CUSTOM_LOCATOR_PATH_ELT(TernaryBranch) /// Performing a pattern patch. CUSTOM_LOCATOR_PATH_ELT(PatternMatch) +/// Points to a particular attribute associated with one of +/// the arguments e.g. `inout` or its type e.g. `@escaping`. +/// +/// This is very useful when dealing with argument-to-parameter +/// failures because it allows to express in the locator kind +/// of a problem. +CUSTOM_LOCATOR_PATH_ELT(ArgumentAttribute) + #undef LOCATOR_PATH_ELT #undef CUSTOM_LOCATOR_PATH_ELT #undef SIMPLE_LOCATOR_PATH_ELT From 3efa052aae8d03b0795f0e8948f970ff14502975 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 18 May 2020 13:09:56 -0700 Subject: [PATCH 083/625] [Diagnostics] Adjust r-value -> l-value diagnostic to account for `ArgumentAttribute` --- lib/Sema/CSDiagnostics.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 38934e2e096ca..6900f5bd38989 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -1239,6 +1239,14 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() { if (auto callExpr = dyn_cast(diagExpr)) { Expr *argExpr = callExpr->getArg(); loc = callExpr->getFn()->getLoc(); + auto *locator = getLocator(); + + // `argument attribute` is used for identification purposes + // only, so it could be looked through in this situation. + if (locator->isLastElement()) { + auto path = locator->getPath(); + locator = getConstraintLocator(getRawAnchor(), path.drop_back()); + } if (isa(callExpr) || isa(callExpr)) { subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement; @@ -1247,16 +1255,14 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() { } else if (isa(callExpr)) { subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement; rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue; - auto argTuple = dyn_cast(argExpr); - diagExpr = argTuple->getElement(0); - } else if (getLocator()->getPath().size() > 0) { - auto argElt = - getLocator()->castLastElementTo(); - + diagExpr = castToExpr(simplifyLocatorToAnchor(locator)); + } else if (auto argElt = + locator + ->getLastElementAs()) { subElementDiagID = diag::cannot_pass_rvalue_inout_subelement; rvalueDiagID = diag::cannot_pass_rvalue_inout; if (auto argTuple = dyn_cast(argExpr)) - diagExpr = argTuple->getElement(argElt.getArgIdx()); + diagExpr = argTuple->getElement(argElt->getArgIdx()); else if (auto parens = dyn_cast(argExpr)) diagExpr = parens->getSubExpr(); } else { From 9347a091e112b8d65b723f917c1e9ce88344c7c4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 18 May 2020 13:10:26 -0700 Subject: [PATCH 084/625] [ConstraintSystem] Adjust `getCalleeLocator` and `simplifyLocator` to handle `ArgumentAttribute` - `getCalleeLocator`, if given locator ends at `ArgumentAttribute` strip the last element which makes sure that produced locator always refers directly to argument-to-parameter conversion. - `simplifyLocator`, always leave `ArgumentAttribute` in the path because it's useful for diagnostics. --- lib/Sema/ConstraintSystem.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index bde7cfa464cb4..316b90be2d775 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -462,6 +462,10 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator( return getConstraintLocator(anchor, LocatorPathElt::ApplyFunction()); } + if (locator->isLastElement()) { + return getConstraintLocator(anchor, path.drop_back()); + } + // If we have a locator that starts with a key path component element, we // may have a callee given by a property or subscript component. if (auto componentElt = @@ -3527,6 +3531,13 @@ void constraints::simplifyLocator(ASTNode &anchor, continue; } + case ConstraintLocator::ArgumentAttribute: { + // At this point we should have already found argument expression + // this attribute belogs to, so we can leave this element in place + // because it points out exact location useful for diagnostics. + break; + } + default: // FIXME: Lots of other cases to handle. break; From 5db1c70cd019f57ff59149a978bb7300b2de3307 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 18 May 2020 13:13:59 -0700 Subject: [PATCH 085/625] [CSFix] Extend locator with `ArgumentAttribute` for escaping/inout fixes If either `MarkExplicitlyEscaping` or `TreatRValueAsLValue` fix points to an argument-to-parameter conversion, let's add more more clarifying argument to the locator to pinpoint the problem. --- lib/Sema/CSFix.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 29d3f6006c529..c3875c5500cf9 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -119,6 +119,10 @@ bool TreatRValueAsLValue::diagnose(const Solution &solution, TreatRValueAsLValue *TreatRValueAsLValue::create(ConstraintSystem &cs, ConstraintLocator *locator) { + if (locator->isLastElement()) + locator = cs.getConstraintLocator( + locator, LocatorPathElt::ArgumentAttribute::forInOut()); + return new (cs.getAllocator()) TreatRValueAsLValue(cs, locator); } @@ -168,6 +172,10 @@ bool MarkExplicitlyEscaping::diagnose(const Solution &solution, MarkExplicitlyEscaping * MarkExplicitlyEscaping::create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator) { + if (locator->isLastElement()) + locator = cs.getConstraintLocator( + locator, LocatorPathElt::ArgumentAttribute::forEscaping()); + return new (cs.getAllocator()) MarkExplicitlyEscaping(cs, lhs, rhs, locator); } From 6216242c9cb77423bf355db9876910a874d4ac5e Mon Sep 17 00:00:00 2001 From: Greg Titus Date: Mon, 18 May 2020 13:40:29 -0700 Subject: [PATCH 086/625] If the missing generic requirement includes type variables, don't emit an unhelpful note for it. Fixes SR-12759 --- lib/Sema/TypeCheckProtocol.cpp | 3 ++ .../protocol/req/missing_conformance.swift | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 0de8b1ceee583..64d4e772bd0e9 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -784,6 +784,9 @@ static Optional findMissingGenericRequirementForSolutionFix( default: return Optional(); } + + if (missingType->hasTypeVariable()) + return Optional(); auto missingRequirementMatch = [&](Type type) -> RequirementMatch { Requirement requirement(requirementKind, type, missingType); diff --git a/test/decl/protocol/req/missing_conformance.swift b/test/decl/protocol/req/missing_conformance.swift index 74d09e2621d5a..c838d20cd8557 100644 --- a/test/decl/protocol/req/missing_conformance.swift +++ b/test/decl/protocol/req/missing_conformance.swift @@ -110,3 +110,31 @@ struct S3 : P12 { // expected-error {{type 'S3' does not conform to protocol 'P1 // expected-note@-1 {{candidate can not infer 'A' = 'P11' because 'P11' is not a nominal type and so can't conform to 'P11'}} } +// SR-12759 +struct CountSteps1 : Collection { + init(count: Int) { self.count = count } + var count: Int + + var startIndex: Int { 0 } + var endIndex: Int { count } + func index(after i: Int) -> Int { + totalSteps += 1 // expected-error {{cannot find 'totalSteps' in scope}} + return i + 1 + } + subscript(i: Int) -> Int { return i } +} + +extension CountSteps1 // expected-error {{type 'CountSteps1' does not conform to protocol 'RandomAccessCollection'}} + // expected-error@-1 {{conditional conformance of type 'CountSteps1' to protocol 'RandomAccessCollection' does not imply conformance to inherited protocol 'BidirectionalCollection'}} + // expected-note@-2 {{did you mean to explicitly state the conformance like 'extension CountSteps1: BidirectionalCollection where ...'?}} + // expected-error@-3 {{type 'CountSteps1' does not conform to protocol 'BidirectionalCollection'}} + : RandomAccessCollection + where T : Equatable +{ + typealias Index = Int + func index(_ i: Index, offsetBy d: Int) -> Index { + return i + d + } +} + + From 917c937fc9bba57b5891169efea79ae8f51452aa Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 May 2020 14:33:41 -0700 Subject: [PATCH 087/625] Allow shadowing checks to deal with operator decls Add overloads of `removeShadowedDecls` that deal with operator and precedencegroup decls, and template the existing shadowing logic such that it can process them. --- include/swift/AST/Decl.h | 8 ++++ include/swift/AST/NameLookup.h | 20 ++++++++++ lib/AST/NameLookup.cpp | 68 ++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index eb6af822e7ab7..b1fdf5451c56d 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -7048,6 +7048,10 @@ class PrecedenceGroupDecl : public Decl { return Name; } + // This is needed to allow templated code to work with both ValueDecls and + // PrecedenceGroupDecls. + DeclBaseName getBaseName() const { return Name; } + SourceLoc getLBraceLoc() const { return LBraceLoc; } SourceLoc getRBraceLoc() const { return RBraceLoc; } @@ -7205,6 +7209,10 @@ class OperatorDecl : public Decl { SourceLoc getNameLoc() const { return NameLoc; } Identifier getName() const { return name; } + // This is needed to allow templated code to work with both ValueDecls and + // OperatorDecls. + DeclBaseName getBaseName() const { return name; } + /// Get the list of identifiers after the colon in the operator declaration. /// /// This list includes the names of designated types. For infix operators, the diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 911a259dd0135..544b5b9bdf54c 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -455,6 +455,26 @@ bool removeOverriddenDecls(SmallVectorImpl &decls); bool removeShadowedDecls(SmallVectorImpl &decls, const DeclContext *dc); +/// Remove any operators in the given set that are shadowed by +/// other operators in that set. +/// +/// \param decls The set of operators being considered. +/// \param dc The DeclContext from which the lookup was performed. +/// +/// \returns true if any shadowed declarations were removed. +bool removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc); + +/// Remove any precedence groups in the given set that are shadowed by +/// other precedence groups in that set. +/// +/// \param decls The set of precedence groups being considered. +/// \param dc The DeclContext from which the lookup was performed. +/// +/// \returns true if any shadowed declarations were removed. +bool removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc); + /// Finds decls visible in the given context and feeds them to the given /// VisibleDeclConsumer. If the current DeclContext is nested in a function, /// the SourceLoc is used to determine which declarations in that function diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index b6b2e577d00d6..5cdcb59602aa2 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -247,10 +247,10 @@ static ConstructorComparison compareConstructors(ConstructorDecl *ctor1, /// Given a set of declarations whose names and signatures have matched, /// figure out which of these declarations have been shadowed by others. -static void recordShadowedDeclsAfterSignatureMatch( - ArrayRef decls, - const DeclContext *dc, - llvm::SmallPtrSetImpl &shadowed) { +template +static void +recordShadowedDeclsAfterSignatureMatch(ArrayRef decls, const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { assert(decls.size() > 1 && "Nothing collided"); // Compare each declaration to every other declaration. This is @@ -354,9 +354,9 @@ static void recordShadowedDeclsAfterSignatureMatch( // This is due to the fact that in Swift 4, we only gave custom overload // types to properties in extensions of generic types, otherwise we // used the null type. - if (!ctx.isSwiftVersionAtLeast(5)) { - auto secondSig = secondDecl->getOverloadSignature(); - auto firstSig = firstDecl->getOverloadSignature(); + if (!ctx.isSwiftVersionAtLeast(5) && isa(firstDecl)) { + auto secondSig = cast(secondDecl)->getOverloadSignature(); + auto firstSig = cast(firstDecl)->getOverloadSignature(); if (firstSig.IsVariable && secondSig.IsVariable) if (firstSig.InExtensionOfGenericType != secondSig.InExtensionOfGenericType) @@ -583,8 +583,8 @@ static void recordShadowedDecls(ArrayRef decls, // Check whether we have shadowing for signature collisions. for (auto signature : collisionTypes) { - recordShadowedDeclsAfterSignatureMatch(collisions[signature], dc, - shadowed); + ArrayRef collidingDecls = collisions[signature]; + recordShadowedDeclsAfterSignatureMatch(collidingDecls, dc, shadowed); } // Check whether we have shadowing for imported initializer collisions. @@ -594,11 +594,25 @@ static void recordShadowedDecls(ArrayRef decls, } } -bool swift::removeShadowedDecls(SmallVectorImpl &decls, - const DeclContext *dc) { +static void +recordShadowedDecls(ArrayRef decls, const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { + // Always considered to have the same signature. + recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed); +} + +static void +recordShadowedDecls(ArrayRef decls, + const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { + // Always considered to have the same signature. + recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed); +} + +template +static bool removeShadowedDeclsImpl(Container &decls, const DeclContext *dc) { // Collect declarations with the same (full) name. - llvm::SmallDenseMap> - collidingDeclGroups; + llvm::SmallDenseMap> collidingDeclGroups; bool anyCollisions = false; for (auto decl : decls) { // Record this declaration based on its full name. @@ -614,7 +628,7 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, return false; // Walk through the declarations again, marking any declarations that shadow. - llvm::SmallPtrSet shadowed; + llvm::SmallPtrSet shadowed; for (auto decl : decls) { auto known = collidingDeclGroups.find(decl->getName()); if (known == collidingDeclGroups.end()) { @@ -633,8 +647,8 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, // Remove shadowed declarations from the list of declarations. bool anyRemoved = false; decls.erase(std::remove_if(decls.begin(), decls.end(), - [&](ValueDecl *vd) { - if (shadowed.count(vd) > 0) { + [&](T decl) { + if (shadowed.count(decl) > 0) { anyRemoved = true; return true; } @@ -646,6 +660,28 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, return anyRemoved; } +bool swift::removeShadowedDecls(SmallVectorImpl &decls, + const DeclContext *dc) { + return removeShadowedDeclsImpl(decls, dc); +} + +bool swift::removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc) { +#ifndef NDEBUG + // Make sure all the operators have the same fixity. + if (decls.size() > 1) { + for (auto *op : decls) + assert(op->getFixity() == decls[0]->getFixity()); + } +#endif + return removeShadowedDeclsImpl(decls, dc); +} + +bool swift::removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc) { + return removeShadowedDeclsImpl(decls, dc); +} + namespace { enum class DiscriminatorMatch { NoDiscriminator, From 54df0a4e8d0fe3000eb4972b13212486f3fbe5ee Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 May 2020 14:33:42 -0700 Subject: [PATCH 088/625] [Frontend] Add flag to enable new operator lookup For now disabled by default, but once we get a new language mode, we should flip it on by default. --- include/swift/Basic/LangOptions.h | 4 ++++ include/swift/Option/FrontendOptions.td | 8 ++++++++ lib/Frontend/CompilerInvocation.cpp | 3 +++ 3 files changed, 15 insertions(+) diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 4aa154527254c..ee67a287fa82c 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -267,6 +267,10 @@ namespace swift { /// Build the ASTScope tree lazily bool LazyASTScopes = true; + /// Whether to enable the new operator decl and precedencegroup lookup + /// behavior. This is a staging flag, and will be removed in the future. + bool EnableNewOperatorLookup = false; + /// Use Clang function types for computing canonical types. /// If this option is false, the clang function types will still be computed /// but will not be used for checking type equality. diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c8168fde7d545..5f21197687f34 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -483,6 +483,14 @@ def disable_invalid_ephemeralness_as_error : def switch_checking_invocation_threshold_EQ : Joined<["-"], "switch-checking-invocation-threshold=">; +def enable_new_operator_lookup : + Flag<["-"], "enable-new-operator-lookup">, + HelpText<"Enable the new operator decl and precedencegroup lookup behavior">; + +def disable_new_operator_lookup : + Flag<["-"], "disable-new-operator-lookup">, + HelpText<"Disable the new operator decl and precedencegroup lookup behavior">; + def enable_source_import : Flag<["-"], "enable-source-import">, HelpText<"Enable importing of Swift source files">; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d26dd923dfbbe..0d79955319d34 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -409,6 +409,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.StressASTScopeLookup |= Args.hasArg(OPT_stress_astscope_lookup); Opts.WarnIfASTScopeLookup |= Args.hasArg(OPT_warn_if_astscope_lookup); Opts.LazyASTScopes |= Args.hasArg(OPT_lazy_astscopes); + Opts.EnableNewOperatorLookup = Args.hasFlag(OPT_enable_new_operator_lookup, + OPT_disable_new_operator_lookup, + /*default*/ false); Opts.UseClangFunctionTypes |= Args.hasArg(OPT_use_clang_function_types); Opts.NamedLazyMemberLoading &= !Args.hasArg(OPT_disable_named_lazy_member_loading); From 912baa8a8b503b723cfb36576202cf23bd73eeba Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 May 2020 14:33:42 -0700 Subject: [PATCH 089/625] [Serialization] Use direct operator lookup for xrefs We don't need to look at re-exports when resolving cross references. Luckily the old lookup logic didn't, but the new logic will. Therefore switch it over to calling the appropriate request for a direct operator lookup. In addition, return a deserialization error instead of silently returning nullptr if the lookup fails. --- lib/Serialization/Deserialization.cpp | 28 +++++++++++++++++++++------ lib/Serialization/ModuleFormat.h | 15 ++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ef371a520ce13..94403b6c8a8b5 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1364,19 +1364,35 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { Identifier opName = getIdentifier(IID); pathTrace.addOperator(opName); + auto &ctx = getContext(); + auto desc = OperatorLookupDescriptor::forModule(baseModule, opName); switch (rawOpKind) { case OperatorKind::Infix: - return baseModule->lookupInfixOperator(opName); case OperatorKind::Prefix: - return baseModule->lookupPrefixOperator(opName); - case OperatorKind::Postfix: - return baseModule->lookupPostfixOperator(opName); - case OperatorKind::PrecedenceGroup: - return baseModule->lookupPrecedenceGroup(opName); + case OperatorKind::Postfix: { + auto req = DirectOperatorLookupRequest{ + desc, getASTOperatorFixity(static_cast(rawOpKind))}; + auto results = evaluateOrDefault(ctx.evaluator, req, {}); + if (results.size() != 1) { + return llvm::make_error("operator not found", pathTrace, + opName); + } + return results[0]; + } + case OperatorKind::PrecedenceGroup: { + auto results = evaluateOrDefault( + ctx.evaluator, DirectPrecedenceGroupLookupRequest{desc}, {}); + if (results.size() != 1) { + return llvm::make_error("precedencegroup not found", + pathTrace, opName); + } + return results[0]; + } default: // Unknown operator kind. fatal(); } + llvm_unreachable("Unhandled case in switch!"); } case XREF_GENERIC_PARAM_PATH_PIECE: diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index f338cde1562f1..09f53e1658124 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -401,6 +401,21 @@ static inline OperatorKind getStableFixity(OperatorFixity fixity) { llvm_unreachable("Unhandled case in switch"); } +/// Translates a stable Serialization fixity back to an AST operator fixity. +static inline OperatorFixity getASTOperatorFixity(OperatorKind fixity) { + switch (fixity) { + case Prefix: + return OperatorFixity::Prefix; + case Postfix: + return OperatorFixity::Postfix; + case Infix: + return OperatorFixity::Infix; + case PrecedenceGroup: + llvm_unreachable("Not an operator kind"); + } + llvm_unreachable("Unhandled case in switch"); +} + // These IDs must \em not be renumbered or reordered without incrementing // the module version. enum GenericRequirementKind : uint8_t { From cc062ee2bb96c4624dc787e394f021f5258ae804 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 May 2020 14:33:43 -0700 Subject: [PATCH 090/625] Fix precedencegroup and operator decl lookup Re-implement operator and precedencegroup decl lookup to use `namelookup::getAllImports` and existing decl shadowing logic. This allows us to find operator decls through `@_exported` imports, prefer operator decls defined in the same module over imported decls, and fixes a couple of other subtle issues. Because this new implementation is technically source breaking, as we can find multiple results where we used to only find one result, it's placed behind the new Frontend flag `-enable-new-operator-lookup` (with the aim of enabling it by default when we get a new language mode). However the new logic will always be used if the result is unambiguous. This means that e.g `@_exported` operators will be instantly available as long as there's only one candidate. If multiple candidates are found, we fall back to the old logic. Resolves SR-12132. Resolves rdar://59198796. --- include/swift/AST/Decl.h | 18 -- include/swift/AST/DeclContext.h | 29 +++ include/swift/AST/Module.h | 15 -- include/swift/AST/NameLookupRequests.h | 139 ++++++---- include/swift/AST/NameLookupTypeIDZone.def | 4 +- include/swift/AST/OperatorNameLookup.h | 127 +++++++++ include/swift/AST/SourceFile.h | 2 - include/swift/AST/TypeCheckRequests.h | 5 +- lib/AST/CMakeLists.txt | 1 + lib/AST/Module.cpp | 240 ----------------- lib/AST/NameLookupRequests.cpp | 13 +- lib/AST/OperatorNameLookup.cpp | 243 ++++++++++++++++++ lib/Sema/CSApply.cpp | 12 +- lib/Sema/CSDiagnostics.h | 5 +- lib/Sema/TypeCheckDecl.cpp | 134 ++++------ lib/Sema/TypeCheckDeclPrimary.cpp | 4 +- lib/Sema/TypeCheckExpr.cpp | 27 +- lib/Sema/TypeChecker.h | 4 +- lib/Serialization/ModuleFile.cpp | 3 - .../Inputs/lookup_other_noncompat.swift | 5 + .../operator/Inputs/redeclaration_other.swift | 10 + test/decl/operator/lookup.swift | 113 ++++++++ test/decl/operator/lookup_compatibility.swift | 29 +-- test/decl/operator/redeclaration.swift | 31 +++ 24 files changed, 761 insertions(+), 452 deletions(-) create mode 100644 include/swift/AST/OperatorNameLookup.h create mode 100644 lib/AST/OperatorNameLookup.cpp create mode 100644 test/decl/operator/Inputs/lookup_other_noncompat.swift create mode 100644 test/decl/operator/Inputs/redeclaration_other.swift create mode 100644 test/decl/operator/lookup.swift create mode 100644 test/decl/operator/redeclaration.swift diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index b1fdf5451c56d..632eca1c9120c 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -7273,12 +7273,6 @@ class InfixOperatorDecl : public OperatorDecl { PrecedenceGroupDecl *getPrecedenceGroup() const; - /// True if this decl's attributes conflict with those declared by another - /// operator. - bool conflictsWith(InfixOperatorDecl *other) { - return getPrecedenceGroup() != other->getPrecedenceGroup(); - } - static bool classof(const Decl *D) { return D->getKind() == DeclKind::InfixOperator; } @@ -7307,12 +7301,6 @@ class PrefixOperatorDecl : public OperatorDecl { return { getOperatorLoc(), getNameLoc() }; } - /// True if this decl's attributes conflict with those declared by another - /// PrefixOperatorDecl. - bool conflictsWith(PrefixOperatorDecl *other) { - return false; - } - static bool classof(const Decl *D) { return D->getKind() == DeclKind::PrefixOperator; } @@ -7340,12 +7328,6 @@ class PostfixOperatorDecl : public OperatorDecl { SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; } - - /// True if this decl's attributes conflict with those declared by another - /// PostfixOperatorDecl. - bool conflictsWith(PostfixOperatorDecl *other) { - return false; - } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PostfixOperator; diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index 70dcf0aaabb2b..223d9c0cbbc81 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -54,6 +54,9 @@ namespace swift { class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; + class InfixOperatorDecl; + class InfixOperatorLookupResult; + class PrecedenceGroupDecl; class ProtocolDecl; class Requirement; class SourceFile; @@ -61,6 +64,9 @@ namespace swift { class ModuleDecl; class GenericTypeDecl; class NominalTypeDecl; + class PrecedenceGroupLookupResult; + class PostfixOperatorDecl; + class PrefixOperatorDecl; class ProtocolConformance; class ValueDecl; class Initializer; @@ -561,6 +567,29 @@ class alignas(1 << DeclContextAlignInBits) DeclContext { ObjCSelector selector, SmallVectorImpl &results) const; + /// Looks up an infix operator with a given \p name. + /// + /// This returns a vector of results, as it's possible to find multiple infix + /// operators with different precedence groups. + InfixOperatorLookupResult lookupInfixOperator(Identifier name) const; + + /// Looks up an prefix operator with a given \p name. + /// + /// If multiple results are found, one is chosen in a stable manner, as + /// prefix operator decls cannot differ other than in name. If no results are + /// found, returns \c nullptr. + PrefixOperatorDecl *lookupPrefixOperator(Identifier name) const; + + /// Looks up an postfix operator with a given \p name. + /// + /// If multiple results are found, one is chosen in a stable manner, as + /// postfix operator decls cannot differ other than in name. If no results are + /// found, returns \c nullptr. + PostfixOperatorDecl *lookupPostfixOperator(Identifier name) const; + + /// Looks up a precedence group with a given \p name. + PrecedenceGroupLookupResult lookupPrecedenceGroup(Identifier name) const; + /// Return the ASTContext for a specified DeclContext by /// walking up to the enclosing module and returning its ASTContext. LLVM_READONLY diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index c5a70a6e66773..0f4b5a2b8597d 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -592,21 +592,6 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// FIXME: Remove the integrated REPL. void clearLookupCache(); - /// @{ - - /// Look up the given operator in this module. - /// - /// If the operator is not found, or if there is an ambiguity, returns null. - InfixOperatorDecl *lookupInfixOperator(Identifier name, - SourceLoc diagLoc = {}); - PrefixOperatorDecl *lookupPrefixOperator(Identifier name, - SourceLoc diagLoc = {}); - PostfixOperatorDecl *lookupPostfixOperator(Identifier name, - SourceLoc diagLoc = {}); - PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name, - SourceLoc diagLoc = {}); - /// @} - /// Finds all class members defined in this module. /// /// This does a simple local lookup, not recursively looking through imports. diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index df8c0dea04179..af893196fe5f7 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -594,14 +594,10 @@ class OperatorLookupDescriptor final { using Storage = llvm::PointerUnion; Storage fileOrModule; Identifier name; - bool isCascading; - SourceLoc diagLoc; private: - OperatorLookupDescriptor(Storage fileOrModule, Identifier name, - bool isCascading, SourceLoc diagLoc) - : fileOrModule(fileOrModule), name(name), isCascading(isCascading), - diagLoc(diagLoc) {} + OperatorLookupDescriptor(Storage fileOrModule, Identifier name) + : fileOrModule(fileOrModule), name(name) {} public: /// Retrieves the files to perform lookup in. @@ -613,14 +609,20 @@ class OperatorLookupDescriptor final { return fileOrModule.dyn_cast(); } + /// Retrieve the file or module for the lookup, as a DeclContext. + DeclContext *getDC() const { + if (auto *module = getModule()) + return module; + return fileOrModule.get(); + } + friend llvm::hash_code hash_value(const OperatorLookupDescriptor &desc) { - return llvm::hash_combine(desc.fileOrModule, desc.name, desc.isCascading); + return llvm::hash_combine(desc.fileOrModule, desc.name); } friend bool operator==(const OperatorLookupDescriptor &lhs, const OperatorLookupDescriptor &rhs) { - return lhs.fileOrModule == rhs.fileOrModule && lhs.name == rhs.name && - lhs.isCascading == rhs.isCascading; + return lhs.fileOrModule == rhs.fileOrModule && lhs.name == rhs.name; } friend bool operator!=(const OperatorLookupDescriptor &lhs, @@ -628,16 +630,15 @@ class OperatorLookupDescriptor final { return !(lhs == rhs); } - static OperatorLookupDescriptor forFile(FileUnit *file, Identifier name, - bool isCascading, SourceLoc diagLoc) { - return OperatorLookupDescriptor(file, name, isCascading, diagLoc); + static OperatorLookupDescriptor forFile(FileUnit *file, Identifier name) { + return OperatorLookupDescriptor(file, name); } - static OperatorLookupDescriptor forModule(ModuleDecl *mod, Identifier name, - bool isCascading, - SourceLoc diagLoc) { - return OperatorLookupDescriptor(mod, name, isCascading, diagLoc); + static OperatorLookupDescriptor forModule(ModuleDecl *mod, Identifier name) { + return OperatorLookupDescriptor(mod, name); } + + static OperatorLookupDescriptor forDC(const DeclContext *DC, Identifier name); }; void simple_display(llvm::raw_ostream &out, @@ -645,34 +646,6 @@ void simple_display(llvm::raw_ostream &out, SourceLoc extractNearestSourceLoc(const OperatorLookupDescriptor &desc); -template -class LookupOperatorRequest - : public SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached> { - using SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached>::SimpleRequest; - -private: - friend SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached>; - - // Evaluation. - OperatorType *evaluate(Evaluator &evaluator, - OperatorLookupDescriptor desc) const; - -public: - // Cached. - bool isCached() const { return true; } -}; - -using LookupPrefixOperatorRequest = LookupOperatorRequest; -using LookupInfixOperatorRequest = LookupOperatorRequest; -using LookupPostfixOperatorRequest = LookupOperatorRequest; -using LookupPrecedenceGroupRequest = LookupOperatorRequest; - /// Looks up an operator in a given file or module without looking through /// imports. class DirectOperatorLookupRequest @@ -770,6 +743,84 @@ class LookupConformanceInModuleRequest ProtocolConformanceRef result) const; }; +/// Look up an 'infix operator' decl by name. +class LookupInfixOperatorRequest + : public SimpleRequest( + OperatorLookupDescriptor), + RequestFlags::Cached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + TinyPtrVector + evaluate(Evaluator &evaluator, OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up an 'prefix operator' decl by name. +class LookupPrefixOperatorRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + PrefixOperatorDecl *evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up an 'postfix operator' decl by name. +class LookupPostfixOperatorRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + PostfixOperatorDecl *evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up a precedencegroup decl by name. +class LookupPrecedenceGroupRequest + : public SimpleRequest( + OperatorLookupDescriptor), + RequestFlags::Cached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + TinyPtrVector + evaluate(Evaluator &evaluator, OperatorLookupDescriptor descriptor) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + #define SWIFT_TYPEID_ZONE NameLookup #define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/AST/NameLookupTypeIDZone.def b/include/swift/AST/NameLookupTypeIDZone.def index de346c54f8806..b67a2bbabe078 100644 --- a/include/swift/AST/NameLookupTypeIDZone.def +++ b/include/swift/AST/NameLookupTypeIDZone.def @@ -89,11 +89,11 @@ SWIFT_REQUEST(NameLookup, LookupPrefixOperatorRequest, PrefixOperatorDecl *(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupInfixOperatorRequest, - InfixOperatorDecl *(OperatorLookupDescriptor), + TinyPtrVector(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupPostfixOperatorRequest, PostfixOperatorDecl *(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupPrecedenceGroupRequest, - PrecedenceGroupDecl *(OperatorLookupDescriptor), + TinyPtrVector(OperatorLookupDescriptor), Cached, NoLocationInfo) diff --git a/include/swift/AST/OperatorNameLookup.h b/include/swift/AST/OperatorNameLookup.h new file mode 100644 index 0000000000000..6cea9e69e7d26 --- /dev/null +++ b/include/swift/AST/OperatorNameLookup.h @@ -0,0 +1,127 @@ +//===--- OperatorNameLookup.h - Operator and Precedence Lookup --*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 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 interfaces for looking up operator and precedence group +// declarations. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_AST_OPERATOR_NAME_LOOKUP_H +#define SWIFT_AST_OPERATOR_NAME_LOOKUP_H + +#include "swift/AST/Identifier.h" +#include "swift/AST/Module.h" +#include "llvm/ADT/TinyPtrVector.h" + +namespace swift { + +/// Base class for infix operator and precedence group lookup results. +template +class OperatorLookupResultBase { +protected: + const DeclContext *ModuleDC; + Identifier Name; + TinyPtrVector Results; + +private: + const Derived &asDerived() const { + return *static_cast(this); + } + +public: + OperatorLookupResultBase(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : ModuleDC(moduleDC), Name(name), Results(std::move(results)) {} + + /// Retrieve the underlying results vector. + TinyPtrVector get() && { return std::move(Results); } + + /// If the lookup produced a single result, returns it. Otherwise returns + /// \c nullptr. + DeclTy *getSingle() const { + return Results.size() == 1 ? Results[0] : nullptr; + } + + /// If the lookup produced a single result, returns it. Otherwise, emits an + /// ambiguity or missing decl diagnostic, and returns \c nullptr. + DeclTy *getSingleOrDiagnose(SourceLoc loc, bool forBuiltin = false) const { + if (auto single = getSingle()) + return single; + + if (isAmbiguous()) { + asDerived().diagnoseAmbiguity(loc); + } else { + assert(!hasResults()); + asDerived().diagnoseMissing(loc, forBuiltin); + } + return nullptr; + } + + using const_iterator = typename decltype(Results)::const_iterator; + const_iterator begin() const { return Results.begin(); } + const_iterator end() const { return Results.end(); } + + /// Whether the lookup produced at least one result. + bool hasResults() const { return !Results.empty(); } + + /// Whether the lookup produced multiple ambiguous results. + bool isAmbiguous() const { return Results.size() > 1; } + + friend bool operator==(const OperatorLookupResultBase &lhs, + const OperatorLookupResultBase &rhs) { + return lhs.Results == rhs.Results; + } + friend bool operator!=(const OperatorLookupResultBase &lhs, + const OperatorLookupResultBase &rhs) { + return !(lhs == rhs); + } + friend void simple_display(llvm::raw_ostream &out, + const OperatorLookupResultBase &result) { + simple_display(out, result.Results); + } +}; + +/// The result of a precedence group lookup. +class PrecedenceGroupLookupResult final + : public OperatorLookupResultBase { + friend class OperatorLookupResultBase; + +public: + PrecedenceGroupLookupResult(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} + + void diagnoseAmbiguity(SourceLoc loc) const; + void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; +}; + +/// The result of an infix operator lookup. +class InfixOperatorLookupResult final + : public OperatorLookupResultBase { + friend class OperatorLookupResultBase; + +public: + InfixOperatorLookupResult(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} + + void diagnoseAmbiguity(SourceLoc loc) const; + void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; +}; + +} // end namespace swift + +#endif diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 820af1095f4e9..844c1e57baf79 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -30,7 +30,6 @@ class SourceFile final : public FileUnit { friend class ParseSourceFileRequest; public: - class Impl; struct SourceFileSyntaxInfo; /// Possible attributes for imports in source files. @@ -198,7 +197,6 @@ class SourceFile final : public FileUnit { ParserStatePtr(/*ptr*/ nullptr, /*deleter*/ nullptr); friend ASTContext; - friend Impl; public: /// Appends the given declaration to the end of the top-level decls list. Do diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 4889f32160f5e..d1912a6d3a36e 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1531,7 +1531,8 @@ void simple_display(llvm::raw_ostream &out, const PrecedenceGroupDescriptor &d); class ValidatePrecedenceGroupRequest : public SimpleRequest( + PrecedenceGroupDescriptor), RequestFlags::Cached> { public: using SimpleRequest::SimpleRequest; @@ -1540,7 +1541,7 @@ class ValidatePrecedenceGroupRequest friend SimpleRequest; // Evaluation. - PrecedenceGroupDecl * + TinyPtrVector evaluate(Evaluator &evaluator, PrecedenceGroupDescriptor descriptor) const; public: diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 5be2d5ae2bfd1..d3b8062e5e51d 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -61,6 +61,7 @@ add_swift_host_library(swiftAST STATIC ModuleNameLookup.cpp NameLookup.cpp NameLookupRequests.cpp + OperatorNameLookup.cpp Parameter.cpp Pattern.cpp PlatformKind.cpp diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c8a667ebe38ab..46d51a4be12d6 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1051,72 +1051,6 @@ LookupConformanceInModuleRequest::evaluate( return ProtocolConformanceRef(conformance); } -namespace { - template - struct OperatorLookup { - // Don't fold this into the static_assert: this would trigger an MSVC bug - // that causes the assertion to fail. - static constexpr T* ptr = static_cast(nullptr); - static_assert(ptr, "Only usable with operators"); - }; - - template <> - struct OperatorLookup { - static PrefixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // We can return the first prefix operator. All prefix operators of the - // same name are equivalent. - DirectOperatorLookupRequest req{desc, OperatorFixity::Prefix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static InfixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // Return the first result if it exists. - DirectOperatorLookupRequest req{desc, OperatorFixity::Infix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static PostfixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // We can return the first postfix operator. All postfix operators of the - // same name are equivalent. - DirectOperatorLookupRequest req{desc, OperatorFixity::Postfix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static PrecedenceGroupDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // Return the first result if it exists. - auto results = - evaluateOrDefault(eval, DirectPrecedenceGroupLookupRequest{desc}, {}); - return results.empty() ? nullptr : results[0]; - } - }; -} // end anonymous namespace - -/// A helper class to sneak around C++ access control rules. -class SourceFile::Impl { -public: - /// Only intended for use by lookupOperatorDeclForName. - static ArrayRef - getImportsForSourceFile(const SourceFile &SF) { - return *SF.Imports; - } -}; - struct SourceFile::SourceFileSyntaxInfo { const bool Enable; /// The root of the syntax tree representing the source file. @@ -1137,180 +1071,6 @@ void SourceFile::setSyntaxRoot(syntax::SourceFileSyntax &&Root) { SyntaxInfo->SyntaxRoot.emplace(Root); } -template -static Optional -lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name, - bool isCascading); - -template -using ImportedOperatorsMap = llvm::SmallDenseMap; - -template -static typename ImportedOperatorsMap::iterator -checkOperatorConflicts(const SourceFile &SF, SourceLoc loc, - ImportedOperatorsMap &importedOperators) { - // Check for conflicts. - auto i = importedOperators.begin(), end = importedOperators.end(); - auto start = i; - for (++i; i != end; ++i) { - if (i->first->conflictsWith(start->first)) { - if (loc.isValid()) { - ASTContext &C = SF.getASTContext(); - C.Diags.diagnose(loc, diag::ambiguous_operator_decls); - start->first->diagnose(diag::found_this_operator_decl); - i->first->diagnose(diag::found_this_operator_decl); - } - return end; - } - } - return start; -} - -template<> -typename ImportedOperatorsMap::iterator -checkOperatorConflicts(const SourceFile &SF, SourceLoc loc, - ImportedOperatorsMap &importedGroups) { - if (importedGroups.size() == 1) - return importedGroups.begin(); - - // Any sort of ambiguity is an error. - if (loc.isValid()) { - ASTContext &C = SF.getASTContext(); - C.Diags.diagnose(loc, diag::ambiguous_precedence_groups); - for (auto &entry : importedGroups) { - entry.first->diagnose(diag::found_this_precedence_group); - } - } - return importedGroups.end(); -} - -// Returns None on error, Optional(nullptr) if no operator decl found, or -// Optional(decl) if decl was found. -template -static Optional -lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc, - Identifier Name, bool includePrivate, - bool isCascading) { - auto &eval = File.getASTContext().evaluator; - auto desc = OperatorLookupDescriptor::forFile(const_cast(&File), - Name, isCascading, - /*diagLoc*/ SourceLoc()); - switch (File.getKind()) { - case FileUnitKind::Builtin: - // The Builtin module declares no operators. - return nullptr; - case FileUnitKind::Synthesized: - // Synthesized files currently declare no operators. - return nullptr; - case FileUnitKind::Source: - break; - case FileUnitKind::SerializedAST: - case FileUnitKind::ClangModule: - case FileUnitKind::DWARFModule: - return OperatorLookup::lookup(eval, desc); - } - - auto &SF = cast(File); - assert(SF.ASTStage >= SourceFile::ImportsResolved); - - // Check if the decl exists on the file. - if (auto *op = OperatorLookup::lookup(eval, desc)) - return op; - - // Look for imported operator decls. - // Record whether they come from re-exported modules. - // FIXME: We ought to prefer operators elsewhere in this module before we - // check imports. - auto ownModule = SF.getParentModule(); - ImportedOperatorsMap importedOperators; - for (auto &imported : SourceFile::Impl::getImportsForSourceFile(SF)) { - // Protect against source files that contrive to import their own modules. - if (imported.module.importedModule == ownModule) - continue; - - bool isExported = - imported.importOptions.contains(SourceFile::ImportFlags::Exported); - if (!includePrivate && !isExported) - continue; - - Optional maybeOp = lookupOperatorDeclForName( - imported.module.importedModule, Loc, Name, isCascading); - if (!maybeOp) - return None; - - if (OP_DECL *op = *maybeOp) - importedOperators[op] |= isExported; - } - - llvm::PointerIntPair result = {nullptr, - true}; - - if (!importedOperators.empty()) { - auto start = checkOperatorConflicts(SF, Loc, importedOperators); - if (start == importedOperators.end()) - return None; - result = { start->first, start->second }; - } - - if (includePrivate || result.getInt()) - return result.getPointer(); - return nullptr; -} - -template -static Optional -lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name, - bool isCascading) { - OP_DECL *result = nullptr; - for (const FileUnit *File : M->getFiles()) { - auto next = lookupOperatorDeclForName(*File, Loc, Name, false, - isCascading); - if (!next.hasValue()) - return next; - - // FIXME: Diagnose ambiguity. - if (*next && result) - return None; - if (*next) - result = *next; - } - return result; -} - -template -OperatorType *LookupOperatorRequest::evaluate( - Evaluator &evaluator, OperatorLookupDescriptor desc) const { - auto *file = desc.fileOrModule.get(); - auto result = - lookupOperatorDeclForName(*file, desc.diagLoc, desc.name, - /*includePrivate*/ true, - desc.isCascading); - if (!result.hasValue()) - return nullptr; - - if (!result.getValue()) { - result = lookupOperatorDeclForName(file->getParentModule(), - desc.diagLoc, desc.name, - desc.isCascading); - } - return result.hasValue() ? result.getValue() : nullptr; -} - -#define LOOKUP_OPERATOR(Kind) \ - Kind##Decl *ModuleDecl::lookup##Kind(Identifier name, SourceLoc loc) { \ - auto result = lookupOperatorDeclForName( \ - this, loc, name, /*isCascading*/ false); \ - return result ? *result : nullptr; \ - } \ - template Kind##Decl *LookupOperatorRequest::evaluate( \ - Evaluator &e, OperatorLookupDescriptor) const; - -LOOKUP_OPERATOR(PrefixOperator) -LOOKUP_OPERATOR(InfixOperator) -LOOKUP_OPERATOR(PostfixOperator) -LOOKUP_OPERATOR(PrecedenceGroup) -#undef LOOKUP_OPERATOR - void DirectOperatorLookupRequest::writeDependencySink( evaluator::DependencyCollector &reqTracker, TinyPtrVector ops) const { diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index b526d8108bd9a..3989f74f02943 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -281,6 +281,17 @@ SourceLoc swift::extractNearestSourceLoc(const DirectLookupDescriptor &desc) { // LookupOperatorRequest computation. //----------------------------------------------------------------------------// +OperatorLookupDescriptor OperatorLookupDescriptor::forDC(const DeclContext *DC, + Identifier name) { + auto *moduleDC = DC->getModuleScopeContext(); + if (auto *file = dyn_cast(moduleDC)) { + return OperatorLookupDescriptor::forFile(file, name); + } else { + auto *mod = cast(moduleDC->getAsDecl()); + return OperatorLookupDescriptor::forModule(mod, name); + } +} + ArrayRef OperatorLookupDescriptor::getFiles() const { if (auto *module = getModule()) return module->getFiles(); @@ -298,7 +309,7 @@ void swift::simple_display(llvm::raw_ostream &out, } SourceLoc swift::extractNearestSourceLoc(const OperatorLookupDescriptor &desc) { - return desc.diagLoc; + return extractNearestSourceLoc(desc.fileOrModule); } void DirectLookupRequest::writeDependencySink( diff --git a/lib/AST/OperatorNameLookup.cpp b/lib/AST/OperatorNameLookup.cpp new file mode 100644 index 0000000000000..b074fbf30f630 --- /dev/null +++ b/lib/AST/OperatorNameLookup.cpp @@ -0,0 +1,243 @@ +//===--- OperatorNameLookup.cpp - Operator and Precedence Lookup *- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 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 implements interfaces for performing operator and precedence group +// declaration lookup. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/OperatorNameLookup.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/DiagnosticsSema.h" +#include "swift/AST/ImportCache.h" +#include "swift/AST/NameLookupRequests.h" + +#define DEBUG_TYPE "operator-name-lookup" + +using namespace swift; +using namespace swift::namelookup; + +template +static TinyPtrVector lookupOperatorImpl( + DeclContext *moduleDC, Identifier name, + llvm::function_ref &)> + lookupDirect) { + assert(moduleDC->isModuleScopeContext()); + auto &ctx = moduleDC->getASTContext(); + + // First try to use the new operator lookup logic. + { + TinyPtrVector results; + for (auto &import : getAllImports(moduleDC)) { + auto *mod = import.importedModule; + lookupDirect(OperatorLookupDescriptor::forModule(mod, name), results); + } + + // If there aren't multiple results, or the new logic is completely enabled, + // perform shadowing checks and return. Otherwise fall through to the old + // logic. + if (results.size() <= 1 || ctx.LangOpts.EnableNewOperatorLookup) { + removeShadowedDecls(results, moduleDC); + return std::move(results); + } + } + + // There are three stages to the old operator lookup: + // 1) Lookup directly in the file. + // 2) Lookup in the file's direct imports (not looking through exports). + // 3) Lookup in other files. + // If any step yields results, we return them without performing the next + // steps. Note that this means when we come to look in other files, we can + // accumulate ambiguities across files, unlike when looking in the original + // file, where we can bail early. + + TinyPtrVector results; + SmallPtrSet visitedModules; + + // Protect against source files that contrive to import their own modules. + visitedModules.insert(moduleDC->getParentModule()); + + auto lookupInFileAndImports = [&](FileUnit *file, + bool includePrivate) -> bool { + // If we find something in the file itself, bail without checking imports. + lookupDirect(OperatorLookupDescriptor::forFile(file, name), results); + if (!results.empty()) + return true; + + // Only look into SourceFile imports. + auto *SF = dyn_cast(file); + if (!SF) + return false; + + for (auto &import : SF->getImports()) { + auto *mod = import.module.importedModule; + if (!visitedModules.insert(mod).second) + continue; + + bool isExported = + import.importOptions.contains(SourceFile::ImportFlags::Exported); + if (!includePrivate && !isExported) + continue; + + lookupDirect(OperatorLookupDescriptor::forModule(mod, name), results); + } + return !results.empty(); + }; + + // If we have a SourceFile context, search it and its private imports. + auto *SF = dyn_cast(moduleDC); + if (SF && lookupInFileAndImports(SF, /*includePrivate*/ true)) + return std::move(results); + + // Search all the other files of the module, this time excluding private + // imports. + auto *mod = moduleDC->getParentModule(); + for (auto *file : mod->getFiles()) { + if (file != SF) + lookupInFileAndImports(file, /*includePrivate*/ false); + } + return std::move(results); +} + +static TinyPtrVector +lookupOperator(DeclContext *moduleDC, Identifier name, OperatorFixity fixity) { + auto &eval = moduleDC->getASTContext().evaluator; + return lookupOperatorImpl( + moduleDC, name, + [&](OperatorLookupDescriptor desc, + TinyPtrVector &results) { + auto ops = evaluateOrDefault( + eval, DirectOperatorLookupRequest{desc, fixity}, {}); + for (auto *op : ops) + results.push_back(op); + }); +} + +void InfixOperatorLookupResult::diagnoseAmbiguity(SourceLoc loc) const { + auto &ctx = ModuleDC->getASTContext(); + ctx.Diags.diagnose(loc, diag::ambiguous_operator_decls); + for (auto *op : *this) + op->diagnose(diag::found_this_operator_decl); +} + +void InfixOperatorLookupResult::diagnoseMissing(SourceLoc loc, + bool forBuiltin) const { + ModuleDC->getASTContext().Diags.diagnose(loc, diag::unknown_binop); +} + +TinyPtrVector +LookupInfixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Infix); + + // If we have a single result, return it directly. This avoids having to look + // up its precedence group. + if (ops.size() == 1) + return {cast(ops[0])}; + + // Otherwise take the first infix operator we see with a particular precedence + // group. This avoids an ambiguity if two different modules declare the same + // operator with the same precedence. + TinyPtrVector results; + SmallPtrSet groups; + for (auto *op : ops) { + auto *infix = cast(op); + if (groups.insert(infix->getPrecedenceGroup()).second) + results.push_back(infix); + } + return results; +} + +InfixOperatorLookupResult +DeclContext::lookupInfixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + auto ops = evaluateOrDefault(getASTContext().evaluator, + LookupInfixOperatorRequest{desc}, {}); + // Wrap the result in a InfixOperatorLookupResult. The request doesn't + // return this directly to avoid unnecessarily caching the name and context. + return InfixOperatorLookupResult(this, name, std::move(ops)); +} + +PrefixOperatorDecl * +LookupPrefixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Prefix); + if (ops.empty()) + return nullptr; + + // We can return the first prefix operator. All prefix operators of the same + // name are equivalent. + return cast(ops[0]); +} + +PrefixOperatorDecl *DeclContext::lookupPrefixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + return evaluateOrDefault(getASTContext().evaluator, + LookupPrefixOperatorRequest{desc}, nullptr); +} + +PostfixOperatorDecl * +LookupPostfixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Postfix); + if (ops.empty()) + return nullptr; + + // We can return the first postfix operator. All postfix operators of the same + // name are equivalent. + return cast(ops[0]); +} + +PostfixOperatorDecl *DeclContext::lookupPostfixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + return evaluateOrDefault(getASTContext().evaluator, + LookupPostfixOperatorRequest{desc}, nullptr); +} + +void PrecedenceGroupLookupResult::diagnoseAmbiguity(SourceLoc loc) const { + auto &ctx = ModuleDC->getASTContext(); + ctx.Diags.diagnose(loc, diag::ambiguous_precedence_groups); + for (auto *group : *this) + group->diagnose(diag::found_this_precedence_group); +} + +void PrecedenceGroupLookupResult::diagnoseMissing(SourceLoc loc, + bool forBuiltin) const { + auto &ctx = ModuleDC->getASTContext(); + auto diagID = forBuiltin ? diag::missing_builtin_precedence_group + : diag::unknown_precedence_group; + ctx.Diags.diagnose(loc, diagID, Name); +} + +TinyPtrVector +LookupPrecedenceGroupRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + return lookupOperatorImpl( + desc.getDC(), desc.name, + [&](OperatorLookupDescriptor desc, + TinyPtrVector &results) { + auto groups = evaluateOrDefault( + evaluator, DirectPrecedenceGroupLookupRequest{desc}, {}); + for (auto *group : groups) + results.push_back(group); + }); +} + +PrecedenceGroupLookupResult +DeclContext::lookupPrecedenceGroup(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + auto groups = evaluateOrDefault(getASTContext().evaluator, + LookupPrecedenceGroupRequest{desc}, {}); + // Wrap the result in a PrecedenceGroupLookupResult. The request doesn't + // return this directly to avoid unnecessarily caching the name and context. + return PrecedenceGroupLookupResult(this, name, std::move(groups)); +} diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index b6db0facd2475..cc313d5867d1b 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -29,6 +29,7 @@ #include "swift/AST/Initializer.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericSignature.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" @@ -7637,8 +7638,10 @@ bool swift::exprNeedsParensOutsideFollowingOperator( bool swift::exprNeedsParensBeforeAddingNilCoalescing(DeclContext *DC, Expr *expr) { + auto &ctx = DC->getASTContext(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); + DC, ctx.Id_NilCoalescingPrecedence, SourceLoc()) + .getSingle(); if (!asPG) return true; return exprNeedsParensInsideFollowingOperator(DC, expr, asPG); @@ -7647,9 +7650,12 @@ bool swift::exprNeedsParensBeforeAddingNilCoalescing(DeclContext *DC, bool swift::exprNeedsParensAfterAddingNilCoalescing(DeclContext *DC, Expr *expr, Expr *rootExpr) { + auto &ctx = DC->getASTContext(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); - if (!asPG) return true; + DC, ctx.Id_NilCoalescingPrecedence, SourceLoc()) + .getSingle(); + if (!asPG) + return true; return exprNeedsParensOutsideFollowingOperator(DC, expr, rootExpr, asPG); } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 64428d227d763..2f64337fbabe3 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -25,6 +25,7 @@ #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/Expr.h" #include "swift/AST/Identifier.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/Types.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/ArrayRef.h" @@ -813,7 +814,7 @@ class MissingExplicitConversionFailure final : public ContextualFailure { bool exprNeedsParensBeforeAddingAs(const Expr *expr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); + DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()).getSingle(); if (!asPG) return true; return exprNeedsParensInsideFollowingOperator(DC, const_cast(expr), @@ -823,7 +824,7 @@ class MissingExplicitConversionFailure final : public ContextualFailure { bool exprNeedsParensAfterAddingAs(const Expr *expr, const Expr *rootExpr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); + DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()).getSingle(); if (!asPG) return true; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e7c00c73fa87b..37df0f4dc19e0 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -35,6 +35,7 @@ #include "swift/AST/GenericSignatureBuilder.h" #include "swift/AST/Initializer.h" #include "swift/AST/NameLookup.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PropertyWrappers.h" #include "swift/AST/ProtocolConformance.h" @@ -1321,21 +1322,6 @@ static void checkPrecedenceCircularity(DiagnosticEngine &D, } while (!stack.empty()); } -static PrecedenceGroupDecl * -lookupPrecedenceGroup(const PrecedenceGroupDescriptor &descriptor) { - auto *dc = descriptor.dc; - if (auto sf = dc->getParentSourceFile()) { - auto desc = OperatorLookupDescriptor::forFile( - sf, descriptor.ident, dc->isCascadingContextForLookup(false), - descriptor.nameLoc); - return evaluateOrDefault(sf->getASTContext().evaluator, - LookupPrecedenceGroupRequest{desc}, nullptr); - } else { - return dc->getParentModule()->lookupPrecedenceGroup(descriptor.ident, - descriptor.nameLoc); - } -} - static PrecedenceGroupDecl *lookupPrecedenceGroupForRelation( DeclContext *dc, PrecedenceGroupDecl::Relation rel, PrecedenceGroupDescriptor::PathDirection direction) { @@ -1350,10 +1336,8 @@ static PrecedenceGroupDecl *lookupPrecedenceGroupForRelation( llvm::handleAllErrors(result.takeError(), [](const Error &E) {}); return nullptr; } - if (!result.get()) { - ctx.Diags.diagnose(rel.NameLoc, diag::unknown_precedence_group, rel.Name); - } - return result.get(); + return PrecedenceGroupLookupResult(dc, rel.Name, std::move(*result)) + .getSingleOrDiagnose(rel.NameLoc); } void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { @@ -1392,10 +1376,8 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { // If we didn't find anything, try doing a raw lookup for the group before // diagnosing the 'lowerThan' within the same-module restriction. This can // allow us to diagnose even if we have a precedence group cycle. - if (!group) { - group = lookupPrecedenceGroup(PrecedenceGroupDescriptor{ - dc, rel.Name, rel.NameLoc, PrecedenceGroupDescriptor::LowerThan}); - } + if (!group) + group = dc->lookupPrecedenceGroup(rel.Name).getSingle(); if (group && group->getDeclContext()->getParentModule() == dc->getParentModule()) { @@ -1416,22 +1398,25 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { checkPrecedenceCircularity(Diags, PGD); } -PrecedenceGroupDecl * ValidatePrecedenceGroupRequest::evaluate( +TinyPtrVector ValidatePrecedenceGroupRequest::evaluate( Evaluator &eval, PrecedenceGroupDescriptor descriptor) const { - if (auto *group = lookupPrecedenceGroup(descriptor)) { + auto groups = descriptor.dc->lookupPrecedenceGroup(descriptor.ident); + for (auto *group : groups) validatePrecedenceGroup(group); - return group; - } - return nullptr; + // Return the raw results vector, which will get wrapped back in a + // PrecedenceGroupLookupResult by the TypeChecker entry point. This dance + // avoids unnecessarily caching the name and context for the lookup. + return std::move(groups).get(); } -PrecedenceGroupDecl *TypeChecker::lookupPrecedenceGroup(DeclContext *dc, - Identifier name, - SourceLoc nameLoc) { - return evaluateOrDefault( +PrecedenceGroupLookupResult +TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, + SourceLoc nameLoc) { + auto groups = evaluateOrDefault( dc->getASTContext().evaluator, - ValidatePrecedenceGroupRequest({dc, name, nameLoc, None}), nullptr); + ValidatePrecedenceGroupRequest({dc, name, nameLoc, None}), {}); + return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } static NominalTypeDecl *resolveSingleNominalTypeDecl( @@ -1480,7 +1465,6 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto enableOperatorDesignatedTypes = ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes; - auto &Diags = ctx.Diags; PrecedenceGroupDecl *group = nullptr; auto identifiers = IOD->getIdentifiers(); @@ -1488,20 +1472,18 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto name = identifiers[0].Item; auto loc = identifiers[0].Loc; - group = TypeChecker::lookupPrecedenceGroup(dc, name, loc); - - if (group) { + auto canResolveType = [&]() -> bool { + return enableOperatorDesignatedTypes && + resolveSingleNominalTypeDecl(dc, loc, name, ctx, + TypeResolutionFlags::SilenceErrors); + }; + + // Make sure not to diagnose in the case where we failed to find a + // precedencegroup, but we could resolve a type instead. + auto groups = TypeChecker::lookupPrecedenceGroup(dc, name, loc); + if (groups.hasResults() || !canResolveType()) { + group = groups.getSingleOrDiagnose(loc); identifiers = identifiers.slice(1); - } else { - // If we're either not allowing types, or we are allowing them - // and this identifier is not a type, emit an error as if it's - // a precedence group. - if (!(enableOperatorDesignatedTypes && - resolveSingleNominalTypeDecl(dc, loc, name, ctx, - TypeResolutionFlags::SilenceErrors))) { - Diags.diagnose(loc, diag::unknown_precedence_group, name); - identifiers = identifiers.slice(1); - } } } @@ -1511,13 +1493,9 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, assert(identifiers.empty() || enableOperatorDesignatedTypes); if (!group) { - group = TypeChecker::lookupPrecedenceGroup(dc, ctx.Id_DefaultPrecedence, - SourceLoc()); - } - - if (!group) { - Diags.diagnose(IOD->getLoc(), diag::missing_builtin_precedence_group, - ctx.Id_DefaultPrecedence); + auto groups = TypeChecker::lookupPrecedenceGroup( + dc, ctx.Id_DefaultPrecedence, SourceLoc()); + group = groups.getSingleOrDiagnose(IOD->getLoc(), /*forBuiltin*/ true); } auto nominalTypes = IOD->getDesignatedNominalTypes(); @@ -1797,24 +1775,15 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { FD->diagnose(diag::operator_in_local_scope); } - auto desc = OperatorLookupDescriptor::forFile( - FD->getDeclContext()->getParentSourceFile(), operatorName, - FD->isCascadingContextForLookup(false), FD->getLoc()); - OperatorDecl *op = nullptr; + NullablePtr op; if (FD->isUnaryOperator()) { if (FD->getAttrs().hasAttribute()) { - op = evaluateOrDefault(evaluator, - LookupPrefixOperatorRequest{desc}, nullptr); + op = FD->lookupPrefixOperator(operatorName); } else if (FD->getAttrs().hasAttribute()) { - op = evaluateOrDefault(evaluator, - LookupPostfixOperatorRequest{desc}, nullptr); + op = FD->lookupPostfixOperator(operatorName); } else { - auto prefixOp = evaluateOrDefault(evaluator, - LookupPrefixOperatorRequest{desc}, - nullptr); - auto postfixOp = evaluateOrDefault(evaluator, - LookupPostfixOperatorRequest{desc}, - nullptr); + auto *prefixOp = FD->lookupPrefixOperator(operatorName); + auto *postfixOp = FD->lookupPostfixOperator(operatorName); // If we found both prefix and postfix, or neither prefix nor postfix, // complain. We can't fix this situation. @@ -1823,9 +1792,11 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // If we found both, point at them. if (prefixOp) { - diags.diagnose(prefixOp, diag::unary_operator_declaration_here, false) + diags.diagnose(prefixOp, diag::unary_operator_declaration_here, + /*isPostfix*/ false) .fixItInsert(FD->getLoc(), "prefix "); - diags.diagnose(postfixOp, diag::unary_operator_declaration_here, true) + diags.diagnose(postfixOp, diag::unary_operator_declaration_here, + /*isPostfix*/ true) .fixItInsert(FD->getLoc(), "postfix "); } else { // FIXME: Introduce a Fix-It that adds the operator declaration? @@ -1842,7 +1813,8 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // Fix the AST and determine the insertion text. const char *insertionText; auto &C = FD->getASTContext(); - if (postfixOp) { + auto isPostfix = static_cast(postfixOp); + if (isPostfix) { insertionText = "postfix "; op = postfixOp; FD->getAttrs().add(new (C) PostfixAttr(/*implicit*/false)); @@ -1854,15 +1826,20 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // Emit diagnostic with the Fix-It. diags.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute, - static_cast(postfixOp)) + isPostfix) .fixItInsert(FD->getFuncLoc(), insertionText); - diags.diagnose(op, diag::unary_operator_declaration_here, - static_cast(postfixOp)); + op.get()->diagnose(diag::unary_operator_declaration_here, isPostfix); } } else if (FD->isBinaryOperator()) { - op = evaluateOrDefault(evaluator, - LookupInfixOperatorRequest{desc}, - nullptr); + auto results = FD->lookupInfixOperator(operatorName); + + // If we have an ambiguity, diagnose and return. Otherwise fall through, as + // we have a custom diagnostic for missing operator decls. + if (results.isAmbiguous()) { + results.diagnoseAmbiguity(FD->getLoc()); + return nullptr; + } + op = results.getSingle(); } else { diags.diagnose(FD, diag::invalid_arg_count_for_operator); return nullptr; @@ -1910,8 +1887,7 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { opDiagnostic.fixItInsert(insertionLoc, insertion); return nullptr; } - - return op; + return op.get(); } bool swift::isMemberOperator(FuncDecl *decl, Type type) { diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index d9e2333066ece..39686d11c3f80 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -430,9 +430,7 @@ static void checkOperatorOrPrecedenceGroupRedeclaration( auto *module = currentFile->getParentModule(); auto &ctx = module->getASTContext(); - auto desc = OperatorLookupDescriptor::forModule(module, decl->getName(), - /*cascades*/ true, - /*diagLoc*/ SourceLoc()); + auto desc = OperatorLookupDescriptor::forModule(module, decl->getName()); auto otherDecls = lookupOthers(desc); for (auto *other : otherDecls) { if (other == decl || other->isInvalid()) diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index c68113bb49531..41753a5b75e94 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -18,6 +18,7 @@ #include "TypeChecker.h" #include "swift/AST/NameLookup.h" #include "swift/AST/NameLookupRequests.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/Decl.h" #include "swift/AST/Initializer.h" #include "swift/AST/ParameterList.h" @@ -130,32 +131,18 @@ Expr *TypeChecker::substituteInputSugarTypeForResult(ApplyExpr *E) { static PrecedenceGroupDecl *lookupPrecedenceGroupForOperator(DeclContext *DC, Identifier name, SourceLoc loc) { - auto desc = OperatorLookupDescriptor::forFile( - DC->getParentSourceFile(), name, DC->isCascadingContextForLookup(true), - loc); - auto &Ctx = DC->getASTContext(); - if (auto op = evaluateOrDefault(Ctx.evaluator, - LookupInfixOperatorRequest{desc}, - nullptr)) { - return op->getPrecedenceGroup(); - } else { - Ctx.Diags.diagnose(loc, diag::unknown_binop); - } - return nullptr; + auto *op = DC->lookupInfixOperator(name).getSingleOrDiagnose(loc); + return op ? op->getPrecedenceGroup() : nullptr; } PrecedenceGroupDecl * TypeChecker::lookupPrecedenceGroupForInfixOperator(DeclContext *DC, Expr *E) { /// Look up the builtin precedence group with the given name. - auto getBuiltinPrecedenceGroup = [](DeclContext *DC, Identifier name, - SourceLoc loc) { - auto group = TypeChecker::lookupPrecedenceGroup(DC, name, loc); - if (!group) { - DC->getASTContext().Diags.diagnose( - loc, diag::missing_builtin_precedence_group, name); - } - return group; + auto getBuiltinPrecedenceGroup = [&](DeclContext *DC, Identifier name, + SourceLoc loc) -> PrecedenceGroupDecl * { + auto groups = TypeChecker::lookupPrecedenceGroup(DC, name, loc); + return groups.getSingleOrDiagnose(loc, /*forBuiltin*/ true); }; auto &Context = DC->getASTContext(); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index dabd2c602e014..a52659072deaa 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1012,8 +1012,8 @@ LookupResult lookupConstructors( PrecedenceGroupDecl *lookupPrecedenceGroupForInfixOperator(DeclContext *dc, Expr *op); -PrecedenceGroupDecl *lookupPrecedenceGroup(DeclContext *dc, Identifier name, - SourceLoc nameLoc); +PrecedenceGroupLookupResult +lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); /// Check whether the given declaration can be written as a /// member of the given base type. diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index c065390337623..d246ee346d22a 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -2247,9 +2247,6 @@ OperatorDecl *ModuleFile::lookupOperator(Identifier name, if (getStableFixity(fixity) == item.first) return cast(getDecl(item.second)); } - - // FIXME: operators re-exported from other modules? - return nullptr; } diff --git a/test/decl/operator/Inputs/lookup_other_noncompat.swift b/test/decl/operator/Inputs/lookup_other_noncompat.swift new file mode 100644 index 0000000000000..db4d2ab60ca0b --- /dev/null +++ b/test/decl/operator/Inputs/lookup_other_noncompat.swift @@ -0,0 +1,5 @@ + +// Also declared in the files being tested. +precedencegroup RedeclaredInModule {} +// expected-note@-1 {{previous precedence group declaration here}} +// expected-note@-2 {{found this matching precedence group}} diff --git a/test/decl/operator/Inputs/redeclaration_other.swift b/test/decl/operator/Inputs/redeclaration_other.swift new file mode 100644 index 0000000000000..f60b80c446209 --- /dev/null +++ b/test/decl/operator/Inputs/redeclaration_other.swift @@ -0,0 +1,10 @@ +precedencegroup RedeclaredAcrossFiles {} // expected-note {{previous precedence group declaration here}} + +infix operator ^^^ // expected-note {{previous operator declaration here}} +prefix operator >>> // expected-note {{previous operator declaration here}} +postfix operator <<< // expected-note {{previous operator declaration here}} + +precedencegroup P1 {} +infix operator ^^^^ : P1 // expected-note {{previous operator declaration here}} + +infix operator &&& diff --git a/test/decl/operator/lookup.swift b/test/decl/operator/lookup.swift new file mode 100644 index 0000000000000..1c40082d17000 --- /dev/null +++ b/test/decl/operator/lookup.swift @@ -0,0 +1,113 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleD.swift -module-name D -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleC.swift -module-name C -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleB.swift -module-name B -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleA.swift -module-name A -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_module_exportsAC.swift -module-name ExportsAC -o %t -I %t +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/lookup_other.swift %S/Inputs/lookup_other2.swift %S/Inputs/lookup_other_noncompat.swift -I %t -enable-new-operator-lookup + +import ExportsAC +import B + +infix operator ^^^ : DeclaredAcrossFiles +func ^^^ (lhs: Int, rhs: Int) -> Int { 0 } +func &&& (lhs: Int, rhs: Int) -> Int { 0 } + +// The operator decl >>> is declared in module A, which we should be able to +// see through ExportsAC. +prefix func >>> (rhs: Double) {} + +// Make sure we can also see precedencegroups in module A through ExportsAC. +infix operator ^^^^ : DeclaredInModuleA + +// The operator decl for ??? is declared in both modules A and B, but has the +// same default precedence group in both, so there's no ambiguity. +func ??? (lhs: Int, rhs: Int) {} + +// Same for ???!, declared in modules ExportsAC and B, but has the same +// precedence group in both. +func ???! (lhs: Int, rhs: Int) {} + +// The operator decl for ???? is declared in both modules A and B, and has a +// different precedence group in each. Therefore ambiguous. +func ???? (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} + +// Same for ????!, declared in both modules ExportsAC and B, and has a different +// precedence group in each. Therefore ambiguous. +func ????! (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} + +// The precedencegroup is declared in both modules A and B, therefore ambiguous. +infix operator : DeclaredInModulesAB // expected-error {{multiple precedence groups found}} + +// The precedencegroup is declared in both modules ExportsAC and B, therefore +// ambiguous. +infix operator : DeclaredInModulesBExportsAC // expected-error {{multiple precedence groups found}} + +// While this precedencegroup is declared in both modules A and B, it's also +// declared in this module, which therefore shadows those decls. +infix operator : DeclaredInModulesABShadowed + +// The operator decl for : ShadowsModuleA + +// This precedencegroup is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former. +infix operator : ShadowsModulesAC + +// This operator decl is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former. +func ????? (lhs: Int, rhs: Int) {} + +// This operator decl is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former, despite them having different +// precedencegroups. +func ?????? (lhs: Int, rhs: Int) {} + +// Module D is imported through exports in both lookup_other and lookup_other2. +// Make sure we correctly handle visiting the same module twice. +infix operator <> : DeclaredInModuleD + +// Also declared in lookup_other. +precedencegroup RedeclaredInModule {} +// expected-error@-1 {{precedence group redeclared}} +// expected-note@-2 {{found this matching precedence group}} + +infix operator *** : RedeclaredInModule // expected-error {{multiple precedence groups found}} + +func testOperatorLookup() { + // In lookup_other, DeclaredAcrossFiles is left associative, whereas in + // module B it is non-associative. Make sure we use lookup_other's. + _ = 5 ^^^ 5 ^^^ 5 // Okay. + + // Same for &&&, in lookup_other it is declared as left associative. + _ = 5 &&& 5 &&& 5 + + // The operator >>> is declared in module A, which we should be able to see + // through ExportsAC. + >>>1 + + // We've been evil and overriden TernaryPrecedence in both modules A and B. + // Make sure we emit an ambiguity error without emitting a 'broken stdlib' + // error. + true ? () : () // expected-error {{multiple precedence groups found}} +} + +precedencegroup CastingPrecedence { + lowerThan: AssignmentPrecedence +} + +func testBuiltinPrecedenceGroupOverriding() { + // Evil, but allowed. + var x = 0 + x = 0 as Int // expected-error {{cannot convert value of type '()' to type 'Int' in coercion}} +} diff --git a/test/decl/operator/lookup_compatibility.swift b/test/decl/operator/lookup_compatibility.swift index 603ab9149fd3c..cf6db1e5c7b78 100644 --- a/test/decl/operator/lookup_compatibility.swift +++ b/test/decl/operator/lookup_compatibility.swift @@ -14,13 +14,15 @@ infix operator ^^^ : DeclaredAcrossFiles func ^^^ (lhs: Int, rhs: Int) -> Int { 0 } func &&& (lhs: Int, rhs: Int) -> Int { 0 } -// FIXME(SR-12132): The operator decl >>> is declared in module A, which we -// should be able to see through ExportsAC. -prefix func >>> (rhs: Double) {} // expected-error {{operator implementation without matching operator declaration}} +// The operator decl >>> is declared in module A, which we should be able to +// see through ExportsAC. Note that this is possible even with the compatibility +// behavior as we can use the new lookup logic when the result is unambiguous. +prefix func >>> (rhs: Double) {} -// FIXME(SR-12132): We should also see precedencegroups in module A through -// ExportsAC. -infix operator ^^^^ : DeclaredInModuleA // expected-error {{unknown precedence group 'DeclaredInModuleA'}} +// Make sure we can also see precedencegroups in module A through ExportsAC. +// Note that this is possible even with the compatibility behavior as we can use +// the new lookup logic when the result is unambiguous. +infix operator ^^^^ : DeclaredInModuleA // The operator decl for ??? is declared in both modules A and B, but has the // same default precedence group in both, so there's no ambiguity. @@ -38,9 +40,7 @@ func ???? (lhs: Int, rhs: Int) {} // The operator decl for ????! is declared in both modules ExportsAC and B, and // has a different precedence group in each. Therefore ambiguous. -// FIXME: We shouldn't emit the unknown operator decl error. func ????! (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} -// expected-error@-1 {{operator implementation without matching operator declaration}} // Same as ????, the precedencegroup is declared in both modules A and B, but // we don't look into module A for compatibility. @@ -48,9 +48,7 @@ infix operator : DeclaredInModulesAB // The precedencegroup is declared in both modules ExportsAC and B, therefore // ambiguous. -// FIXME: We shouldn't emit the 'unknown precedence group' error. infix operator : DeclaredInModulesBExportsAC // expected-error {{multiple precedence groups found}} -// expected-error@-1 {{unknown precedence group 'DeclaredInModulesBExportsAC'}} // This precedencegroup is declared in this module as well as in both modules A // and B. The decl in this module should shadow the imported ones, but for @@ -82,10 +80,9 @@ func ????? (lhs: Int, rhs: Int) {} // precedencegroups. func ?????? (lhs: Int, rhs: Int) {} -// FIXME: Module D is imported through exports in both lookup_other and -// lookup_other2, but we fail to detect the fact that we're visiting the same -// thing twice. -infix operator <> : DeclaredInModuleD // expected-error {{unknown precedence group 'DeclaredInModuleD'}} +// Module D is imported through exports in both lookup_other and lookup_other2. +// Make sure we correctly handle visiting the same module twice. +infix operator <> : DeclaredInModuleD // Also declared in lookup_other. To preserve compatibility, we allow an // unambiguous lookup that will favor this declaration over lookup_other. @@ -109,9 +106,9 @@ func testOperatorLookup() { >>>1 // We've been evil and overriden TernaryPrecedence in both modules A and B. - // FIXME: We shouldn't emit the 'broken stdlib' error. + // Make sure we emit an ambiguity error without emitting a 'broken stdlib' + // error. true ? () : () // expected-error {{multiple precedence groups found}} - // expected-error@-1 {{broken standard library: missing builtin precedence group 'TernaryPrecedence'}} } precedencegroup CastingPrecedence { diff --git a/test/decl/operator/redeclaration.swift b/test/decl/operator/redeclaration.swift new file mode 100644 index 0000000000000..ce07817fe2eb4 --- /dev/null +++ b/test/decl/operator/redeclaration.swift @@ -0,0 +1,31 @@ +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/redeclaration_other.swift -enable-new-operator-lookup + +precedencegroup RedeclaredAcrossFiles {} // expected-error {{precedence group redeclared}} + +precedencegroup RedeclaredSameFile {} // expected-note {{previous precedence group declaration here}} +precedencegroup RedeclaredSameFile {} // expected-error {{precedence group redeclared}} + +precedencegroup RedeclaredSameFile2 { // expected-note {{previous precedence group declaration here}} + assignment: true +} +precedencegroup RedeclaredSameFile2 {} // expected-error {{precedence group redeclared}} + +// These are all declared in the other file. +infix operator ^^^ // expected-error {{operator redeclared}} +prefix operator >>> // expected-error {{operator redeclared}} +postfix operator <<< // expected-error {{operator redeclared}} +infix operator ^^^^ // expected-error {{operator redeclared}} + +// This is declared as an infix operator in the other file, so no problem. +prefix operator &&& +postfix operator &&& + +infix operator %%% // expected-note {{previous operator declaration here}} +infix operator %%% // expected-error {{operator redeclared}} + +prefix operator %%% // expected-note {{previous operator declaration here}} +prefix operator %%% // expected-error {{operator redeclared}} + +precedencegroup P2 {} +infix operator *** : P2 // expected-note {{previous operator declaration here}} +infix operator *** // expected-error {{operator redeclared}} From e7cb6bb48c3b94b798309fd8d48d049a27905cee Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 May 2020 14:33:43 -0700 Subject: [PATCH 091/625] [Sema] Diagnose cross-file operator redeclarations Previously we permitted operator redeclarations across files as the user could shadow imported operator decls on a per-file basis, and we would prefer an imported operator decl over one in another file. However with the new operator lookup implementation, operators in the current module always shadow imported decls. As such, we should start diagnosing cross-file redeclarations when the new lookup logic is enabled. Resolves rdar://48731166 --- lib/Sema/TypeCheckDeclPrimary.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 39686d11c3f80..71fc61cf6b057 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -436,18 +436,23 @@ static void checkOperatorOrPrecedenceGroupRedeclaration( if (other == decl || other->isInvalid()) continue; - // Emit a redeclaration error if the two declarations occur in the same - // source file. We currently allow redeclarations across source files to - // allow the user to shadow operator decls from imports, as we currently - // favor those decls over ones from other files. - // FIXME: Once we prefer operator decls from the same module, start - // diagnosing redeclarations across files. + bool shouldDiagnose = false; if (currentFile == other->getDeclContext()->getParentSourceFile()) { - // Make sure we get the diagnostic ordering to be sensible. + // For a same-file redeclaration, make sure we get the diagnostic ordering + // to be sensible. if (decl->getLoc().isValid() && other->getLoc().isValid() && ctx.SourceMgr.isBeforeInBuffer(decl->getLoc(), other->getLoc())) { std::swap(decl, other); } + shouldDiagnose = true; + } else { + // If the declarations are in different files, only diagnose if we've + // enabled the new operator lookup behaviour where decls in the current + // module are now favored over imports. + shouldDiagnose = ctx.LangOpts.EnableNewOperatorLookup; + } + + if (shouldDiagnose) { ctx.Diags.diagnose(decl, diagID); ctx.Diags.diagnose(other, noteID); decl->setInvalid(); From ffc990f999f4dc7a32af2139d8fd2c3d05276ddd Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Mon, 18 May 2020 16:52:41 -0700 Subject: [PATCH 092/625] [driver/sourcekit] Avoid creating temporary output files in TMPDIR When producing frontend arguments for sourcekitd, force the output mode to -typecheck so that we do not create any temporary output files in the driver. Previously, any sourcekitd operation that created a compiler invocation would create 0-sized .o file inside $TMPDIR that would never be cleaned up. The new swift-driver project handles temporaries much better as VirtualPath, and should not need this approach. rdar://62366123 --- include/swift/Driver/FrontendUtil.h | 6 +++- lib/Driver/FrontendUtil.cpp | 22 +++++++++++++- test/SourceKit/Misc/no-driver-outputs.swift | 29 +++++++++++++++++++ .../lib/SwiftLang/SwiftASTManager.cpp | 2 +- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test/SourceKit/Misc/no-driver-outputs.swift diff --git a/include/swift/Driver/FrontendUtil.h b/include/swift/Driver/FrontendUtil.h index 78e307cd47000..cfa46e017a67b 100644 --- a/include/swift/Driver/FrontendUtil.h +++ b/include/swift/Driver/FrontendUtil.h @@ -33,6 +33,9 @@ namespace driver { /// \param Action Called with the list of frontend arguments if there were no /// errors in processing \p ArgList. This is a callback rather than a return /// value to avoid copying the arguments more than necessary. +/// \param ForceNoOutputs If true, override the output mode to "-typecheck" and +/// produce no outputs. For example, this disables "-emit-module" and "-c" and +/// prevents the creation of temporary files. /// /// \returns True on error, or if \p Action returns true. /// @@ -40,7 +43,8 @@ namespace driver { /// suitable for use in REPL or immediate modes. bool getSingleFrontendInvocationFromDriverArguments( ArrayRef ArgList, DiagnosticEngine &Diags, - llvm::function_ref FrontendArgs)> Action); + llvm::function_ref FrontendArgs)> Action, + bool ForceNoOutputs = false); } // end namespace driver } // end namespace swift diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp index bd771faf28c5b..17c565a7ea92f 100644 --- a/lib/Driver/FrontendUtil.cpp +++ b/lib/Driver/FrontendUtil.cpp @@ -25,7 +25,8 @@ using namespace swift::driver; bool swift::driver::getSingleFrontendInvocationFromDriverArguments( ArrayRef Argv, DiagnosticEngine &Diags, - llvm::function_ref FrontendArgs)> Action) { + llvm::function_ref FrontendArgs)> Action, + bool ForceNoOutputs) { SmallVector Args; Args.push_back(""); // FIXME: Remove dummy argument. Args.insert(Args.end(), Argv.begin(), Argv.end()); @@ -57,6 +58,25 @@ bool swift::driver::getSingleFrontendInvocationFromDriverArguments( if (Diags.hadAnyError()) return true; + if (ForceNoOutputs) { + // Clear existing output modes. + ArgList->eraseArg(options::OPT_modes_Group); + // Disable other output options that conflict with -typecheck. + ArgList->eraseArg(options::OPT_emit_module); + ArgList->eraseArg(options::OPT_emit_module_path); + ArgList->eraseArg(options::OPT_emit_module_source_info_path); + ArgList->eraseArg(options::OPT_emit_module_interface); + ArgList->eraseArg(options::OPT_emit_module_interface_path); + ArgList->eraseArg(options::OPT_emit_objc_header); + ArgList->eraseArg(options::OPT_emit_objc_header_path); + + unsigned index = ArgList->MakeIndex("-typecheck"); + // Takes ownership of the Arg. + ArgList->append(new llvm::opt::Arg( + TheDriver.getOpts().getOption(options::OPT_typecheck), + ArgList->getArgString(index), index)); + } + std::unique_ptr TC = TheDriver.buildToolChain(*ArgList); if (Diags.hadAnyError()) return true; diff --git a/test/SourceKit/Misc/no-driver-outputs.swift b/test/SourceKit/Misc/no-driver-outputs.swift new file mode 100644 index 0000000000000..f3e11065eb183 --- /dev/null +++ b/test/SourceKit/Misc/no-driver-outputs.swift @@ -0,0 +1,29 @@ +// REQUIRES: shell + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s -- %s +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=syntax-map %s -- %s -c -o %t/foo.o +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -c -o %t/foo.o +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -emit-module -module-name main -emit-module-path %t/main.swiftmodule -emit-module-interface -enable-library-evolution -emit-module-interface-path %t/main.swiftinterface -emit-objc-header -emit-objc-header-path %t/main.h -c -o %t/foo.o +// RUN: ls %t/ | count 0 + +// RUN: %empty-directory(%t) +// RUN: env TMPDIR=%t __XPC_TMPDIR=%t %sourcekitd-test -req=sema %s -- %s -emit-module -module-name main -emit-module-path %t/main.swiftmodule -emit-executable -o %t/foo +// RUN: ls %t/ | count 0 diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 0b4a9d238c3d4..e67659954ebfc 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -507,7 +507,7 @@ bool SwiftASTManager::initCompilerInvocation( bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( Args, Diags, [&](ArrayRef FrontendArgs) { return Invocation.parseArgs(FrontendArgs, Diags); - }); + }, /*ForceNoOutputs=*/true); // Remove the StreamDiagConsumer as it's no longer needed. Diags.removeConsumer(DiagConsumer); From d764fe8ae06f82c69a13f2d685b9a922bfb8cf2b Mon Sep 17 00:00:00 2001 From: Greg Titus Date: Mon, 18 May 2020 18:51:00 -0700 Subject: [PATCH 093/625] Pass down solution to simplify types, and map missingType to translate taus to generic param names for emissions. --- lib/Sema/TypeCheckProtocol.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 64d4e772bd0e9..0667f6188ab92 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -751,8 +751,8 @@ static const RequirementEnvironment &getOrCreateRequirementEnvironment( } static Optional findMissingGenericRequirementForSolutionFix( - constraints::ConstraintFix *fix, ValueDecl *witness, - ProtocolConformance *conformance, + constraints::Solution &solution, constraints::ConstraintFix *fix, + ValueDecl *witness, ProtocolConformance *conformance, const RequirementEnvironment &reqEnvironment) { Type type, missingType; RequirementKind requirementKind; @@ -784,9 +784,15 @@ static Optional findMissingGenericRequirementForSolutionFix( default: return Optional(); } - - if (missingType->hasTypeVariable()) - return Optional(); + + type = solution.simplifyType(type); + missingType = solution.simplifyType(missingType); + + missingType = missingType->mapTypeOutOfContext(); + if (missingType->hasTypeParameter()) + if (auto env = conformance->getGenericEnvironment()) + if (auto assocType = env->mapTypeIntoContext(missingType)) + missingType = assocType; auto missingRequirementMatch = [&](Type type) -> RequirementMatch { Requirement requirement(requirementKind, type, missingType); @@ -989,7 +995,7 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, if (solution && conformance && solution->Fixes.size()) { for (auto fix : solution->Fixes) { if (auto result = findMissingGenericRequirementForSolutionFix( - fix, witness, conformance, reqEnvironment)) + *solution, fix, witness, conformance, reqEnvironment)) return *result; } } From 3f5c53a6b87480db6e83678c1ae7a6398f59c1f0 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Tue, 19 May 2020 11:53:11 +0200 Subject: [PATCH 094/625] Reenable a test for UnicodeScalar This test was disabled back in 2017 when the new integer protocols were landing due to regressions in error messages. It is better to have a working test that verifies the desired behavior (UnicodeScalar not supporting arithmetic and the type checker producing somewhat readable messages), rather than a disabled test because the error messages are not perfect. --- test/stdlib/UnicodeScalarDiagnostics.swift | 38 +++++++++------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/test/stdlib/UnicodeScalarDiagnostics.swift b/test/stdlib/UnicodeScalarDiagnostics.swift index def2ac3f22ca0..6446f3e7155bb 100644 --- a/test/stdlib/UnicodeScalarDiagnostics.swift +++ b/test/stdlib/UnicodeScalarDiagnostics.swift @@ -1,38 +1,30 @@ -// FIXME(integers): confusing diagnostics when new integer protocols are -// implemented. -// XFAIL: * - // RUN: %target-typecheck-verify-swift +// FIXME: The clarity of these diagnostics could be improved. +// + func isString(_ s: inout String) {} func test_UnicodeScalarDoesNotImplementArithmetic(_ us: UnicodeScalar, i: Int) { var a1 = "a" + "b" // OK isString(&a1) let a2 = "a" - "b" // expected-error {{binary operator '-' cannot be applied to two 'String' operands}} - // expected-note @-1 {{overloads for '-' exist with these partially matching parameter lists:}} let a3 = "a" * "b" // expected-error {{binary operator '*' cannot be applied to two 'String' operands}} - // expected-note @-1 {{overloads for '*' exist with these partially matching parameter lists:}} let a4 = "a" / "b" // expected-error {{binary operator '/' cannot be applied to two 'String' operands}} - // expected-note @-1 {{overloads for '/' exist with these partially matching parameter lists:}} - let b1 = us + us // expected-error {{binary operator '+' cannot be applied to two 'UnicodeScalar' operands}} - // expected-note @-1 {{overloads for '+' exist with these partially matching parameter lists:}} - let b2 = us - us // expected-error {{binary operator '-' cannot be applied to two 'UnicodeScalar' operands}} - // expected-note @-1 {{overloads for '-' exist with these partially matching parameter lists:}} - let b3 = us * us // expected-error {{binary operator '*' cannot be applied to two 'UnicodeScalar' operands}} - // expected-note @-1 {{overloads for '*' exist with these partially matching parameter lists:}} - let b4 = us / us // expected-error {{binary operator '/' cannot be applied to two 'UnicodeScalar' operands}} - // expected-note @-1 {{overloads for '/' exist with these partially matching parameter lists:}} + let b1 = us + us // expected-error {{referencing operator function '+' on 'RangeReplaceableCollection' requires that 'UnicodeScalar' (aka 'Unicode.Scalar') conform to 'RangeReplaceableCollection'}} + let b2 = us - us // expected-error {{referencing operator function '-' on 'FloatingPoint' requires that 'UnicodeScalar' (aka 'Unicode.Scalar') conform to 'FloatingPoint'}} + let b3 = us * us // expected-error {{referencing operator function '*' on 'FloatingPoint' requires that 'UnicodeScalar' (aka 'Unicode.Scalar') conform to 'FloatingPoint'}} + let b4 = us / us // expected-error {{referencing operator function '/' on 'FloatingPoint' requires that 'UnicodeScalar' (aka 'Unicode.Scalar') conform to 'FloatingPoint'}} - let c1 = us + i // expected-error {{binary operator '+' cannot be applied to operands of type 'UnicodeScalar' and 'Int'}} expected-note{{overloads for '+' exist with these partially matching parameter lists:}} - let c2 = us - i // expected-error {{binary operator '-' cannot be applied to operands of type 'UnicodeScalar' and 'Int'}} expected-note{{overloads for '-' exist with these partially matching parameter lists: (UnsafeMutablePointer, Int), (UnsafePointer, Int)}} - let c3 = us * i // expected-error {{binary operator '*' cannot be applied to operands of type 'UnicodeScalar' and 'Int'}} expected-note {{expected an argument list of type '(Int, Int)'}} - let c4 = us / i // expected-error {{binary operator '/' cannot be applied to operands of type 'UnicodeScalar' and 'Int'}} expected-note {{expected an argument list of type '(Int, Int)'}} + let c1 = us + i // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let c2 = us - i // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let c3 = us * i // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let c4 = us / i // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} - let d1 = i + us // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'UnicodeScalar'}} expected-note{{overloads for '+' exist with these partially matching parameter lists:}} - let d2 = i - us // expected-error {{binary operator '-' cannot be applied to operands of type 'Int' and 'UnicodeScalar'}} expected-note {{expected an argument list of type '(Int, Int)'}} - let d3 = i * us // expected-error {{binary operator '*' cannot be applied to operands of type 'Int' and 'UnicodeScalar'}} expected-note {{expected an argument list of type '(Int, Int)'}} - let d4 = i / us // expected-error {{binary operator '/' cannot be applied to operands of type 'Int' and 'UnicodeScalar'}} expected-note {{expected an argument list of type '(Int, Int)'}} + let d1 = i + us // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let d2 = i - us // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let d3 = i * us // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} + let d4 = i / us // expected-error {{cannot convert value of type 'UnicodeScalar' (aka 'Unicode.Scalar') to expected argument type 'Int'}} } From b6d0ef5c815bf5d29145206191105ee97f6bde7a Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Tue, 19 May 2020 17:09:03 +0200 Subject: [PATCH 095/625] Remove support for a broken std::regex in libstdc++ 4.8 Out of all operating systems ever supported by Swift, only Ubuntu 14.04 had libstdc++ 4.8, and Swift has sunset support for Ubuntu 14.04 for a while now. --- CMakeLists.txt | 3 -- cmake/modules/SwiftCheckCXXNativeRegex.cmake | 32 ------------------- include/swift/Config.h.in | 2 -- lib/IDE/SyntaxModel.cpp | 2 -- test/IDE/coloring_comments.swift | 1 - .../CodeComplete/complete_crash1.swift | 1 - .../CodeComplete/complete_filter.swift | 1 - .../CodeComplete/complete_fuzzy.swift | 2 -- .../complete_group_overloads.swift | 2 -- .../complete_import_module_flag.swift | 1 - .../CodeComplete/complete_inner.swift | 8 ++--- .../CodeComplete/complete_literals.swift | 1 - .../complete_moduleimportdepth.swift | 1 - .../CodeComplete/complete_name.swift | 1 - .../CodeComplete/complete_operators.swift | 1 - .../CodeComplete/complete_requestlimit.swift | 2 -- .../CodeComplete/complete_sort_order.swift | 1 - .../CodeComplete/complete_stems.swift | 2 -- .../CodeComplete/complete_structure.swift | 1 - .../CodeComplete/complete_test.swift | 2 -- .../CodeComplete/complete_type_match.swift | 1 - test/SourceKit/SyntaxMapData/syntaxmap.swift | 1 - test/lit.site.cfg.in | 3 -- 23 files changed, 3 insertions(+), 69 deletions(-) delete mode 100644 cmake/modules/SwiftCheckCXXNativeRegex.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 163463405c81d..93d6d11347fd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -555,9 +555,6 @@ if(XCODE) swift_common_xcode_cxx_config() endif() -include(SwiftCheckCXXNativeRegex) -check_cxx_native_regex(SWIFT_HAVE_WORKING_STD_REGEX) - # If SWIFT_HOST_VARIANT_SDK not given, try to detect from the CMAKE_SYSTEM_NAME. if(SWIFT_HOST_VARIANT_SDK) set(SWIFT_HOST_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}") diff --git a/cmake/modules/SwiftCheckCXXNativeRegex.cmake b/cmake/modules/SwiftCheckCXXNativeRegex.cmake deleted file mode 100644 index 2e320bd8f9fb9..0000000000000 --- a/cmake/modules/SwiftCheckCXXNativeRegex.cmake +++ /dev/null @@ -1,32 +0,0 @@ -function(check_cxx_native_regex result_var_name) - if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") - # Apple operating systems use libc++, which has a working std::regex. - set("${result_var_name}" TRUE PARENT_SCOPE) - else() - if(CMAKE_CROSSCOMPILING) - # Can't run C source when cross-compiling; assume false until we have a static check. - set("${result_var_name}" FALSE PARENT_SCOPE) - else() - # libstdc++ 4.8 has an incomplete std::regex implementation, and crashes - # on many regexes. - # libstdc++ 4.9 works. - set(std_regex_test_source - " - #include - const std::regex broken_regex{ - \"([a]+)\", - std::regex::ECMAScript | std::regex::nosubs}; - - int main() {} - ") - - check_cxx_source_runs("${std_regex_test_source}" "${result_var_name}_TEST") - if ("${${result_var_name}_TEST}") - set("${result_var_name}" TRUE PARENT_SCOPE) - else() - set("${result_var_name}" FALSE PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - diff --git a/include/swift/Config.h.in b/include/swift/Config.h.in index ec8030b3d1b03..b4e46a98b7b79 100644 --- a/include/swift/Config.h.in +++ b/include/swift/Config.h.in @@ -4,8 +4,6 @@ #ifndef SWIFT_CONFIG_H #define SWIFT_CONFIG_H -#cmakedefine SWIFT_HAVE_WORKING_STD_REGEX 1 - #cmakedefine HAVE_WAIT4 1 #cmakedefine HAVE_PROC_PID_RUSAGE 1 diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index 69df1b49fd1b6..c0bed82855d06 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -1509,7 +1509,6 @@ bool ModelASTWalker::processComment(CharSourceRange Range) { bool ModelASTWalker::findUrlStartingLoc(StringRef Text, unsigned &Start, std::regex &Regex) { -#ifdef SWIFT_HAVE_WORKING_STD_REGEX static const auto MailToPosition = std::find(URLProtocols.begin(), URLProtocols.end(), "mailto"); @@ -1541,7 +1540,6 @@ bool ModelASTWalker::findUrlStartingLoc(StringRef Text, } } } -#endif return false; } diff --git a/test/IDE/coloring_comments.swift b/test/IDE/coloring_comments.swift index 16767eb9d5c8f..4e503face3f17 100644 --- a/test/IDE/coloring_comments.swift +++ b/test/IDE/coloring_comments.swift @@ -1,5 +1,4 @@ // RUN: %target-swift-ide-test -syntax-coloring -source-filename %s | %FileCheck %s -// XFAIL: broken_std_regex // CHECK: /* foo is the best */ /* foo is the best */ diff --git a/test/SourceKit/CodeComplete/complete_crash1.swift b/test/SourceKit/CodeComplete/complete_crash1.swift index 106c7683dd5e7..e190b7f87e0ac 100644 --- a/test/SourceKit/CodeComplete/complete_crash1.swift +++ b/test/SourceKit/CodeComplete/complete_crash1.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %complete-test -tok=TOK1 -hide-none %s import QuartzCore diff --git a/test/SourceKit/CodeComplete/complete_filter.swift b/test/SourceKit/CodeComplete/complete_filter.swift index a39eef9162158..6b7369832ab0f 100644 --- a/test/SourceKit/CodeComplete/complete_filter.swift +++ b/test/SourceKit/CodeComplete/complete_filter.swift @@ -11,7 +11,6 @@ func foo() { x.#^FOO,,a,aa,ab,abc,abcd^# } -// XFAIL: broken_std_regex // RUN: %sourcekitd-test -req=complete.open -pos=11:5 %s -- %s > %t.all // RUN: %FileCheck -check-prefix=CHECK-ALL %s < %t.all // CHECK-ALL: key.name: "aaa diff --git a/test/SourceKit/CodeComplete/complete_fuzzy.swift b/test/SourceKit/CodeComplete/complete_fuzzy.swift index 5b93ae884154c..28be66b25965f 100644 --- a/test/SourceKit/CodeComplete/complete_fuzzy.swift +++ b/test/SourceKit/CodeComplete/complete_fuzzy.swift @@ -9,8 +9,6 @@ func footastic() {} // ===- Without a filter, we group. -// XFAIL: broken_std_regex - // RUN: %complete-test %s -group=stems -tok=TOP_LEVEL_NO_FILTER | %FileCheck %s -check-prefix=TOP_LEVEL_NO_FILTER // RUN: %complete-test %s -group=stems -fuzz -tok=TOP_LEVEL_NO_FILTER | %FileCheck %s -check-prefix=TOP_LEVEL_NO_FILTER func test1() { diff --git a/test/SourceKit/CodeComplete/complete_group_overloads.swift b/test/SourceKit/CodeComplete/complete_group_overloads.swift index dbeea5604c4a4..02648d994c654 100644 --- a/test/SourceKit/CodeComplete/complete_group_overloads.swift +++ b/test/SourceKit/CodeComplete/complete_group_overloads.swift @@ -1,5 +1,3 @@ -// XFAIL: broken_std_regex - struct A {} struct B {} diff --git a/test/SourceKit/CodeComplete/complete_import_module_flag.swift b/test/SourceKit/CodeComplete/complete_import_module_flag.swift index 954774ff50e3b..1ca1329a9bc70 100644 --- a/test/SourceKit/CodeComplete/complete_import_module_flag.swift +++ b/test/SourceKit/CodeComplete/complete_import_module_flag.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %empty-directory(%t) // RUN: %swift -Xcc -I%S/Inputs -emit-module -o %t/auxiliary_file.swiftmodule %S/Inputs/auxiliary_file.swift // RUN: %complete-test -group=none -hide-none -raw -tok=TOP_LEVEL_0 %s -- -Xfrontend -import-module -Xfrontend auxiliary_file -I %t -I %S/Inputs | %FileCheck %s diff --git a/test/SourceKit/CodeComplete/complete_inner.swift b/test/SourceKit/CodeComplete/complete_inner.swift index 660de8c88063c..1c11f13ca57b7 100644 --- a/test/SourceKit/CodeComplete/complete_inner.swift +++ b/test/SourceKit/CodeComplete/complete_inner.swift @@ -1,5 +1,3 @@ -// XFAIL: broken_std_regex - class Foo {} class Base { init() {} @@ -30,18 +28,18 @@ func test010(x: E1, y: FooBar) { } } -// RUN: %sourcekitd-test -req=complete.open -pos=26:11 -req-opts=filtertext=on %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_0a +// RUN: %sourcekitd-test -req=complete.open -pos=24:11 -req-opts=filtertext=on %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_0a // INNER_POSTFIX_0a-NOT: key.description: "one{{.+}}" // INNER_POSTFIX_0a: key.description: "one",{{$}} // INNER_POSTFIX_0a-NOT: key.description: "one{{.+}}" -// RUN: %sourcekitd-test -req=complete.open -pos=26:11 -req-opts=filtertext=one %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_0b +// RUN: %sourcekitd-test -req=complete.open -pos=24:11 -req-opts=filtertext=one %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_0b // INNER_POSTFIX_0b-NOT: key.description: "one{{.+}}" // INNER_POSTFIX_0b: key.description: "one",{{$}} // INNER_POSTFIX_0b: key.description: "one.",{{$}} // INNER_POSTFIX_0b-NOT: key.description: "one{{.+}}" -// RUN: %sourcekitd-test -req=complete.open -pos=29:9 -req-opts=filtertext=pro %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_1 +// RUN: %sourcekitd-test -req=complete.open -pos=27:9 -req-opts=filtertext=pro %s -- %s | %FileCheck %s -check-prefix=INNER_POSTFIX_1 // INNER_POSTFIX_1-NOT: key.description: "prop{{.+}}" // INNER_POSTFIX_1: key.description: "prop",{{$}} // INNER_POSTFIX_1-NOT: key.description: "prop{{.+}}" diff --git a/test/SourceKit/CodeComplete/complete_literals.swift b/test/SourceKit/CodeComplete/complete_literals.swift index 2a0b2329ca702..a21d5b2a58ae3 100644 --- a/test/SourceKit/CodeComplete/complete_literals.swift +++ b/test/SourceKit/CodeComplete/complete_literals.swift @@ -1,7 +1,6 @@ () let var1 = 1 let var2: Int = 1 -// XFAIL: broken_std_regex // RUN: %sourcekitd-test -req=complete -pos=1:2 %s -- %s | %FileCheck %s -check-prefix=COMPLETE_1 // RUN: %sourcekitd-test -req=complete -pos=2:12 %s -- %s | %FileCheck %s -check-prefix=COMPLETE_1 // RUN: %sourcekitd-test -req=complete -pos=3:17 %s -- %s | %FileCheck %s -check-prefix=COMPLETE_2 diff --git a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift index 808ab0d9a03d9..cbb6e11821ebe 100644 --- a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift +++ b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift @@ -5,7 +5,6 @@ func test() { #^A^# } -// XFAIL: broken_std_regex // REQUIRES: objc_interop // RUN: %complete-test -hide-none -group=none -tok=A %s -raw -- -I %S/Inputs -F %S/../Inputs/libIDE-mock-sdk > %t // RUN: %FileCheck %s < %t diff --git a/test/SourceKit/CodeComplete/complete_name.swift b/test/SourceKit/CodeComplete/complete_name.swift index 752c48d3dc302..21c7cf5032cd9 100644 --- a/test/SourceKit/CodeComplete/complete_name.swift +++ b/test/SourceKit/CodeComplete/complete_name.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %complete-test -raw -tok=INIT_NAME %s | %FileCheck %s -check-prefix=INIT_NAME // RUN: %complete-test -raw -tok=METHOD_NAME %s | %FileCheck %s -check-prefix=METHOD_NAME diff --git a/test/SourceKit/CodeComplete/complete_operators.swift b/test/SourceKit/CodeComplete/complete_operators.swift index 42152a3dab1ce..a6d7053fa70d0 100644 --- a/test/SourceKit/CodeComplete/complete_operators.swift +++ b/test/SourceKit/CodeComplete/complete_operators.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %complete-test -tok=INT_OPERATORS %s | %FileCheck %s // RUN: %complete-test -add-inner-results -tok=INT_OPERATORS_INNER %s | %FileCheck %s -check-prefix=INNER // RUN: %complete-test -raw -hide-none -tok=INT_OPERATORS %s | %FileCheck %s -check-prefix=RAW diff --git a/test/SourceKit/CodeComplete/complete_requestlimit.swift b/test/SourceKit/CodeComplete/complete_requestlimit.swift index a22cc32c70fc8..3dad6b6a7592e 100644 --- a/test/SourceKit/CodeComplete/complete_requestlimit.swift +++ b/test/SourceKit/CodeComplete/complete_requestlimit.swift @@ -1,5 +1,3 @@ -// XFAIL: broken_std_regex - struct A {} struct B { let a: A diff --git a/test/SourceKit/CodeComplete/complete_sort_order.swift b/test/SourceKit/CodeComplete/complete_sort_order.swift index 653935446f104..9e2a70bb3d5f2 100644 --- a/test/SourceKit/CodeComplete/complete_sort_order.swift +++ b/test/SourceKit/CodeComplete/complete_sort_order.swift @@ -7,7 +7,6 @@ func test() { } -// XFAIL: broken_std_regex // RUN: %sourcekitd-test -req=complete -req-opts=hidelowpriority=0 -pos=7:1 %s -- %s > %t.orig // RUN: %sourcekitd-test -req=complete -req-opts=hidelowpriority=0,sort.byname=0 -pos=7:1 %s -- %s > %t.orig.off // RUN: %FileCheck -check-prefix=NAME_SORTED %s < %t.orig diff --git a/test/SourceKit/CodeComplete/complete_stems.swift b/test/SourceKit/CodeComplete/complete_stems.swift index fc5fbb301bece..5620a296f843e 100644 --- a/test/SourceKit/CodeComplete/complete_stems.swift +++ b/test/SourceKit/CodeComplete/complete_stems.swift @@ -1,5 +1,3 @@ -// XFAIL: broken_std_regex - func aaaBbb() {} func aaaaBbb() {} func aaaCcc() {} diff --git a/test/SourceKit/CodeComplete/complete_structure.swift b/test/SourceKit/CodeComplete/complete_structure.swift index 1133d1918e4c8..208f09dfc8720 100644 --- a/test/SourceKit/CodeComplete/complete_structure.swift +++ b/test/SourceKit/CodeComplete/complete_structure.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %complete-test %s -group=none -fuzz -structure -tok=S1_DOT | %FileCheck %s -check-prefix=S1_DOT // RUN: %complete-test %s -group=none -add-inner-results -fuzz -structure -tok=S1_POSTFIX | %FileCheck %s -check-prefix=S1_POSTFIX // RUN: %complete-test %s -group=none -add-inner-results -fuzz -structure -tok=S1_POSTFIX_INIT | %FileCheck %s -check-prefix=S1_INIT diff --git a/test/SourceKit/CodeComplete/complete_test.swift b/test/SourceKit/CodeComplete/complete_test.swift index d28999a7cbbfb..b094d670a3022 100644 --- a/test/SourceKit/CodeComplete/complete_test.swift +++ b/test/SourceKit/CodeComplete/complete_test.swift @@ -48,5 +48,3 @@ struct ForDiff { func diff(x: ForDiff) { x.#^DIFF^# } - -// XFAIL: broken_std_regex diff --git a/test/SourceKit/CodeComplete/complete_type_match.swift b/test/SourceKit/CodeComplete/complete_type_match.swift index 09d3ff945bc20..2d7088f6b8e44 100644 --- a/test/SourceKit/CodeComplete/complete_type_match.swift +++ b/test/SourceKit/CodeComplete/complete_type_match.swift @@ -1,4 +1,3 @@ -// XFAIL: broken_std_regex // RUN: %complete-test -top=0 -tok=TOP_LEVEL_0 %s | %FileCheck %s -check-prefix=TOP_LEVEL_0 // RUN: %complete-test -top=0 -tok=TOP_LEVEL_1 %s | %FileCheck %s -check-prefix=TOP_LEVEL_1 // RUN: %complete-test -top=0 -tok=TOP_LEVEL_2 %s | %FileCheck %s -check-prefix=TOP_LEVEL_2 diff --git a/test/SourceKit/SyntaxMapData/syntaxmap.swift b/test/SourceKit/SyntaxMapData/syntaxmap.swift index 3a10ff7c178c3..c8af17a33c3ab 100644 --- a/test/SourceKit/SyntaxMapData/syntaxmap.swift +++ b/test/SourceKit/SyntaxMapData/syntaxmap.swift @@ -1,3 +1,2 @@ -// XFAIL: broken_std_regex // RUN: %sourcekitd-test -req=syntax-map %S/Inputs/syntaxmap.swift > %t.response // RUN: %diff -u %s.response %t.response diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 69107930747b0..7df41178b775c 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -89,9 +89,6 @@ if "@SWIFT_OPTIMIZED@" == "TRUE": if "@SWIFT_STDLIB_USE_NONATOMIC_RC@" == "TRUE": config.available_features.add("nonatomic_rc") -if "@SWIFT_HAVE_WORKING_STD_REGEX@" == "FALSE": - config.available_features.add('broken_std_regex') - if "@SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS@" == "TRUE": config.available_features.add('runtime_function_counters') From d3c685d7350cf2356cf037c08843686b0dafb192 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 18 May 2020 10:42:22 -0700 Subject: [PATCH 096/625] IRGen: Correctly compute the offset for a non-fixed field after an empty field Introduce getByteOffsetDuringLayout() so that we can treat empty fields just like other fixed sized field while performing layout. rdar://62349871 --- lib/IRGen/GenHeap.cpp | 2 +- lib/IRGen/StructLayout.cpp | 3 +- lib/IRGen/StructLayout.h | 26 +++++++++++- test/IRGen/partial_apply.sil | 79 ++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 09b938a92921a..ec3d205149d3a 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -292,7 +292,7 @@ static llvm::Value *calcInitOffset(swift::irgen::IRGenFunction &IGF, auto &prevElt = layout.getElement(i - 1); auto prevType = layout.getElementTypes()[i - 1]; // Start calculating offsets from the last fixed-offset field. - Size lastFixedOffset = layout.getElement(i - 1).getByteOffset(); + Size lastFixedOffset = layout.getElement(i - 1).getByteOffsetDuringLayout(); if (auto *fixedType = dyn_cast(&prevElt.getType())) { // If the last fixed-offset field is also fixed-size, we can // statically compute the end of the fixed-offset fields. diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index 4b2d8598065ee..7be5b032566ae 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -312,7 +312,8 @@ void StructLayoutBuilder::addNonFixedSizeElement(ElementLayout &elt) { /// Add an empty element to the aggregate. void StructLayoutBuilder::addEmptyElement(ElementLayout &elt) { - elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal)); + auto byteOffset = isFixedLayout() ? CurSize : Size(0); + elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal), CurSize); } /// Add an element at the fixed offset of the current end of the diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h index bc20701d74a1f..541c2cd268988 100644 --- a/lib/IRGen/StructLayout.h +++ b/lib/IRGen/StructLayout.h @@ -114,6 +114,14 @@ class ElementLayout { /// The offset in bytes from the start of the struct. unsigned ByteOffset; + /// The offset in bytes from the start of the struct, except EmptyFields are + /// placed at the current byte offset instead of 0. For the purpose of the + /// final layout empty fields are placed at offset 0, that however creates a + /// whole slew of special cases to deal with. Instead of dealing with these + /// special cases during layout, we pretend that empty fields are placed + /// just like any other field at the current offset. + unsigned ByteOffsetForLayout; + /// The index of this element, either in the LLVM struct (if fixed) /// or in the non-fixed elements array (if non-fixed). unsigned Index : 28; @@ -142,13 +150,15 @@ class ElementLayout { TheKind = other.TheKind; IsPOD = other.IsPOD; ByteOffset = other.ByteOffset; + ByteOffsetForLayout = other.ByteOffsetForLayout; Index = other.Index; } - void completeEmpty(IsPOD_t isPOD) { + void completeEmpty(IsPOD_t isPOD, Size byteOffset) { TheKind = unsigned(Kind::Empty); IsPOD = unsigned(isPOD); ByteOffset = 0; + ByteOffsetForLayout = byteOffset.getValue(); Index = 0; // make a complete write of the bitfield } @@ -156,6 +166,7 @@ class ElementLayout { TheKind = unsigned(Kind::InitialNonFixedSize); IsPOD = unsigned(isPOD); ByteOffset = 0; + ByteOffsetForLayout = ByteOffset; Index = 0; // make a complete write of the bitfield } @@ -163,6 +174,7 @@ class ElementLayout { TheKind = unsigned(Kind::Fixed); IsPOD = unsigned(isPOD); ByteOffset = byteOffset.getValue(); + ByteOffsetForLayout = ByteOffset; Index = structIndex; assert(getByteOffset() == byteOffset); @@ -172,6 +184,7 @@ class ElementLayout { TheKind = unsigned(Kind::EmptyTailAllocatedCType); IsPOD = unsigned(isPOD); ByteOffset = byteOffset.getValue(); + ByteOffsetForLayout = ByteOffset; Index = 0; assert(getByteOffset() == byteOffset); @@ -228,6 +241,17 @@ class ElementLayout { return Size(ByteOffset); } + /// The offset in bytes from the start of the struct, except EmptyFields are + /// placed at the current byte offset instead of 0. For the purpose of the + /// final layout empty fields are placed at offset 0, that however creates a + /// whole slew of special cases to deal with. Instead of dealing with these + /// special cases during layout, we pretend that empty fields are placed + /// just like any other field at the current offset. + Size getByteOffsetDuringLayout() const { + assert(isCompleted() && hasByteOffset()); + return Size(ByteOffsetForLayout); + } + /// Given that this element has a fixed offset, return the index in /// the LLVM struct. unsigned getStructIndex() const { diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil index 14da9028dfb95..e318718773a5d 100644 --- a/test/IRGen/partial_apply.sil +++ b/test/IRGen/partial_apply.sil @@ -767,3 +767,82 @@ bb0(%x : $*ResilientInt, %y : $SwiftClass): %t = tuple() return %t : $() } + +protocol Proto1 {} +protocol Proto2 {} +struct EmptyType : Proto1 { } + +struct SomeType : Proto2 { + var d : ResilientInt // some resilient type + var x : Int +} + +sil @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + +// CHECK-64-LABEL: define swiftcc void @empty_followed_by_non_fixed(%T13partial_apply8SomeTypeV* noalias nocapture %0) +// CHECK-64: [[FLAGS:%.*]] = load i32, i32* +// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 +// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 +// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1 +// Make sure we take the header offset (16) into account. +// CHECK-64: [[TMP:%.*]] = add i64 16, [[ALIGNMASK]] +// CHECK-64: [[OFFSET:%.*]] = and i64 [[TMP]], [[NOTALIGNMASK]] +// CHECK-64: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @swift_allocObject +// CHECK-64: [[CAST:%.*]] = bitcast %swift.refcounted* [[CONTEXT]] to <{ %swift.refcounted }>* +// CHECK-64: [[CAST2:%.*]] = bitcast <{ %swift.refcounted }>* [[CAST]] to i8* +// CHECK-64: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[CAST2]], i64 [[OFFSET]] +// CHECK-64: [[CAST3:%.*]] = bitcast i8* [[GEP]] to %T13partial_apply8SomeTypeV* +// CHECK-64: call %T13partial_apply8SomeTypeV* @"$s13partial_apply8SomeTypeVWOb"(%T13partial_apply8SomeTypeV* {{.*}}, %T13partial_apply8SomeTypeV* [[CAST3]]) + +sil @empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType) -> () { +entry(%0 : $EmptyType, %1: $*SomeType): + %5 = alloc_stack $EmptyType + store %0 to %5 : $*EmptyType + %31 = function_ref @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + %32 = alloc_stack $EmptyType + copy_addr %5 to [initialization] %32 : $*EmptyType + %34 = alloc_stack $SomeType + copy_addr %1 to [initialization] %34 : $*SomeType // id: %35 + %36 = partial_apply [callee_guaranteed] %31(%32, %34) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + release_value %36: $@callee_guaranteed () ->() + dealloc_stack %34 : $*SomeType + dealloc_stack %32 : $*EmptyType + dealloc_stack %5 : $*EmptyType + %40 = tuple() + return %40 : $() +} + +struct FixedType { + var f: Int32 +} +// CHECK-64-LABEL: define{{.*}} swiftcc void @fixed_followed_by_empty_followed_by_non_fixed +// CHECK-64-NOT: ret +// CHECK-64: [[FLAGS:%.*]] = load i32, i32* +// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 +// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 +// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1 +// Make sure we compute the correct offset of the non-fixed field. +// CHECK-64: [[TMP:%.*]] = add i64 20, [[ALIGNMASK]] +// CHECK-64: ret + +sil @foo2 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () +sil @fixed_followed_by_empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType, FixedType) -> () { +entry(%0 : $EmptyType, %1: $*SomeType, %3: $FixedType): + %5 = alloc_stack $EmptyType + store %0 to %5 : $*EmptyType + %7 = alloc_stack $FixedType + store %3 to %7 : $*FixedType + %31 = function_ref @foo2 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () + %32 = alloc_stack $EmptyType + copy_addr %5 to [initialization] %32 : $*EmptyType + %34 = alloc_stack $SomeType + copy_addr %1 to [initialization] %34 : $*SomeType // id: %35 + %36 = partial_apply [callee_guaranteed] %31(%7, %32, %34) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () + release_value %36: $@callee_guaranteed () ->() + dealloc_stack %34 : $*SomeType + dealloc_stack %32 : $*EmptyType + dealloc_stack %7 : $*FixedType + dealloc_stack %5 : $*EmptyType + %40 = tuple() + return %40 : $() +} From b01889c813fae41e600c20410a38dbed8075688d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 19 May 2020 09:04:03 -0700 Subject: [PATCH 097/625] Acutally use the variable I introduced --- lib/IRGen/StructLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index 7be5b032566ae..66f11250ab5a5 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -313,7 +313,7 @@ void StructLayoutBuilder::addNonFixedSizeElement(ElementLayout &elt) { /// Add an empty element to the aggregate. void StructLayoutBuilder::addEmptyElement(ElementLayout &elt) { auto byteOffset = isFixedLayout() ? CurSize : Size(0); - elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal), CurSize); + elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal), byteOffset); } /// Add an element at the fixed offset of the current end of the From 1e74c202effa9913625d771d650488ef5b6263af Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 19 May 2020 17:04:59 +0000 Subject: [PATCH 098/625] build: optimize the build of LLVMSupport Rather than build multiple copies of LLVMSupport (4x!) build it one and merge it into the various targets. This would ideally not be needed to be named explicitly everywhere, but that requires using `add_library` rather than `add_swift_target_library`. --- stdlib/CMakeLists.txt | 1 + stdlib/public/LLVMSupport/CMakeLists.txt | 13 +++++++++---- stdlib/public/Reflection/CMakeLists.txt | 9 ++------- stdlib/public/SwiftRemoteMirror/CMakeLists.txt | 7 +------ stdlib/public/core/CMakeLists.txt | 2 +- stdlib/public/runtime/CMakeLists.txt | 7 +------ unittests/runtime/CMakeLists.txt | 1 + unittests/runtime/LongTests/CMakeLists.txt | 1 + 8 files changed, 17 insertions(+), 24 deletions(-) diff --git a/stdlib/CMakeLists.txt b/stdlib/CMakeLists.txt index e5eb948a2294a..bfeb17e2f2d2d 100644 --- a/stdlib/CMakeLists.txt +++ b/stdlib/CMakeLists.txt @@ -62,6 +62,7 @@ endif() # built and cause link failures for mismatches. Without linking that library, # we get link failures regardless, so instead, this just disables the checks. add_compile_definitions($<$,$>:LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1>) +include_directories(BEFORE ${CMAKE_PROJECT_SOURCE_DIR}/include) set(SWIFT_STDLIB_LIBRARY_BUILD_TYPES) if(SWIFT_BUILD_DYNAMIC_STDLIB) diff --git a/stdlib/public/LLVMSupport/CMakeLists.txt b/stdlib/public/LLVMSupport/CMakeLists.txt index b34e481e665ab..1e688137c17d3 100644 --- a/stdlib/public/LLVMSupport/CMakeLists.txt +++ b/stdlib/public/LLVMSupport/CMakeLists.txt @@ -18,7 +18,12 @@ set(LLVM_USE_PERF NO) configure_file(${PROJECT_SOURCE_DIR}/include/llvm/Config/llvm-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/llvm/Config/llvm-config.h) -add_library(swiftLLVMSupport INTERFACE) -target_include_directories(swiftLLVMSupport INTERFACE - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_PROJECT_SOURCE_DIR}/include) +add_swift_target_library(swiftLLVMSupport OBJECT_LIBRARY + ErrorHandling.cpp + Hashing.cpp + MemAlloc.cpp + SmallPtrSet.cpp + SmallVector.cpp + StringRef.cpp + INSTALL_IN_COMPONENT + never_install) diff --git a/stdlib/public/Reflection/CMakeLists.txt b/stdlib/public/Reflection/CMakeLists.txt index 61f470fea8581..90e0025692f00 100644 --- a/stdlib/public/Reflection/CMakeLists.txt +++ b/stdlib/public/Reflection/CMakeLists.txt @@ -9,13 +9,7 @@ set(swiftReflection_SOURCES "${SWIFT_SOURCE_DIR}/lib/Demangling/NodePrinter.cpp" "${SWIFT_SOURCE_DIR}/lib/Demangling/ManglingUtils.cpp" "${SWIFT_SOURCE_DIR}/lib/Demangling/Punycode.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/ErrorHandling.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/Hashing.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/MemAlloc.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallPtrSet.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallVector.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/StringRef.cpp") + "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp") # When we're building with assertions, include the demangle node dumper to aid # in debugging. @@ -28,5 +22,6 @@ add_swift_target_library(swiftReflection STATIC ${swiftReflection_SOURCES} C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS} -DswiftCore_EXPORTS LINK_FLAGS ${SWIFT_RUNTIME_LINK_FLAGS} + INCORPORATE_OBJECT_LIBRARIES swiftLLVMSupport SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT dev) diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt index 917f56264f257..08e174a41ca32 100644 --- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt +++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt @@ -4,18 +4,13 @@ if(SWIFT_BUILD_DYNAMIC_STDLIB) add_swift_target_library(swiftRemoteMirror SHARED DONT_EMBED_BITCODE NOSWIFTRT SwiftRemoteMirror.cpp - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/ErrorHandling.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/Hashing.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/MemAlloc.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallPtrSet.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallVector.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/StringRef.cpp" LINK_LIBRARIES swiftReflection C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS} -DswiftRemoteMirror_EXPORTS LINK_FLAGS ${SWIFT_RUNTIME_LINK_FLAGS} + INCORPORATE_OBJECT_LIBRARIES swiftLLVMSupport SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT swift-remote-mirror) diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 95ee7f07826a5..3f9c7362c5803 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -319,7 +319,7 @@ add_swift_target_library(swiftCore PRIVATE_LINK_LIBRARIES ${swift_core_private_link_libraries} INCORPORATE_OBJECT_LIBRARIES - swiftRuntime swiftStdlibStubs + swiftRuntime swiftLLVMSupport swiftStdlibStubs FRAMEWORK_DEPENDS ${swift_core_framework_depends} INSTALL_IN_COMPONENT diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 27c41abcd7479..eaf77fe23e015 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -63,12 +63,6 @@ set(swift_runtime_sources RefCount.cpp RuntimeInvocationsTracking.cpp SwiftDtoa.cpp - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/ErrorHandling.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/Hashing.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/MemAlloc.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallPtrSet.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/SmallVector.cpp" - "${SWIFT_SOURCE_DIR}/stdlib/public/LLVMSupport/StringRef.cpp" "${SWIFT_SOURCE_DIR}/lib/Demangling/OldDemangler.cpp" "${SWIFT_SOURCE_DIR}/lib/Demangling/Demangler.cpp" "${SWIFT_SOURCE_DIR}/lib/Demangling/NodePrinter.cpp" @@ -180,6 +174,7 @@ add_swift_target_library(swiftRuntime OBJECT_LIBRARY ${swift_runtime_library_compile_flags} ${_RUNTIME_NONATOMIC_FLAGS} LINK_FLAGS ${swift_runtime_linker_flags} + INCORPORATE_OBJECT_LIBRARIES swiftLLVMSupport SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT never_install) diff --git a/unittests/runtime/CMakeLists.txt b/unittests/runtime/CMakeLists.txt index cf4d55b7d29b1..b151e7eb38145 100644 --- a/unittests/runtime/CMakeLists.txt +++ b/unittests/runtime/CMakeLists.txt @@ -74,6 +74,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # from the swiftCore dylib, so we need to link to both the runtime archive # and the stdlib. $ + $ ) # The local stdlib implementation provides definitions of the swiftCore diff --git a/unittests/runtime/LongTests/CMakeLists.txt b/unittests/runtime/LongTests/CMakeLists.txt index e4b6142b4894b..9a744261daa6d 100644 --- a/unittests/runtime/LongTests/CMakeLists.txt +++ b/unittests/runtime/LongTests/CMakeLists.txt @@ -37,6 +37,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # from the swiftCore dylib, so we need to link to both the runtime archive # and the stdlib. $ + $ ) # The local stdlib implementation provides definitions of the swiftCore From d4e09b0944a60e92eb9b658e11daf8e93f1f05dd Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 15 May 2020 15:32:03 -0700 Subject: [PATCH 099/625] [silgen] Add an extra swift-version 5 run to initializer tests. We currently run these in swift-version 4 by default. This caused us to miss some bugs that only occur in swift-version 5 due to initializer changes happening in swift 5. This at least will allow us to catch such issues in the future. NOTE: I am also going to change objc_throwing_initializers.swift in the same way, but after I fix the bugs that adding -swift-version 5 exposes therein (which is actually ) --- .../convenience_init_peer_delegation.swift | 17 ++++++++++++++++- test/Interpreter/failable_initializers.swift | 4 +++- test/Interpreter/initializers.swift | 4 +++- .../objc_failable_initializers.swift | 10 ++++++++++ test/Interpreter/protocol_initializers.swift | 10 +++++++++- .../protocol_initializers_class.swift | 8 +++----- test/Interpreter/throwing_initializers.swift | 4 +++- 7 files changed, 47 insertions(+), 10 deletions(-) diff --git a/test/Interpreter/convenience_init_peer_delegation.swift b/test/Interpreter/convenience_init_peer_delegation.swift index be1cb83e66de3..5a97589dfb2a2 100644 --- a/test/Interpreter/convenience_init_peer_delegation.swift +++ b/test/Interpreter/convenience_init_peer_delegation.swift @@ -1,14 +1,29 @@ // RUN: %empty-directory(%t) - +// // RUN: %target-build-swift %s -Xfrontend -disable-objc-attr-requires-foundation-module -o %t/main // RUN: %target-codesign %t/main // RUN: %target-run %t/main | %FileCheck %s +// RUN: %empty-directory(%t) +// // RUN: sed -e 's/required//g' < %s > %t/without_required.swift // RUN: %target-build-swift %t/without_required.swift -Xfrontend -disable-objc-attr-requires-foundation-module -o %t/without_required // RUN: %target-codesign %t/without_required // RUN: %target-run %t/without_required | %FileCheck %s +// RUN: %empty-directory(%t) +// +// RUN: %target-build-swift %s -Xfrontend -disable-objc-attr-requires-foundation-module -o %t/main -swift-version 5 +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main | %FileCheck %s + +// RUN: %empty-directory(%t) +// +// RUN: sed -e 's/required//g' < %s > %t/without_required.swift +// RUN: %target-build-swift %t/without_required.swift -Xfrontend -disable-objc-attr-requires-foundation-module -o %t/without_required -swift-version 5 +// RUN: %target-codesign %t/without_required +// RUN: %target-run %t/without_required | %FileCheck %s + // REQUIRES: executable_test // REQUIRES: objc_interop // XFAIL: CPU=arm64e diff --git a/test/Interpreter/failable_initializers.swift b/test/Interpreter/failable_initializers.swift index 28fd7f2926bc3..9ca1d54c329f7 100644 --- a/test/Interpreter/failable_initializers.swift +++ b/test/Interpreter/failable_initializers.swift @@ -1,4 +1,6 @@ -// RUN: %target-run-simple-swift +// RUN: %target-run-simple-swift(-swift-version 4) +// RUN: %target-run-simple-swift(-swift-version 5) + // REQUIRES: executable_test import StdlibUnittest diff --git a/test/Interpreter/initializers.swift b/test/Interpreter/initializers.swift index 36bcb374de91a..97715d025cd58 100644 --- a/test/Interpreter/initializers.swift +++ b/test/Interpreter/initializers.swift @@ -1,4 +1,6 @@ -// RUN: %target-run-simple-swift | %FileCheck %s +// RUN: %target-run-simple-swift(-swift-version 4) | %FileCheck %s +// RUN: %target-run-simple-swift(-swift-version 5) | %FileCheck %s + // REQUIRES: executable_test // Test initialization and initializer inheritance. diff --git a/test/Interpreter/objc_failable_initializers.swift b/test/Interpreter/objc_failable_initializers.swift index e45b2fd4774a3..637fb94c9b60f 100644 --- a/test/Interpreter/objc_failable_initializers.swift +++ b/test/Interpreter/objc_failable_initializers.swift @@ -5,6 +5,16 @@ // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out +// RUN: %empty-directory(%t) +// +// target-build-swift assumes we want -swift-version 4. Behavior in initializers +// changed in swift 5, so we want to explicitly check it as well. +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out -swift-version 5 +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + // REQUIRES: executable_test // REQUIRES: objc_interop diff --git a/test/Interpreter/protocol_initializers.swift b/test/Interpreter/protocol_initializers.swift index e399337af6d1b..cfdd42bfa8977 100644 --- a/test/Interpreter/protocol_initializers.swift +++ b/test/Interpreter/protocol_initializers.swift @@ -1,8 +1,16 @@ + // RUN: %empty-directory(%t) -// RUN: %target-build-swift -swift-version 5 %s -o %t/a.out +// +// RUN: %target-build-swift %s -o %t/a.out // RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// RUN: %empty-directory(%t) // +// RUN: %target-build-swift -swift-version 5 %s -o %t/a.out +// RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out + // REQUIRES: executable_test import StdlibUnittest diff --git a/test/Interpreter/protocol_initializers_class.swift b/test/Interpreter/protocol_initializers_class.swift index 9a841b7f66224..a5ce65f2e8d08 100644 --- a/test/Interpreter/protocol_initializers_class.swift +++ b/test/Interpreter/protocol_initializers_class.swift @@ -1,8 +1,6 @@ -// RUN: %empty-directory(%t) -// RUN: %target-build-swift -swift-version 5 %s -o %t/a.out -// RUN: %target-codesign %t/a.out -// -// RUN: %target-run %t/a.out +// RUN: %target-run-simple-swift(-swift-version 4) +// RUN: %target-run-simple-swift(-swift-version 5) + // REQUIRES: executable_test import StdlibUnittest diff --git a/test/Interpreter/throwing_initializers.swift b/test/Interpreter/throwing_initializers.swift index 1ea9171fa5382..59f256596ff73 100644 --- a/test/Interpreter/throwing_initializers.swift +++ b/test/Interpreter/throwing_initializers.swift @@ -1,4 +1,6 @@ -// RUN: %target-run-simple-swift +// RUN: %target-run-simple-swift(-swift-version 4) +// RUN: %target-run-simple-swift(-swift-version 5) + // REQUIRES: executable_test import StdlibUnittest From aa0f555cde55ce8689dcd02d233591844902cdfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Mon, 18 May 2020 20:54:20 -0700 Subject: [PATCH 100/625] No dummy constraint in the public swiftinterface for SPI extensions rdar://problem/63352700 --- lib/Frontend/ModuleInterfaceSupport.cpp | 13 ++++++++++--- test/SPI/private_swiftinterface.swift | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 79b655fbcdbce..39694452f81d6 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -345,12 +345,18 @@ class InheritedProtocolCollector { /// in \p map. /// /// \sa recordConditionalConformances - static void collectSkippedConditionalConformances(PerTypeMap &map, - const Decl *D) { + static void collectSkippedConditionalConformances( + PerTypeMap &map, + const Decl *D, + const PrintOptions &printOptions) { auto *extension = dyn_cast(D); if (!extension || !extension->isConstrainedExtension()) return; + // Skip SPI extensions in the public interface. + if (!printOptions.PrintSPIs && extension->isSPI()) + return; + const NominalTypeDecl *nominal = extension->getExtendedNominal(); if (!isPublicOrUsableFromInline(nominal)) return; @@ -497,8 +503,9 @@ bool swift::emitSwiftInterface(raw_ostream &out, if (!D->shouldPrintInContext(printOptions) || !printOptions.shouldPrint(D)) { + InheritedProtocolCollector::collectSkippedConditionalConformances( - inheritedProtocolMap, D); + inheritedProtocolMap, D, printOptions); continue; } diff --git a/test/SPI/private_swiftinterface.swift b/test/SPI/private_swiftinterface.swift index e0021dba83809..79168d2fd953c 100644 --- a/test/SPI/private_swiftinterface.swift +++ b/test/SPI/private_swiftinterface.swift @@ -87,3 +87,25 @@ private class PrivateClassLocal {} // CHECK-PRIVATE: @_spi(LocalSPI) public func extensionSPIMethod() // CHECK-PUBLIC-NOT: extensionSPIMethod } + +// Test the dummy conformance printed to replace private types used in +// conditional conformances. rdar://problem/63352700 + +// Conditional conformances using SPI types should appear in full in the +// private swiftinterface. +public struct PublicType {} +@_spi(LocalSPI) public protocol SPIProto {} +private protocol PrivateConstraint {} +@_spi(LocalSPI) public protocol SPIProto2 {} + +@_spi(LocalSPI) +extension PublicType: SPIProto2 where T: SPIProto2 {} +// CHECK-PRIVATE: extension PublicType : {{.*}}.SPIProto2 where T : {{.*}}.SPIProto2 +// CHECK-PUBLIC-NOT: _ConstraintThatIsNotPartOfTheAPIOfThisLibrary + +// The dummy conformance should be only in the private swiftinterface for +// SPI extensions. +@_spi(LocalSPI) +extension PublicType: SPIProto where T: PrivateConstraint {} +// CHECK-PRIVATE: extension {{.*}}.PublicType : {{.*}}.SPIProto where T : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary +// CHECK-PUBLIC-NOT: _ConstraintThatIsNotPartOfTheAPIOfThisLibrary From cccb21aca6d7d39e445b583b78299742839e3a18 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 19 May 2020 13:58:05 -0700 Subject: [PATCH 101/625] [driver] Add test for new behaviour in createCompilerInvocation Test for "ForceNoOutputs" flag. --- test/Driver/createCompilerInvocation.swift | 26 ++++++++++++++++++++++ tools/swift-ide-test/swift-ide-test.cpp | 16 ++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/test/Driver/createCompilerInvocation.swift b/test/Driver/createCompilerInvocation.swift index 0151cd7ea6cfa..30a340e598ad5 100644 --- a/test/Driver/createCompilerInvocation.swift +++ b/test/Driver/createCompilerInvocation.swift @@ -7,3 +7,29 @@ // CHECK-FAIL: error: unable to create a CompilerInvocation // CHECK-NOWARN-NOT: warning + +// RUN: %swift-ide-test_plain -test-createCompilerInvocation -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library %s 2>&1 | %FileCheck %s --check-prefix=NORMAL_ARGS --implicit-check-not="error: " +// NORMAL_ARGS: Frontend Arguments BEGIN +// NORMAL_ARGS-DAG: -o{{$}} +// NORMAL_ARGS-DAG: foo-{{[a-z0-9]+}}.o +// NORMAL_ARGS-DAG: -c{{$}} +// NORMAL_ARGS-DAG: -module-name +// NORMAL_ARGS-DAG: -emit-module-path +// NORMAL_ARGS-DAG: -emit-module-doc-path +// NORMAL_ARGS-DAG: -emit-module-source-info-path +// NORMAL_ARGS-DAG: -emit-module-interface-path +// NORMAL_ARGS-DAG: -emit-objc-header-path +// NORMAL_ARGS: Frontend Arguments END + +// RUN: %swift-ide-test_plain -test-createCompilerInvocation -force-no-outputs -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library %s 2>&1 > %t.nooutput_args +// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS --implicit-check-not="error: " < %t.nooutput_args +// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS_NEG --implicit-check-not="error: " < %t.nooutput_args +// NOOUTPUT_ARGS_NEG-NOT: -o{{$}} +// NOOUTPUT_ARGS_NEG-NOT: foo-{{[a-z0-9]+}}.o +// NOOUTPUT_ARGS_NEG-NOT: -o{{$}} +// NOOUTPUT_ARGS_NEG-NOT: -emit + +// NOOUTPUT_ARGS: Frontend Arguments BEGIN +// NOOUTPUT_ARGS-DAG: -typecheck +// NOOUTPUT_ARGS-DAG: -module-name +// NOOUTPUT_ARGS: Frontend Arguments END diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index f1795d894969d..244765c3cba13 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -3223,7 +3223,7 @@ static int doPrintUSRs(const CompilerInvocation &InitInvok, return 0; } -static int doTestCreateCompilerInvocation(ArrayRef Args) { +static int doTestCreateCompilerInvocation(ArrayRef Args, bool ForceNoOutputs) { PrintingDiagnosticConsumer PDC; SourceManager SM; DiagnosticEngine Diags(SM); @@ -3232,8 +3232,13 @@ static int doTestCreateCompilerInvocation(ArrayRef Args) { CompilerInvocation CI; bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( Args, Diags, [&](ArrayRef FrontendArgs) { + llvm::outs() << "Frontend Arguments BEGIN\n"; + for (const char *arg : FrontendArgs) { + llvm::outs() << arg << "\n"; + } + llvm::outs() << "Frontend Arguments END\n"; return CI.parseArgs(FrontendArgs, Diags); - }); + }, ForceNoOutputs); if (HadError) { llvm::errs() << "error: unable to create a CompilerInvocation\n"; @@ -3271,8 +3276,13 @@ int main(int argc, char *argv[]) { // llvm::cl::ParseCommandLineOptions. StringRef FirstArg(argv[1]); if (FirstArg == "-test-createCompilerInvocation") { + bool ForceNoOutputs = false; ArrayRef Args(argv + 2, argc - 2); - return doTestCreateCompilerInvocation(Args); + if (argc > 2 && StringRef(argv[2]) == "-force-no-outputs") { + ForceNoOutputs = true; + Args = Args.drop_front(); + } + return doTestCreateCompilerInvocation(Args, ForceNoOutputs); } } From cfbcd85904ac7d89a3aefb89ed864165a924c120 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Tue, 19 May 2020 19:12:09 +0200 Subject: [PATCH 102/625] Fix and reenable NewArray.swift.gyb --- validation-test/stdlib/NewArray.swift.gyb | 54 ++++++++++------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/validation-test/stdlib/NewArray.swift.gyb b/validation-test/stdlib/NewArray.swift.gyb index 2e9d4eb7d36c7..4bfb174b34905 100644 --- a/validation-test/stdlib/NewArray.swift.gyb +++ b/validation-test/stdlib/NewArray.swift.gyb @@ -10,13 +10,11 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// -// RUN-DISABLED: %target-run-simple-swift | %FileCheck %s // RUN: %empty-directory(%t) // RUN: %gyb %s -o %t/NewArray.swift // RUN: %line-directive %t/NewArray.swift -- %target-build-swift %t/NewArray.swift -o %t/a.out -Xfrontend -disable-access-control // RUN: %target-run %t/a.out 2>&1 | %line-directive %t/NewArray.swift -- %FileCheck %t/NewArray.swift --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // REQUIRES: executable_test -// XFAIL: * import StdlibUnittest import StdlibCollectionUnittest @@ -40,15 +38,14 @@ protocol MyArrayProtocol : RandomAccessCollection, RangeReplaceableCollection, MutableCollection, - ArrayLiteralConvertible { - - associatedtype Iterator : IteratorProtocol - + ExpressibleByArrayLiteral + where ArrayLiteralElement == Element +{ var _owner: AnyObject? { get } var capacity: Int { get } - func += < + static func += < S : Sequence >(lhs: inout Self, rhs: S) where S.Iterator.Element == Iterator.Element @@ -89,8 +86,7 @@ func test< T : MyArrayProtocol >(_: T.Type, _ label: String) where -T.Iterator.Element == LifetimeTracked, -T.Iterator.Element == T.Element, +T.Element == LifetimeTracked, T.Index == Int { print("test: \(label)...", terminator: "") @@ -113,15 +109,15 @@ T.Index == Int { x += LifetimeTracked(0).. Array { +func nsArrayOfStrings() -> NSArray { let src: ContiguousArray = ["foo", "bar", "baz"] return src.withUnsafeBufferPointer { - let ns = NSArray( + return NSArray( objects: unsafeBitCast($0.baseAddress!, to: UnsafeMutablePointer.self), count: $0.count) - return ns as! [NSString] } } +func swiftArrayWithNSArrayOfStrings() -> Array { + return nsArrayOfStrings() as! [NSString] +} + func testCocoa() { print("== Cocoa ==") // CHECK-objc: == Cocoa == - var a = nsArrayOfStrings() + var a = swiftArrayWithNSArrayOfStrings() printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -232,7 +231,7 @@ func testCocoa() { printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz, qux] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -246,12 +245,12 @@ func testCocoa() { printSequence(b) // CHECK-objc-NEXT: [foo, bar, baz] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() a.insert("bag", at: 2) printSequence(a) // CHECK-objc-NEXT: [foo, bar, bag, baz] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() a.reserveCapacity(30) printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -269,12 +268,6 @@ func testCocoa() { testCocoa() #endif // _runtime(_ObjC) -extension ArraySlice { - mutating func qsort(_ compare: @escaping (Element, Element) -> Bool) { - _introSort(&self, subRange: Range(self.indices), by: compare) - } -} - func testSlice() { print("== ArraySlice ==") // CHECK: == ArraySlice == @@ -301,14 +294,13 @@ func testSlice() { printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 41, 5, 6, 7, 8, 9] let c = b - b[b.startIndex..( - _ArrayBuffer(nsArray: nsArrayOfStrings()._buffer._asCocoaArray())) + let a = Array(_buffer: _ArrayBuffer(nsArray: nsArrayOfStrings())) printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -456,8 +448,8 @@ func testIsEmptyFirstLast${A}() { print("<\(${A}(3..<43).first!)>") // CHECK-NEXT: <3> print("<\(${A}(3..<43).last!)>") // CHECK-NEXT: <42> - print("<\(${A}().first)>") // CHECK-NEXT: nil - print("<\(${A}().last)>") // CHECK-NEXT: nil + print("<\(String(describing: ${A}().first))>") // CHECK-NEXT: nil + print("<\(String(describing:${A}().last))>") // CHECK-NEXT: nil var a = ${A}(LifetimeTracked(0).. Date: Tue, 19 May 2020 15:12:16 -0700 Subject: [PATCH 103/625] Fix test on linux --- test/IRGen/partial_apply.sil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil index e318718773a5d..b7607cb996163 100644 --- a/test/IRGen/partial_apply.sil +++ b/test/IRGen/partial_apply.sil @@ -779,7 +779,7 @@ struct SomeType : Proto2 { sil @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () -// CHECK-64-LABEL: define swiftcc void @empty_followed_by_non_fixed(%T13partial_apply8SomeTypeV* noalias nocapture %0) +// CHECK-64-LABEL: define{{.*}} swiftcc void @empty_followed_by_non_fixed(%T13partial_apply8SomeTypeV* noalias nocapture %0) // CHECK-64: [[FLAGS:%.*]] = load i32, i32* // CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 // CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 From af27e8f18378769b8bb6650cb73e45df2045b50b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 19 May 2020 11:28:40 -0700 Subject: [PATCH 104/625] [CodeCompletion] Avoid suggesting duplicated module names in global completion result. Overly modules have the same name as the shadowed modules. We should not list both names because they are identical. Maintain a set of seen module names to avoid suggesting duplicated names. rdar://problem/63370253 --- lib/IDE/CodeCompletion.cpp | 12 ++++-- .../Headers/OverlayTest.h | 2 + .../OverlayTest.framework/Headers/Overlayed.h | 13 +++++++ .../Modules/module.modulemap | 7 ++++ .../mock-sdk/OverlayTest.swiftinterface | 10 +++++ test/IDE/complete_overlaymodule.swift | 37 +++++++++++++++++++ 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface create mode 100644 test/IDE/complete_overlaymodule.swift diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 6d7e0434eb437..63d59acd325a5 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -6196,6 +6196,8 @@ void CodeCompletionCallbacksImpl::doneParsing() { break; } + llvm::SmallPtrSet seenModuleNames; + for (auto &Request: Lookup.RequestedCachedResults) { // Use the current SourceFile as the DeclContext so that we can use it to // perform qualified lookup, and to get the correct visibility for @@ -6248,7 +6250,9 @@ void CodeCompletionCallbacksImpl::doneParsing() { return; // already handled. RequestedModules.push_back({std::move(K), TheModule, Request.OnlyTypes, Request.OnlyPrecedenceGroups}); - if (Request.IncludeModuleQualifier) + + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(TheModule->getName()).second) Lookup.addModuleName(TheModule); } }; @@ -6263,8 +6267,10 @@ void CodeCompletionCallbacksImpl::doneParsing() { Lookup.getToplevelCompletions(Request.OnlyTypes); // Add the qualifying module name - if (Request.IncludeModuleQualifier) - Lookup.addModuleName(CurDeclContext->getParentModule()); + auto curModule = CurDeclContext->getParentModule(); + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(curModule->getName()).second) + Lookup.addModuleName(curModule); // Add results for all imported modules. ModuleDecl::ImportFilter ImportFilter; diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h new file mode 100644 index 0000000000000..b91209ef648da --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h @@ -0,0 +1,2 @@ +#include + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h new file mode 100644 index 0000000000000..48336b32085b6 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h @@ -0,0 +1,13 @@ + +#ifndef OVERLAYED_H +#define OVERLAYED_H + +struct __attribute__((swift_name("Overlayed"))) OVOverlayed { + double x, y, z; +}; + +double OVOverlayedInOriginalFunc(struct OVOverlayed s) __attribute__((swift_name("Overlayed.inOriginalFunc(self:)"))); + +struct OVOverlayed createOverlayed(); + +#endif diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap new file mode 100644 index 0000000000000..52db6e58085c2 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module OverlayTest { + umbrella header "OverlayTest.h" + + export * + module * { export * } +} + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface new file mode 100644 index 0000000000000..ad75d7f67b6ea --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface @@ -0,0 +1,10 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name OverlayTest + +@_exported import OverlayTest + +public extension Overlayed { + public func inOverlayFunc() {} +} + +public func createOverlayedInOverlay() -> Overlayed diff --git a/test/IDE/complete_overlaymodule.swift b/test/IDE/complete_overlaymodule.swift new file mode 100644 index 0000000000000..b4cd14d62c226 --- /dev/null +++ b/test/IDE/complete_overlaymodule.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=TYPE_GLOBAL | %FileCheck %s --check-prefix=TYPE_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_GLOBAL | %FileCheck %s --check-prefix=EXPR_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_MEMBER | %FileCheck %s --check-prefix=EXPR_MEMBER + +import OverlayTest + +func testGlobalType() { + let _: #^TYPE_GLOBAL^# +// TYPE_GLOBAL: Begin completions +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// TYPE_GLOBAL: End completions +} +func testGlobalExpr() { + let _ = #^EXPR_GLOBAL^# +// EPXR_GLOBAL: Begin completions +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest]: createOverlayedInOverlay()[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest.Overlayed]: createOverlayed()[#Overlayed#]; +// EPXR_GLOBAL: End completions +} +func testGlobalExpr(value: Overlayed) { + value.#^EXPR_MEMBER^# +// EXPR_MEMBER: Begin completions, 6 items +// EXPR_MEMBER-DAG: Keyword[self]/CurrNominal: self[#Overlayed#]; name=self +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: x[#Double#]; name=x +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: y[#Double#]; name=y +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: z[#Double#]; name=z +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOverlayFunc()[#Void#]; name=inOverlayFunc() +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOriginalFunc()[#Double#]; name=inOriginalFunc() +// EXPR_MEMBER: End completions +} From 5cbf3f3e07d430ae7a3a41b19ca7e379b82e186f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 19 May 2020 22:39:05 +0000 Subject: [PATCH 105/625] stdlib: remove `llvm-config.h` from swiftLLVMSupport Remove the bundled generated `llvm-config.h` as the options do not apply to the runtime usage for LLVMSupport. The configuration is known statically. --- .../include/llvm/Config/llvm-config.h.cmake | 82 ------------------- stdlib/include/llvm/Support/Compiler.h | 2 - stdlib/public/LLVMSupport/CMakeLists.txt | 20 ----- 3 files changed, 104 deletions(-) delete mode 100644 stdlib/include/llvm/Config/llvm-config.h.cmake diff --git a/stdlib/include/llvm/Config/llvm-config.h.cmake b/stdlib/include/llvm/Config/llvm-config.h.cmake deleted file mode 100644 index 475c93efd653d..0000000000000 --- a/stdlib/include/llvm/Config/llvm-config.h.cmake +++ /dev/null @@ -1,82 +0,0 @@ -/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- 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 enumerates variables from the LLVM configuration so that they - can be in exported headers and won't override package specific directives. - This is a C header that can be included in the llvm-c headers. */ - -#ifndef LLVM_CONFIG_H -#define LLVM_CONFIG_H - -/* Define if LLVM_ENABLE_DUMP is enabled */ -#cmakedefine LLVM_ENABLE_DUMP - -/* Target triple LLVM will generate code for by default */ -#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" - -/* Define if threads enabled */ -#cmakedefine01 LLVM_ENABLE_THREADS - -/* Has gcc/MSVC atomic intrinsics */ -#cmakedefine01 LLVM_HAS_ATOMICS - -/* Host triple LLVM will be executed on */ -#cmakedefine LLVM_HOST_TRIPLE "${LLVM_HOST_TRIPLE}" - -/* LLVM architecture name for the native architecture, if available */ -#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} - -/* LLVM name for the native AsmParser init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser - -/* LLVM name for the native AsmPrinter init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter - -/* LLVM name for the native Disassembler init function, if available */ -#cmakedefine LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler - -/* LLVM name for the native Target init function, if available */ -#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target - -/* LLVM name for the native TargetInfo init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo - -/* LLVM name for the native target MC init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC - -/* Define if this is Unixish platform */ -#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} - -/* Define if we have the Intel JIT API runtime support library */ -#cmakedefine01 LLVM_USE_INTEL_JITEVENTS - -/* Define if we have the oprofile JIT-support library */ -#cmakedefine01 LLVM_USE_OPROFILE - -/* Define if we have the perf JIT-support library */ -#cmakedefine01 LLVM_USE_PERF - -/* Major version of the LLVM API */ -#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} - -/* Minor version of the LLVM API */ -#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} - -/* Patch version of the LLVM API */ -#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} - -/* LLVM version string */ -#define LLVM_VERSION_STRING "${PACKAGE_VERSION}" - -/* Whether LLVM records statistics for use with GetStatistics(), - * PrintStatistics() or PrintStatisticsJSON() - */ -#cmakedefine01 LLVM_FORCE_ENABLE_STATS - -#endif diff --git a/stdlib/include/llvm/Support/Compiler.h b/stdlib/include/llvm/Support/Compiler.h index 79af6f5d3c686..c6b8c8f4f6605 100644 --- a/stdlib/include/llvm/Support/Compiler.h +++ b/stdlib/include/llvm/Support/Compiler.h @@ -15,8 +15,6 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H -#include "llvm/Config/llvm-config.h" - #ifdef __cplusplus #include #endif diff --git a/stdlib/public/LLVMSupport/CMakeLists.txt b/stdlib/public/LLVMSupport/CMakeLists.txt index 1e688137c17d3..0df322e5172b1 100644 --- a/stdlib/public/LLVMSupport/CMakeLists.txt +++ b/stdlib/public/LLVMSupport/CMakeLists.txt @@ -1,23 +1,3 @@ - -set(LLVM_DEFAULT_TARGET_TRIPLE) -set(LLVM_ENABLE_DUMP) -set(LLVM_ENABLE_THREADS YES) -set(LLVM_FORCE_ENABLE_STATS NO) -set(LLVM_HAS_ATOMICS YES) -set(LLVM_HOST_TRIPLE) -set(LLVM_NATIVE_ARCH) -if(SWIFT_PRIMARY_VARIANT_SDK STREQUAL Windows) - set(LLVM_ON_UNIX NO) -else() - set(LLVM_ON_UNIX YES) -endif() -set(LLVM_USE_INTEL_JITEVENTS NO) -set(LLVM_USE_OPROFILE NO) -set(LLVM_USE_PERF NO) - -configure_file(${PROJECT_SOURCE_DIR}/include/llvm/Config/llvm-config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/llvm/Config/llvm-config.h) - add_swift_target_library(swiftLLVMSupport OBJECT_LIBRARY ErrorHandling.cpp Hashing.cpp From f57a6cfd6dd07d2aa4ed6e4f0c01a5f6f0d11bd6 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 15 May 2020 13:29:09 -0700 Subject: [PATCH 106/625] [silgen] Teach CleanupCloner how to handle OwnedValueWritebackCleanups correctly. Previously we would just forward the cleanup and create a normal "destroy" cleanup resulting in early deallocation and use after frees along error paths. As part of this I also had to tweak how DI recognizes self init writebacks to not use SILLocations. This is approach is more robust (since we aren't relying on SourceLocs/have verifiers to make sure we don't violate SIL) and also avoids issues from the write back store not necessarily have the same SILLocation. --- lib/SILGen/Cleanup.cpp | 34 +- lib/SILGen/Cleanup.h | 39 +- lib/SILGen/SILGenExpr.cpp | 6 + lib/SILGen/SILGenFunction.h | 2 + .../Mandatory/DIMemoryUseCollector.cpp | 31 +- .../Mandatory/DefiniteInitialization.cpp | 1 + ..._composed_with_throwing_initializers.swift | 678 ++++++++++++++++++ .../objc_throwing_initializers.swift | 10 + ..._init_markuninitialized_delegatingself.sil | 49 +- 9 files changed, 839 insertions(+), 11 deletions(-) create mode 100644 test/Interpreter/objc_failable_composed_with_throwing_initializers.swift diff --git a/lib/SILGen/Cleanup.cpp b/lib/SILGen/Cleanup.cpp index e92f5dbd443ce..20eb0cc3c8e7e 100644 --- a/lib/SILGen/Cleanup.cpp +++ b/lib/SILGen/Cleanup.cpp @@ -220,6 +220,21 @@ void CleanupManager::setCleanupState(CleanupsDepth depth, CleanupState state) { popTopDeadCleanups(); } +std::tuple> +CleanupManager::getFlagsAndWritebackBuffer(CleanupHandle depth) { + auto iter = stack.find(depth); + assert(iter != stack.end() && "can't change end of cleanups stack"); + assert(iter->getState() != CleanupState::Dead && + "Trying to get writeback buffer of a dead cleanup?!"); + + auto resultFlags = iter->getFlags(); + Optional result; + bool foundValue = iter->getWritebackBuffer([&](SILValue v) { result = v; }); + (void)foundValue; + assert(result.hasValue() == foundValue); + return std::make_tuple(resultFlags, result); +} + void CleanupManager::forwardCleanup(CleanupsDepth handle) { auto iter = stack.find(handle); assert(iter != stack.end() && "can't change end of cleanups stack"); @@ -344,7 +359,16 @@ void CleanupStateRestorationScope::pop() && { popImpl(); } //===----------------------------------------------------------------------===// CleanupCloner::CleanupCloner(SILGenFunction &SGF, const ManagedValue &mv) - : SGF(SGF), hasCleanup(mv.hasCleanup()), isLValue(mv.isLValue()) {} + : SGF(SGF), hasCleanup(mv.hasCleanup()), isLValue(mv.isLValue()), + writebackBuffer(None) { + if (hasCleanup) { + auto handle = mv.getCleanup(); + auto state = SGF.Cleanups.getFlagsAndWritebackBuffer(handle); + if (SILValue value = std::get<1>(state).getValueOr(SILValue())) { + writebackBuffer = value; + } + } +} CleanupCloner::CleanupCloner(SILGenBuilder &builder, const ManagedValue &mv) : CleanupCloner(builder.getSILGenFunction(), mv) {} @@ -372,6 +396,14 @@ ManagedValue CleanupCloner::clone(SILValue value) const { return ManagedValue::forUnmanaged(value); } + if (writebackBuffer.hasValue()) { + auto loc = RegularLocation::getAutoGeneratedLocation(); + auto cleanup = + SGF.enterOwnedValueWritebackCleanup(loc, *writebackBuffer, value); + return ManagedValue::forExclusivelyBorrowedOwnedObjectRValue(value, + cleanup); + } + if (value->getType().isAddress()) { return SGF.emitManagedBufferWithCleanup(value); } diff --git a/lib/SILGen/Cleanup.h b/lib/SILGen/Cleanup.h index 175b2cc6bb31a..cf8b98df606e3 100644 --- a/lib/SILGen/Cleanup.h +++ b/lib/SILGen/Cleanup.h @@ -19,6 +19,7 @@ #include "swift/Basic/DiverseStack.h" #include "swift/SIL/SILLocation.h" +#include "swift/SIL/SILValue.h" #include "llvm/ADT/SmallVector.h" namespace swift { @@ -75,10 +76,23 @@ llvm::raw_ostream &operator<<(raw_ostream &os, CleanupState state); class LLVM_LIBRARY_VISIBILITY Cleanup { friend class CleanupManager; + friend class CleanupCloner; - unsigned allocatedSize; +protected: + // A set of flags that categorize the type of cleanup such that it can be + // recreated via SILGenFunction methods based on the type of argument input. + // + // Example: Distinguishing in between @owned cleanups with a writeback buffer + // (ExclusiveBorrowCleanup) or ones that involve formal access cleanups. + enum class Flags : uint8_t { + None = 0, + ExclusiveBorrowCleanup = 1, + }; +private: CleanupState state; + unsigned allocatedSize : 24; + Flags flags : 8; protected: Cleanup() {} @@ -99,6 +113,16 @@ class LLVM_LIBRARY_VISIBILITY Cleanup { virtual void emit(SILGenFunction &SGF, CleanupLocation loc, ForUnwind_t forUnwind) = 0; virtual void dump(SILGenFunction &SGF) const = 0; + +protected: + Flags getFlags() const { return flags; } + + /// Call func passing in the SILValue address that this cleanup will write + /// back to if supported and any flags associated with the cleanup. Returns + /// false otherwise. + virtual bool getWritebackBuffer(function_ref func) { + return false; + } }; /// A cleanup depth is generally used to denote the set of cleanups @@ -117,6 +141,7 @@ typedef DiverseStackImpl::stable_iterator CleanupHandle; class LLVM_LIBRARY_VISIBILITY CleanupManager { friend class Scope; + friend class CleanupCloner; SILGenFunction &SGF; @@ -229,7 +254,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager { /// Set the state of the cleanup at the given depth. /// The transition must be non-trivial and legal. void setCleanupState(CleanupHandle depth, CleanupState state); - + /// True if there are any active cleanups in the scope between the two /// cleanup handles. bool hasAnyActiveCleanups(CleanupsDepth from, CleanupsDepth to); @@ -246,6 +271,12 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager { /// Verify that the given cleanup handle is valid. void checkIterator(CleanupHandle handle) const; + +private: + // Look up the flags and optionally the writeback address associated with the + // cleanup at \p depth. If + std::tuple> + getFlagsAndWritebackBuffer(CleanupHandle depth); }; /// An RAII object that allows the state of a cleanup to be @@ -274,10 +305,14 @@ class CleanupStateRestorationScope { void popImpl(); }; +/// Extract enough information from a managed value to reliably clone its +/// cleanup (if it has any) on a newly computed type. This includes modeling +/// writeback buffers. class CleanupCloner { SILGenFunction &SGF; bool hasCleanup; bool isLValue; + Optional writebackBuffer; public: CleanupCloner(SILGenFunction &SGF, const ManagedValue &mv); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 58f6c3396929d..a64ad886888f0 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -722,6 +722,7 @@ namespace { /// cleanup to take ownership of the value and thus prevent it form being /// written back. struct OwnedValueWritebackCleanup final : Cleanup { + using Flags = Cleanup::Flags; /// We store our own loc so that we can ensure that DI ignores our writeback. SILLocation loc; @@ -733,6 +734,11 @@ struct OwnedValueWritebackCleanup final : Cleanup { SILValue value) : loc(loc), lvalueAddress(lvalueAddress), value(value) {} + bool getWritebackBuffer(function_ref func) override { + func(lvalueAddress); + return true; + } + void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override { SILValue valueToStore = value; SILType lvalueObjTy = lvalueAddress->getType().getObjectType(); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 854fa87b50c0e..ca922d32de6bf 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -1188,6 +1188,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction CleanupHandle enterDeallocateUninitializedArrayCleanup(SILValue array); void emitUninitializedArrayDeallocation(SILLocation loc, SILValue array); + /// Emit a cleanup for an owned value that should be written back at end of + /// scope if the value is not forwarded. CleanupHandle enterOwnedValueWritebackCleanup(SILLocation loc, SILValue address, SILValue newValue); diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index 8bbb9d30ed1aa..b83872daea424 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -1639,6 +1639,7 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() { } // A store of a load from the box is ignored. + // // SILGen emits these if delegation to another initializer was // interrupted before the initializer was called. SILValue src = SI->getSrc(); @@ -1778,14 +1779,30 @@ void ClassInitElementUseCollector::collectClassInitSelfLoadUses( } } - // If this load's value is being stored back into the delegating - // mark_uninitialized buffer and it is a self init use, skip the - // use. This is to handle situations where due to usage of a metatype to - // allocate, we do not actually consume self. + // If this load's value is being stored immediately back into the delegating + // mark_uninitialized buffer, skip the use. + // + // This is to handle situations where we do not actually consume self as a + // result of situations such as: + // + // 1. The usage of a metatype to allocate the object. + // + // 2. If our self init call has a throwing function as an argument that + // actually throws. if (auto *SI = dyn_cast(User)) { - if (SI->getDest() == MUI && - (isSelfInitUse(User) || isSuperInitUse(User))) { - continue; + if (SI->getDest() == MUI) { + SILValue src = SI->getSrc(); + + // Look through conversions. + while (auto *conversion = dyn_cast(src)) { + src = conversion->getConverted(); + } + + if (auto *li = dyn_cast(src)) { + if (li->getOperand() == MUI) { + continue; + } + } } } diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 8250a4eba1993..65e5513dc1d7e 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -785,6 +785,7 @@ void LifetimeChecker::doIt() { break; case DIUseKind::LoadForTypeOfSelf: handleLoadForTypeOfSelfUse(Use); + break; } } diff --git a/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift b/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift new file mode 100644 index 0000000000000..9a365a5b687f6 --- /dev/null +++ b/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift @@ -0,0 +1,678 @@ +// RUN: %empty-directory(%t) +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// RUN: %empty-directory(%t) +// +// target-build-swift assumes we want -swift-version 4. Behavior in initializers +// changed in swift 5, so we want to explicitly check it as well. +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out -swift-version 5 +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +// These tests are failable tests that compose with throwing initializers. They +// all catch the throw on failure and return None. + +import Foundation +import ObjCClasses +import StdlibUnittest + +var FailableComposedWithThrowingInitTestSuite = TestSuite("FailableInitObjCComposedWithThrowingInits") +defer { runAllTests() } + +enum E : Error { + case X +} + +func maybeThrow(_ shouldThrow: Bool, _ result: Int? = nil) throws -> Int { + if shouldThrow { + throw E.X + } + return result ?? 0 +} + +func mustFail(f: () -> T?) { + if f() != nil { + preconditionFailure("Didn't fail") + } +} + +class Bear : NSLifetimeTracked { + let x: LifetimeTracked + + /* Designated */ + init(n: Int) { + x = LifetimeTracked(0) + } + + init?(n: Int, before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + } + + init?(n: Int, after: Bool) { + self.x = LifetimeTracked(0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, after: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Convenience */ + convenience init?(before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.init(n: v) + } + + convenience init?(during: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + convenience init?(before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + convenience init?(after: Bool) { + self.init(n: 0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(before: Bool, after: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.init(n: value) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(during: Bool, after: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Exotic */ + convenience init!(IUO: Bool) { + self.init(before: IUO) + } + + convenience init(force: Bool) { + self.init(before: force)! + } +} + +class PolarBear : Bear { + let y: LifetimeTracked + + /* Designated */ + override init(n: Int) { + self.y = LifetimeTracked(0) + super.init(n: n) + } + + override init?(n: Int, before: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: value) + } + + init?(n: Int, during: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + override init?(n: Int, after: Bool) { + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, during: Bool, after: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + override init?(n: Int, before: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } +} + +class GuineaPig : Bear { + let y: LifetimeTracked + let t: T + + init?(t: T, during: Bool) { + self.y = LifetimeTracked(0) + self.t = t + super.init(n: 0, before: during) + } +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Root") { + mustFail { Bear(n: 0, before: true) } + mustFail { Bear(n: 0, after: true) } + mustFail { Bear(n: 0, before: true, after: false) } + mustFail { Bear(n: 0, before: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Derived") { + mustFail { PolarBear(n: 0, before: true) } + mustFail { PolarBear(n: 0, during: true) } + mustFail { PolarBear(n: 0, before: true, during: false) } + mustFail { PolarBear(n: 0, before: false, during: true) } + mustFail { PolarBear(n: 0, after: true) } + mustFail { PolarBear(n: 0, during: true, after: false) } + mustFail { PolarBear(n: 0, during: false, after: true) } + mustFail { PolarBear(n: 0, before: true, after: false) } + mustFail { PolarBear(n: 0, before: false, after: true) } + mustFail { PolarBear(n: 0, before: true, during: false, after: false) } + mustFail { PolarBear(n: 0, before: false, during: true, after: false) } + mustFail { PolarBear(n: 0, before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("DesignatedInitFailure_DerivedGeneric") { + mustFail { GuineaPig(t: LifetimeTracked(0), during: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Root") { + mustFail { Bear(before: true) } + mustFail { Bear(during: true) } + mustFail { Bear(before: true, during: false) } + mustFail { Bear(before: false, during: true) } + mustFail { Bear(after: true) } + mustFail { Bear(before: true, after: false) } + mustFail { Bear(before: false, after: true) } + mustFail { Bear(during: true, after: false) } + mustFail { Bear(during: false, after: true) } + mustFail { Bear(before: true, during: false, after: false) } + mustFail { Bear(before: false, during: true, after: false) } + mustFail { Bear(before: false, during: false, after: true) } + + _ = Bear(IUO: false) + _ = Bear(force: false) + + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Derived") { + mustFail { PolarBear(before: true) } + mustFail { PolarBear(during: true) } + mustFail { PolarBear(before: true, during: false) } + mustFail { PolarBear(before: false, during: true) } + mustFail { PolarBear(after: true) } + mustFail { PolarBear(before: true, after: false) } + mustFail { PolarBear(before: false, after: true) } + mustFail { PolarBear(during: true, after: false) } + mustFail { PolarBear(during: false, after: true) } + mustFail { PolarBear(before: true, during: false, after: false) } + mustFail { PolarBear(before: false, during: true, after: false) } + mustFail { PolarBear(before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +// @objc + +class AtObjCBear : NSLifetimeTracked { + let x: LifetimeTracked + + /* Designated */ + @objc init(n: Int) { + x = LifetimeTracked(0) + } + + @objc init?(n: Int, before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + } + + @objc init?(n: Int, after: Bool) { + self.x = LifetimeTracked(0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, after: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Convenience */ + @objc convenience init?(before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.init(n: v) + } + + @objc convenience init?(during: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc convenience init?(after: Bool) { + self.init(n: 0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, after: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.init(n: value) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(during: Bool, after: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Exotic */ + @objc convenience init!(IUO: Bool) { + self.init(before: IUO) + } + + @objc convenience init(force: Bool) { + self.init(before: force)! + } +} + +class AtObjCPolarBear : AtObjCBear { + let y: LifetimeTracked + + /* Designated */ + @objc override init(n: Int) { + self.y = LifetimeTracked(0) + super.init(n: n) + } + + @objc override init?(n: Int, before: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: value) + } + + @objc init?(n: Int, during: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc override init?(n: Int, after: Bool) { + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, during: Bool, after: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc override init?(n: Int, before: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Root") { + mustFail { AtObjCBear(n: 0, before: true) } + mustFail { AtObjCBear(n: 0, after: true) } + mustFail { AtObjCBear(n: 0, before: true, after: false) } + mustFail { AtObjCBear(n: 0, before: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Derived") { + mustFail { AtObjCPolarBear(n: 0, before: true) } + mustFail { AtObjCPolarBear(n: 0, during: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, during: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: true) } + mustFail { AtObjCPolarBear(n: 0, after: true) } + mustFail { AtObjCPolarBear(n: 0, during: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, during: false, after: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, after: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, during: false, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Root") { + mustFail { AtObjCBear(before: true) } + mustFail { AtObjCBear(during: true) } + mustFail { AtObjCBear(before: true, during: false) } + mustFail { AtObjCBear(before: false, during: true) } + mustFail { AtObjCBear(after: true) } + mustFail { AtObjCBear(before: true, after: false) } + mustFail { AtObjCBear(before: false, after: true) } + mustFail { AtObjCBear(during: true, after: false) } + mustFail { AtObjCBear(during: false, after: true) } + mustFail { AtObjCBear(before: true, during: false, after: false) } + mustFail { AtObjCBear(before: false, during: true, after: false) } + mustFail { AtObjCBear(before: false, during: false, after: true) } + + _ = AtObjCBear(IUO: false) + _ = AtObjCBear(force: false) + + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Derived") { + mustFail { AtObjCPolarBear(before: true) } + mustFail { AtObjCPolarBear(during: true) } + mustFail { AtObjCPolarBear(before: true, during: false) } + mustFail { AtObjCPolarBear(before: false, during: true) } + mustFail { AtObjCPolarBear(after: true) } + mustFail { AtObjCPolarBear(before: true, after: false) } + mustFail { AtObjCPolarBear(before: false, after: true) } + mustFail { AtObjCPolarBear(during: true, after: false) } + mustFail { AtObjCPolarBear(during: false, after: true) } + mustFail { AtObjCPolarBear(before: true, during: false, after: false) } + mustFail { AtObjCPolarBear(before: false, during: true, after: false) } + mustFail { AtObjCPolarBear(before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} diff --git a/test/Interpreter/objc_throwing_initializers.swift b/test/Interpreter/objc_throwing_initializers.swift index ea6aaca8c2bbb..f8cf7dfd0e24f 100644 --- a/test/Interpreter/objc_throwing_initializers.swift +++ b/test/Interpreter/objc_throwing_initializers.swift @@ -5,6 +5,16 @@ // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out +// RUN: %empty-directory(%t) +// +// target-build-swift assumes we want -swift-version 4. Behavior in initializers +// changed in swift 5, so we want to explicitly check it as well. +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out -swift-version 5 +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + // REQUIRES: executable_test // REQUIRES: objc_interop diff --git a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil index 2f71618c1e085..b41c5bab7eb6d 100644 --- a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil +++ b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil @@ -31,6 +31,8 @@ class DerivedClassWithNontrivialStoredProperties : RootClassWithNontrivialStored override init() } +sil @getThrowingValue : $@convention(thin) () -> (Int, @error Error) + // CHECK-LABEL: @self_init_assert_instruction // CHECK: apply // CHECK-NEXT: store @@ -323,5 +325,50 @@ bb4: br bb5(%24 : $Optional) bb5(%26 : $Optional): - return %26 : $Optional + return %26 : $Optional +} + +sil @selfinit_derivedclass_peerconvenience_init : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + +// Make sure that we do not error when we store back in the fail block here. +sil hidden [ossa] @convenience_init_with_throwing_argument : $@convention(method) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned Optional { +bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties): + %1 = alloc_stack $DerivedClassWithNontrivialStoredProperties, let, name "self" + %2 = mark_uninitialized [delegatingselfallocated] %1 : $*DerivedClassWithNontrivialStoredProperties + store %0 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + %6 = load [take] %2 : $*DerivedClassWithNontrivialStoredProperties + %7 = function_ref @getThrowingValue : $@convention(thin) () -> (Int, @error Error) + try_apply %7() : $@convention(thin) () -> (Int, @error Error), normal bb1, error bb5 + +bb1(%9 : $Int): + %10 = function_ref @selfinit_derivedclass_peerconvenience_init : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + %11 = apply %10(%6) : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + store %11 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + %13 = load [copy] %2 : $*DerivedClassWithNontrivialStoredProperties + %14 = enum $Optional, #Optional.some!enumelt, %13 : $DerivedClassWithNontrivialStoredProperties + destroy_addr %2 : $*DerivedClassWithNontrivialStoredProperties + dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties + br bb3(%14 : $Optional) + +bb2: + destroy_addr %2 : $*DerivedClassWithNontrivialStoredProperties + dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties + %20 = enum $Optional, #Optional.none!enumelt + br bb3(%20 : $Optional) + +bb3(%22 : @owned $Optional): + return %22 : $Optional + +bb4(%24 : @owned $Error): + %25 = begin_borrow %24 : $Error + %26 = copy_value %25 : $Error + debug_value %26 : $Error, let, name "error" + destroy_value %26 : $Error + end_borrow %25 : $Error + destroy_value %24 : $Error + br bb2 + +bb5(%32 : @owned $Error): + store %6 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + br bb4(%32 : $Error) } From bfa335e9f1eaa01e2f4ccc0dc30526a8553b4bec Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 19 May 2020 16:17:14 -0700 Subject: [PATCH 107/625] [utils/build-parser-lib] Remove rogue equal character for version flag --- utils/build-parser-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build-parser-lib b/utils/build-parser-lib index 8a313e53f0ea0..de9da5609199a 100755 --- a/utils/build-parser-lib +++ b/utils/build-parser-lib @@ -113,7 +113,7 @@ class Builder(object): "-DCMAKE_OSX_DEPLOYMENT_TARGET=" + deployment_version, "-DSWIFT_DARWIN_DEPLOYMENT_VERSION_IOS=" + deployment_version, ] - llvm_c_flags += " -miphoneos-version-min==" + deployment_version + llvm_c_flags += " -miphoneos-version-min=" + deployment_version elif self.host == "appletvsimulator": deployment_version = "10.0" From c33775796438a15ae9717a4de1a70839ea3906af Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 20 May 2020 01:25:42 +0300 Subject: [PATCH 108/625] [NFC] Sema: get rid of redundant DeclContext parameter to checkConformancesInContext --- include/swift/AST/DeclContext.h | 5 ++++- lib/AST/DeclContext.cpp | 2 +- lib/Sema/DerivedConformanceCodable.cpp | 2 +- lib/Sema/TypeCheckDeclPrimary.cpp | 8 ++++---- lib/Sema/TypeCheckProtocol.cpp | 22 ++++++++-------------- lib/Sema/TypeChecker.h | 2 +- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index ae57b1ad9eb0e..cd7fc9e22c6aa 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -813,7 +813,10 @@ class IterableDeclContext { const Decl *getDecl() const; /// Return 'this' as a \c GenericContext. - const GenericContext *getAsGenericContext() const; + GenericContext *getAsGenericContext(); + const GenericContext *getAsGenericContext() const { + return const_cast(this)->getAsGenericContext(); + } /// Get the DeclID this Decl was deserialized from. serialization::DeclID getDeclID() const { diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index eafb59de31fe6..77a36cf695c22 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -773,7 +773,7 @@ IterableDeclContext::getDecl() const { llvm_unreachable("Unhandled IterableDeclContextKind in switch."); } -const GenericContext *IterableDeclContext::getAsGenericContext() const { +GenericContext *IterableDeclContext::getAsGenericContext() { switch (getIterableContextKind()) { case IterableDeclContextKind::NominalTypeDecl: return cast(this); diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index c2fddac40d360..ae8f1d7b1ea94 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -372,7 +372,7 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) { return nullptr; // Forcibly derive conformance to CodingKey. - TypeChecker::checkConformancesInContext(enumDecl, enumDecl); + TypeChecker::checkConformancesInContext(enumDecl); // Add to the type. target->addMember(enumDecl); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index d9e2333066ece..f4fb62ce90c5e 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1759,7 +1759,7 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkDeclCircularity(ED); - TypeChecker::checkConformancesInContext(ED, ED); + TypeChecker::checkConformancesInContext(ED); } void visitStructDecl(StructDecl *SD) { @@ -1789,7 +1789,7 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkDeclCircularity(SD); - TypeChecker::checkConformancesInContext(SD, SD); + TypeChecker::checkConformancesInContext(SD); } /// Check whether the given properties can be @NSManaged in this class. @@ -2023,7 +2023,7 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkDeclCircularity(CD); - TypeChecker::checkConformancesInContext(CD, CD); + TypeChecker::checkConformancesInContext(CD); maybeDiagnoseClassWithoutInitializers(CD); } @@ -2362,7 +2362,7 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkPatternBindingCaptures(ED); - TypeChecker::checkConformancesInContext(ED, ED); + TypeChecker::checkConformancesInContext(ED); TypeChecker::checkDeclAttributes(ED); checkAccessControl(ED); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 498c04256420d..43bbcd18ef54a 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -5034,25 +5034,19 @@ LookupAllConformancesInContextRequest::evaluate( return IDC->getLocalConformances(ConformanceLookupKind::All); } -void TypeChecker::checkConformancesInContext(DeclContext *dc, - IterableDeclContext *idc) { +void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) { + auto *const dc = idc->getAsGenericContext(); + // For anything imported from Clang, lazily check conformances. if (isa(dc->getModuleScopeContext())) return; + const auto *const nominal = dc->getSelfNominalTypeDecl(); + if (!nominal) + return; + // Determine the access level of this conformance. - Decl *currentDecl = nullptr; - AccessLevel defaultAccess; - if (auto ext = dyn_cast(dc)) { - const NominalTypeDecl *nominal = ext->getExtendedNominal(); - if (!nominal) - return; - defaultAccess = nominal->getFormalAccess(); - currentDecl = ext; - } else { - defaultAccess = cast(dc)->getFormalAccess(); - currentDecl = cast(dc); - } + const auto defaultAccess = nominal->getFormalAccess(); // Check each of the conformances associated with this context. auto conformances = diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index dabd2c602e014..33961ce7894cd 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -915,7 +915,7 @@ ProtocolConformanceRef conformsToProtocol(Type T, ProtocolDecl *Proto, void checkConformance(NormalProtocolConformance *conformance); /// Check all of the conformances in the given context. -void checkConformancesInContext(DeclContext *dc, IterableDeclContext *idc); +void checkConformancesInContext(IterableDeclContext *idc); /// Check that the type of the given property conforms to NSCopying. ProtocolConformanceRef checkConformanceToNSCopying(VarDecl *var); From b41e8503fe8cae1191f81142d64b36abb7107663 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Tue, 19 May 2020 17:17:33 -0700 Subject: [PATCH 109/625] [gardening] Remove addressed FIXME. --- lib/Sema/TypeCheckAttr.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index ccac659fb96f5..eb2d702d3407b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1957,9 +1957,6 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) { // } // // Of course, this function's body does not type-check. - // - // FIXME: Stop using the legacy type checker here. However, it will still be - // necessary to type-check the function at that point. file->DelayedFunctions.push_back(func); // Register the func as the main decl in the module. If there are multiples From 653fa07260497ab736c7667158e9e59226723af4 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 18 May 2020 19:04:04 -0400 Subject: [PATCH 110/625] GSB: Fix maybeResolveEquivalenceClass() with member type of superclass-constrained type Name lookup might find an associated type whose protocol is not in our conforms-to list, if we have a superclass constraint and the superclass conforms to the associated type's protocol. We used to return an unresolved type in this case, which would result in the constraint getting delayed forever and dropped. While playing wack-a-mole with regressing crashers, I had to do some refactoring to get all the tests to pass. Unfortuanately these refactorings don't lend themselves well to being peeled off into their own commits: - maybeAddSameTypeRequirementForNestedType() was almost identical to concretizeNestedTypeFromConcreteParent(), except for superclasses instead of concrete same-type constraints. I merged them together. - We used to drop same-type constraints where the subject type was an ErrorType, because maybeResolveEquivalenceClass() would return an unresolved type in this case. This violated some invariants around nested types of ArchetypeTypes, because now it was possible for a nested type of a concrete type to be non-concrete, if the type witness in the conformance was missing due to an error. Fix this by removing the ErrorType hack, and adjusting a couple of other places to handle ErrorTypes in order to avoid regressing with invalid code. Fixes , , . --- lib/AST/GenericSignatureBuilder.cpp | 206 ++++++++---------- ...4-unhandled-pullback-indirect-result.swift | 3 +- test/Constraints/same_types.swift | 7 +- test/Generics/Inputs/sr8945-other.swift | 3 + test/Generics/sr8945.swift | 17 ++ test/IDE/print_ast_tc_decls_errors.swift | 2 +- test/decl/protocol/req/recursion.swift | 2 +- .../0159-rdar40009245.swift | 1 + .../0163-sr8033.swift | 1 + 9 files changed, 113 insertions(+), 129 deletions(-) rename test/AutoDiff/{compiler_crashers => compiler_crashers_fixed}/sr12744-unhandled-pullback-indirect-result.swift (84%) create mode 100644 test/Generics/Inputs/sr8945-other.swift create mode 100644 test/Generics/sr8945.swift diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index 68fecd1fdd1ba..4e28d30ce26f5 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -2390,43 +2390,6 @@ Type ResolvedType::getDependentType(GenericSignatureBuilder &builder) const { return result->isTypeParameter() ? result : Type(); } -/// If there is a same-type requirement to be added for the given nested type -/// due to a superclass constraint on the parent type, add it now. -static void maybeAddSameTypeRequirementForNestedType( - ResolvedType nested, - const RequirementSource *superSource, - GenericSignatureBuilder &builder) { - // If there's no super conformance, we're done. - if (!superSource) return; - - // If the nested type is already concrete, we're done. - if (nested.getAsConcreteType()) return; - - // Dig out the associated type. - AssociatedTypeDecl *assocType = nullptr; - if (auto depMemTy = - nested.getDependentType(builder)->getAs()) - assocType = depMemTy->getAssocType(); - else - return; - - // Dig out the type witness. - auto superConformance = superSource->getProtocolConformance().getConcrete(); - auto concreteType = superConformance->getTypeWitness(assocType); - if (!concreteType) return; - - // We should only have interface types here. - assert(!superConformance->getType()->hasArchetype()); - assert(!concreteType->hasArchetype()); - - // Add the same-type constraint. - auto nestedSource = superSource->viaParent(builder, assocType); - - builder.addSameTypeRequirement( - nested.getUnresolvedType(), concreteType, nestedSource, - GenericSignatureBuilder::UnresolvedHandlingKind::GenerateConstraints); -} - auto PotentialArchetype::getOrCreateEquivalenceClass( GenericSignatureBuilder &builder) const -> EquivalenceClass * { @@ -2562,7 +2525,9 @@ static void concretizeNestedTypeFromConcreteParent( // If we don't already have a conformance of the parent to this protocol, // add it now; it was elided earlier. if (parentEquiv->conformsTo.count(proto) == 0) { - auto source = parentEquiv->concreteTypeConstraints.front().source; + auto source = (!isSuperclassConstrained + ? parentEquiv->concreteTypeConstraints.front().source + : parentEquiv->superclassConstraints.front().source); parentEquiv->recordConformanceConstraint(builder, parent, proto, source); } @@ -2592,7 +2557,7 @@ static void concretizeNestedTypeFromConcreteParent( if (conformance.isConcrete()) { witnessType = conformance.getConcrete()->getTypeWitness(assocType); - if (!witnessType || witnessType->hasError()) + if (!witnessType) return; // FIXME: should we delay here? } else if (auto archetype = concreteParent->getAs()) { witnessType = archetype->getNestedType(assocType->getName()); @@ -2657,20 +2622,11 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance( // If we have a potential archetype that requires more processing, do so now. if (shouldUpdatePA) { - // If there's a superclass constraint that conforms to the protocol, - // add the appropriate same-type relationship. - const auto proto = assocType->getProtocol(); - if (proto) { - if (auto superSource = builder.resolveSuperConformance(this, proto)) { - maybeAddSameTypeRequirementForNestedType(resultPA, superSource, - builder); - } - } - // We know something concrete about the parent PA, so we need to propagate // that information to this new archetype. - if (isConcreteType()) { - concretizeNestedTypeFromConcreteParent(this, resultPA, builder); + if (auto equivClass = getEquivalenceClassIfPresent()) { + if (equivClass->concreteType || equivClass->superclass) + concretizeNestedTypeFromConcreteParent(this, resultPA, builder); } } @@ -3618,50 +3574,29 @@ static Type getStructuralType(TypeDecl *typeDecl, bool keepSugar) { return typeDecl->getDeclaredInterfaceType(); } -static Type substituteConcreteType(GenericSignatureBuilder &builder, - PotentialArchetype *basePA, +static Type substituteConcreteType(Type parentType, TypeDecl *concreteDecl) { + if (parentType->is()) + return parentType; + assert(concreteDecl); auto *dc = concreteDecl->getDeclContext(); - auto *proto = dc->getSelfProtocolDecl(); // Form an unsubstituted type referring to the given type declaration, // for use in an inferred same-type requirement. auto type = getStructuralType(concreteDecl, /*keepSugar=*/true); - SubstitutionMap subMap; - if (proto) { - // Substitute in the type of the current PotentialArchetype in - // place of 'Self' here. - auto parentType = basePA->getDependentType(builder.getGenericParams()); - - subMap = SubstitutionMap::getProtocolSubstitutions( - proto, parentType, ProtocolConformanceRef(proto)); - } else { - // Substitute in the superclass type. - auto parentPA = basePA->getEquivalenceClassIfPresent(); - auto parentType = - parentPA->concreteType ? parentPA->concreteType : parentPA->superclass; - auto parentDecl = parentType->getAnyNominal(); - - subMap = parentType->getContextSubstitutionMap( - parentDecl->getParentModule(), dc); - } + auto subMap = parentType->getContextSubstitutionMap( + dc->getParentModule(), dc); return type.subst(subMap); -}; +} ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( Type type, ArchetypeResolutionKind resolutionKind, bool wantExactPotentialArchetype) { - // An error type is best modeled as an unresolved potential archetype, since - // there's no way to be sure what it is actually meant to be. - if (type->is()) { - return ResolvedType::forUnresolved(nullptr); - } - // The equivalence class of a generic type is known directly. if (auto genericParam = type->getAs()) { unsigned index = GenericParamKey(genericParam).findIndexIn( @@ -3683,8 +3618,11 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( wantExactPotentialArchetype); if (!resolvedBase) return resolvedBase; // If the base is concrete, so is this member. - if (resolvedBase.getAsConcreteType()) - return ResolvedType::forConcrete(type); + if (auto parentType = resolvedBase.getAsConcreteType()) { + auto concreteType = substituteConcreteType(parentType, + depMemTy->getAssocType()); + return ResolvedType::forConcrete(concreteType); + } // Find the nested type declaration for this. auto baseEquivClass = resolvedBase.getEquivalenceClass(*this); @@ -3701,59 +3639,84 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( basePA = baseEquivClass->members.front(); } - AssociatedTypeDecl *nestedTypeDecl = nullptr; if (auto assocType = depMemTy->getAssocType()) { // Check whether this associated type references a protocol to which - // the base conforms. If not, it's unresolved. - if (baseEquivClass->conformsTo.find(assocType->getProtocol()) + // the base conforms. If not, it's either concrete or unresolved. + auto *proto = assocType->getProtocol(); + if (baseEquivClass->conformsTo.find(proto) == baseEquivClass->conformsTo.end()) { - if (!baseEquivClass->concreteType || - !lookupConformance(type->getCanonicalType(), - baseEquivClass->concreteType, - assocType->getProtocol())) { + if (baseEquivClass->concreteType && + lookupConformance(type->getCanonicalType(), + baseEquivClass->concreteType, + proto)) { + // Fall through + } else if (baseEquivClass->superclass && + lookupConformance(type->getCanonicalType(), + baseEquivClass->superclass, + proto)) { + // Fall through + } else { return ResolvedType::forUnresolved(baseEquivClass); } + + // FIXME: Instead of falling through, we ought to return a concrete + // type here, but then we fail to update a nested PotentialArchetype + // if one happens to already exist. It would be cleaner if concrete + // types never had nested PotentialArchetypes. } - nestedTypeDecl = assocType; + auto nestedPA = + basePA->updateNestedTypeForConformance(*this, assocType, + resolutionKind); + if (!nestedPA) + return ResolvedType::forUnresolved(baseEquivClass); + + // If base resolved to the anchor, then the nested potential archetype + // we found is the resolved potential archetype. Return it directly, + // so it doesn't need to be resolved again. + if (basePA == resolvedBase.getPotentialArchetypeIfKnown()) + return ResolvedType(nestedPA); + + // Compute the resolved dependent type to return. + Type resolvedBaseType = resolvedBase.getDependentType(*this); + Type resolvedMemberType = + DependentMemberType::get(resolvedBaseType, assocType); + + return ResolvedType(resolvedMemberType, + nestedPA->getOrCreateEquivalenceClass(*this)); } else { - auto *typeAlias = + auto *concreteDecl = baseEquivClass->lookupNestedType(*this, depMemTy->getName()); - if (!typeAlias) + if (!concreteDecl) return ResolvedType::forUnresolved(baseEquivClass); - auto type = substituteConcreteType(*this, basePA, typeAlias); - return maybeResolveEquivalenceClass(type, resolutionKind, - wantExactPotentialArchetype); - } + Type parentType; + auto *proto = concreteDecl->getDeclContext()->getSelfProtocolDecl(); + if (!proto) { + parentType = (baseEquivClass->concreteType + ? baseEquivClass->concreteType + : baseEquivClass->superclass); + } else { + if (baseEquivClass->concreteType && + lookupConformance(type->getCanonicalType(), + baseEquivClass->concreteType, + proto)) { + parentType = baseEquivClass->concreteType; + } else if (baseEquivClass->superclass && + lookupConformance(type->getCanonicalType(), + baseEquivClass->superclass, + proto)) { + parentType = baseEquivClass->superclass; + } else { + parentType = basePA->getDependentType(getGenericParams()); + } + } - auto nestedPA = - basePA->updateNestedTypeForConformance(*this, nestedTypeDecl, - resolutionKind); - if (!nestedPA) - return ResolvedType::forUnresolved(baseEquivClass); - - // If base resolved to the anchor, then the nested potential archetype - // we found is the resolved potential archetype. Return it directly, - // so it doesn't need to be resolved again. - if (basePA == resolvedBase.getPotentialArchetypeIfKnown()) - return ResolvedType(nestedPA); - - // Compute the resolved dependent type to return. - Type resolvedBaseType = resolvedBase.getDependentType(*this); - Type resolvedMemberType; - if (auto assocType = dyn_cast(nestedTypeDecl)) { - resolvedMemberType = - DependentMemberType::get(resolvedBaseType, assocType); - } else { - // Note: strange case that might not even really be dependent. - resolvedMemberType = - DependentMemberType::get(resolvedBaseType, depMemTy->getName()); + auto concreteType = substituteConcreteType(parentType, concreteDecl); + return maybeResolveEquivalenceClass(concreteType, resolutionKind, + wantExactPotentialArchetype); } - - return ResolvedType(resolvedMemberType, - nestedPA->getOrCreateEquivalenceClass(*this)); } // If it's not a type parameter, it won't directly resolve to one. @@ -5556,7 +5519,8 @@ GenericSignatureBuilder::finalize(SourceLoc loc, // Don't allow a generic parameter to be equivalent to a concrete type, // because then we don't actually have a parameter. auto equivClass = rep->getOrCreateEquivalenceClass(*this); - if (equivClass->concreteType) { + if (equivClass->concreteType && + !equivClass->concreteType->is()) { if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten()){ Impl->HadAnyError = true; diff --git a/test/AutoDiff/compiler_crashers/sr12744-unhandled-pullback-indirect-result.swift b/test/AutoDiff/compiler_crashers_fixed/sr12744-unhandled-pullback-indirect-result.swift similarity index 84% rename from test/AutoDiff/compiler_crashers/sr12744-unhandled-pullback-indirect-result.swift rename to test/AutoDiff/compiler_crashers_fixed/sr12744-unhandled-pullback-indirect-result.swift index 24f38b4c6d3f0..02b04fde3df58 100644 --- a/test/AutoDiff/compiler_crashers/sr12744-unhandled-pullback-indirect-result.swift +++ b/test/AutoDiff/compiler_crashers_fixed/sr12744-unhandled-pullback-indirect-result.swift @@ -1,5 +1,4 @@ -// RUN: not --crash %target-swift-frontend -emit-sil -verify %s -// REQUIRES: asserts +// RUN: %target-swift-frontend -emit-sil -verify %s // SR-12744: Pullback generation crash for unhandled indirect result. // May be due to inconsistent derivative function type calculation logic in diff --git a/test/Constraints/same_types.swift b/test/Constraints/same_types.swift index 40341de91cb6e..cb479f1bfad8b 100644 --- a/test/Constraints/same_types.swift +++ b/test/Constraints/same_types.swift @@ -89,15 +89,14 @@ func test6(_ t: T) -> (Y, X) where T.Bar == Y { } func test7(_ t: T) -> (Y, X) where T.Bar == Y, T.Bar.Foo == X { - // expected-warning@-1{{redundant same-type constraint 'T.Bar.Foo' == 'X'}} - // expected-note@-2{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}} + // expected-warning@-1{{neither type in same-type constraint ('Y.Foo' (aka 'X') or 'X') refers to a generic parameter or associated type}} return (t.bar, t.bar.foo) } func fail4(_ t: T) -> (Y, Z) where - T.Bar == Y, // expected-note{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}} - T.Bar.Foo == Z { // expected-error{{'T.Bar.Foo' cannot be equal to both 'Z' and 'Y.Foo' (aka 'X')}} + T.Bar == Y, + T.Bar.Foo == Z { // expected-error{{generic signature requires types 'Y.Foo' (aka 'X') and 'Z' to be the same}} return (t.bar, t.bar.foo) // expected-error{{cannot convert return expression of type '(Y, X)' to return type '(Y, Z)'}} } diff --git a/test/Generics/Inputs/sr8945-other.swift b/test/Generics/Inputs/sr8945-other.swift new file mode 100644 index 0000000000000..e05a421f7683f --- /dev/null +++ b/test/Generics/Inputs/sr8945-other.swift @@ -0,0 +1,3 @@ +public protocol P { + associatedtype T +} diff --git a/test/Generics/sr8945.swift b/test/Generics/sr8945.swift new file mode 100644 index 0000000000000..728310202b255 --- /dev/null +++ b/test/Generics/sr8945.swift @@ -0,0 +1,17 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module %S/Inputs/sr8945-other.swift -emit-module-path %t/other.swiftmodule -module-name other +// RUN: %target-swift-frontend -emit-silgen %s -I%t + +import other + +public class C : P { + public typealias T = Int +} + +public func takesInt(_: Int) {} + +public func foo(_: T, _ xs: S) where S.Element == T.T { + for x in xs { + takesInt(x) + } +} diff --git a/test/IDE/print_ast_tc_decls_errors.swift b/test/IDE/print_ast_tc_decls_errors.swift index 5dadb3a2d1877..802c10a7dea84 100644 --- a/test/IDE/print_ast_tc_decls_errors.swift +++ b/test/IDE/print_ast_tc_decls_errors.swift @@ -192,7 +192,7 @@ protocol AssociatedType1 { // TYREPR: {{^}} associatedtype AssociatedTypeDecl4 : FooNonExistentProtocol, BarNonExistentProtocol{{$}} associatedtype AssociatedTypeDecl5 : FooClass -// CHECK: {{^}} associatedtype AssociatedTypeDecl5 : FooClass{{$}} +// CHECK: {{^}} associatedtype AssociatedTypeDecl5{{$}} } //===--- diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift index 009449cccafae..3026cb561d389 100644 --- a/test/decl/protocol/req/recursion.swift +++ b/test/decl/protocol/req/recursion.swift @@ -49,7 +49,7 @@ public struct S where A.T == S { // expected-error {{circular reference // expected-note@-3 {{while resolving type 'S'}} func f(a: A.T) { g(a: id(t: a)) - // expected-error@-1 {{cannot convert value of type 'A.T' to expected argument type 'S'}} + // expected-error@-1 {{type of expression is ambiguous without more context}} _ = A.T.self } diff --git a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift index 442d7928c0d1a..d12abc8df6b1b 100644 --- a/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift +++ b/validation-test/compiler_crashers_2_fixed/0159-rdar40009245.swift @@ -2,6 +2,7 @@ protocol P { associatedtype A : P where A.X == Self + // expected-error@-1{{'X' is not a member type of 'Self.A}} associatedtype X : P where P.A == Self // expected-error@-1{{associated type 'A' can only be used with a concrete type or generic parameter base}} } diff --git a/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift b/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift index 22e1c8f909c85..3553340caf55c 100644 --- a/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift +++ b/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift @@ -7,3 +7,4 @@ protocol P1 { } extension Foo: P1 where A : P1 {} // expected-error {{unsupported recursion for reference to associated type 'A' of type 'Foo'}} // expected-error@-1 {{type 'Foo' does not conform to protocol 'P1'}} +// expected-error@-2 {{type 'Foo' in conformance requirement does not refer to a generic parameter or associated type}} From 1607ecfb0a9b0d389dbbb7b4721d76bdb8977b4e Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Wed, 20 May 2020 08:08:51 +0200 Subject: [PATCH 111/625] Fix warnings in loadable-types.h. The copy and move assignment operators weren't returning anything and were hence producing "non-void function does not return a value" warnings. As the test doesn't actually need a definition for these operators, I've removed the definition and simply declared them. --- test/Interop/Cxx/class/Inputs/loadable-types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Interop/Cxx/class/Inputs/loadable-types.h b/test/Interop/Cxx/class/Inputs/loadable-types.h index c2698961c4b41..5f92b6ef7d089 100644 --- a/test/Interop/Cxx/class/Inputs/loadable-types.h +++ b/test/Interop/Cxx/class/Inputs/loadable-types.h @@ -60,7 +60,7 @@ struct StructWithSubobjectMoveConstructor { }; struct StructWithCopyAssignment { - StructWithCopyAssignment &operator=(const StructWithCopyAssignment &) {} + StructWithCopyAssignment &operator=(const StructWithCopyAssignment &); }; struct StructWithInheritedCopyAssignment : StructWithCopyAssignment {}; @@ -70,7 +70,7 @@ struct StructWithSubobjectCopyAssignment { }; struct StructWithMoveAssignment { - StructWithMoveAssignment &operator=(StructWithMoveAssignment &&) {} + StructWithMoveAssignment &operator=(StructWithMoveAssignment &&); }; struct StructWithInheritedMoveAssignment : StructWithMoveAssignment {}; From 3ae3a7b4597f8f20faef80e1d071367f7e37037f Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Wed, 20 May 2020 03:46:48 -0500 Subject: [PATCH 112/625] Restore documentation for the pattern-matching operator as applied to RangeExpressions The previous documentation of this operator in `Range` context was lost sometime during 2017. This new version is a simplified version of the original copy, with substantial inspiration taken from the present-day documentation of the same operator on `Optional`. Fixes [SR-12842](https://bugs.swift.org/browse/SR-12842). --- stdlib/public/core/Range.swift | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift index 71357d1476dce..85e7db7b7c9c2 100644 --- a/stdlib/public/core/Range.swift +++ b/stdlib/public/core/Range.swift @@ -74,6 +74,25 @@ public protocol RangeExpression { } extension RangeExpression { + + /// Returns a Boolean value indicating whether a value is included in a + /// range. + /// + /// You can use the pattern-matching operator (`~=`) to test whether a value + /// is included in a range. The pattern-matching operator is used + /// internally in `case` statements for pattern matching. The following + /// example uses the `~=` operator to test whether an integer is included in + /// a range of single-digit numbers: + /// + /// let chosenNumber = 3 + /// if 0..<10 ~= chosenNumber { + /// print("\(chosenNumber) is a single digit.") + /// } + /// // Prints "3 is a single digit." + /// + /// - Parameters: + /// - pattern: A range. + /// - bound: A value to match against `pattern`. @inlinable public static func ~= (pattern: Self, value: Bound) -> Bool { return pattern.contains(value) From 131e1d3b9c2c956592d1e8529030af71177f3abc Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Wed, 20 May 2020 13:37:02 +0200 Subject: [PATCH 113/625] Removed support for iOS 8.2 and earlier from lit.cfg --- test/lit.cfg | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/test/lit.cfg b/test/lit.cfg index 7bd3a75e9fb70..7019fa87aee70 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -60,24 +60,6 @@ def darwin_get_sdk_version(sdk_path): "ProductBuildVersion"]).rstrip() return (name, vers, build) - -def darwin_sdk_build_version_split(version): - m = re.search("([0-9]+)([A-Z])([0-9]+)", version) - return (int(m.group(1)), m.group(2), int(m.group(3))) - - -def darwin_sdk_build_version_cmp(lhs, rhs): - # The `_cmp` function is provided to port the Python 2 global `cmp` - # function forward to Python 3. The function implementation is taken - # directly from the recommendation that announced its removal. - # See: https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons - def _cmp(a, b): - return (a > b) - (a < b) - return _cmp( - darwin_sdk_build_version_split(lhs), - darwin_sdk_build_version_split(rhs)) - - # Run sw_vers on the target to be tested and return the results. def darwin_get_sw_vers(commandPrefix=[]): name = lit.util.executeCommand( @@ -98,19 +80,7 @@ def darwin_get_ios_sim_vers(): def get_simulator_command(run_os, run_cpu, sdk_path): (name, vers, build) = darwin_get_sdk_version(sdk_path) if run_os == 'ios': - # There are two binaries for the iOS simulator: 'sim' and 'simctl'. - # 'sim' is only supported for iOS <= 8.1 and early versions of 8.2. - # 'simctl' is supported for iOS >= 8.2. - # 'simctl' used to have a bug where it failed to propagate the exit - # code of the child process. This was fixed only in the middle of 8.2 - # development cycle. - if ((darwin_sdk_build_version_cmp(build, "12E999") <= 0) or - (darwin_sdk_build_version_cmp("12F1", build) <= 0 and - darwin_sdk_build_version_cmp(build, "12F12") <= 0) or - (darwin_sdk_build_version_cmp("12H1", build) <= 0 and - darwin_sdk_build_version_cmp(build, "12H11") <= 0)): - return "sim" - elif run_cpu == "i386": + if run_cpu == "i386": if min(darwin_get_ios_sim_vers()) > 10.3: print("ERROR: Install iOS 10.3 or older simulator for 32bit testing") print("INFO: Xcode -> Preferences -> Components -> Simulators") @@ -130,15 +100,6 @@ def get_lldb_python_path(lldb_build_root): lldb_path = os.path.join(lldb_build_root, 'bin', 'lldb') return subprocess.check_output([lldb_path, "-P"]).rstrip() -assert darwin_sdk_build_version_cmp("11A1", "12A1") < 0 -assert darwin_sdk_build_version_cmp("12A1", "11A1") > 0 - -assert darwin_sdk_build_version_cmp("11A1", "11B1") < 0 -assert darwin_sdk_build_version_cmp("11B1", "11A1") > 0 - -assert darwin_sdk_build_version_cmp("11A22", "11A100") < 0 -assert darwin_sdk_build_version_cmp("11A100", "11A22") > 0 - ### # Check that the object root is known. From a0b651727246c02107fc4051c45800345d587f31 Mon Sep 17 00:00:00 2001 From: Valeriy Van Date: Wed, 20 May 2020 14:08:26 +0200 Subject: [PATCH 114/625] Fixes filter function of RangeReplaceableCollection. Addresses ticket SR-12648 --- stdlib/public/core/RangeReplaceableCollection.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift index 6b2fda0a7767a..729849b7b1d40 100644 --- a/stdlib/public/core/RangeReplaceableCollection.swift +++ b/stdlib/public/core/RangeReplaceableCollection.swift @@ -1082,7 +1082,11 @@ extension RangeReplaceableCollection { public __consuming func filter( _ isIncluded: (Element) throws -> Bool ) rethrows -> Self { - return try Self(self.lazy.filter(isIncluded)) + var result = Self() + for element in self where try isIncluded(element) { + result.append(element) + } + return result } } From 6bf0f26ecd7add55c31e8027be15435b1248a6de Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Wed, 20 May 2020 15:28:12 +0200 Subject: [PATCH 115/625] Emit `/DEFAULTLIB` directive for `#pragma comment(lib, ...)` in a C module. This is important, for example, for linking correctly to the C++ standard library on Windows, which uses `#pragma comment(lib, ...)` in its headers to specify the correct library to link against. --- lib/IRGen/GenClangDecl.cpp | 11 ++++++++++ .../autolink-coff-c-pragma-transitive.h | 1 + test/IRGen/Inputs/autolink-coff-c-pragma.h | 3 +++ test/IRGen/Inputs/module.modulemap | 9 +++++++++ test/IRGen/autolink-coff-c-pragma.swift | 20 +++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 test/IRGen/Inputs/autolink-coff-c-pragma-transitive.h create mode 100644 test/IRGen/Inputs/autolink-coff-c-pragma.h create mode 100644 test/IRGen/Inputs/module.modulemap create mode 100644 test/IRGen/autolink-coff-c-pragma.swift diff --git a/lib/IRGen/GenClangDecl.cpp b/lib/IRGen/GenClangDecl.cpp index 304ddf5bf2b92..577307ce502d9 100644 --- a/lib/IRGen/GenClangDecl.cpp +++ b/lib/IRGen/GenClangDecl.cpp @@ -113,6 +113,17 @@ IRGenModule::getAddrOfClangGlobalDecl(clang::GlobalDecl global, } void IRGenModule::finalizeClangCodeGen() { + // Ensure that code is emitted for any `PragmaCommentDecl`s. (These are + // always guaranteed to be directly below the TranslationUnitDecl.) + // In Clang, this happens automatically during the Sema phase, but here we + // need to take care of it manually because our Clang CodeGenerator is not + // attached to Clang Sema as an ASTConsumer. + for (const auto *D : ClangASTContext->getTranslationUnitDecl()->decls()) { + if (const auto *PCD = dyn_cast(D)) { + emitClangDecl(PCD); + } + } + ClangCodeGen->HandleTranslationUnit( *const_cast(ClangASTContext)); } diff --git a/test/IRGen/Inputs/autolink-coff-c-pragma-transitive.h b/test/IRGen/Inputs/autolink-coff-c-pragma-transitive.h new file mode 100644 index 0000000000000..d3644cee43cb4 --- /dev/null +++ b/test/IRGen/Inputs/autolink-coff-c-pragma-transitive.h @@ -0,0 +1 @@ +#pragma comment(lib, "transitive-module") diff --git a/test/IRGen/Inputs/autolink-coff-c-pragma.h b/test/IRGen/Inputs/autolink-coff-c-pragma.h new file mode 100644 index 0000000000000..6d2705ff4e152 --- /dev/null +++ b/test/IRGen/Inputs/autolink-coff-c-pragma.h @@ -0,0 +1,3 @@ +#include "autolink-coff-c-pragma-transitive.h" + +#pragma comment(lib, "module") diff --git a/test/IRGen/Inputs/module.modulemap b/test/IRGen/Inputs/module.modulemap new file mode 100644 index 0000000000000..d396471ea63e0 --- /dev/null +++ b/test/IRGen/Inputs/module.modulemap @@ -0,0 +1,9 @@ +module AutolinkCoffCPragma { + header "autolink-coff-c-pragma.h" + export * +} + +module AutolinkCoffCPragmaTransitive { + header "autolink-coff-c-pragma-transitive.h" + export * +} diff --git a/test/IRGen/autolink-coff-c-pragma.swift b/test/IRGen/autolink-coff-c-pragma.swift new file mode 100644 index 0000000000000..0b4d8b389d64f --- /dev/null +++ b/test/IRGen/autolink-coff-c-pragma.swift @@ -0,0 +1,20 @@ +// Tests that a `#pragma comment(lib, ...)` in a C header imported as a module +// causes a corresponding `/DEFAULTLIB` directive to be emitted. +// +// We test that this is true also for C headers included transitively from +// another C header. + +// RUN: %swift -module-name Swift -target x86_64-unknown-windows-msvc -I %S/Inputs -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=CHECK-MSVC-IR +// RUN: %swift -module-name Swift -target x86_64-unknown-windows-msvc -I %S/Inputs -S %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=CHECK-MSVC-ASM + +// REQUIRES: CODEGENERATOR=X86 + +import AutolinkCoffCPragma + +// CHECK-MSVC-IR: !llvm.linker.options = !{!{{[0-9]+}}, !{{[0-9]+}}} +// CHECK-MSVC-IR-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:module.lib"} +// CHECK-MSVC-IR-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:transitive-module.lib"} + +// CHECK-MSVC-ASM: .section .drectve +// CHECK-MSVC-ASM-DAG: .ascii " /DEFAULTLIB:module.lib" +// CHECK-MSVC-ASM-DAG: .ascii " /DEFAULTLIB:transitive-module.lib" From b6a79b5a73d900887323aff440470e7ef8264a9e Mon Sep 17 00:00:00 2001 From: David Goldman Date: Wed, 20 May 2020 10:06:54 -0400 Subject: [PATCH 116/625] [SourceKit] Don't handle OperationKind::all --- tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index c6a728171c403..46e4ab3d83012 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -3191,8 +3191,8 @@ static Optional getUIDForOperationKind(trace::OperationKind OpKind) { return CompileOperationIndexSource; case trace::OperationKind::CodeCompletion: return CompileOperationCodeCompletion; - case trace::OperationKind::All: - return None; + default: + llvm_unreachable("Unknown operation kind"); } } From 2b2f7dcd2fb6cda1ec1e6ccafa6b2bc7c6695e91 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 20 May 2020 07:00:33 -0700 Subject: [PATCH 117/625] Adjust to AllocaInst MaybeAlign -> Align api change --- lib/IRGen/GenCall.cpp | 9 ++++++--- lib/IRGen/GenDecl.cpp | 4 ++-- lib/IRGen/GenOpaque.cpp | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index ed01996f0bc47..0cb4dfb09157a 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -2117,7 +2117,8 @@ static void emitCoerceAndExpand(IRGenFunction &IGF, Explosion &in, Alignment(coercionTyLayout->getAlignment().value()); auto alloca = cast(temporary.getAddress()); if (alloca->getAlignment() < coercionTyAlignment.getValue()) { - alloca->setAlignment(llvm::MaybeAlign(coercionTyAlignment.getValue())); + alloca->setAlignment( + llvm::MaybeAlign(coercionTyAlignment.getValue()).valueOrOne()); temporary = Address(temporary.getAddress(), coercionTyAlignment); } @@ -2395,7 +2396,8 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, auto ABIAlign = AI.getIndirectAlign(); if (ABIAlign > addr.getAlignment()) { auto *AS = cast(addr.getAddress()); - AS->setAlignment(llvm::MaybeAlign(ABIAlign.getQuantity())); + AS->setAlignment( + llvm::MaybeAlign(ABIAlign.getQuantity()).valueOrOne()); addr = Address(addr.getAddress(), Alignment(ABIAlign.getQuantity())); } } @@ -3087,7 +3089,8 @@ static void adjustAllocaAlignment(const llvm::DataLayout &DL, Alignment layoutAlignment = Alignment(layout->getAlignment().value()); auto alloca = cast(allocaAddr.getAddress()); if (alloca->getAlignment() < layoutAlignment.getValue()) { - alloca->setAlignment(llvm::MaybeAlign(layoutAlignment.getValue())); + alloca->setAlignment( + llvm::MaybeAlign(layoutAlignment.getValue()).valueOrOne()); allocaAddr = Address(allocaAddr.getAddress(), layoutAlignment); } } diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 97ad57e20d1a6..3509626efd883 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -4378,7 +4378,7 @@ Address IRGenFunction::createAlloca(llvm::Type *type, llvm::AllocaInst *alloca = new llvm::AllocaInst(type, IGM.DataLayout.getAllocaAddrSpace(), name, AllocaIP); - alloca->setAlignment(llvm::MaybeAlign(alignment.getValue())); + alloca->setAlignment(llvm::MaybeAlign(alignment.getValue()).valueOrOne()); return Address(alloca, alignment); } @@ -4389,7 +4389,7 @@ Address IRGenFunction::createAlloca(llvm::Type *type, const llvm::Twine &name) { llvm::AllocaInst *alloca = new llvm::AllocaInst( type, IGM.DataLayout.getAllocaAddrSpace(), ArraySize, - llvm::MaybeAlign(alignment.getValue()), name, AllocaIP); + llvm::MaybeAlign(alignment.getValue()).valueOrOne(), name, AllocaIP); return Address(alloca, alignment); } diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp index 25d2635b1c195..07558c8068780 100644 --- a/lib/IRGen/GenOpaque.cpp +++ b/lib/IRGen/GenOpaque.cpp @@ -575,7 +575,7 @@ StackAddress IRGenFunction::emitDynamicAlloca(llvm::Type *eltTy, // Emit the dynamic alloca. auto *alloca = Builder.IRBuilderBase::CreateAlloca(eltTy, arraySize, name); - alloca->setAlignment(llvm::MaybeAlign(align.getValue())); + alloca->setAlignment(llvm::MaybeAlign(align.getValue()).valueOrOne()); assert(!isInEntryBlock || getActiveDominancePoint().isUniversal() && From 28a61eaa19401677152bee78d9911cd7ef42d1ba Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Wed, 20 May 2020 11:01:08 -0400 Subject: [PATCH 118/625] [Test] Have llvm-support-odr-violation.sh use platform-dylib-dir. platform-module-dir isn't quite right, since we're looking for libswiftCore.dylib. rdar://problem/63437032 --- test/stdlib/llvm-support-odr-violation.test-sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stdlib/llvm-support-odr-violation.test-sh b/test/stdlib/llvm-support-odr-violation.test-sh index 09b6aea648656..3621136b105d4 100644 --- a/test/stdlib/llvm-support-odr-violation.test-sh +++ b/test/stdlib/llvm-support-odr-violation.test-sh @@ -1,2 +1,2 @@ -// RUN: %llvm-nm --defined-only -C %platform-module-dir/%target-library-name(swiftCore) | %FileCheck --allow-empty %s +// RUN: %llvm-nm --defined-only -C %platform-dylib-dir/%target-library-name(swiftCore) | %FileCheck --allow-empty %s // CHECK-NOT: [^:]llvm:: From 0637e17957c821f9eb6ba5ca3431c988438980e8 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 19 May 2020 23:59:35 +0000 Subject: [PATCH 119/625] runtime: improve error handling path for the runtime Rather than use `fprintf` for the error handling path use the platform specific error handling systems (`asl_log`, `__android_log_printf`) if available. The standard file streams are not available on all platforms (e.g. Android). --- stdlib/public/LLVMSupport/ErrorHandling.cpp | 50 ++++++++++++++++----- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/stdlib/public/LLVMSupport/ErrorHandling.cpp b/stdlib/public/LLVMSupport/ErrorHandling.cpp index ad8e8ae5b73ff..f40c614d46a6f 100644 --- a/stdlib/public/LLVMSupport/ErrorHandling.cpp +++ b/stdlib/public/LLVMSupport/ErrorHandling.cpp @@ -21,22 +21,50 @@ # include #else # include +# include #endif +#include + +#if defined(__APPLE__) +#include +#elif defined(__ANDROID__) +#include +#endif + +namespace { +void error(const char *fmt, ...) { + char buffer[1024]; + va_list argp; + + va_start(argp, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, argp); + va_end(argp); + +#if defined(__APPLE__) + asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", buffer); +#elif defined(__ANDROID__) + __android_log_printf(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", buffer); +#elif defined(_WIN32) +#define STDERR_FILENO 2 + _write(STDERR_FILENO, buffer, strlen(buffer)); +#else + write(STDERR_FILENO, buffer, strlen(buffer)); +#endif +} +} + using namespace llvm; void __swift::__runtime::llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) { - report_fatal_error(std::string(Reason), GenCrashDiag); + error("LLVM ERROR: %s\n", Reason); + abort(); } void __swift::__runtime::llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) { - // Blast the result out to stderr. We don't try hard to make sure this - // succeeds (e.g. handling EINTR) and we can't use errs() here because - // raw ostreams can call report_fatal_error. - fprintf(stderr, "LLVM ERROR: %s\n", Reason.c_str()); - abort(); + report_fatal_error(Reason.c_str(), GenCrashDiag); } void __swift::__runtime::llvm::report_fatal_error(StringRef Reason, @@ -48,7 +76,7 @@ void __swift::__runtime::llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) { // Don't call the normal error handler. It may allocate memory. Directly write // an OOM to stderr and abort. - fprintf(stderr, "LLVM ERROR: out of memory\n"); + error("LLVM ERROR: out of memory\n"); abort(); } @@ -58,11 +86,11 @@ void __swift::__runtime::llvm::llvm_unreachable_internal( // llvm_unreachable is intended to be used to indicate "impossible" // situations, and not legitimate runtime errors. if (msg) - fprintf(stderr, "%s\n", msg); - fprintf(stderr, "UNREACHABLE executed"); + error("%s\n", msg); + error("UNREACHABLE executed"); if (file) - fprintf(stderr, " at %s:%u", file, line); - fprintf(stderr, "!\n"); + error(" at %s:%u", file, line); + error("!\n"); abort(); #ifdef LLVM_BUILTIN_UNREACHABLE // Windows systems and possibly others don't declare abort() to be noreturn, From 6116f7d528aa188e886f815bf693259cab09d9ea Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 6 May 2020 15:49:21 -0700 Subject: [PATCH 120/625] [CodeCompletion] Disable fast-completion dependecy checking test cases while investigating. rdar://problem/62923248 --- test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift | 1 + test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift | 1 + test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift | 1 + test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift | 1 + 4 files changed, 4 insertions(+) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift b/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift index 2675887fc0dbf..4710a68489d1d 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift b/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift index 68965b5e9a97d..bf1e727ae15a3 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift b/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift index d9d6f90daf3d6..da85e9ce70768 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift b/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift index 30cbd7b97a37f..31404c00a919c 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) From 7789e2c87c8a577c65e661ca689b34f9140da117 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 20 May 2020 06:31:36 -0700 Subject: [PATCH 121/625] IRGen: Fix enumPayload value witness emission for huge types LLVM's isel does not like integer types beyond a certain size (llvm::IntegerType::MAX_INT_BITS). rdar://63189452 --- lib/IRGen/GenType.cpp | 53 ++++++++++++++++++++++++--------- test/IRGen/Inputs/huge_c_type.h | 31 +++++++++++++++++++ test/IRGen/huge_c_type.swift | 11 +++++++ 3 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 test/IRGen/Inputs/huge_c_type.h create mode 100644 test/IRGen/huge_c_type.swift diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 4dfd535594683..7c8423d1f357b 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -687,15 +687,26 @@ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload( llvm::Value *caseIndexFromValue = zero; if (fixedSize > Size(0)) { - // Read up to one pointer-sized 'chunk' of the payload. - // The size of the chunk does not have to be a power of 2. - auto *caseIndexType = llvm::IntegerType::get(Ctx, - fixedSize.getValueInBits()); - auto *caseIndexAddr = Builder.CreateBitCast(valueAddr, - caseIndexType->getPointerTo()); - caseIndexFromValue = Builder.CreateZExtOrTrunc( - Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), - IGM.Int32Ty); + // llvm only supports integer types upto a certain size (i.e selection dag + // will crash). + if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) { + // Read up to one pointer-sized 'chunk' of the payload. + // The size of the chunk does not have to be a power of 2. + auto *caseIndexType = + llvm::IntegerType::get(Ctx, fixedSize.getValueInBits()); + auto *caseIndexAddr = + Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo()); + caseIndexFromValue = Builder.CreateZExtOrTrunc( + Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), + IGM.Int32Ty); + } else { + auto *caseIndexType = llvm::IntegerType::get(Ctx, 32); + auto *caseIndexAddr = + Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo()); + caseIndexFromValue = Builder.CreateZExtOrTrunc( + Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), + IGM.Int32Ty); + } } auto *result1 = Builder.CreateAdd( @@ -867,11 +878,25 @@ void irgen::storeFixedTypeEnumTagSinglePayload( payloadIndex->addIncoming(payloadIndex0, payloadLT4BB); if (fixedSize > Size(0)) { - // Write the value to the payload as a zero extended integer. - auto *intType = Builder.getIntNTy(fixedSize.getValueInBits()); - Builder.CreateStore( - Builder.CreateZExtOrTrunc(payloadIndex, intType), - Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) { + // Write the value to the payload as a zero extended integer. + auto *intType = Builder.getIntNTy(fixedSize.getValueInBits()); + Builder.CreateStore( + Builder.CreateZExtOrTrunc(payloadIndex, intType), + Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + } else { + // Write the value to the payload as a zero extended integer. + Size limit = IGM.getPointerSize(); + auto *intType = Builder.getIntNTy(limit.getValueInBits()); + Builder.CreateStore( + Builder.CreateZExtOrTrunc(payloadIndex, intType), + Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + // Zero the remainder of the payload. + auto zeroAddr = Builder.CreateConstByteArrayGEP(valueAddr, limit); + auto zeroSize = Builder.CreateSub( + size, llvm::ConstantInt::get(size->getType(), limit.getValue())); + Builder.CreateMemSet(zeroAddr, Builder.getInt8(0), zeroSize); + } } // Write to the extra tag bytes, if any. emitSetTag(IGF, extraTagBitsAddr, extraTagIndex, numExtraTagBytes); diff --git a/test/IRGen/Inputs/huge_c_type.h b/test/IRGen/Inputs/huge_c_type.h new file mode 100644 index 0000000000000..42b2a9d7be35b --- /dev/null +++ b/test/IRGen/Inputs/huge_c_type.h @@ -0,0 +1,31 @@ +#include + +typedef uint8_t bool; + +#define CREATE_ARRAY(T, N) \ + struct { \ + T data[N]; \ + size_t size; \ + } + +typedef struct { + int32_t a; + double b[16]; +} Thing; + +typedef struct { + uint64_t a; + bool b; + CREATE_ARRAY(Thing, 16) c; + uint32_t d; + uint64_t e; + uint64_t f; + CREATE_ARRAY(uint32_t, 4) g; + CREATE_ARRAY(uint64_t, 4) h; + CREATE_ARRAY(uint64_t, 4) i; +} Thing2; + +typedef struct { + int64_t a; + CREATE_ARRAY(Thing2, 512) c; +} Thing3; diff --git a/test/IRGen/huge_c_type.swift b/test/IRGen/huge_c_type.swift new file mode 100644 index 0000000000000..93d969726f6da --- /dev/null +++ b/test/IRGen/huge_c_type.swift @@ -0,0 +1,11 @@ +// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -disable-llvm-optzns -emit-ir | %FileCheck %s +// Make sure that this does not crash during LLVM's ISel. It does not like huge +// llvm::IntegerTypes. +// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -c + + +// CHECK-NOT:i9535616 + +public func doIt(a: Thing3) { + print(a) +} From 115bd2855b733266108a618e6bddc9c6c9ba947d Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Fri, 15 May 2020 18:54:07 -0700 Subject: [PATCH 122/625] Naive Dependency Replay Finish off private intransitive dependencies with an implementation of dependency replay. For the sake of illustration, imagine a chain of requests A -> B -> C -> ... Supposing each request is never cached, then every invocation of the compiler with the same inputs will always kick off the exact same set of requests. For the purposes of dependency tracking, that also means every single lookup request will run without issue, and all dependencies will be accurately reported. But we live in a world with cached requests. Suppose request B* is cached. The first time we encounter that request, its evaluation order looks identical: A -> B* -> C -> ... If we are in a mode that compiles single primaries, this is not a problem because every request graph will look like this. But if we are in a mode where we are compiling multiple primaries, then subsequent request graphs will *actually* hit the cache and never execute request C or any of its dependent computations! A -> B* Supposing C was a lookup request, that means the name(s) looked up downstream of B* will *never* be recorded in the referenced name tracker which can lead to miscompilation. Note that this is not a problem inherent to the design of the request evaluator - caches in the compiler have *always* hidden dependent lookups. In fact, the request evaluator provides us our first opportunity to resolve this correctness bug! --- include/swift/AST/AnyRequest.h | 31 +++++++- include/swift/AST/Evaluator.h | 15 ++-- include/swift/AST/EvaluatorDependencies.h | 80 ++++++++++++++++++++- lib/AST/Evaluator.cpp | 86 ++++++++++++++++++++--- 4 files changed, 196 insertions(+), 16 deletions(-) diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h index 63332fd68e7a6..669174e3bf978 100644 --- a/include/swift/AST/AnyRequest.h +++ b/include/swift/AST/AnyRequest.h @@ -66,6 +66,9 @@ struct AnyRequestVTable { static SourceLoc getNearestLoc(const void *ptr) { return static_cast(ptr)->getNearestLoc(); } + static bool isCached(const void *ptr) { + return static_cast(ptr)->isCached(); + } }; const uint64_t typeID; @@ -78,8 +81,29 @@ struct AnyRequestVTable { const std::function diagnoseCycle; const std::function noteCycleStep; const std::function getNearestLoc; + const std::function isCached; - template + template ::type * = nullptr> + static const AnyRequestVTable *get() { + static const AnyRequestVTable vtable = { + TypeID::value, + sizeof(Request), + &Impl::copy, + &Impl::getHash, + &Impl::deleter, + &Impl::isEqual, + &Impl::simpleDisplay, + &Impl::diagnoseCycle, + &Impl::noteCycleStep, + &Impl::getNearestLoc, + &Impl::isCached, + }; + return &vtable; + } + + template ::type * = nullptr> static const AnyRequestVTable *get() { static const AnyRequestVTable vtable = { TypeID::value, @@ -92,6 +116,7 @@ struct AnyRequestVTable { &Impl::diagnoseCycle, &Impl::noteCycleStep, &Impl::getNearestLoc, + [](auto){ return false; }, }; return &vtable; } @@ -194,6 +219,10 @@ class AnyRequestBase { return getVTable()->getNearestLoc(getRawStorage()); } + bool isCached() const { + return getVTable()->isCached(getRawStorage()); + } + /// Compare two instances for equality. friend bool operator==(const AnyRequestBase &lhs, const AnyRequestBase &rhs) { diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 59de0280e6869..c2503e20e3f2f 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -431,19 +431,22 @@ class Evaluator { } private: - // Report the result of evaluating a request that is not a dependency sink - - // which is to say do nothing. - template ::type * = nullptr> + // Report the result of evaluating a request that is not a dependency sink. + template ::type * = nullptr> void reportEvaluatedResult(const Request &r, - const typename Request::OutputType &o) {} + const typename Request::OutputType &o) { + collector.replay(ActiveRequest(r)); + } // Report the result of evaluating a request that is a dependency sink. template ::type * = nullptr> void reportEvaluatedResult(const Request &r, const typename Request::OutputType &o) { - r.writeDependencySink(collector, o); + return collector.record(activeRequests, [&r, &o](auto &c) { + return r.writeDependencySink(c, o); + }); } public: diff --git a/include/swift/AST/EvaluatorDependencies.h b/include/swift/AST/EvaluatorDependencies.h index ceb16440c67bf..5009dfaf0332b 100644 --- a/include/swift/AST/EvaluatorDependencies.h +++ b/include/swift/AST/EvaluatorDependencies.h @@ -18,6 +18,7 @@ #ifndef SWIFT_AST_EVALUATOR_DEPENDENCIES_H #define SWIFT_AST_EVALUATOR_DEPENDENCIES_H +#include "swift/AST/AnyRequest.h" #include "swift/AST/AttrKind.h" #include "swift/AST/SourceFile.h" #include "llvm/ADT/PointerIntPair.h" @@ -113,6 +114,70 @@ struct DependencyCollector { /// A stack of dependency sources in the order they were evaluated. llvm::SmallVector dependencySources; + struct Reference { + public: + enum class Kind { + Empty, + Tombstone, + UsedMember, + PotentialMember, + TopLevel, + Dynamic, + } kind; + + NominalTypeDecl *subject; + DeclBaseName name; + + private: + Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name) + : kind(kind), subject(subject), name(name) {} + + public: + static Reference empty() { + return {Kind::Empty, llvm::DenseMapInfo::getEmptyKey(), + llvm::DenseMapInfo::getEmptyKey()}; + } + + static Reference tombstone() { + return {Kind::Empty, + llvm::DenseMapInfo::getTombstoneKey(), + llvm::DenseMapInfo::getTombstoneKey()}; + } + + public: + static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name) { + return {Kind::UsedMember, subject, name}; + } + + static Reference potentialMember(NominalTypeDecl *subject) { + return {Kind::PotentialMember, subject, DeclBaseName()}; + } + + static Reference topLevel(DeclBaseName name) { + return {Kind::TopLevel, nullptr, name}; + } + + static Reference dynamic(DeclBaseName name) { + return {Kind::Dynamic, nullptr, name}; + } + + public: + struct Info { + static inline Reference getEmptyKey() { return Reference::empty(); } + static inline Reference getTombstoneKey() { + return Reference::tombstone(); + } + static inline unsigned getHashValue(const Reference &Val) { + return llvm::hash_combine(Val.kind, Val.subject, + Val.name.getAsOpaquePointer()); + } + static bool isEqual(const Reference &LHS, const Reference &RHS) { + return LHS.kind == RHS.kind && LHS.subject == RHS.subject && + LHS.name == RHS.name; + } + }; + }; + public: enum class Mode { // Enables the current "status quo" behavior of the dependency collector. @@ -128,8 +193,21 @@ struct DependencyCollector { ExperimentalPrivateDependencies, }; Mode mode; + llvm::DenseMap> + requestReferences; + llvm::DenseSet scratch; + bool isRecording; + + explicit DependencyCollector(Mode mode) + : mode{mode}, requestReferences{}, scratch{}, isRecording{false} {}; - explicit DependencyCollector(Mode mode) : mode{mode} {}; +private: + void realizeOrRecord(const Reference &ref); + +public: + void replay(const swift::ActiveRequest &req); + void record(const llvm::SetVector &stack, + llvm::function_ref rec); public: /// Registers a named reference from the current dependency scope to a member diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index b4a8ea3a369cb..c0ba9d52db9b6 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/SaveAndRestore.h" using namespace swift; @@ -378,24 +379,93 @@ void Evaluator::dumpDependenciesGraphviz() const { printDependenciesGraphviz(llvm::dbgs()); } +void evaluator::DependencyCollector::realizeOrRecord(const Reference &ref) { + if (isRecording) { + scratch.insert(std::move(ref)); + return; + } + + auto *tracker = getActiveDependencyTracker(); + if (!tracker) { + return; + } + + switch (ref.kind) { + case Reference::Kind::Empty: + case Reference::Kind::Tombstone: + llvm_unreachable("cannot record empty dependency"); + case Reference::Kind::UsedMember: + tracker->addUsedMember({ref.subject, ref.name}, isActiveSourceCascading()); + break; + case Reference::Kind::PotentialMember: + tracker->addUsedMember({ref.subject, Identifier()}, + isActiveSourceCascading()); + break; + case Reference::Kind::TopLevel: + tracker->addTopLevelName(ref.name, isActiveSourceCascading()); + break; + case Reference::Kind::Dynamic: + tracker->addDynamicLookupName(ref.name, isActiveSourceCascading()); + break; + } +} + void evaluator::DependencyCollector::addUsedMember(NominalTypeDecl *subject, DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addUsedMember({subject, name}, isActiveSourceCascading()); + return realizeOrRecord(Reference::usedMember(subject, name)); } void evaluator::DependencyCollector::addPotentialMember( NominalTypeDecl *subject) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addUsedMember({subject, Identifier()}, isActiveSourceCascading()); + return realizeOrRecord(Reference::potentialMember(subject)); } void evaluator::DependencyCollector::addTopLevelName(DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addTopLevelName(name, isActiveSourceCascading()); + return realizeOrRecord(Reference::topLevel(name)); } void evaluator::DependencyCollector::addDynamicLookupName(DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addDynamicLookupName(name, isActiveSourceCascading()); + return realizeOrRecord(Reference::dynamic(name)); +} + +void evaluator::DependencyCollector::record( + const llvm::SetVector &stack, + llvm::function_ref rec) { + assert(!isRecording && "Probably not a good idea to allow nested recording"); + if (mode == Mode::StatusQuo) { + return rec(*this); + } + + llvm::SaveAndRestore restore(isRecording, true); + scratch = {}; + rec(*this); + for (const auto &request : stack) { + if (!request.isCached()) { + continue; + } + + auto entry = requestReferences.find_as(request); + if (entry == requestReferences.end()) { + requestReferences.insert({AnyRequest(request), scratch}); + continue; + } + + entry->second.insert(scratch.begin(), scratch.end()); + } +} + +void evaluator::DependencyCollector::replay(const swift::ActiveRequest &req) { + if (mode == Mode::StatusQuo) { + return; + } + + assert(!isRecording && "Probably not a good idea to allow nested recording"); + auto entry = requestReferences.find_as(req); + if (entry == requestReferences.end()) { + return; + } + + for (const auto &ref : entry->second) { + realizeOrRecord(ref); + } } From 097e451fbed08d788af1f8c36007841dd923f63d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 20 May 2020 11:11:43 -0700 Subject: [PATCH 123/625] Test does not work on linux --- test/IRGen/huge_c_type.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/test/IRGen/huge_c_type.swift b/test/IRGen/huge_c_type.swift index 93d969726f6da..402d3e437d63a 100644 --- a/test/IRGen/huge_c_type.swift +++ b/test/IRGen/huge_c_type.swift @@ -3,6 +3,7 @@ // llvm::IntegerTypes. // RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -c +// REQUIRES: OS=macosx || OS=ios // CHECK-NOT:i9535616 From 7d187d3517cb68275899b3bde89efb0b11bb4c2d Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 10 May 2020 22:00:34 +0100 Subject: [PATCH 124/625] test: enable WebAssembly/WASI in lit.cfg --- test/lit.cfg | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/test/lit.cfg b/test/lit.cfg index 5d67e1403481b..1570fac4143f2 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -2,7 +2,7 @@ # # This source file is part of the Swift.org open source project # -# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +# 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 @@ -297,6 +297,8 @@ config.swift_refactor = inferSwiftBinary('swift-refactor') config.swift_demangle_yamldump = inferSwiftBinary('swift-demangle-yamldump') config.benchmark_o = inferSwiftBinary('Benchmark_O') config.benchmark_driver = inferSwiftBinary('Benchmark_Driver') +config.wasmer = inferSwiftBinary('wasmer') +config.wasm_ld = inferSwiftBinary('wasm-ld') config.swift_utils = make_path(config.swift_src_root, 'utils') config.line_directive = make_path(config.swift_utils, 'line-directive') @@ -1340,6 +1342,73 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': '-L%s' % make_path(test_resource_dir, config.target_sdk_name)]) # The Swift interpreter is not available when targeting Android. config.available_features.discard('swift_interpreter') +elif run_os == 'wasi': + lit_config.note("Testing WebAssembly/WASI " + config.variant_triple) + + config.target_object_format = "wasm" + config.target_shared_library_prefix = 'lib' + config.target_shared_library_suffix = ".a" + config.target_sdk_name = "wasi" + config.target_runtime = "native" + + config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") + + config.target_build_swift = ' '.join([ + config.swiftc, + '-target', config.variant_triple, + '-Xcc', '--sysroot=%s' % config.variant_sdk, + '-Xclang-linker', '--sysroot=%s' % config.variant_sdk, + '-toolchain-stdlib-rpath', resource_dir_opt, + mcp_opt, config.swift_test_options, + config.swift_driver_test_options, swift_execution_tests_extra_flags]) + config.target_codesign = "echo" + config.target_build_swift_dylib = ( + "%s -parse-as-library -emit-library -o '\\1'" + % (config.target_build_swift)) + config.target_add_rpath = '' + config.target_swift_frontend = ' '.join([ + config.swift, + '-frontend', + '-target', config.variant_triple, + '-Xcc', '--sysroot=%s' % config.variant_sdk, + resource_dir_opt, mcp_opt, + config.swift_test_options, config.swift_frontend_test_options]) + subst_target_swift_frontend_mock_sdk = config.target_swift_frontend + subst_target_swift_frontend_mock_sdk_after = "" + config.target_run = '%s run --backend cranelift --' % config.wasmer + if 'interpret' in lit_config.params: + use_interpreter_for_simple_runs() + config.target_sil_opt = ( + '%s -target %s %s %s %s' % + (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options)) + config.target_swift_symbolgraph_extract = ' '.join([ + config.swift_symbolgraph_extract, + '-target', config.variant_triple, + mcp_opt]) + config.target_swift_ide_test = ( + '%s -target %s %s %s %s' % + (config.swift_ide_test, config.variant_triple, resource_dir_opt, + mcp_opt, ccp_opt)) + subst_target_swift_ide_test_mock_sdk = config.target_swift_ide_test + subst_target_swift_ide_test_mock_sdk_after = "" + config.target_swiftc_driver = ( + "%s -target %s -toolchain-stdlib-rpath %s %s" % + (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt)) + config.target_swift_modulewrap = ( + '%s -modulewrap -target %s' % + (config.swiftc, config.variant_triple)) + config.target_swift_emit_pcm = ( + '%s -emit-pcm -target %s' % + (config.swiftc, config.variant_triple)) + config.target_clang = ( + "%s -target %s %s -fobjc-runtime=ios-5.0" % + (config.clang, config.variant_triple, clang_mcp_opt)) + config.target_ld = ( + "%s -L%r" % + (config.wasm_ld, make_path(test_resource_dir, config.target_sdk_name))) + + # The Swift interpreter is not available when targeting WebAssembly/WASI. + config.available_features.discard('swift_interpreter') else: lit_config.fatal("Don't know how to define target_run and " From 946796ce5b96c4abe9ce1c3caf7180e4cb6d6f9c Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Wed, 20 May 2020 23:40:22 +0300 Subject: [PATCH 125/625] Serialization: Use checked substitution map deserialization for type nodes --- lib/Serialization/Deserialization.cpp | 35 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ef371a520ce13..f9992f5ff963b 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -4848,7 +4848,9 @@ class TypeDeserializer { auto substitutedType = substitutedTypeOrError.get(); // Read the substitutions. - auto subMap = MF.getSubstitutionMap(substitutionsID); + auto subMapOrError = MF.getSubstitutionMapChecked(substitutionsID); + if (!subMapOrError) + return subMapOrError.takeError(); auto parentTypeOrError = MF.getTypeChecked(parentTypeID); if (!parentTypeOrError) @@ -4858,11 +4860,12 @@ class TypeDeserializer { if (alias && alias->getAttrs().isUnavailable(ctx) && alias->isCompatibilityAlias()) { - return alias->getUnderlyingType().subst(subMap); + return alias->getUnderlyingType().subst(subMapOrError.get()); } auto parentType = parentTypeOrError.get(); - return TypeAliasType::get(alias, parentType, subMap, substitutedType); + return TypeAliasType::get(alias, parentType, subMapOrError.get(), + substitutedType); } Expected deserializeNominalType(ArrayRef scratch, @@ -5180,9 +5183,11 @@ class TypeDeserializer { return opaqueTypeOrError.takeError(); auto opaqueDecl = cast(opaqueTypeOrError.get()); - auto subs = MF.getSubstitutionMap(subsID); + auto subsOrError = MF.getSubstitutionMapChecked(subsID); + if (!subsOrError) + return subsOrError.takeError(); - return OpaqueTypeArchetypeType::get(opaqueDecl, subs); + return OpaqueTypeArchetypeType::get(opaqueDecl, subsOrError.get()); } Expected deserializeNestedArchetypeType(ArrayRef scratch, @@ -5317,8 +5322,11 @@ class TypeDeserializer { if (!layout) return nullptr; - auto subMap = MF.getSubstitutionMap(subMapID); - return SILBoxType::get(ctx, layout, subMap); + auto subMapOrError = MF.getSubstitutionMapChecked(subMapID); + if (!subMapOrError) + return subMapOrError.takeError(); + + return SILBoxType::get(ctx, layout, subMapOrError.get()); } Expected deserializeSILFunctionType(ArrayRef scratch, @@ -5503,16 +5511,19 @@ class TypeDeserializer { GenericSignature invocationSig = MF.getGenericSignature(rawInvocationGenericSig); - SubstitutionMap invocationSubs = - MF.getSubstitutionMap(rawInvocationSubs).getCanonical(); - SubstitutionMap patternSubs = - MF.getSubstitutionMap(rawPatternSubs).getCanonical(); + auto invocationSubsOrErr = MF.getSubstitutionMapChecked(rawInvocationSubs); + if (!invocationSubsOrErr) + return invocationSubsOrErr.takeError(); + auto patternSubsOrErr = MF.getSubstitutionMapChecked(rawPatternSubs); + if (!patternSubsOrErr) + return patternSubsOrErr.takeError(); return SILFunctionType::get(invocationSig, extInfo, coroutineKind.getValue(), calleeConvention.getValue(), allParams, allYields, allResults, errorResult, - patternSubs, invocationSubs, + patternSubsOrErr.get().getCanonical(), + invocationSubsOrErr.get().getCanonical(), ctx, witnessMethodConformance); } From b25c4665e4f3d8a6f247c8277daf87783a37fd88 Mon Sep 17 00:00:00 2001 From: Anthony Latsis Date: Mon, 18 May 2020 23:26:10 +0300 Subject: [PATCH 126/625] GenericSignatureImpl, #31712: Plug remaining relevant methods with type param. assertions --- include/swift/AST/GenericSignature.h | 4 ++-- lib/AST/GenericSignature.cpp | 9 +++++---- lib/AST/SubstitutionMap.cpp | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 4d347fae5b9d8..271e07899698f 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -329,12 +329,12 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final /// Determine whether the given dependent type is equal to a concrete type. bool isConcreteType(Type type) const; - /// Return the concrete type that the given dependent type is constrained to, + /// Return the concrete type that the given type parameter is constrained to, /// or the null Type if it is not the subject of a concrete same-type /// constraint. Type getConcreteType(Type type) const; - /// Return the layout constraint that the given dependent type is constrained + /// Return the layout constraint that the given type parameter is constrained /// to, or the null LayoutConstraint if it is not the subject of layout /// constraint. LayoutConstraint getLayoutConstraint(Type type) const; diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index ade97c2355846..a1a36e38096a4 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -428,7 +428,7 @@ Type GenericSignatureImpl::getSuperclassBound(Type type) const { /// required to conform. GenericSignature::RequiredProtocols GenericSignatureImpl::getRequiredProtocols(Type type) const { - if (!type->isTypeParameter()) return { }; + assert(type->isTypeParameter() && "Expected a type parameter"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = @@ -479,11 +479,11 @@ bool GenericSignatureImpl::isConcreteType(Type type) const { return bool(getConcreteType(type)); } -/// Return the concrete type that the given dependent type is constrained to, +/// Return the concrete type that the given type parameter is constrained to, /// or the null Type if it is not the subject of a concrete same-type /// constraint. Type GenericSignatureImpl::getConcreteType(Type type) const { - if (!type->isTypeParameter()) return Type(); + assert(type->isTypeParameter() && "Expected a type parameter"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = @@ -496,7 +496,8 @@ Type GenericSignatureImpl::getConcreteType(Type type) const { } LayoutConstraint GenericSignatureImpl::getLayoutConstraint(Type type) const { - if (!type->isTypeParameter()) return LayoutConstraint(); + assert(type->isTypeParameter() && + "Only type parameters can have layout constraints"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 61d4695a4d9db..074e432f4893c 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -271,7 +271,7 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const { // The generic parameter may have been made concrete by the generic signature, // substitute into the concrete type. - if (auto concreteType = genericSig->getConcreteType(genericParam)){ + if (auto concreteType = genericSig->getConcreteType(genericParam)) { // Set the replacement type to an error, to block infinite recursion. replacementType = ErrorType::get(concreteType); From 720d3d2f2adb8691e800a1dcd6293a51d6597782 Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Tue, 19 May 2020 15:03:38 -0700 Subject: [PATCH 127/625] [SymbolGraph] Show get/set on property/subscript full declarations But don't show them in subheading contexts. rdar://63233897 --- lib/SymbolGraphGen/SymbolGraph.cpp | 16 +- ...DeclarationFragments.swift => Basic.swift} | 6 +- .../Properties/ComputedProperties.swift | 162 ++++++++++++++++++ .../Properties/ProtocolRequirements.swift | 82 +++++++++ .../Properties/Subscripts.swift | 95 ++++++++++ 5 files changed, 355 insertions(+), 6 deletions(-) rename test/SymbolGraph/Symbols/Mixins/DeclarationFragments/{DeclarationFragments.swift => Basic.swift} (81%) create mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift create mode 100644 test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift diff --git a/lib/SymbolGraphGen/SymbolGraph.cpp b/lib/SymbolGraphGen/SymbolGraph.cpp index fb60ff321df7c..29ade8e54f166 100644 --- a/lib/SymbolGraphGen/SymbolGraph.cpp +++ b/lib/SymbolGraphGen/SymbolGraph.cpp @@ -48,9 +48,9 @@ PrintOptions SymbolGraph::getDeclarationFragmentsPrintOptions() const { Opts.FunctionDefinitions = false; Opts.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::MatchSource; - Opts.PrintGetSetOnRWProperties = false; - Opts.PrintPropertyAccessors = false; - Opts.PrintSubscriptAccessors = false; + Opts.PrintGetSetOnRWProperties = true; + Opts.PrintPropertyAccessors = true; + Opts.PrintSubscriptAccessors = true; Opts.SkipUnderscoredKeywords = true; Opts.SkipAttributes = true; Opts.PrintOverrideKeyword = true; @@ -76,6 +76,16 @@ SymbolGraph::getSubHeadingDeclarationFragmentsPrintOptions() const { auto Options = getDeclarationFragmentsPrintOptions(); Options.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly; + + //--------------------------------------------------------------------------// + // Although we want these in the full declaration presentation, + // particularly for protocol requirements, + // we don't want to show these in subheadings. + Options.PrintGetSetOnRWProperties = false; + Options.PrintPropertyAccessors = false; + Options.PrintSubscriptAccessors = false; + //--------------------------------------------------------------------------// + Options.VarInitializers = false; Options.PrintDefaultArgumentValue = false; Options.PrintEmptyArgumentNames = false; diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/DeclarationFragments.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift similarity index 81% rename from test/SymbolGraph/Symbols/Mixins/DeclarationFragments/DeclarationFragments.swift rename to test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift index 423f5d73cf92b..2c46cf5c7c853 100644 --- a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/DeclarationFragments.swift +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Basic.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -module-name DeclarationFragments -emit-module -emit-module-path %t/ -// RUN: %target-swift-symbolgraph-extract -module-name DeclarationFragments -I %t -pretty-print -output-dir %t -// RUN: %FileCheck %s --input-file %t/DeclarationFragments.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 public func foo(f: @escaping () -> (), ext int: Int = 2, s: S) {} diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift new file mode 100644 index 0000000000000..250bbb694268a --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ComputedProperties.swift @@ -0,0 +1,162 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name ComputedProperties -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name ComputedProperties -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/ComputedProperties.symbols.json --check-prefix=XFULL +// RUN: %FileCheck %s --input-file %t/ComputedProperties.symbols.json --check-prefix=XSUBHEADING +// RUN: %FileCheck %s --input-file %t/ComputedProperties.symbols.json --check-prefix=YFULL +// RUN: %FileCheck %s --input-file %t/ComputedProperties.symbols.json --check-prefix=YSUBHEADING + +public struct S { + // We should show { get set } here for the + // full declaration, but not for subheadings. + public var x: Int { + get { return 7 } + set {} + } + public private(set) var y: Int { + get { return 7 } + set {} + } +} + +// XFULL-LABEL: "precise": "s:18ComputedProperties1SV1xSivp" +// XFULL: "declarationFragments": [ +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "keyword", +// XFULL-NEXT: "spelling": "var" +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "text", +// XFULL-NEXT: "spelling": " " +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "identifier", +// XFULL-NEXT: "spelling": "x" +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "text", +// XFULL-NEXT: "spelling": ": " +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "typeIdentifier", +// XFULL-NEXT: "spelling": "Int", +// XFULL-NEXT: "preciseIdentifier": "s:Si" +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "text", +// XFULL-NEXT: "spelling": " { " +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "keyword", +// XFULL-NEXT: "spelling": "get" +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "text", +// XFULL-NEXT: "spelling": " " +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "keyword", +// XFULL-NEXT: "spelling": "set" +// XFULL-NEXT: }, +// XFULL-NEXT: { +// XFULL-NEXT: "kind": "text", +// XFULL-NEXT: "spelling": " }" +// XFULL-NEXT: } +// XFULL-NEXT: ], + +// XSUBHEADING-LABEL: "precise": "s:18ComputedProperties1SV1xSivp" +// XSUBHEADING: names +// XSUBHEADING: "subHeading": [ +// XSUBHEADING-NEXT: { +// XSUBHEADING-NEXT: "kind": "keyword", +// XSUBHEADING-NEXT: "spelling": "var" +// XSUBHEADING-NEXT: }, +// XSUBHEADING-NEXT: { +// XSUBHEADING-NEXT: "kind": "text", +// XSUBHEADING-NEXT: "spelling": " " +// XSUBHEADING-NEXT: }, +// XSUBHEADING-NEXT: { +// XSUBHEADING-NEXT: "kind": "identifier", +// XSUBHEADING-NEXT: "spelling": "x" +// XSUBHEADING-NEXT: }, +// XSUBHEADING-NEXT: { +// XSUBHEADING-NEXT: "kind": "text", +// XSUBHEADING-NEXT: "spelling": ": " +// XSUBHEADING-NEXT: }, +// XSUBHEADING-NEXT: { +// XSUBHEADING-NEXT: "kind": "typeIdentifier", +// XSUBHEADING-NEXT: "spelling": "Int", +// XSUBHEADING-NEXT: "preciseIdentifier": "s:Si" +// XSUBHEADING-NEXT: } +// XSUBHEADING-NEXT: ] + +// YFULL-LABEL: "precise": "s:18ComputedProperties1SV1ySivp" +// YFULL: "declarationFragments": [ +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "keyword", +// YFULL-NEXT: "spelling": "var" +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "text", +// YFULL-NEXT: "spelling": " " +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "identifier", +// YFULL-NEXT: "spelling": "y" +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "text", +// YFULL-NEXT: "spelling": ": " +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "typeIdentifier", +// YFULL-NEXT: "spelling": "Int", +// YFULL-NEXT: "preciseIdentifier": "s:Si" +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "text", +// YFULL-NEXT: "spelling": " { " +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "keyword", +// YFULL-NEXT: "spelling": "get" +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "text", +// YFULL-NEXT: "spelling": " " +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "keyword", +// YFULL-NEXT: "spelling": "set" +// YFULL-NEXT: }, +// YFULL-NEXT: { +// YFULL-NEXT: "kind": "text", +// YFULL-NEXT: "spelling": " }" +// YFULL-NEXT: } +// YFULL-NEXT: ] + +// YSUBHEADING-LABEL: "precise": "s:18ComputedProperties1SV1ySivp" +// YSUBHEADING: names +// YSUBHEADING: "subHeading": [ +// YSUBHEADING-NEXT: { +// YSUBHEADING-NEXT: "kind": "keyword", +// YSUBHEADING-NEXT: "spelling": "var" +// YSUBHEADING-NEXT: }, +// YSUBHEADING-NEXT: { +// YSUBHEADING-NEXT: "kind": "text", +// YSUBHEADING-NEXT: "spelling": " " +// YSUBHEADING-NEXT: }, +// YSUBHEADING-NEXT: { +// YSUBHEADING-NEXT: "kind": "identifier", +// YSUBHEADING-NEXT: "spelling": "y" +// YSUBHEADING-NEXT: }, +// YSUBHEADING-NEXT: { +// YSUBHEADING-NEXT: "kind": "text", +// YSUBHEADING-NEXT: "spelling": ": " +// YSUBHEADING-NEXT: }, +// YSUBHEADING-NEXT: { +// YSUBHEADING-NEXT: "kind": "typeIdentifier", +// YSUBHEADING-NEXT: "spelling": "Int", +// YSUBHEADING-NEXT: "preciseIdentifier": "s:Si" +// YSUBHEADING-NEXT: } +// YSUBHEADING-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift new file mode 100644 index 0000000000000..d4e74ea184184 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/ProtocolRequirements.swift @@ -0,0 +1,82 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name ProtocolRequirements -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name ProtocolRequirements -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/ProtocolRequirements.symbols.json --check-prefix=FULL +// RUN: %FileCheck %s --input-file %t/ProtocolRequirements.symbols.json --check-prefix=SUBHEADING + +public protocol P { + // We should show { get set } here for the + // full declaration, but not for subheadings. + var x: Int { get set } +} + +// FULL-LABEL: "precise": "s:20ProtocolRequirements1PP1xSivp" +// FULL: "declarationFragments": [ +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "var" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "identifier", +// FULL-NEXT: "spelling": "x" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": ": " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "typeIdentifier", +// FULL-NEXT: "spelling": "Int", +// FULL-NEXT: "preciseIdentifier": "s:Si" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " { " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "get" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "set" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " }" +// FULL-NEXT: } +// FULL-NEXT: ] + +// SUBHEADING-LABEL: "precise": "s:20ProtocolRequirements1PP1xSivp" +// SUBHEADING: names +// SUBHEADING: "subHeading": [ +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "keyword", +// SUBHEADING-NEXT: "spelling": "var" +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "text", +// SUBHEADING-NEXT: "spelling": " " +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "identifier", +// SUBHEADING-NEXT: "spelling": "x" +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "text", +// SUBHEADING-NEXT: "spelling": ": " +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "typeIdentifier", +// SUBHEADING-NEXT: "spelling": "Int", +// SUBHEADING-NEXT: "preciseIdentifier": "s:Si" +// SUBHEADING-NEXT: } +// SUBHEADING-NEXT: ] diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift new file mode 100644 index 0000000000000..6e05712bb16e8 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Properties/Subscripts.swift @@ -0,0 +1,95 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name Subscripts -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name Subscripts -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/Subscripts.symbols.json --check-prefix=FULL +// RUN: %FileCheck %s --input-file %t/Subscripts.symbols.json --check-prefix=SUBHEADING + +public struct S { + public subscript(i: Int) -> Int { + get { + return 7 + } + set {} + } +} + +// FULL-LABEL: "precise": "s:10Subscripts1SVyS2icip" +// FULL: "declarationFragments": [ +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "subscript" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": "(" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "internalParam", +// FULL-NEXT: "spelling": "i" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": ": " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "typeIdentifier", +// FULL-NEXT: "spelling": "Int", +// FULL-NEXT: "preciseIdentifier": "s:Si" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": ") -> " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "typeIdentifier", +// FULL-NEXT: "spelling": "Int", +// FULL-NEXT: "preciseIdentifier": "s:Si" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " { " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "get" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " " +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "keyword", +// FULL-NEXT: "spelling": "set" +// FULL-NEXT: }, +// FULL-NEXT: { +// FULL-NEXT: "kind": "text", +// FULL-NEXT: "spelling": " }" +// FULL-NEXT: } +// FULL-NEXT: ] + +// SUBHEADING-LABEL: "precise": "s:10Subscripts1SVyS2icip" +// SUBHEADING: names +// SUBHEADING: "subHeading": [ +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "keyword", +// SUBHEADING-NEXT: "spelling": "subscript" +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "text", +// SUBHEADING-NEXT: "spelling": "(" +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "typeIdentifier", +// SUBHEADING-NEXT: "spelling": "Int", +// SUBHEADING-NEXT: "preciseIdentifier": "s:Si" +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "text", +// SUBHEADING-NEXT: "spelling": ") -> " +// SUBHEADING-NEXT: }, +// SUBHEADING-NEXT: { +// SUBHEADING-NEXT: "kind": "typeIdentifier", +// SUBHEADING-NEXT: "spelling": "Int", +// SUBHEADING-NEXT: "preciseIdentifier": "s:Si" +// SUBHEADING-NEXT: } +// SUBHEADING-NEXT: ] From ffca352dafe1a17bd8a8f08e51817f24a8cc2b4d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Wed, 20 May 2020 14:55:39 -0700 Subject: [PATCH 128/625] [AutoDiff] Remove flaky SR-12650 negative test. (#31919) `@noDerivative` parameter mangling was added, so the test is not meaningful. The test occasionally flaked during CI, so it is better to remove it. --- ...noderivative-parameter-type-mangling.swift | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift diff --git a/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift b/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift deleted file mode 100644 index 2d3083da33ab6..0000000000000 --- a/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %target-build-swift -g %s - -// SR-12650: IRGenDebugInfo type reconstruction crash because `@noDerivative` -// parameters are not mangled. - -import _Differentiation -func id(_ x: Float, _ y: Float) -> Float { x } -let transformed: @differentiable (Float, @noDerivative Float) -> Float = id - -// Incorrect reconstructed type for $sS3fIedgyyd_D -// Original type: -// (sil_function_type type=@differentiable @callee_guaranteed (Float, @noDerivative Float) -> Float -// (input=struct_type decl=Swift.(file).Float) -// (input=struct_type decl=Swift.(file).Float) -// (result=struct_type decl=Swift.(file).Float) -// (substitution_map generic_signature=) -// (substitution_map generic_signature=)) -// Reconstructed type: -// (sil_function_type type=@differentiable @callee_guaranteed (Float, Float) -> Float -// (input=struct_type decl=Swift.(file).Float) -// (input=struct_type decl=Swift.(file).Float) -// (result=struct_type decl=Swift.(file).Float) -// (substitution_map generic_signature=) -// (substitution_map generic_signature=)) -// Stack dump: -// ... -// 1. Swift version 5.3-dev (LLVM 803d1b184d, Swift 477af9f90d) -// 2. While evaluating request IRGenSourceFileRequest(IR Generation for file "noderiv.swift") -// 0 swift 0x00000001104c7ae8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 -// 1 swift 0x00000001104c6a68 llvm::sys::RunSignalHandlers() + 248 -// 2 swift 0x00000001104c80dd SignalHandler(int) + 285 -// 3 libsystem_platform.dylib 0x00007fff718335fd _sigtramp + 29 -// 4 libsystem_platform.dylib 000000000000000000 _sigtramp + 18446603338611739168 -// 5 libsystem_c.dylib 0x00007fff71709808 abort + 120 -// 6 swift 0x0000000110604152 (anonymous namespace)::IRGenDebugInfoImpl::getOrCreateType(swift::irgen::DebugTypeInfo) (.cold.20) + 146 -// 7 swift 0x000000010c24ab1e (anonymous namespace)::IRGenDebugInfoImpl::getOrCreateType(swift::irgen::DebugTypeInfo) + 3614 -// 8 swift 0x000000010c245437 swift::irgen::IRGenDebugInfo::emitGlobalVariableDeclaration(llvm::GlobalVariable*, llvm::StringRef, llvm::StringRef, swift::irgen::DebugTypeInfo, bool, bool, llvm::Optional) + 167 From 518ce5c25d9e2334b84d3df77bc4330c8cb84783 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 20 May 2020 14:56:12 -0700 Subject: [PATCH 129/625] test: repair SILOptimizer AutoDiff test on Windows The module name is not specified but the test explicitly overfits to an expected name. Adjust the test invocation to accommodate the expectation. --- test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift b/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift index cd3d05554820e..5a922cad39f82 100644 --- a/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift +++ b/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -emit-sil -Xllvm -sil-print-after=differentiation %s -o /dev/null 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -emit-sil -Xllvm -sil-print-after=differentiation %s -module-name null -o /dev/null 2>&1 | %FileCheck %s // Test differentiation of semantic member accessors: // - Stored property accessors. From 0a7929e80f07db947d6839c05207c54c3bce449c Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 18 May 2020 13:36:56 -0700 Subject: [PATCH 130/625] Refine Naive Dependency Collection Algorithm Split off the notion of "recording" dependencies from the notion of "collecting" dependencies. This corrects an oversight in the previous design where dependency replay and recording were actually not "free" in WMO where we actually never track dependencies. This architecture also lays the groundwork for the removal of the referenced name trackers. The algorithm builds upon the infrastructure for dependency sources and sinks laid down during the cut over to request-based dependency tracking in #30723. The idea of the naive algorithm is this: For a chain of requests A -> B* -> C -> D* -> ... -> L where L is a lookup request and all starred requests are cached, once L writes into the dependency collector, the active stack is walked and at each cache-point the results of dependency collection are associated with the request itself (in this example, B* and D* have all the names L found associated with them). Subsequent evaluations of these cached requests (B* and D* et al) will then *replay* the previous lookup results from L into the active referenced name tracker. One complication is, suppose the evaluation of a cached request involves multiple downstream name lookups. More concretely, suppose we have the following request trace: A* -> B -> L | -> C -> L | -> D -> L | -> ... Then A* must see the union of the results of each L. If this reminds anyone of a union-find, that is no accident! A persistent union-find a la Conchon and Filliatre is probably in order to help bring down peak heap usage... --- include/swift/AST/Evaluator.h | 14 ++-- include/swift/AST/EvaluatorDependencies.h | 87 +++++++++++++--------- include/swift/AST/IRGenRequests.h | 2 +- include/swift/AST/NameLookupRequests.h | 10 +-- include/swift/AST/ParseRequests.h | 4 +- include/swift/AST/SILGenRequests.h | 2 +- include/swift/AST/SimpleRequest.h | 2 +- include/swift/AST/TypeCheckRequests.h | 10 +-- lib/AST/Evaluator.cpp | 90 ++++++++++++++--------- lib/AST/NameLookupRequests.cpp | 14 ++-- lib/AST/TypeCheckRequests.cpp | 10 +-- lib/IRGen/IRGenRequests.cpp | 2 +- lib/Parse/ParseRequests.cpp | 4 +- lib/SILGen/SILGenRequests.cpp | 2 +- 14 files changed, 145 insertions(+), 108 deletions(-) diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index c2503e20e3f2f..64eb1c1379421 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -225,7 +225,7 @@ class Evaluator { /// so all clients must cope with cycles. llvm::DenseMap> dependencies; - evaluator::DependencyCollector collector; + evaluator::DependencyRecorder recorder; /// Retrieve the request function for the given zone and request IDs. AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID, @@ -268,8 +268,8 @@ class Evaluator { typename std::enable_if::type * = nullptr> llvm::Expected operator()(const Request &request) { - evaluator::DependencyCollector::StackRAII incDeps{collector, - request}; + evaluator::DependencyRecorder::StackRAII incDeps{recorder, + request}; // The request can be cached, but check a predicate to determine // whether this particular instance is cached. This allows more // fine-grained control over which instances get cache. @@ -285,8 +285,8 @@ class Evaluator { typename std::enable_if::type * = nullptr> llvm::Expected operator()(const Request &request) { - evaluator::DependencyCollector::StackRAII incDeps{collector, - request}; + evaluator::DependencyRecorder::StackRAII incDeps{recorder, + request}; return getResultUncached(request); } @@ -436,7 +436,7 @@ class Evaluator { !Request::isDependencySink>::type * = nullptr> void reportEvaluatedResult(const Request &r, const typename Request::OutputType &o) { - collector.replay(ActiveRequest(r)); + recorder.replay(ActiveRequest(r)); } // Report the result of evaluating a request that is a dependency sink. @@ -444,7 +444,7 @@ class Evaluator { typename std::enable_if::type * = nullptr> void reportEvaluatedResult(const Request &r, const typename Request::OutputType &o) { - return collector.record(activeRequests, [&r, &o](auto &c) { + return recorder.record(activeRequests, [&r, &o](auto &c) { return r.writeDependencySink(c, o); }); } diff --git a/include/swift/AST/EvaluatorDependencies.h b/include/swift/AST/EvaluatorDependencies.h index 5009dfaf0332b..3abfa066761c6 100644 --- a/include/swift/AST/EvaluatorDependencies.h +++ b/include/swift/AST/EvaluatorDependencies.h @@ -107,13 +107,9 @@ inline DependencyScope getScopeForAccessLevel(AccessLevel l) { // of individual contexts. using DependencySource = llvm::PointerIntPair; -/// A \c DependencyCollector is an aggregator of named references discovered in a -/// particular \c DependencyScope during the course of request evaluation. -struct DependencyCollector { -private: - /// A stack of dependency sources in the order they were evaluated. - llvm::SmallVector dependencySources; +struct DependencyRecorder; +struct DependencyCollector { struct Reference { public: enum class Kind { @@ -178,36 +174,11 @@ struct DependencyCollector { }; }; -public: - enum class Mode { - // Enables the current "status quo" behavior of the dependency collector. - // - // By default, the dependency collector moves to register dependencies in - // the referenced name trackers at the top of the active dependency stack. - StatusQuo, - // Enables an experimental mode to only register private dependencies. - // - // This mode restricts the dependency collector to ignore changes of - // scope. This has practical effect of charging all unqualified lookups to - // the primary file being acted upon instead of to the destination file. - ExperimentalPrivateDependencies, - }; - Mode mode; - llvm::DenseMap> - requestReferences; + DependencyRecorder &parent; llvm::DenseSet scratch; - bool isRecording; - - explicit DependencyCollector(Mode mode) - : mode{mode}, requestReferences{}, scratch{}, isRecording{false} {}; - -private: - void realizeOrRecord(const Reference &ref); public: - void replay(const swift::ActiveRequest &req); - void record(const llvm::SetVector &stack, - llvm::function_ref rec); + explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {} public: /// Registers a named reference from the current dependency scope to a member @@ -246,6 +217,50 @@ struct DependencyCollector { /// a name that is found by \c AnyObject lookup. void addDynamicLookupName(DeclBaseName name); +public: + const DependencyRecorder &getRecorder() const { return parent; } + bool empty() const { return scratch.empty(); } +}; + +/// A \c DependencyCollector is an aggregator of named references discovered in a +/// particular \c DependencyScope during the course of request evaluation. +struct DependencyRecorder { + friend DependencyCollector; +private: + /// A stack of dependency sources in the order they were evaluated. + llvm::SmallVector dependencySources; + +public: + enum class Mode { + // Enables the current "status quo" behavior of the dependency collector. + // + // By default, the dependency collector moves to register dependencies in + // the referenced name trackers at the top of the active dependency stack. + StatusQuo, + // Enables an experimental mode to only register private dependencies. + // + // This mode restricts the dependency collector to ignore changes of + // scope. This has practical effect of charging all unqualified lookups to + // the primary file being acted upon instead of to the destination file. + ExperimentalPrivateDependencies, + }; + Mode mode; + llvm::DenseMap> + requestReferences; + bool isRecording; + + explicit DependencyRecorder(Mode mode) + : mode{mode}, requestReferences{}, isRecording{false} {}; + +private: + void realize(const DependencyCollector::Reference &ref); + +public: + void replay(const swift::ActiveRequest &req); + void record(const llvm::SetVector &stack, + llvm::function_ref rec); + public: /// Returns the scope of the current active scope. /// @@ -275,14 +290,14 @@ struct DependencyCollector { /// dependency source stack. It is specialized to be zero-cost for /// requests that are not dependency sources. template > struct StackRAII { - StackRAII(DependencyCollector &DC, const Request &Req) {} + StackRAII(DependencyRecorder &DR, const Request &Req) {} }; template struct StackRAII::type> { - NullablePtr Coll; - StackRAII(DependencyCollector &coll, const Request &Req) { + NullablePtr Coll; + StackRAII(DependencyRecorder &coll, const Request &Req) { auto Source = Req.readDependencySource(coll); // If there is no source to introduce, bail. This can occur if // a request originates in the context of a module. diff --git a/include/swift/AST/IRGenRequests.h b/include/swift/AST/IRGenRequests.h index dd19afa4bedb6..3cd8212176aee 100644 --- a/include/swift/AST/IRGenRequests.h +++ b/include/swift/AST/IRGenRequests.h @@ -200,7 +200,7 @@ class IRGenSourceFileRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; class IRGenWholeModuleRequest diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index df8c0dea04179..e15c8b787dce1 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -189,7 +189,7 @@ class InheritedProtocolsRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &e) const; + readDependencySource(const evaluator::DependencyRecorder &e) const; void writeDependencySink(evaluator::DependencyCollector &tracker, ArrayRef result) const; }; @@ -330,7 +330,7 @@ class GetDestructorRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; class GenericParamListRequest : @@ -434,7 +434,7 @@ class UnqualifiedLookupRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; void writeDependencySink(evaluator::DependencyCollector &tracker, LookupResult res) const; }; @@ -506,7 +506,7 @@ class ModuleQualifiedLookupRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; void writeDependencySink(evaluator::DependencyCollector &tracker, QualifiedLookupResult lookupResult) const; }; @@ -533,7 +533,7 @@ class QualifiedLookupRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// The input type for a direct lookup request. diff --git a/include/swift/AST/ParseRequests.h b/include/swift/AST/ParseRequests.h index b37e00695676e..bd641893490d4 100644 --- a/include/swift/AST/ParseRequests.h +++ b/include/swift/AST/ParseRequests.h @@ -103,7 +103,7 @@ class ParseSourceFileRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; void simple_display(llvm::raw_ostream &out, @@ -125,7 +125,7 @@ class CodeCompletionSecondPassRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// The zone number for the parser. diff --git a/include/swift/AST/SILGenRequests.h b/include/swift/AST/SILGenRequests.h index 3f93c5608ed7b..c47b07a8b3c2b 100644 --- a/include/swift/AST/SILGenRequests.h +++ b/include/swift/AST/SILGenRequests.h @@ -104,7 +104,7 @@ class SILGenerationRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Parses a .sil file into a SILModule. diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h index 2ab9003b6d2f0..42751e142682c 100644 --- a/include/swift/AST/SimpleRequest.h +++ b/include/swift/AST/SimpleRequest.h @@ -232,7 +232,7 @@ SourceLoc extractNearestSourceLoc(const std::tuple &value) { /// the 3 caching kinds defined above. /// \code /// evaluator::DependencySource -/// readDependencySource(const evaluator::DependencyCollector &) const; +/// readDependencySource(const evaluator::DependencyRecorder &) const; /// \endcode /// /// Requests that define dependency sinks should instead override diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 3d96d17924add..200663d00cb80 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -123,7 +123,7 @@ class SuperclassTypeRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &e) const; + readDependencySource(const evaluator::DependencyRecorder &e) const; void writeDependencySink(evaluator::DependencyCollector &tracker, Type t) const; }; @@ -893,7 +893,7 @@ class TypeCheckFunctionBodyUntilRequest : public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Request to obtain a list of stored properties in a nominal type. @@ -2034,7 +2034,7 @@ class TypeCheckSourceFileRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Computes whether the specified type or a super-class/super-protocol has the @@ -2277,7 +2277,7 @@ class LookupAllConformancesInContextRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &eval) const; + readDependencySource(const evaluator::DependencyRecorder &eval) const; void writeDependencySink(evaluator::DependencyCollector &tracker, ProtocolConformanceLookupResult r) const; }; @@ -2305,7 +2305,7 @@ class CheckRedeclarationRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &eval) const; + readDependencySource(const evaluator::DependencyRecorder &eval) const; void writeDependencySink(evaluator::DependencyCollector &tracker, evaluator::SideEffect) const; }; diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index c0ba9d52db9b6..d1e5b7aa16e1f 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -61,12 +61,13 @@ void Evaluator::registerRequestFunctions( requestFunctionsByZone.push_back({zoneID, functions}); } -static evaluator::DependencyCollector::Mode +static evaluator::DependencyRecorder::Mode computeDependencyModeFromFlags(bool enableExperimentalPrivateDeps) { - using Mode = evaluator::DependencyCollector::Mode; + using Mode = evaluator::DependencyRecorder::Mode; if (enableExperimentalPrivateDeps) { return Mode::ExperimentalPrivateDependencies; } + return Mode::StatusQuo; } @@ -75,8 +76,7 @@ Evaluator::Evaluator(DiagnosticEngine &diags, bool debugDumpCycles, bool enableExperimentalPrivateDeps) : diags(diags), debugDumpCycles(debugDumpCycles), buildDependencyGraph(buildDependencyGraph), - collector{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} { -} + recorder{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} {} void Evaluator::emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath) { std::error_code error; @@ -379,32 +379,27 @@ void Evaluator::dumpDependenciesGraphviz() const { printDependenciesGraphviz(llvm::dbgs()); } -void evaluator::DependencyCollector::realizeOrRecord(const Reference &ref) { - if (isRecording) { - scratch.insert(std::move(ref)); - return; - } - +void evaluator::DependencyRecorder::realize( + const DependencyCollector::Reference &ref) { auto *tracker = getActiveDependencyTracker(); - if (!tracker) { - return; - } + assert(tracker && "cannot realize dependency without name tracker!"); + using Kind = evaluator::DependencyCollector::Reference::Kind; switch (ref.kind) { - case Reference::Kind::Empty: - case Reference::Kind::Tombstone: + case Kind::Empty: + case Kind::Tombstone: llvm_unreachable("cannot record empty dependency"); - case Reference::Kind::UsedMember: + case Kind::UsedMember: tracker->addUsedMember({ref.subject, ref.name}, isActiveSourceCascading()); break; - case Reference::Kind::PotentialMember: + case Kind::PotentialMember: tracker->addUsedMember({ref.subject, Identifier()}, isActiveSourceCascading()); break; - case Reference::Kind::TopLevel: + case Kind::TopLevel: tracker->addTopLevelName(ref.name, isActiveSourceCascading()); break; - case Reference::Kind::Dynamic: + case Kind::Dynamic: tracker->addDynamicLookupName(ref.name, isActiveSourceCascading()); break; } @@ -412,33 +407,55 @@ void evaluator::DependencyCollector::realizeOrRecord(const Reference &ref) { void evaluator::DependencyCollector::addUsedMember(NominalTypeDecl *subject, DeclBaseName name) { - return realizeOrRecord(Reference::usedMember(subject, name)); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::usedMember(subject, name)); + } + return parent.realize(Reference::usedMember(subject, name)); } void evaluator::DependencyCollector::addPotentialMember( NominalTypeDecl *subject) { - return realizeOrRecord(Reference::potentialMember(subject)); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::potentialMember(subject)); + } + return parent.realize(Reference::potentialMember(subject)); } void evaluator::DependencyCollector::addTopLevelName(DeclBaseName name) { - return realizeOrRecord(Reference::topLevel(name)); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::topLevel(name)); + } + return parent.realize(Reference::topLevel(name)); } void evaluator::DependencyCollector::addDynamicLookupName(DeclBaseName name) { - return realizeOrRecord(Reference::dynamic(name)); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::dynamic(name)); + } + return parent.realize(Reference::dynamic(name)); } -void evaluator::DependencyCollector::record( +void evaluator::DependencyRecorder::record( const llvm::SetVector &stack, llvm::function_ref rec) { assert(!isRecording && "Probably not a good idea to allow nested recording"); - if (mode == Mode::StatusQuo) { - return rec(*this); + if (!getActiveDependencyTracker()) { + return; } llvm::SaveAndRestore restore(isRecording, true); - scratch = {}; - rec(*this); + + DependencyCollector collector{*this}; + rec(collector); + if (collector.empty()) { + return; + } + + assert(mode != Mode::StatusQuo); for (const auto &request : stack) { if (!request.isCached()) { continue; @@ -446,26 +463,31 @@ void evaluator::DependencyCollector::record( auto entry = requestReferences.find_as(request); if (entry == requestReferences.end()) { - requestReferences.insert({AnyRequest(request), scratch}); + requestReferences.insert({AnyRequest(request), collector.scratch}); continue; } - entry->second.insert(scratch.begin(), scratch.end()); + entry->second.insert(collector.scratch.begin(), collector.scratch.end()); } } -void evaluator::DependencyCollector::replay(const swift::ActiveRequest &req) { - if (mode == Mode::StatusQuo) { +void evaluator::DependencyRecorder::replay(const swift::ActiveRequest &req) { + assert(!isRecording && "Probably not a good idea to allow nested recording"); + + if (mode == Mode::StatusQuo || !getActiveDependencyTracker()) { + return; + } + + if (!req.isCached()) { return; } - assert(!isRecording && "Probably not a good idea to allow nested recording"); auto entry = requestReferences.find_as(req); if (entry == requestReferences.end()) { return; } for (const auto &ref : entry->second) { - realizeOrRecord(ref); + realize(ref); } } diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index b526d8108bd9a..5b44f7fa0dce2 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -89,7 +89,7 @@ void InheritedProtocolsRequest::cacheResult(ArrayRef PDs) const } evaluator::DependencySource InheritedProtocolsRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto *PD = std::get<0>(getStorage()); // Ignore context changes for protocols outside our module. This // prevents transitive cascading edges when e.g. our private @@ -184,7 +184,7 @@ void ExtendedNominalRequest::writeDependencySink( auto *SF = std::get<0>(getStorage())->getParentSourceFile(); if (!SF) return; - if (SF != tracker.getActiveDependencySourceOrNull()) + if (SF != tracker.getRecorder().getActiveDependencySourceOrNull()) return; tracker.addPotentialMember(value); } @@ -208,7 +208,7 @@ void GetDestructorRequest::cacheResult(DestructorDecl *value) const { } evaluator::DependencySource GetDestructorRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { // Looking up the deinitializer currently always occurs in a private // scope because it is impossible to reference 'deinit' in user code, and a // valid 'deinit' declaration cannot occur outside of the @@ -338,7 +338,7 @@ swift::extractNearestSourceLoc(const LookupConformanceDescriptor &desc) { //----------------------------------------------------------------------------// evaluator::DependencySource ModuleQualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { auto *DC = std::get<0>(getStorage()); auto options = std::get<3>(getStorage()); @@ -385,7 +385,7 @@ void LookupConformanceInModuleRequest::writeDependencySink( if (!Adoptee) return; - auto *source = reqTracker.getActiveDependencySourceOrNull(); + auto *source = reqTracker.getRecorder().getActiveDependencySourceOrNull(); if (!source) return; @@ -402,7 +402,7 @@ void LookupConformanceInModuleRequest::writeDependencySink( //----------------------------------------------------------------------------// evaluator::DependencySource UnqualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &) const { + const evaluator::DependencyRecorder &) const { auto &desc = std::get<0>(getStorage()); // FIXME(Evaluator Incremental Dependencies): This maintains compatibility // with the existing scheme, but the existing scheme is totally ad-hoc. We @@ -426,7 +426,7 @@ void UnqualifiedLookupRequest::writeDependencySink( //----------------------------------------------------------------------------// evaluator::DependencySource QualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &) const { + const evaluator::DependencyRecorder &) const { auto *dc = std::get<0>(getStorage()); auto opts = std::get<3>(getStorage()); // FIXME(Evaluator Incremental Dependencies): This is an artifact of the diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index be94bfb98449e..91d3a48763dae 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -158,7 +158,7 @@ void SuperclassTypeRequest::cacheResult(Type value) const { } evaluator::DependencySource SuperclassTypeRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { const auto access = std::get<0>(getStorage())->getFormalAccess(); return { e.getActiveDependencySourceOrNull(), @@ -1349,7 +1349,7 @@ void CheckRedeclarationRequest::cacheResult(evaluator::SideEffect) const { } evaluator::DependencySource CheckRedeclarationRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { auto *current = std::get<0>(getStorage()); auto *currentDC = current->getDeclContext(); return { @@ -1384,7 +1384,7 @@ void CheckRedeclarationRequest::writeDependencySink( evaluator::DependencySource LookupAllConformancesInContextRequest::readDependencySource( - const evaluator::DependencyCollector &collector) const { + const evaluator::DependencyRecorder &collector) const { const auto *nominal = std::get<0>(getStorage()) ->getAsGenericContext() ->getSelfNominalTypeDecl(); @@ -1427,7 +1427,7 @@ void ResolveTypeEraserTypeRequest::cacheResult(Type value) const { //----------------------------------------------------------------------------// evaluator::DependencySource TypeCheckSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), evaluator::DependencyScope::Cascading}; } @@ -1460,7 +1460,7 @@ void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const { evaluator::DependencySource TypeCheckFunctionBodyUntilRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { // We're going under a function body scope, unconditionally flip the scope // to private. return { diff --git a/lib/IRGen/IRGenRequests.cpp b/lib/IRGen/IRGenRequests.cpp index ed62a24084d8f..5116c83c1abde 100644 --- a/lib/IRGen/IRGenRequests.cpp +++ b/lib/IRGen/IRGenRequests.cpp @@ -53,7 +53,7 @@ SourceLoc swift::extractNearestSourceLoc(const IRGenDescriptor &desc) { } evaluator::DependencySource IRGenSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto &desc = std::get<0>(getStorage()); return { desc.Ctx.dyn_cast(), diff --git a/lib/Parse/ParseRequests.cpp b/lib/Parse/ParseRequests.cpp index c424b959e9dde..8f1f9d23cd3b5 100644 --- a/lib/Parse/ParseRequests.cpp +++ b/lib/Parse/ParseRequests.cpp @@ -168,7 +168,7 @@ ArrayRef ParseSourceFileRequest::evaluate(Evaluator &evaluator, } evaluator::DependencySource ParseSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), evaluator::DependencyScope::Cascading}; } @@ -196,7 +196,7 @@ void swift::simple_display(llvm::raw_ostream &out, evaluator::DependencySource CodeCompletionSecondPassRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), e.getActiveSourceScope()}; } diff --git a/lib/SILGen/SILGenRequests.cpp b/lib/SILGen/SILGenRequests.cpp index a854ebe37a5ee..6d441591d31e4 100644 --- a/lib/SILGen/SILGenRequests.cpp +++ b/lib/SILGen/SILGenRequests.cpp @@ -47,7 +47,7 @@ SourceLoc swift::extractNearestSourceLoc(const SILGenDescriptor &desc) { } evaluator::DependencySource SILGenerationRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto &desc = std::get<0>(getStorage()); // We don't track dependencies in whole-module mode. From 940a6d78fd98436371b4c831aab008d05934f6eb Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 20 May 2020 16:58:45 -0700 Subject: [PATCH 131/625] Try renabling test on all platforms --- test/IRGen/Inputs/huge_c_type.h | 2 +- test/IRGen/huge_c_type.swift | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/IRGen/Inputs/huge_c_type.h b/test/IRGen/Inputs/huge_c_type.h index 42b2a9d7be35b..2afde356161e4 100644 --- a/test/IRGen/Inputs/huge_c_type.h +++ b/test/IRGen/Inputs/huge_c_type.h @@ -5,7 +5,7 @@ typedef uint8_t bool; #define CREATE_ARRAY(T, N) \ struct { \ T data[N]; \ - size_t size; \ + uint64_t size; \ } typedef struct { diff --git a/test/IRGen/huge_c_type.swift b/test/IRGen/huge_c_type.swift index 402d3e437d63a..ebbed0263aeda 100644 --- a/test/IRGen/huge_c_type.swift +++ b/test/IRGen/huge_c_type.swift @@ -3,8 +3,6 @@ // llvm::IntegerTypes. // RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -c -// REQUIRES: OS=macosx || OS=ios - // CHECK-NOT:i9535616 public func doIt(a: Thing3) { From c4e67e29edeb60c195726812a8317707b45ab258 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 19 Apr 2020 07:59:25 -0700 Subject: [PATCH 132/625] [Diagnostics] Add -diagnostic-style=(llvm|swift) to control printed output This default formatting style remains the same "LLVM style". "Swift style" is what was previously enabled via -enable-experimental-diagnostic-formatting --- include/swift/Basic/DiagnosticOptions.h | 4 +++- .../Frontend/PrintingDiagnosticConsumer.h | 10 +++++++--- include/swift/Option/FrontendOptions.td | 4 ---- include/swift/Option/Options.td | 7 +++++++ lib/Driver/ToolChains.cpp | 1 + lib/Frontend/CompilerInvocation.cpp | 18 ++++++++++++++++-- lib/Frontend/PrintingDiagnosticConsumer.cpp | 8 ++++++-- lib/FrontendTool/FrontendTool.cpp | 6 ++---- test/Driver/color-diagnostics.swift | 2 +- test/diagnostics/educational-notes.swift | 4 ++-- .../pretty-printed-diagnostics.swift | 2 +- .../pretty-printed-diags-in-clang-buffer.swift | 2 +- ...ty-printed-source-loc-directive-diags.swift | 2 +- 13 files changed, 48 insertions(+), 22 deletions(-) diff --git a/include/swift/Basic/DiagnosticOptions.h b/include/swift/Basic/DiagnosticOptions.h index 58531d5908641..31e6149412692 100644 --- a/include/swift/Basic/DiagnosticOptions.h +++ b/include/swift/Basic/DiagnosticOptions.h @@ -32,6 +32,8 @@ class DiagnosticOptions { VerifyAndApplyFixes } VerifyMode = NoVerify; + enum FormattingStyle { LLVM, Swift }; + /// Indicates whether to allow diagnostics for \c locations if /// \c VerifyMode is not \c NoVerify. bool VerifyIgnoreUnknown = false; @@ -61,7 +63,7 @@ class DiagnosticOptions { // If set to true, use the more descriptive experimental formatting style for // diagnostics. - bool EnableExperimentalFormatting = false; + FormattingStyle PrintedFormattingStyle = FormattingStyle::LLVM; std::string DiagnosticDocumentationPath = ""; diff --git a/include/swift/Frontend/PrintingDiagnosticConsumer.h b/include/swift/Frontend/PrintingDiagnosticConsumer.h index a4720ce5c6f51..cbbca307f6297 100644 --- a/include/swift/Frontend/PrintingDiagnosticConsumer.h +++ b/include/swift/Frontend/PrintingDiagnosticConsumer.h @@ -18,8 +18,9 @@ #ifndef SWIFT_PRINTINGDIAGNOSTICCONSUMER_H #define SWIFT_PRINTINGDIAGNOSTICCONSUMER_H -#include "swift/Basic/LLVM.h" #include "swift/AST/DiagnosticConsumer.h" +#include "swift/Basic/DiagnosticOptions.h" +#include "swift/Basic/LLVM.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Process.h" @@ -33,7 +34,8 @@ class PrintingDiagnosticConsumer : public DiagnosticConsumer { bool ForceColors = false; bool PrintEducationalNotes = false; bool DidErrorOccur = false; - bool ExperimentalFormattingEnabled = false; + DiagnosticOptions::FormattingStyle FormattingStyle = + DiagnosticOptions::FormattingStyle::LLVM; // The current snippet used to display an error/warning/remark and the notes // implicitly associated with it. Uses `std::unique_ptr` so that // `AnnotatedSourceSnippet` can be forward declared. @@ -65,7 +67,9 @@ class PrintingDiagnosticConsumer : public DiagnosticConsumer { PrintEducationalNotes = ShouldPrint; } - void enableExperimentalFormatting() { ExperimentalFormattingEnabled = true; } + void setFormattingStyle(DiagnosticOptions::FormattingStyle style) { + FormattingStyle = style; + } bool didErrorOccur() { return DidErrorOccur; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c8168fde7d545..5d640b7588c11 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -131,10 +131,6 @@ def enable_cross_import_overlays : Flag<["-"], "enable-cross-import-overlays">, def disable_cross_import_overlays : Flag<["-"], "disable-cross-import-overlays">, HelpText<"Do not automatically import declared cross-import overlays.">; -def enable_experimental_diagnostic_formatting : - Flag<["-"], "enable-experimental-diagnostic-formatting">, - HelpText<"Enable experimental diagnostic formatting features.">; - def diagnostic_documentation_path : Separate<["-"], "diagnostic-documentation-path">, MetaVarName<"">, HelpText<"Path to diagnostic documentation resources">; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a430124cc7f27..b771b48b3895d 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -370,6 +370,13 @@ def debug_diagnostic_names : Flag<["-"], "debug-diagnostic-names">, def print_educational_notes : Flag<["-"], "print-educational-notes">, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, HelpText<"Include educational notes in printed diagnostic output, if available">; +def diagnostic_style : Separate<["-"], "diagnostic-style">, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, + MetaVarName<"