diff --git a/README.md b/README.md index 67163d29fdba8..8c58de108142a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ |---|:---:|:---:| |**[Ubuntu 18.04](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/x86_64_ubuntu_18_04_tensorflow.json)** | x86_64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-18.04-tensorflow/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-18.04-tensorflow)| |**[macOS 10.13](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/x86_64_macos_high_sierra_tensorflow.json)** | x86_64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-macOS-tensorflow/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-macOS-tensorflow)| -|**[Ubuntu 18.04 (GPU)](https://github.com/apple/swift-community-hosted-continuous-integration/blob/master/nodes/x86_64_ubuntu_18_04_tensorflow_gpu.json)** | x86_64 |[![Build Status](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-18.04-tensorflow-gpu/lastCompletedBuild/badge/icon)](https://ci-external.swift.org/job/oss-swift-RA-linux-ubuntu-18.04-tensorflow-gpu)| ## Welcome to Swift diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 80cc61ac08be3..f4247df1468c3 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -29,7 +29,7 @@ #define SWIFT_AST_AST_SCOPE_H #include "swift/AST/ASTNode.h" -#include "swift/AST/NameLookup.h" // for DeclVisibilityKind +#include "swift/AST/NameLookup.h" #include "swift/AST/SimpleRequest.h" #include "swift/Basic/Compiler.h" #include "swift/Basic/Debug.h" @@ -444,7 +444,6 @@ class ASTScopeImpl { // It is not an instance variable or inherited type. static bool lookupLocalBindingsInPattern(const Pattern *p, - DeclVisibilityKind vis, DeclConsumer consumer); /// When lookup must stop before the outermost scope, return the scope to stop @@ -1024,10 +1023,10 @@ class AbstractPatternEntryScope : public ASTScopeImpl { public: PatternBindingDecl *const decl; const unsigned patternEntryIndex; - const DeclVisibilityKind vis; + const bool isLocalBinding; AbstractPatternEntryScope(PatternBindingDecl *, unsigned entryIndex, - DeclVisibilityKind); + bool); virtual ~AbstractPatternEntryScope() {} const PatternBindingEntry &getPatternEntry() const; @@ -1044,8 +1043,8 @@ class AbstractPatternEntryScope : public ASTScopeImpl { class PatternEntryDeclScope final : public AbstractPatternEntryScope { public: PatternEntryDeclScope(PatternBindingDecl *pbDecl, unsigned entryIndex, - DeclVisibilityKind vis) - : AbstractPatternEntryScope(pbDecl, entryIndex, vis) {} + bool isLocalBinding) + : AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding) {} virtual ~PatternEntryDeclScope() {} protected: @@ -1072,8 +1071,8 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope { public: PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex, - DeclVisibilityKind vis) - : AbstractPatternEntryScope(pbDecl, entryIndex, vis), + bool isLocalBinding) + : AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding), initAsWrittenWhenCreated(pbDecl->getOriginalInit(entryIndex)) {} virtual ~PatternEntryInitializerScope() {} @@ -1658,10 +1657,22 @@ class CaseStmtBodyScope final : public ASTScopeImpl { }; class BraceStmtScope final : public AbstractStmtScope { + BraceStmt *const stmt; + + /// Declarations which are in scope from the beginning of the statement. + SmallVector localFuncsAndTypes; + + /// Declarations that are normally in scope only after their + /// definition. + SmallVector localVars; public: - BraceStmt *const stmt; - BraceStmtScope(BraceStmt *e) : stmt(e) {} + BraceStmtScope(BraceStmt *e, + SmallVector localFuncsAndTypes, + SmallVector localVars) + : stmt(e), + localFuncsAndTypes(localFuncsAndTypes), + localVars(localVars) {} virtual ~BraceStmtScope() {} protected: diff --git a/include/swift/AST/AbstractSourceFileDepGraphFactory.h b/include/swift/AST/AbstractSourceFileDepGraphFactory.h index 80ed4122ec1b2..a0991efd8ad93 100644 --- a/include/swift/AST/AbstractSourceFileDepGraphFactory.h +++ b/include/swift/AST/AbstractSourceFileDepGraphFactory.h @@ -24,10 +24,6 @@ namespace fine_grained_dependencies { /// \c SourceFile or a unit test class AbstractSourceFileDepGraphFactory { 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; @@ -48,8 +44,7 @@ class AbstractSourceFileDepGraphFactory { public: /// Expose this layer to enable faking up a constructor for testing. /// See the instance variable comments for explanation. - AbstractSourceFileDepGraphFactory(bool includePrivateDeps, - bool hadCompilationError, + AbstractSourceFileDepGraphFactory(bool hadCompilationError, StringRef swiftDeps, StringRef fileFingerprint, bool emitDotFileAfterConstruction, diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 96673673353a2..8e899934bc1b4 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -950,9 +950,6 @@ class alignas(1 << DeclAlignInBits) Decl { /// If this returns true, the decl can be safely casted to ValueDecl. bool isPotentiallyOverridable() const; - /// Returns true if this Decl cannot be seen by any other source file - bool isPrivateToEnclosingFile() const; - /// If an alternative module name is specified for this decl, e.g. using /// @_originalDefinedIn attribute, this function returns this module name. StringRef getAlternateModuleName() const; diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index d57cd07ea8b4c..f9a6df52039a5 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -603,7 +603,7 @@ class AbstractASTScopeDeclConsumer { /// of type -vs- instance lookup results. /// /// \return true if the lookup should be stopped at this point. - virtual bool consume(ArrayRef values, DeclVisibilityKind vis, + virtual bool consume(ArrayRef values, NullablePtr baseDC = nullptr) = 0; /// Look for members of a nominal type or extension scope. @@ -613,6 +613,14 @@ class AbstractASTScopeDeclConsumer { lookInMembers(DeclContext *const scopeDC, NominalTypeDecl *const nominal) = 0; + /// Called for local VarDecls that might not yet be in scope. + /// + /// Note that the set of VarDecls visited here are going to be a + /// superset of those visited in consume(). + virtual bool consumePossiblyNotInScope(ArrayRef values) { + return false; + } + /// Called right before looking at the parent scope of a BraceStmt. /// /// \return true if the lookup should be stopped at this point. @@ -636,7 +644,7 @@ class ASTScopeDeclGatherer : public AbstractASTScopeDeclConsumer { public: virtual ~ASTScopeDeclGatherer() = default; - bool consume(ArrayRef values, DeclVisibilityKind vis, + bool consume(ArrayRef values, NullablePtr baseDC = nullptr) override; /// Eventually this functionality should move into ASTScopeLookup diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 40d8c719a02d1..5ee6f3e74e2fb 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -330,21 +330,10 @@ namespace swift { /// of active clauses aren't hoisted into the enclosing scope. bool DisablePoundIfEvaluation = false; - /// Instead of hashing tokens inside of NominalType and ExtensionBodies into - /// the interface hash, hash them into per-iterable-decl-context - /// fingerprints. Fine-grained dependency types won't dirty every provides - /// in a file when the user adds a member to, e.g., a struct. - bool EnableTypeFingerprints = true; - /// When using fine-grained dependencies, emit dot files for every swiftdeps /// file. bool EmitFineGrainedDependencySourcefileDotFiles = false; - /// To mimic existing system, set to false. - /// To experiment with including file-private and private dependency info, - /// set to true. - bool FineGrainedDependenciesIncludeIntrafileOnes = false; - /// Whether to enable experimental differentiable programming features: /// `@differentiable` declaration attribute, etc. bool EnableExperimentalDifferentiableProgramming = false; diff --git a/include/swift/Driver/Compilation.h b/include/swift/Driver/Compilation.h index d970a9cf834cd..6c75516c71e90 100644 --- a/include/swift/Driver/Compilation.h +++ b/include/swift/Driver/Compilation.h @@ -265,9 +265,6 @@ class Compilation { const bool OnlyOneDependencyFile; private: - /// Is the parser recording token hashes for each type body? - const bool EnableTypeFingerprints; - /// Helpful for debugging, but slows down the driver. So, only turn on when /// needed. const bool VerifyFineGrainedDependencyGraphAfterEveryImport; @@ -275,9 +272,6 @@ class Compilation { /// needed. const bool EmitFineGrainedDependencyDotFileAfterEveryImport; - /// Experiment with intrafile dependencies - const bool FineGrainedDependenciesIncludeIntrafileOnes; - /// Experiment with source-range-based dependencies const bool EnableSourceRangeDependencies; @@ -319,11 +313,8 @@ class Compilation { bool ShowDriverTimeCompilation = false, std::unique_ptr Stats = nullptr, bool OnlyOneDependencyFile = false, - bool EnableTypeFingerprints = - LangOptions().EnableTypeFingerprints, bool VerifyFineGrainedDependencyGraphAfterEveryImport = false, bool EmitFineGrainedDependencyDotFileAfterEveryImport = false, - bool FineGrainedDependenciesIncludeIntrafileOnes = false, bool EnableSourceRangeDependencies = false, bool CompareIncrementalSchemes = false, StringRef CompareIncrementalSchemesPath = "", @@ -386,8 +377,6 @@ class Compilation { } void disableIncrementalBuild(Twine why); - bool getEnableTypeFingerprints() const { return EnableTypeFingerprints; } - bool getVerifyFineGrainedDependencyGraphAfterEveryImport() const { return VerifyFineGrainedDependencyGraphAfterEveryImport; } @@ -396,10 +385,6 @@ class Compilation { return EmitFineGrainedDependencyDotFileAfterEveryImport; } - bool getFineGrainedDependenciesIncludeIntrafileOnes() const { - return FineGrainedDependenciesIncludeIntrafileOnes; - } - bool getEnableSourceRangeDependencies() const { return EnableSourceRangeDependencies; } diff --git a/include/swift/Driver/FineGrainedDependencyDriverGraph.h b/include/swift/Driver/FineGrainedDependencyDriverGraph.h index ba461842bb36e..07029becc8be8 100644 --- a/include/swift/Driver/FineGrainedDependencyDriverGraph.h +++ b/include/swift/Driver/FineGrainedDependencyDriverGraph.h @@ -189,8 +189,6 @@ class ModuleDepGraph { 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 - ... @@ -296,14 +294,12 @@ class ModuleDepGraph { /// \p stats may be null ModuleDepGraph(const bool verifyFineGrainedDependencyGraphAfterEveryImport, const bool emitFineGrainedDependencyDotFileAfterEveryImport, - const bool EnableTypeFingerprints, const bool shouldTraceDependencies, UnifiedStatsReporter *stats) : verifyFineGrainedDependencyGraphAfterEveryImport( verifyFineGrainedDependencyGraphAfterEveryImport), emitFineGrainedDependencyDotFileAfterEveryImport( emitFineGrainedDependencyDotFileAfterEveryImport), - EnableTypeFingerprints(EnableTypeFingerprints), currentPathIfTracing( shouldTraceDependencies ? llvm::Optional>( @@ -314,11 +310,10 @@ class ModuleDepGraph { } /// For unit tests. - ModuleDepGraph(const bool EnableTypeFingerprints, - const bool EmitDotFilesForDebugging = false) + ModuleDepGraph(const bool EmitDotFilesForDebugging = false) : ModuleDepGraph( true, /*emitFineGrainedDependencyDotFileAfterEveryImport=*/ - EmitDotFilesForDebugging, EnableTypeFingerprints, false, nullptr) {} + EmitDotFilesForDebugging, false, nullptr) {} //============================================================================ // MARK: ModuleDepGraph - updating from a switdeps file diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a1c2b34fc1f59..7c80c7c03e68e 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -139,14 +139,6 @@ def driver_always_rebuild_dependents : Flag<["-"], "driver-always-rebuild-dependents">, InternalDebugOpt, HelpText<"Always rebuild dependents of files that have been modified">; -def enable_type_fingerprints : -Flag<["-"], "enable-type-fingerprints">, Flags<[FrontendOption, HelpHidden]>, -HelpText<"Enable per-nominal and extension body fingerprints">; - -def disable_type_fingerprints : -Flag<["-"], "disable-type-fingerprints">, Flags<[FrontendOption, HelpHidden]>, -HelpText<"Disable per-nominal and extension body fingerprints">; - def enable_only_one_dependency_file : Flag<["-"], "enable-only-one-dependency-file">, Flags<[DoesNotAffectIncrementalBuild]>, HelpText<"Enables incremental build optimization that only produces one dependencies file">; @@ -190,11 +182,6 @@ Flag<["-"], "driver-emit-fine-grained-dependency-dot-file-after-every-import">, InternalDebugOpt, HelpText<"Emit dot files every time driver imports an fine-grained swiftdeps file.">; -def fine_grained_dependency_include_intrafile : -Flag<["-"], "fine-grained-dependency-include-intrafile">, -Flags<[FrontendOption, HelpHidden]>, -HelpText<"Include within-file dependencies.">; - def emit_fine_grained_dependency_sourcefile_dot_files : Flag<["-"], "emit-fine-grained-dependency-sourcefile-dot-files">, Flags<[FrontendOption, HelpHidden]>, diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index 0c6d22b4bca5c..aa82c8014afc2 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -667,10 +667,30 @@ class NodeAdder NullablePtr visitBraceStmt(BraceStmt *bs, ASTScopeImpl *p, ScopeCreator &scopeCreator) { + SmallVector localFuncsAndTypes; + SmallVector localVars; + + // All types and functions are visible anywhere within a brace statement + // scope. When ordering matters (i.e. var decl) we will have split the brace + // statement into nested scopes. + for (auto braceElement : bs->getElements()) { + if (auto localBinding = braceElement.dyn_cast()) { + if (auto *vd = dyn_cast(localBinding)) { + if (isa(vd) || isa(vd)) { + localFuncsAndTypes.push_back(vd); + } else if (auto *var = dyn_cast(localBinding)) { + localVars.push_back(var); + } + } + } + } + auto maybeBraceScope = - scopeCreator.ifUniqueConstructExpandAndInsert(p, bs); + scopeCreator.ifUniqueConstructExpandAndInsert( + p, bs, std::move(localFuncsAndTypes), std::move(localVars)); if (auto *s = scopeCreator.getASTContext().Stats) ++s->getFrontendCounters().NumBraceStmtASTScopes; + return maybeBraceScope.getPtrOr(p); } @@ -681,23 +701,23 @@ class NodeAdder if (auto *var = patternBinding->getSingleVar()) scopeCreator.addChildrenForKnownAttributes(var, parentScope); - const bool isLocalBinding = patternBinding->getDeclContext()->isLocalContext(); - - const DeclVisibilityKind vis = - isLocalBinding ? DeclVisibilityKind::LocalVariable - : DeclVisibilityKind::MemberOfCurrentNominal; auto *insertionPoint = parentScope; for (auto i : range(patternBinding->getNumPatternEntries())) { + bool isLocalBinding = false; + if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) { + isLocalBinding = varDecl->getDeclContext()->isLocalContext(); + } + insertionPoint = scopeCreator .ifUniqueConstructExpandAndInsert( - insertionPoint, patternBinding, i, vis) + insertionPoint, patternBinding, i, isLocalBinding) .getPtrOr(insertionPoint); - } - ASTScopeAssert(isLocalBinding || insertionPoint == parentScope, - "Bindings at the top-level or members of types should " - "not change the insertion point"); + ASTScopeAssert(isLocalBinding || insertionPoint == parentScope, + "Bindings at the top-level or members of types should " + "not change the insertion point"); + } return insertionPoint; } @@ -971,7 +991,7 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint( "Original inits are always after the '='"); scopeCreator .constructExpandAndInsertUncheckable( - this, decl, patternEntryIndex, vis); + this, decl, patternEntryIndex, isLocalBinding); } // Add accessors for the variables in this pattern. @@ -982,7 +1002,7 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint( // In local context, the PatternEntryDeclScope becomes the insertion point, so // that all any bindings introduecd by the pattern are in scope for subsequent // lookups. - if (vis == DeclVisibilityKind::LocalVariable) + if (isLocalBinding) return {this, "All code that follows is inside this scope"}; return {getParent().get(), "Global and type members do not introduce scopes"}; @@ -1358,8 +1378,9 @@ ASTScopeImpl *LabeledConditionalStmtScope::createNestedConditionalClauseScopes( AbstractPatternEntryScope::AbstractPatternEntryScope( PatternBindingDecl *declBeingScoped, unsigned entryIndex, - DeclVisibilityKind vis) - : decl(declBeingScoped), patternEntryIndex(entryIndex), vis(vis) { + bool isLocalBinding) + : decl(declBeingScoped), patternEntryIndex(entryIndex), + isLocalBinding(isLocalBinding) { ASTScopeAssert(entryIndex < declBeingScoped->getPatternList().size(), "out of bounds"); } diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 47c103e83e608..c49099bce99d2 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -222,7 +222,7 @@ bool ASTScopeImpl::lookInGenericParametersOf( SmallVector bindings; for (auto *param : paramList.get()->getParams()) bindings.push_back(param); - if (consumer.consume(bindings, DeclVisibilityKind::GenericParameter)) + if (consumer.consume(bindings)) return true; return false; } @@ -289,28 +289,26 @@ PatternEntryInitializerScope::getLookupParent() const { bool GenericParamScope::lookupLocalsOrMembers(DeclConsumer consumer) const { auto *param = paramList->getParams()[index]; - return consumer.consume({param}, DeclVisibilityKind::GenericParameter); + return consumer.consume({param}); } bool PatternEntryDeclScope::lookupLocalsOrMembers(DeclConsumer consumer) const { - if (vis != DeclVisibilityKind::LocalVariable) - return false; // look in self type will find this later - return lookupLocalBindingsInPattern(getPattern(), vis, consumer); + if (!isLocalBinding) + return false; + return lookupLocalBindingsInPattern(getPattern(), consumer); } bool ForEachPatternScope::lookupLocalsOrMembers(DeclConsumer consumer) const { - return lookupLocalBindingsInPattern( - stmt->getPattern(), DeclVisibilityKind::LocalVariable, consumer); + return lookupLocalBindingsInPattern(stmt->getPattern(), consumer); } bool CaseLabelItemScope::lookupLocalsOrMembers(DeclConsumer consumer) const { - return lookupLocalBindingsInPattern( - item.getPattern(), DeclVisibilityKind::LocalVariable, consumer); + return lookupLocalBindingsInPattern(item.getPattern(), consumer); } bool CaseStmtBodyScope::lookupLocalsOrMembers(DeclConsumer consumer) const { for (auto *var : stmt->getCaseBodyVariablesOrEmptyArray()) - if (consumer.consume({var}, DeclVisibilityKind::LocalVariable)) + if (consumer.consume({var})) return true; return false; @@ -320,13 +318,12 @@ bool FunctionBodyScope::lookupLocalsOrMembers( DeclConsumer consumer) const { if (auto *paramList = decl->getParameters()) { for (auto *paramDecl : *paramList) - if (consumer.consume({paramDecl}, DeclVisibilityKind::FunctionParameter)) + if (consumer.consume({paramDecl})) return true; } if (decl->getDeclContext()->isTypeContext()) { - return consumer.consume({decl->getImplicitSelfDecl()}, - DeclVisibilityKind::FunctionParameter); + return consumer.consume({decl->getImplicitSelfDecl()}); } // Consider \c var t: T { (did/will/)get/set { ... t }} @@ -335,7 +332,7 @@ bool FunctionBodyScope::lookupLocalsOrMembers( // then t needs to be found as a local binding: if (auto *accessor = dyn_cast(decl)) { if (auto *storage = accessor->getStorage()) - if (consumer.consume({storage}, DeclVisibilityKind::LocalVariable)) + if (consumer.consume({storage})) return true; } @@ -346,7 +343,7 @@ bool SpecializeAttributeScope::lookupLocalsOrMembers( DeclConsumer consumer) const { if (auto *params = whatWasSpecialized->getGenericParams()) for (auto *param : params->getParams()) - if (consumer.consume({param}, DeclVisibilityKind::GenericParameter)) + if (consumer.consume({param})) return true; return false; } @@ -356,7 +353,7 @@ bool DifferentiableAttributeScope::lookupLocalsOrMembers( auto visitAbstractFunctionDecl = [&](AbstractFunctionDecl *afd) { if (auto *params = afd->getGenericParams()) for (auto *param : params->getParams()) - if (consumer.consume({param}, DeclVisibilityKind::GenericParameter)) + if (consumer.consume({param})) return true; return false; }; @@ -371,20 +368,10 @@ bool DifferentiableAttributeScope::lookupLocalsOrMembers( } bool BraceStmtScope::lookupLocalsOrMembers(DeclConsumer consumer) const { - // All types and functions are visible anywhere within a brace statement - // scope. When ordering matters (i.e. var decl) we will have split the brace - // statement into nested scopes. - // - // Don't stop at the first one, there may be local funcs with same base name - // and want them all. - SmallVector localBindings; - for (auto braceElement : stmt->getElements()) { - if (auto localBinding = braceElement.dyn_cast()) { - if (auto *vd = dyn_cast(localBinding)) - localBindings.push_back(vd); - } - } - if (consumer.consume(localBindings, DeclVisibilityKind::LocalVariable)) + if (consumer.consume(localFuncsAndTypes)) + return true; + + if (consumer.consumePossiblyNotInScope(localVars)) return true; if (consumer.finishLookupInBraceStmt(stmt)) @@ -400,8 +387,7 @@ bool PatternEntryInitializerScope::lookupLocalsOrMembers( decl->getInitContext(0)); if (initContext) { if (auto *selfParam = initContext->getImplicitSelfDecl()) { - return consumer.consume({selfParam}, - DeclVisibilityKind::FunctionParameter); + return consumer.consume({selfParam}); } } return false; @@ -409,9 +395,7 @@ bool PatternEntryInitializerScope::lookupLocalsOrMembers( bool CaptureListScope::lookupLocalsOrMembers(DeclConsumer consumer) const { for (auto &e : expr->getCaptureList()) { - if (consumer.consume( - {e.Var}, - DeclVisibilityKind::LocalVariable)) // or FunctionParameter?? + if (consumer.consume({e.Var})) return true; } return false; @@ -420,26 +404,24 @@ bool CaptureListScope::lookupLocalsOrMembers(DeclConsumer consumer) const { bool ClosureParametersScope::lookupLocalsOrMembers( DeclConsumer consumer) const { for (auto param : *closureExpr->getParameters()) - if (consumer.consume({param}, DeclVisibilityKind::FunctionParameter)) + if (consumer.consume({param})) return true; return false; } bool ConditionalClausePatternUseScope::lookupLocalsOrMembers( DeclConsumer consumer) const { - return lookupLocalBindingsInPattern( - pattern, DeclVisibilityKind::LocalVariable, consumer); + return lookupLocalBindingsInPattern(pattern, consumer); } bool ASTScopeImpl::lookupLocalBindingsInPattern(const Pattern *p, - DeclVisibilityKind vis, DeclConsumer consumer) { if (!p) return false; bool isDone = false; p->forEachVariable([&](VarDecl *var) { if (!isDone) - isDone = consumer.consume({var}, vis); + isDone = consumer.consume({var}); }); return isDone; } diff --git a/lib/AST/AbstractSourceFileDepGraphFactory.cpp b/lib/AST/AbstractSourceFileDepGraphFactory.cpp index 6a4ccfdf78ab6..b70ea103a4040 100644 --- a/lib/AST/AbstractSourceFileDepGraphFactory.cpp +++ b/lib/AST/AbstractSourceFileDepGraphFactory.cpp @@ -33,11 +33,10 @@ using namespace fine_grained_dependencies; //============================================================================== AbstractSourceFileDepGraphFactory::AbstractSourceFileDepGraphFactory( - bool includePrivateDeps, bool hadCompilationError, StringRef swiftDeps, + bool hadCompilationError, StringRef swiftDeps, StringRef fileFingerprint, bool emitDotFileAfterConstruction, DiagnosticEngine &diags) - : includePrivateDeps(includePrivateDeps), - hadCompilationError(hadCompilationError), swiftDeps(swiftDeps.str()), + : hadCompilationError(hadCompilationError), swiftDeps(swiftDeps.str()), fileFingerprint(fileFingerprint.str()), emitDotFileAfterConstruction(emitDotFileAfterConstruction), diags(diags) { } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index e0caead297377..86e1f8be8bca9 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1447,7 +1447,8 @@ void PatternBindingEntry::setInit(Expr *E) { VarDecl *PatternBindingEntry::getAnchoringVarDecl() const { SmallVector variables; getPattern()->collectVariables(variables); - assert(!variables.empty()); + if (variables.empty()) + return nullptr; return variables[0]; } @@ -8037,26 +8038,3 @@ void swift::simple_display(llvm::raw_ostream &out, AnyFunctionRef fn) { else out << "closure"; } - -bool Decl::isPrivateToEnclosingFile() const { - if (auto *VD = dyn_cast(this)) - return VD->getFormalAccess() <= AccessLevel::FilePrivate; - switch (getKind()) { - case DeclKind::Import: - case DeclKind::PatternBinding: - case DeclKind::EnumCase: - case DeclKind::TopLevelCode: - case DeclKind::IfConfig: - case DeclKind::PoundDiagnostic: - return true; - - case DeclKind::Extension: - case DeclKind::InfixOperator: - case DeclKind::PrefixOperator: - case DeclKind::PostfixOperator: - return false; - - default: - llvm_unreachable("everything else is a ValueDecl"); - } -} diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index 8aa916c6e128e..25224941d99af 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -933,7 +933,7 @@ bool IterableDeclContext::areTokensHashedForThisBodyInsteadOfInterfaceHash() // corresponding to the fingerprinted nominal dependency node. if (isa(this)) return false; - return getASTContext().LangOpts.EnableTypeFingerprints; + return true; } /// Return the DeclContext to compare when checking private access in diff --git a/lib/AST/FrontendSourceFileDepGraphFactory.cpp b/lib/AST/FrontendSourceFileDepGraphFactory.cpp index c89e1e0318e98..5ca65c70fb870 100644 --- a/lib/AST/FrontendSourceFileDepGraphFactory.cpp +++ b/lib/AST/FrontendSourceFileDepGraphFactory.cpp @@ -65,50 +65,6 @@ static std::string mangleTypeAsContext(const NominalTypeDecl *NTD) { return !NTD ? "" : Mangler.mangleTypeAsContextUSR(NTD); } -//============================================================================== -// MARK: Privacy queries -//============================================================================== - -/// Return true if \ref ED does not contain a member that can affect other -/// files. -static bool allMembersArePrivate(const ExtensionDecl *ED) { - return std::all_of( - ED->getMembers().begin(), ED->getMembers().end(), - [](const Decl *d) { return d->isPrivateToEnclosingFile(); }); -} - -/// \ref inheritedType, an inherited protocol, return true if this inheritance -/// cannot affect other files. -static bool extendedTypeIsPrivate(TypeLoc inheritedType) { - auto type = inheritedType.getType(); - if (!type) - return true; - - if (!type->isExistentialType()) { - // Be conservative. We don't know how to deal with other extended types. - return false; - } - - auto layout = type->getExistentialLayout(); - assert(!layout.explicitSuperclass && - "Should not have a subclass existential " - "in the inheritance clause of an extension"); - for (auto protoTy : layout.getProtocols()) { - if (!protoTy->getDecl()->isPrivateToEnclosingFile()) - return false; - } - - return true; -} - -/// Return true if \ref ED does not inherit a protocol that can affect other -/// files. Was called "justMembers" in ReferenceDependencies.cpp -/// \ref ED might be null. -static bool allInheritedProtocolsArePrivate(const ExtensionDecl *ED) { - return std::all_of(ED->getInherited().begin(), ED->getInherited().end(), - extendedTypeIsPrivate); -} - //============================================================================== // MARK: DependencyKey - creation for Decls //============================================================================== @@ -262,24 +218,11 @@ FrontendSourceFileDepGraphFactory::FrontendSourceFileDepGraphFactory( SourceFile *SF, StringRef outputPath, const DependencyTracker &depTracker, const bool alsoEmitDotFile) : AbstractSourceFileDepGraphFactory( - computeIncludePrivateDeps(SF), SF->getASTContext().hadError(), + SF->getASTContext().hadError(), outputPath, getInterfaceHash(SF), alsoEmitDotFile, SF->getASTContext().Diags), SF(SF), depTracker(depTracker) {} -bool FrontendSourceFileDepGraphFactory::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 FrontendSourceFileDepGraphFactory::getFingerprint(SourceFile *SF) { @@ -297,10 +240,6 @@ namespace { /// Takes all the Decls in a SourceFile, and collects them into buckets by /// groups of DeclKinds. Also casts them to more specific types struct DeclFinder { - /// Existing system excludes private decls in some cases. - /// In the future, we might not want to do this, so use bool to decide. - const bool includePrivateDecls; - // The extracted Decls: ConstPtrVec extensions; ConstPtrVec operators; @@ -319,19 +258,17 @@ struct DeclFinder { /// Construct me and separates the Decls. // clang-format off DeclFinder(ArrayRef topLevelDecls, - const bool includePrivateDecls, - LookupClassMember lookupClassMember) - : includePrivateDecls(includePrivateDecls) { + LookupClassMember lookupClassMember) { for (const Decl *const D : topLevelDecls) { - select(D, extensions, false) || + select(D, extensions) || select(D, operators, false) || + DeclKind::PostfixOperator>(D, operators) || select( - D, precedenceGroups, false) || + D, precedenceGroups) || select(D, topNominals, true) || + DeclKind::Class, DeclKind::Protocol>(D, topNominals) || select(D, topValues, true); + DeclKind::Accessor>(D, topValues); } // clang-format on // The order is important because some of these use instance variables @@ -360,18 +297,7 @@ struct DeclFinder { /// (indirectly recursive) void findNominalsAndOperatorsIn(const NominalTypeDecl *const NTD, const ExtensionDecl *ED = nullptr) { - if (excludeIfPrivate(NTD)) - return; - const bool exposedProtocolIsExtended = - ED && !allInheritedProtocolsArePrivate(ED); - if (ED && !includePrivateDecls && !exposedProtocolIsExtended && - std::all_of( - ED->getMembers().begin(), ED->getMembers().end(), - [&](const Decl *D) { return D->isPrivateToEnclosingFile(); })) { - return; - } - if (includePrivateDecls || !ED || exposedProtocolIsExtended) - allNominals.push_back(NTD); + allNominals.push_back(NTD); potentialMemberHolders.push_back(NTD); findNominalsAndOperatorsInMembers(ED ? ED->getMembers() : NTD->getMembers()); @@ -383,7 +309,7 @@ struct DeclFinder { void findNominalsAndOperatorsInMembers(const DeclRange members) { for (const Decl *const D : members) { auto *VD = dyn_cast(D); - if (!VD || excludeIfPrivate(VD)) + if (!VD) continue; if (VD->getName().isOperator()) memberOperatorDecls.push_back(cast(D)); @@ -396,19 +322,20 @@ struct DeclFinder { void findValuesInExtensions() { for (const auto *ED : extensions) { const auto *const NTD = ED->getExtendedNominal(); - if (!NTD || excludeIfPrivate(NTD)) + if (!NTD) { continue; - if (!includePrivateDecls && - (!allInheritedProtocolsArePrivate(ED) || allMembersArePrivate(ED))) - continue; - for (const auto *member : ED->getMembers()) - if (const auto *VD = dyn_cast(member)) - if (VD->hasName() && - (includePrivateDecls || !VD->isPrivateToEnclosingFile())) { - const auto *const NTD = ED->getExtendedNominal(); - if (NTD) - valuesInExtensions.push_back(std::make_pair(NTD, VD)); - } + } + + for (const auto *member : ED->getMembers()) { + const auto *VD = dyn_cast(member); + if (!VD || !VD->hasName()) { + continue; + } + + if (const auto *const NTD = ED->getExtendedNominal()) { + valuesInExtensions.push_back(std::make_pair(NTD, VD)); + } + } } } @@ -431,30 +358,19 @@ struct DeclFinder { /// \returns true if successful. template - bool select(const Decl *const D, ConstPtrVec &foundDecls, - const bool canExcludePrivateDecls) { + bool select(const Decl *const D, ConstPtrVec &foundDecls) { if (D->getKind() == firstKind) { - auto *dd = cast(D); - const bool exclude = canExcludePrivateDecls && excludeIfPrivate(dd); - if (!exclude) - foundDecls.push_back(cast(D)); + foundDecls.push_back(cast(D)); return true; } - return select(D, foundDecls, - canExcludePrivateDecls); + return select(D, foundDecls); } /// Terminate the template recursion. template - bool select(const Decl *const D, ConstPtrVec &foundDecls, - bool) { + bool select(const Decl *const D, ConstPtrVec &foundDecls) { return false; } - - /// Return true if \param D should be excluded on privacy grounds. - bool excludeIfPrivate(const Decl *const D) { - return !includePrivateDecls && D->isPrivateToEnclosingFile(); - } }; } // namespace @@ -464,7 +380,7 @@ void FrontendSourceFileDepGraphFactory::addAllDefinedDecls() { // Many kinds of Decls become top-level depends. - DeclFinder declFinder(SF->getTopLevelDecls(), includePrivateDeps, + DeclFinder declFinder(SF->getTopLevelDecls(), [this](VisibleDeclConsumer &consumer) { SF->lookupClassMembers({}, consumer); }); @@ -513,14 +429,11 @@ class UsedDeclEnumerator { const DependencyKey sourceFileInterface; const DependencyKey sourceFileImplementation; - const bool includeIntrafileDeps; - function_ref createDefUse; public: UsedDeclEnumerator( SourceFile *SF, const DependencyTracker &depTracker, StringRef swiftDeps, - bool includeIntrafileDeps, function_ref createDefUse) : SF(SF), depTracker(depTracker), swiftDeps(swiftDeps), @@ -528,7 +441,7 @@ class UsedDeclEnumerator { DeclAspect::interface, swiftDeps)), sourceFileImplementation(DependencyKey::createKeyForWholeSourceFile( DeclAspect::implementation, swiftDeps)), - includeIntrafileDeps(includeIntrafileDeps), createDefUse(createDefUse) { + createDefUse(createDefUse) { } public: @@ -581,11 +494,6 @@ class UsedDeclEnumerator { return; } - bool isPrivate = subject->isPrivateToEnclosingFile(); - if (isPrivate && !includeIntrafileDeps) { - return; - } - std::string context = DependencyKey::computeContextForProvidedEntity( subject); @@ -604,7 +512,7 @@ class UsedDeclEnumerator { } // end namespace void FrontendSourceFileDepGraphFactory::addAllUsedDecls() { - UsedDeclEnumerator(SF, depTracker, swiftDeps, includePrivateDeps, + UsedDeclEnumerator(SF, depTracker, swiftDeps, [&](const DependencyKey &def, const DependencyKey &use) { addAUsedDecl(def, use); }) @@ -644,7 +552,7 @@ FrontendSourceFileDepGraphFactory::getFingerprintIfAny(const Decl *d) { ModuleDepGraphFactory::ModuleDepGraphFactory(ModuleDecl *Mod, bool emitDot) : AbstractSourceFileDepGraphFactory( - /*include private*/ true, Mod->getASTContext().hadError(), + Mod->getASTContext().hadError(), Mod->getNameStr(), "0xBADBEEF", emitDot, Mod->getASTContext().Diags), Mod(Mod) {} @@ -656,7 +564,7 @@ void ModuleDepGraphFactory::addAllDefinedDecls() { SmallVector TopLevelDecls; Mod->getTopLevelDecls(TopLevelDecls); - DeclFinder declFinder(TopLevelDecls, includePrivateDeps, + DeclFinder declFinder(TopLevelDecls, [this](VisibleDeclConsumer &consumer) { return Mod->lookupClassMembers({}, consumer); }); diff --git a/lib/AST/FrontendSourceFileDepGraphFactory.h b/lib/AST/FrontendSourceFileDepGraphFactory.h index 898357f72117f..6b2740f54baf2 100644 --- a/lib/AST/FrontendSourceFileDepGraphFactory.h +++ b/lib/AST/FrontendSourceFileDepGraphFactory.h @@ -35,8 +35,6 @@ class FrontendSourceFileDepGraphFactory private: static std::string getFingerprint(SourceFile *SF); - - static bool computeIncludePrivateDeps(SourceFile *SF); static std::string getInterfaceHash(SourceFile *SF); void addAllDefinedDecls() override; diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 552a369b6f0a1..f939ed3b71ac8 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -134,7 +134,12 @@ namespace { /// Can lookup stop searching for results, assuming hasn't looked for outer /// results yet? bool isFirstResultEnough() const; - + + /// Do we want precise scoping of VarDecls? If IncludeOuterResults is on, + /// this is true, which allows us to resolve forward references to + /// local VarDecls from inside local function and closure bodies. + bool hasPreciseScopingOfVarDecls() const; + /// Every time lookup finishes searching a scope, call me /// to record the dividing line between results from first fruitful scope and /// the result. @@ -207,9 +212,11 @@ class ASTScopeDeclConsumerForUnqualifiedLookup void maybeUpdateSelfDC(VarDecl *var); - bool consume(ArrayRef values, DeclVisibilityKind vis, + bool consume(ArrayRef values, NullablePtr baseDC = nullptr) override; + bool consumePossiblyNotInScope(ArrayRef vars) override; + /// returns true if finished bool lookInMembers(DeclContext *const scopeDC, NominalTypeDecl *const nominal) override; @@ -463,6 +470,10 @@ bool UnqualifiedLookupFactory::isFirstResultEnough() const { return !Results.empty() && !options.contains(Flags::IncludeOuterResults); } +bool UnqualifiedLookupFactory::hasPreciseScopingOfVarDecls() const { + return !options.contains(Flags::IncludeOuterResults); +} + void UnqualifiedLookupFactory::recordCompletionOfAScope() { // OK to call (NOOP) if there are more inner results and Results is empty if (IndexOfFirstOuterResult == 0) @@ -551,18 +562,23 @@ void ASTScopeDeclConsumerForUnqualifiedLookup::maybeUpdateSelfDC( } bool ASTScopeDeclConsumerForUnqualifiedLookup::consume( - ArrayRef values, DeclVisibilityKind vis, - NullablePtr baseDC) { + ArrayRef values, NullablePtr baseDC) { for (auto *value: values) { if (factory.isOriginallyTypeLookup && !isa(value)) continue; - // Try to resolve the base for unqualified instance member - // references. This is used by lookInMembers(). if (auto *var = dyn_cast(value)) { + // Try to resolve the base for unqualified instance member + // references. This is used by lookInMembers(). if (var->getName() == factory.Ctx.Id_self) { maybeUpdateSelfDC(var); } + + // Local VarDecls with a pattern binding are visited as part of their + // BraceStmt when hasPreciseScopingOfVarDecls() is off. + if (var->getParentPatternBinding() && + !factory.hasPreciseScopingOfVarDecls()) + continue; } auto fullName = factory.Name.getFullName(); @@ -582,17 +598,6 @@ bool ASTScopeDeclConsumerForUnqualifiedLookup::consume( continue; } - // In order to preserve the behavior of the existing context-based lookup, - // which finds all results for non-local variables at the top level instead - // of stopping at the first one, ignore results at the top level that are - // not local variables. The caller \c lookInASTScopes will - // then do the appropriate work when the scope lookup fails. In - // FindLocalVal::visitBraceStmt, it sees PatternBindingDecls, not VarDecls, - // so a VarDecl at top level would not be found by the context-based lookup. - if (isa(value->getDeclContext()) && - (vis != DeclVisibilityKind::LocalVariable || isa(value))) - return false; - factory.Results.push_back(LookupResultEntry(value)); #ifndef NDEBUG factory.stopForDebuggingIfAddingTargetLookupResult(factory.Results.back()); @@ -602,8 +607,22 @@ bool ASTScopeDeclConsumerForUnqualifiedLookup::consume( return factory.isFirstResultEnough(); } +bool ASTScopeDeclConsumerForUnqualifiedLookup::consumePossiblyNotInScope( + ArrayRef vars) { + if (factory.hasPreciseScopingOfVarDecls()) + return false; + + for (auto *var : vars) { + if (!factory.Name.getFullName().isSimpleName(var->getName())) + continue; + + factory.Results.push_back(LookupResultEntry(var)); + } + + return false; +} + bool ASTScopeDeclGatherer::consume(ArrayRef valuesArg, - DeclVisibilityKind, NullablePtr) { for (auto *v: valuesArg) values.push_back(v); @@ -762,7 +781,7 @@ class ASTScopeDeclConsumerForLocalLookup : name(name), stopAfterInnermostBraceStmt(stopAfterInnermostBraceStmt), results(results) {} - bool consume(ArrayRef values, DeclVisibilityKind vis, + bool consume(ArrayRef values, NullablePtr baseDC) override { for (auto *value: values) { if (!value->getName().matchesRef(name)) diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 1b1e57753b784..11332f958b731 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -121,10 +121,8 @@ Compilation::Compilation(DiagnosticEngine &Diags, bool ShowDriverTimeCompilation, std::unique_ptr StatsReporter, bool OnlyOneDependencyFile, - bool EnableTypeFingerprints, bool VerifyFineGrainedDependencyGraphAfterEveryImport, bool EmitFineGrainedDependencyDotFileAfterEveryImport, - bool FineGrainedDependenciesIncludeIntrafileOnes, bool EnableSourceRangeDependencies, bool CompareIncrementalSchemes, StringRef CompareIncrementalSchemesPath, @@ -149,13 +147,10 @@ Compilation::Compilation(DiagnosticEngine &Diags, Stats(std::move(StatsReporter)), FilelistThreshold(FilelistThreshold), OnlyOneDependencyFile(OnlyOneDependencyFile), - EnableTypeFingerprints(EnableTypeFingerprints), VerifyFineGrainedDependencyGraphAfterEveryImport( VerifyFineGrainedDependencyGraphAfterEveryImport), EmitFineGrainedDependencyDotFileAfterEveryImport( EmitFineGrainedDependencyDotFileAfterEveryImport), - FineGrainedDependenciesIncludeIntrafileOnes( - FineGrainedDependenciesIncludeIntrafileOnes), EnableSourceRangeDependencies(EnableSourceRangeDependencies), EnableCrossModuleIncrementalBuild(EnableCrossModuleIncrementalBuild) { @@ -829,12 +824,12 @@ namespace driver { FineGrainedDepGraph( Comp.getVerifyFineGrainedDependencyGraphAfterEveryImport(), Comp.getEmitFineGrainedDependencyDotFileAfterEveryImport(), - Comp.getEnableTypeFingerprints(), Comp.getTraceDependencies(), + Comp.getTraceDependencies(), Comp.getStatsReporter()), FineGrainedDepGraphForRanges( Comp.getVerifyFineGrainedDependencyGraphAfterEveryImport(), Comp.getEmitFineGrainedDependencyDotFileAfterEveryImport(), - Comp.getEnableTypeFingerprints(), Comp.getTraceDependencies(), + Comp.getTraceDependencies(), Comp.getStatsReporter()), TQ(std::move(TaskQueue)) {} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 6394cb4f65807..ed09cf7bb028e 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1014,19 +1014,12 @@ Driver::buildCompilation(const ToolChain &TC, ArgList->hasFlag(options::OPT_enable_only_one_dependency_file, options::OPT_disable_only_one_dependency_file, false); - const bool EnableTypeFingerprints = - ArgList->hasFlag(options::OPT_enable_type_fingerprints, - options::OPT_disable_type_fingerprints, - LangOptions().EnableTypeFingerprints); - const bool VerifyFineGrainedDependencyGraphAfterEveryImport = ArgList->hasArg( options:: OPT_driver_verify_fine_grained_dependency_graph_after_every_import); const bool EmitFineGrainedDependencyDotFileAfterEveryImport = ArgList->hasArg( options:: OPT_driver_emit_fine_grained_dependency_dot_file_after_every_import); - const bool FineGrainedDependenciesIncludeIntrafileOnes = - ArgList->hasArg(options::OPT_fine_grained_dependency_include_intrafile); const bool EnableCrossModuleDependencies = ArgList->hasArg( options::OPT_enable_experimental_cross_module_incremental_build); @@ -1050,10 +1043,8 @@ Driver::buildCompilation(const ToolChain &TC, ShowDriverTimeCompilation, std::move(StatsReporter), OnlyOneDependencyFile, - EnableTypeFingerprints, VerifyFineGrainedDependencyGraphAfterEveryImport, EmitFineGrainedDependencyDotFileAfterEveryImport, - FineGrainedDependenciesIncludeIntrafileOnes, EnableSourceRangeDependencies, CompareIncrementalSchemes, CompareIncrementalSchemesPath, diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index dc2a9afcf929b..d5ab5a5228b57 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -369,12 +369,6 @@ ModuleDepGraph::integrateSourceFileDepGraphNode( const SourceFileDepGraph &g, const SourceFileDepGraphNode *integrand, const PreexistingNodeIfAny preexistingMatch, const StringRef swiftDepsOfJob) { - - if (!EnableTypeFingerprints && - integrand->getKey().getKind() != NodeKind::sourceFileProvide && - integrand->getFingerprint()) - return None; - if (!integrand->getIsProvides()) return NullablePtr(); // depends are captured by // recordWhatUseDependsUpon below diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 8d5d0b30d7ede..2ff01dd73b4fa 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -259,10 +259,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_O_Group); inputArgs.AddLastArg(arguments, options::OPT_RemoveRuntimeAsserts); inputArgs.AddLastArg(arguments, options::OPT_AssumeSingleThreaded); - inputArgs.AddLastArg(arguments, options::OPT_enable_type_fingerprints); - inputArgs.AddLastArg(arguments, options::OPT_disable_type_fingerprints); - inputArgs.AddLastArg(arguments, - options::OPT_fine_grained_dependency_include_intrafile); inputArgs.AddLastArg(arguments, options::OPT_emit_fine_grained_dependency_sourcefile_dot_files); inputArgs.AddLastArg(arguments, options::OPT_package_description_version); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c4f1c698ac7bd..3d0f6a6180bb1 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -438,17 +438,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.VerifySyntaxTree = true; } - Opts.EnableTypeFingerprints = - Args.hasFlag(options::OPT_enable_type_fingerprints, - options::OPT_disable_type_fingerprints, - LangOptions().EnableTypeFingerprints); - if (Args.hasArg(OPT_emit_fine_grained_dependency_sourcefile_dot_files)) Opts.EmitFineGrainedDependencySourcefileDotFiles = true; - if (Args.hasArg(OPT_fine_grained_dependency_include_intrafile)) - Opts.FineGrainedDependenciesIncludeIntrafileOnes = true; - if (Args.hasArg(OPT_enable_experimental_additive_arithmetic_derivation)) Opts.EnableExperimentalAdditiveArithmeticDerivedConformances = true; diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 9c4ba9940e0e1..eaad0b6499293 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -322,8 +322,6 @@ bool CompletionInstance::performCachedOperationIfPossible( LangOptions langOpts = CI.getASTContext().LangOpts; langOpts.DisableParserLookup = true; - // Ensure all non-function-body tokens are hashed into the interface hash - langOpts.EnableTypeFingerprints = false; TypeCheckerOptions typeckOpts = CI.getASTContext().TypeCheckerOpts; SearchPathOptions searchPathOpts = CI.getASTContext().SearchPathOpts; DiagnosticEngine tmpDiags(tmpSM); @@ -599,10 +597,6 @@ bool swift::ide::CompletionInstance::performOperation( // source text. That breaks an invariant of syntax tree building. Invocation.getLangOptions().BuildSyntaxTree = false; - // Since caching uses the interface hash, and since per type fingerprints - // weaken that hash, disable them here: - Invocation.getLangOptions().EnableTypeFingerprints = false; - // We don't need token list. Invocation.getLangOptions().CollectParsedToken = false; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index da749109d0fd9..412d3f57890f4 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4552,8 +4552,13 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag, // If we're hashing the type body separately, record the curly braces but // nothing inside for the interface hash. + // + // FIXME: There's no real reason code completion cannot also use this code + // path. But it seems to cause lazy parsing in contexts that the current + // implementation does not expect. Optional>> MemberHashingScope; - if (IDC->areTokensHashedForThisBodyInsteadOfInterfaceHash()) { + if (IDC->areTokensHashedForThisBodyInsteadOfInterfaceHash() && + !L->isCodeCompletion()) { recordTokenHash("{"); recordTokenHash("}"); MemberHashingScope.emplace(CurrentTokenHash, llvm::MD5()); @@ -4588,7 +4593,7 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag, if (RBLoc.isInvalid()) hadError = true; - if (!Context.LangOpts.EnableTypeFingerprints) + if (L->isCodeCompletion()) return std::make_pair(decls, None); llvm::MD5::MD5Result result; diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index 7cf0c1a0b0a86..0da6f8379f65f 100644 --- a/lib/Sema/PreCheckExpr.cpp +++ b/lib/Sema/PreCheckExpr.cpp @@ -351,12 +351,77 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // name/module qualifier to access top-level name. lookupOptions |= NameLookupFlags::IncludeOuterResults; - if (Loc.isInvalid()) - DC = DC->getModuleScopeContext(); + LookupResult Lookup; - auto Lookup = TypeChecker::lookupUnqualified(DC, Name, Loc, lookupOptions); + bool AllDeclRefs = true; + SmallVector ResultValues; auto &Context = DC->getASTContext(); + if (Context.LangOpts.DisableParserLookup) { + // First, look for a local binding in scope. + if (Loc.isValid() && !Name.isOperator()) { + SmallVector localDecls; + ASTScope::lookupLocalDecls(DC->getParentSourceFile(), + Name.getFullName(), Loc, + /*stopAfterInnermostBraceStmt=*/false, + ResultValues); + for (auto *localDecl : ResultValues) { + Lookup.add(LookupResultEntry(localDecl), /*isOuter=*/false); + } + } + } + + if (!Lookup) { + // Now, look for all local bindings, even forward references, as well + // as type members and top-level declarations. + if (Loc.isInvalid()) + DC = DC->getModuleScopeContext(); + + Lookup = TypeChecker::lookupUnqualified(DC, Name, Loc, lookupOptions); + + ValueDecl *localDeclAfterUse = nullptr; + auto isValid = [&](ValueDecl *D) { + // If we find something in the current context, it must be a forward + // reference, because otherwise if it was in scope, it would have + // been returned by the call to ASTScope::lookupLocalDecls() above. + if (D->getDeclContext()->isLocalContext() && + D->getDeclContext() == DC && + (Context.LangOpts.DisableParserLookup || + (Loc.isValid() && D->getLoc().isValid() && + Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc()) && + !isa(D)))) { + localDeclAfterUse = D; + return false; + } + return true; + }; + AllDeclRefs = + findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), + /*breakOnMember=*/true, ResultValues, isValid); + + // If local declaration after use is found, check outer results for + // better matching candidates. + if (ResultValues.empty() && localDeclAfterUse) { + auto innerDecl = localDeclAfterUse; + while (localDeclAfterUse) { + if (Lookup.outerResults().empty()) { + Context.Diags.diagnose(Loc, diag::use_local_before_declaration, Name); + Context.Diags.diagnose(innerDecl, diag::decl_declared_here, + localDeclAfterUse->getName()); + Expr *error = new (Context) ErrorExpr(UDRE->getSourceRange()); + return error; + } + + Lookup.shiftDownResults(); + ResultValues.clear(); + localDeclAfterUse = nullptr; + AllDeclRefs = + findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), + /*breakOnMember=*/true, ResultValues, isValid); + } + } + } + if (!Lookup) { // If we failed lookup of an operator, check to see if this is a range // operator misspelling. Otherwise try to diagnose a juxtaposition @@ -487,50 +552,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // FIXME: Need to refactor the way we build an AST node from a lookup result! - SmallVector ResultValues; - ValueDecl *localDeclAfterUse = nullptr; - auto isValid = [&](ValueDecl *D) { - // FIXME: The source-location checks won't make sense once - // EnableASTScopeLookup is the default. - // - // Note that we allow forward references to types, because they cannot - // capture. - if (Loc.isValid() && D->getLoc().isValid() && - D->getDeclContext()->isLocalContext() && - D->getDeclContext() == DC && - Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc()) && - !isa(D)) { - localDeclAfterUse = D; - return false; - } - return true; - }; - bool AllDeclRefs = - findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), - /*breakOnMember=*/true, ResultValues, isValid); - - // If local declaration after use is found, check outer results for - // better matching candidates. - if (localDeclAfterUse) { - auto innerDecl = localDeclAfterUse; - while (localDeclAfterUse) { - if (Lookup.outerResults().empty()) { - Context.Diags.diagnose(Loc, diag::use_local_before_declaration, Name); - Context.Diags.diagnose(innerDecl, diag::decl_declared_here, - localDeclAfterUse->getName()); - Expr *error = new (Context) ErrorExpr(UDRE->getSourceRange()); - return error; - } - - Lookup.shiftDownResults(); - ResultValues.clear(); - localDeclAfterUse = nullptr; - AllDeclRefs = - findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), - /*breakOnMember=*/true, ResultValues, isValid); - } - } - // If we have an unambiguous reference to a type decl, form a TypeExpr. if (Lookup.size() == 1 && UDRE->getRefKind() == DeclRefKind::Ordinary && isa(Lookup[0].getValueDecl())) { diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a4707aa0b2639..5092bf7c99b92 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -572,6 +572,11 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const { if (currentDC->isTypeContext() != other->getDeclContext()->isTypeContext()) continue; + // In local context, only consider exact name matches. + if (currentDC->isLocalContext() && + current->getName() != other->getName()) + continue; + // Check whether the overload signatures conflict (ignoring the type for // now). auto otherSig = other->getOverloadSignature(); diff --git a/localization/CMakeLists.txt b/localization/CMakeLists.txt index 53c7e05e2a757..dcaac27691e35 100644 --- a/localization/CMakeLists.txt +++ b/localization/CMakeLists.txt @@ -19,4 +19,7 @@ add_dependencies(diagnostic-database swift-def-to-yaml-converter) swift_install_in_component( DIRECTORY ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ DESTINATION "share/swift/diagnostics" - COMPONENT compiler) + COMPONENT compiler + PATTERN "*.db" + PATTERN "*.yaml" +) diff --git a/stdlib/private/OSLog/CMakeLists.txt b/stdlib/private/OSLog/CMakeLists.txt index 7241543470fe8..2e37b642fb6c0 100644 --- a/stdlib/private/OSLog/CMakeLists.txt +++ b/stdlib/private/OSLog/CMakeLists.txt @@ -10,6 +10,9 @@ add_swift_target_library(swiftOSLogTestHelper OSLogStringTypes.swift OSLogNSObjectType.swift OSLogFloatingPointTypes.swift + OSLogSwiftProtocols.swift + OSLogPrivacy.swift + OSLogFloatFormatting.swift SWIFT_MODULE_DEPENDS_IOS Darwin ObjectiveC SWIFT_MODULE_DEPENDS_OSX Darwin ObjectiveC diff --git a/stdlib/private/OSLog/OSLogFloatFormatting.swift b/stdlib/private/OSLog/OSLogFloatFormatting.swift new file mode 100644 index 0000000000000..8397f849e5abb --- /dev/null +++ b/stdlib/private/OSLog/OSLogFloatFormatting.swift @@ -0,0 +1,426 @@ +//===--------------------------- OSLogFloatFormatting.swift ------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===------------------------------------------------------------------------------===// + +// This file defines types and functions for specifying formatting of +// floating-point typed interpolations passed to the os log APIs. + +@frozen +public struct OSLogFloatFormatting { + /// When set, a `+` will be printed for all non-negative floats. + @usableFromInline + internal var explicitPositiveSign: Bool + + /// Whether to use uppercase letters to represent numerals greater than 9 + /// (default is to use lowercase). This applies to hexadecimal digits, NaN, Inf, + /// the symbols E and X used to denote exponent and hex format. + @usableFromInline + internal var uppercase: Bool + + // Note: includePrefix is not supported for FloatFormatting. The format specifier %a + // always prints a prefix, %efg don't need one. + + /// Number of digits to display following the radix point. Hex notation does not accept + /// a precision. For non-hex notations, precision can be a dynamic value. The default + /// precision is 6 for non-hex notations. + @usableFromInline + internal var precision: (() -> Int)? + + @usableFromInline + internal enum Notation { + /// Hexadecimal formatting. + case hex + + /// fprintf's `%f` formatting. + /// + /// Prints all digits before the radix point, and `precision` digits following + /// the radix point. If `precision` is zero, the radix point is omitted. + /// + /// Note that very large floating-point values may print quite a lot of digits + /// when using this format, even if `precision` is zero--up to hundreds for + /// `Double`, and thousands for `Float80`. Note also that this format is + /// very likely to print non-zero values as all-zero. If these are a concern, use + /// `.exponential` or `.hybrid` instead. + /// + /// Systems may impose an upper bound on the number of digits that are + /// supported following the radix point. + case fixed + + /// fprintf's `%e` formatting. + /// + /// Prints the number in the form [-]d.ddd...dde±dd, with `precision` significant + /// digits following the radix point. Systems may impose an upper bound on the number + /// of digits that are supported. + case exponential + + /// fprintf's `%g` formatting. + /// + /// Behaves like `.fixed` when the number is scaled close to 1.0, and like + /// `.exponential` if it has a very large or small exponent. + case hybrid + } + + @usableFromInline + internal var notation: Notation + + @_transparent + @usableFromInline + internal init( + explicitPositiveSign: Bool = false, + uppercase: Bool = false, + precision: (() -> Int)?, + notation: Notation + ) { + self.explicitPositiveSign = explicitPositiveSign + self.uppercase = uppercase + self.precision = precision + self.notation = notation + } + + /// Displays an interpolated floating-point value in fprintf's `%f` format with + /// default precision. + /// + /// Prints all digits before the radix point, and 6 digits following the radix point. + /// Note also that this format is very likely to print non-zero values as all-zero. + /// + /// Note that very large floating-point values may print quite a lot of digits + /// when using this format --up to hundreds for `Double`. Note also that this + /// format is very likely to print non-zero values as all-zero. If these are a concern, + /// use `.exponential` or `.hybrid` instead. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static var fixed: OSLogFloatFormatting { .fixed() } + + /// Displays an interpolated floating-point value in fprintf's `%f` format with + /// specified precision, and optional sign and case. + /// + /// Prints all digits before the radix point, and `precision` digits following + /// the radix point. If `precision` is zero, the radix point is omitted. + /// + /// Note that very large floating-point values may print quite a lot of digits + /// when using this format, even if `precision` is zero--up to hundreds for + /// `Double`. Note also that this format is very likely to print non-zero values as + /// all-zero. If these are a concern, use `.exponential` or `.hybrid` instead. + /// + /// Systems may impose an upper bound on the number of digits that are + /// supported following the radix point. + /// + /// All parameters to this function except `precision` must be boolean literals. + /// + /// - Parameters: + /// - precision: Number of digits to display after the radix point. + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func fixed( + precision: @escaping @autoclosure () -> Int, + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: precision, + notation: .fixed + ) + } + + /// Displays an interpolated floating-point value in fprintf's `%f` format with + /// default precision, and optional sign and case. + /// + /// Prints all digits before the radix point, and 6 digits following the radix point. + /// Note also that this format is very likely to print non-zero values as all-zero. + /// + /// Note that very large floating-point values may print quite a lot of digits + /// when using this format, even if `precision` is zero--up to hundreds for + /// `Double`. Note also that this format is very likely to print non-zero values as + /// all-zero. If these are a concern, use `.exponential` or `.hybrid` instead. + /// + /// Systems may impose an upper bound on the number of digits that are + /// supported following the radix point. + /// + /// All parameters to this function must be boolean literals. + /// - Parameters: + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func fixed( + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: nil, + notation: .fixed + ) + } + + /// Displays an interpolated floating-point value in hexadecimal format. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static var hex: OSLogFloatFormatting { .hex() } + + /// Displays an interpolated floating-point value in hexadecimal format with + /// optional sign and case. + /// + /// All parameters to this function must be boolean literals. + /// + /// - Parameters: + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func hex( + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: nil, + notation: .hex + ) + } + + /// Displays an interpolated floating-point value in fprintf's `%e` format. + /// + /// Prints the number in the form [-]d.ddd...dde±dd. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static var exponential: OSLogFloatFormatting { .exponential() } + + /// Displays an interpolated floating-point value in fprintf's `%e` format with + /// specified precision, and optional sign and case. + /// + /// Prints the number in the form [-]d.ddd...dde±dd, with `precision` significant + /// digits following the radix point. Systems may impose an upper bound on the number + /// of digits that are supported. + /// + /// All parameters except `precision` must be boolean literals. + /// + /// - Parameters: + /// - precision: Number of digits to display after the radix point. + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func exponential( + precision: @escaping @autoclosure () -> Int, + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: precision, + notation: .exponential + ) + } + + /// Displays an interpolated floating-point value in fprintf's `%e` format with + /// an optional sign and case. + /// + /// Prints the number in the form [-]d.ddd...dde±dd. + /// + /// All parameters to this function must be boolean literals. + /// + /// - Parameters: + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func exponential( + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: nil, + notation: .exponential + ) + } + + /// Displays an interpolated floating-point value in fprintf's `%g` format. + /// + /// Behaves like `.fixed` when the number is scaled close to 1.0, and like + /// `.exponential` if it has a very large or small exponent. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static var hybrid: OSLogFloatFormatting { .hybrid() } + + /// Displays an interpolated floating-point value in fprintf's `%g` format with the + /// specified precision, and optional sign and case. + /// + /// Behaves like `.fixed` when the number is scaled close to 1.0, and like + /// `.exponential` if it has a very large or small exponent. + /// + /// All parameters except `precision` must be boolean literals. + /// + /// - Parameters: + /// - precision: Number of digits to display after the radix point. + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func hybrid( + precision: @escaping @autoclosure () -> Int, + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: precision, + notation: .hybrid + ) + } + + /// Displays an interpolated floating-point value in fprintf's `%g` format with + /// optional sign and case. + /// + /// Behaves like `.fixed` when the number is scaled close to 1.0, and like + /// `.exponential` if it has a very large or small exponent. + /// + /// All parameters to this function must be boolean literals. + /// + /// - Parameters: + /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative + /// numbers. + /// - uppercase: Pass `true` to use uppercase letters or `false` to use + /// lowercase letters. The default is `false`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + public static func hybrid( + explicitPositiveSign: Bool = false, + uppercase: Bool = false + ) -> OSLogFloatFormatting { + return OSLogFloatFormatting( + explicitPositiveSign: explicitPositiveSign, + uppercase: uppercase, + precision: nil, + notation: .hybrid + ) + } +} + +extension OSLogFloatFormatting { + /// Returns a fprintf-compatible length modifier for a given argument type + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal static func _formatStringLengthModifier( + _ type: I.Type + ) -> String? { + switch type { + // fprintf formatters promote Float to Double + case is Float.Type: return "" + case is Double.Type: return "" +#if !os(Windows) && (arch(i386) || arch(x86_64)) + // fprintf formatters use L for Float80 + case is Float80.Type: return "L" +#endif + default: return nil + } + } + + /// Constructs an os_log format specifier for the given type `type` + /// using the specified alignment `align` and privacy qualifier `privacy`. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal func formatSpecifier( + for type: I.Type, + align: OSLogStringAlignment, + privacy: OSLogPrivacy + ) -> String { + var specification = "%" + // Add privacy qualifier after % sign within curly braces. This is an + // os log specific flag. + if let privacySpecifier = privacy.privacySpecifier { + specification += "{" + specification += privacySpecifier + specification += "}" + } + + // 1. Flags + // IEEE: `+` The result of a signed conversion shall always begin with a sign + // ( '+' or '-' ) + if explicitPositiveSign { + specification += "+" + } + + // IEEE: `-` The result of the conversion shall be left-justified within the field. + // The conversion is right-justified if this flag is not specified. + if case .start = align.anchor { + specification += "-" + } + + if let _ = align.minimumColumnWidth { + // The alignment could be a dynamic value. Therefore, use a star here and pass it + // as an additional argument. + specification += "*" + } + + if let _ = precision { + specification += ".*" + } + + guard let lengthModifier = + OSLogFloatFormatting._formatStringLengthModifier(type) else { + fatalError("Float type has unknown length") + } + specification += lengthModifier + + // 3. Precision and conversion specifier. + switch notation { + case .fixed: + specification += (uppercase ? "F" : "f") + case .exponential: + specification += (uppercase ? "E" : "e") + case .hybrid: + specification += (uppercase ? "G" : "g") + case .hex: + //guard type.radix == 2 else { return nil } + specification += (uppercase ? "A" : "a") + default: + fatalError("Unknown float notation") + } + return specification + } +} + diff --git a/stdlib/private/OSLog/OSLogFloatingPointTypes.swift b/stdlib/private/OSLog/OSLogFloatingPointTypes.swift index b7616b98215b8..e135911d2380b 100644 --- a/stdlib/private/OSLog/OSLogFloatingPointTypes.swift +++ b/stdlib/private/OSLog/OSLogFloatingPointTypes.swift @@ -17,46 +17,88 @@ // // The `appendInterpolation` functions defined in this file accept privacy // options along with the interpolated expression as shown below: -// TODO: support floating-point formatting options. // -// "\(x, privacy: .private\)" +// "\(x, format: .fixed(precision: 10), privacy: .private\)" extension OSLogInterpolation { - /// Define interpolation for expressions of type Float. + /// Defines interpolation for expressions of type Float. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `Float` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - number: the interpolated expression of type Float, which is autoclosured. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - number: The interpolated expression of type Float, which is autoclosured. + /// - format: A formatting option available for float types, defined by the + /// type`OSLogFloatFormatting`. The default is `.fixed`. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ number: @autoclosure @escaping () -> Float, + format: OSLogFloatFormatting = .fixed, + align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto ) { - appendInterpolation(Double(number()), privacy: privacy) + appendInterpolation( + Double(number()), + format: format, + align: align, + privacy: privacy) } /// Define interpolation for expressions of type Double. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `Double` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - number: the interpolated expression of type Double, which is autoclosured. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - number: The interpolated expression of type Double, which is autoclosured. + /// - format: A formatting option available for float types, defined by the + /// type`OSLogFloatFormatting`. The default is `.fixed`. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ number: @autoclosure @escaping () -> Double, + format: OSLogFloatFormatting = .fixed, + align: OSLogStringAlignment = .none, privacy: OSLogPrivacy = .auto ) { guard argumentCount < maxOSLogArgumentCount else { return } + formatString += + format.formatSpecifier(for: Double.self, align: align, privacy: privacy) - formatString += getDoubleFormatSpecifier(privacy: privacy) - addDoubleHeaders(privacy) + // If minimum column width is specified, append this value first. Note that + // the format specifier would use a '*' for width e.g. %*f. + if let minColumns = align.minimumColumnWidth { + appendAlignmentArgument(minColumns) + } + + // If the privacy has a mask, append the mask argument, which is a constant payload. + // Note that this should come after the width but before the precision. + if privacy.hasMask { + appendMaskArgument(privacy) + } + // If minimum number of digits (precision) is specified, append the + // precision before the argument. Note that the format specifier would use + // a '*' for precision: %.*f. + if let precision = format.precision { + appendPrecisionArgument(precision) + } + // Append the double. + addDoubleHeaders(privacy) arguments.append(number) argumentCount += 1 } @@ -82,29 +124,6 @@ extension OSLogInterpolation { preamble = getUpdatedPreamble(privacy: privacy, isScalar: true) } - - /// Construct an os_log format specifier from the given parameters. - /// This function must be constant evaluable and all its arguments - /// must be known at compile time. - @inlinable - @_semantics("constant_evaluable") - @_effects(readonly) - @_optimize(none) - internal func getDoubleFormatSpecifier(privacy: OSLogPrivacy) -> String { - // TODO: this will become more sophisticated when floating-point formatting - // options are supported. - var specifier = "%" - switch privacy { - case .private: - specifier += "{private}" - case .public: - specifier += "{public}" - default: - break - } - specifier += "f" - return specifier - } } extension OSLogArguments { @@ -115,7 +134,7 @@ extension OSLogArguments { @inlinable @_optimize(none) internal mutating func append(_ value: @escaping () -> Double) { - argumentClosures.append({ (position, _) in + argumentClosures.append({ (position, _, _) in serialize(value(), at: &position) }) } @@ -125,14 +144,13 @@ extension OSLogArguments { /// specified by os_log. Note that this is marked transparent instead of /// @inline(__always) as it is used in optimize(none) functions. @_transparent -@usableFromInline +@_alwaysEmitIntoClient internal func doubleSizeInBytes() -> Int { return 8 } /// Serialize a double at the buffer location that `position` points to and /// increment `position` by the byte size of the double. -@inlinable @_alwaysEmitIntoClient @inline(__always) internal func serialize( @@ -145,3 +163,4 @@ internal func serialize( withUnsafeBytes(of: value) { dest.copyMemory(from: $0) } bufferPosition += byteCount } + diff --git a/stdlib/private/OSLog/OSLogIntegerFormatting.swift b/stdlib/private/OSLog/OSLogIntegerFormatting.swift index 9dc1389efd208..2d9a53563c3bc 100644 --- a/stdlib/private/OSLog/OSLogIntegerFormatting.swift +++ b/stdlib/private/OSLog/OSLogIntegerFormatting.swift @@ -17,23 +17,30 @@ public struct OSLogIntegerFormatting { /// The base to use for the string representation. `radix` must be at least 2 /// and at most 36. The default is 10. - public var radix: Int + @usableFromInline + internal var radix: Int /// When set, a `+` will be printed for all non-negative integers. - public var explicitPositiveSign: Bool + @usableFromInline + internal var explicitPositiveSign: Bool /// When set, a prefix: 0b or 0o or 0x will be added when the radix is 2, 8 or /// 16 respectively. - public var includePrefix: Bool + @usableFromInline + internal var includePrefix: Bool /// Whether to use uppercase letters to represent numerals /// greater than 9 (default is to use lowercase). - public var uppercase: Bool + @usableFromInline + internal var uppercase: Bool /// Minimum number of digits to display. Numbers having fewer digits than /// minDigits will be displayed with leading zeros. - public var minDigits: (() -> Int)? + @usableFromInline + internal var minDigits: (() -> Int)? + /// Initializes all stored properties. + /// /// - Parameters: /// - radix: The base to use for the string representation. `radix` must be /// at least 2 and at most 36. The default is 10. @@ -46,9 +53,8 @@ public struct OSLogIntegerFormatting { /// `false`. /// - minDigits: minimum number of digits to display. Numbers will be /// prefixed with zeros if necessary to meet the minimum. The default is 1. - @_semantics("constant_evaluable") - @inlinable - @_optimize(none) + @_transparent + @usableFromInline internal init( radix: Int = 10, explicitPositiveSign: Bool = false, @@ -56,8 +62,6 @@ public struct OSLogIntegerFormatting { uppercase: Bool = false, minDigits: (() -> Int)? ) { - precondition(radix >= 2 && radix <= 36) - self.radix = radix self.explicitPositiveSign = explicitPositiveSign self.includePrefix = includePrefix @@ -65,11 +69,17 @@ public struct OSLogIntegerFormatting { self.minDigits = minDigits } + /// Displays an interpolated integer as a decimal number with the specified number + /// of digits and an optional sign. + /// + /// The parameter `explicitPositiveSign` must be a boolean literal. The + /// parameter `minDigits` can be an arbitrary expression. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. + /// numbers. /// - minDigits: minimum number of digits to display. Numbers will be - /// prefixed with zeros if necessary to meet the minimum. The default is 1. + /// prefixed with zeros if necessary to meet the minimum. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -83,9 +93,13 @@ public struct OSLogIntegerFormatting { minDigits: minDigits) } + /// Displays an interpolated integer as a decimal number with an optional sign. + /// + /// The parameter `explicitPositiveSign` must be a boolean literal. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. + /// numbers. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -98,22 +112,28 @@ public struct OSLogIntegerFormatting { minDigits: nil) } - /// Default decimal format. + /// Displays an interpolated integer as a decimal number. This is the default format for + /// integers. @_semantics("constant_evaluable") @inlinable @_optimize(none) public static var decimal: OSLogIntegerFormatting { .decimal() } + /// Displays an interpolated unsigned integer as a hexadecimal number with the + /// specified parameters. This formatting option should be used only with unsigned + /// integers. + /// + /// All parameters except `minDigits` should be boolean literals. `minDigits` + /// can be an arbitrary expression. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. - /// - includePrefix: Pass `true` to add a prefix: 0b, 0o, 0x to corresponding - /// radices. Default is `false`. + /// numbers. + /// - includePrefix: Pass `true` to add a prefix 0x. /// - uppercase: Pass `true` to use uppercase letters to represent numerals - /// greater than 9, or `false` to use lowercase letters. The default is - /// `false`. + /// greater than 9, or `false` to use lowercase letters. The default is `false`. /// - minDigits: minimum number of digits to display. Numbers will be - /// prefixed with zeros if necessary to meet the minimum. The default is 1. + /// prefixed with zeros if necessary to meet the minimum. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -131,14 +151,17 @@ public struct OSLogIntegerFormatting { minDigits: minDigits) } + /// Displays an interpolated unsigned integer as a hexadecimal number with the specified + /// parameters. This formatting option should be used only with unsigned integers. + /// + /// All parameters should be boolean literals. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. - /// - includePrefix: Pass `true` to add a prefix: 0b, 0o, 0x to corresponding - /// radices. Default is `false`. + /// numbers. + /// - includePrefix: Pass `true` to add a prefix 0x. /// - uppercase: Pass `true` to use uppercase letters to represent numerals - /// greater than 9, or `false` to use lowercase letters. The default is - /// `false`. + /// greater than 9, or `false` to use lowercase letters. The default is `false`. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -155,22 +178,28 @@ public struct OSLogIntegerFormatting { minDigits: nil) } - /// Default hexadecimal format. + /// Displays an interpolated unsigned integer as a hexadecimal number. + /// This formatting option should be used only with unsigned integers. @_semantics("constant_evaluable") @inlinable @_optimize(none) public static var hex: OSLogIntegerFormatting { .hex() } + /// Displays an interpolated unsigned integer as an octal number with the specified + /// parameters. This formatting option should be used only with unsigned + /// integers. + /// + /// All parameters except `minDigits` should be boolean literals. `minDigits` + /// can be an arbitrary expression. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. - /// - includePrefix: Pass `true` to add a prefix: 0b, 0o, 0x to corresponding - /// radices. Default is `false`. + /// numbers. + /// - includePrefix: Pass `true` to add a prefix 0o. /// - uppercase: Pass `true` to use uppercase letters to represent numerals - /// greater than 9, or `false` to use lowercase letters. The default is - /// `false`. + /// greater than 9, or `false` to use lowercase letters. The default is `false`. /// - minDigits: minimum number of digits to display. Numbers will be - /// prefixed with zeros if necessary to meet the minimum. The default is 1. + /// prefixed with zeros if necessary to meet the minimum. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -188,14 +217,17 @@ public struct OSLogIntegerFormatting { minDigits: minDigits) } + /// Displays an interpolated unsigned integer as an octal number with the specified parameters. + /// This formatting option should be used only with unsigned integers. + /// + /// All parameters must be boolean literals. + /// /// - Parameters: /// - explicitPositiveSign: Pass `true` to add a + sign to non-negative - /// numbers. Default is `false`. - /// - includePrefix: Pass `true` to add a prefix: 0b, 0o, 0x to corresponding - /// radices. Default is `false`. + /// numbers. + /// - includePrefix: Pass `true` to add a prefix 0o. /// - uppercase: Pass `true` to use uppercase letters to represent numerals - /// greater than 9, or `false` to use lowercase letters. The default is - /// `false`. + /// greater than 9, or `false` to use lowercase letters. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -212,7 +244,8 @@ public struct OSLogIntegerFormatting { minDigits: nil) } - /// Default octal format. + /// Displays an interpolated unsigned integer as an octal number. + /// This formatting option should be used only with unsigned integers. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -311,13 +344,10 @@ extension OSLogIntegerFormatting { // Add privacy qualifier after % sign within curly braces. This is an // os log specific flag. - switch privacy { - case .private: - specification += "{private}" - case .public: - specification += "{public}" - default: - break + if let privacySpecifier = privacy.privacySpecifier { + specification += "{" + specification += privacySpecifier + specification += "}" } // diff --git a/stdlib/private/OSLog/OSLogIntegerTypes.swift b/stdlib/private/OSLog/OSLogIntegerTypes.swift index 248e90e90c57a..dc24531648d42 100644 --- a/stdlib/private/OSLog/OSLogIntegerTypes.swift +++ b/stdlib/private/OSLog/OSLogIntegerTypes.swift @@ -24,19 +24,23 @@ extension OSLogInterpolation { - /// Define interpolation for expressions of type Int. + /// Defines interpolation for expressions of type Int. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `Int` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - number: the interpolated expression of type Int, which is autoclosured. - /// - format: a formatting option available for integer types, defined by the - /// type`OSLogIntegerFormatting`. The default is .decimal. - /// - align: left or right alignment with the minimum number of columns as - /// defined by the type `OSLogStringAlignment`. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - number: The interpolated expression of type Int, which is autoclosured. + /// - format: A formatting option available for integer types, defined by the + /// type: `OSLogIntegerFormatting`. The default is `.decimal`. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ number: @autoclosure @escaping () -> Int, format: OSLogIntegerFormatting = .decimal, @@ -46,18 +50,12 @@ extension OSLogInterpolation { appendInteger(number, format: format, align: align, privacy: privacy) } - /// Define interpolation for expressions of type Int32. - /// - Parameters: - /// - number: the interpolated expression of type Int32, which is autoclosured. - /// - format: a formatting option available for integer types, defined by the - /// type `OSLogIntegerFormatting`. - /// - align: left or right alignment with the minimum number of columns as - /// defined by the type `OSLogStringAlignment`. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + // Define appendInterpolation overloads for fixed-size integers. + @_semantics("constant_evaluable") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ number: @autoclosure @escaping () -> Int32, format: OSLogIntegerFormatting = .decimal, @@ -67,19 +65,23 @@ extension OSLogInterpolation { appendInteger(number, format: format, align: align, privacy: privacy) } - /// Define interpolation for expressions of type UInt. + /// Defines interpolation for expressions of type UInt. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `Int` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - number: the interpolated expression of type UInt, which is autoclosured. - /// - format: a formatting option available for integer types, defined by the - /// type `OSLogIntegerFormatting`. - /// - align: left or right alignment with the minimum number of columns as - /// defined by the type `OSLogStringAlignment`. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - number: The interpolated expression of type UInt, which is autoclosured. + /// - format: A formatting option available for integer types, defined by the + /// type `OSLogIntegerFormatting`. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ number: @autoclosure @escaping () -> UInt, format: OSLogIntegerFormatting = .decimal, @@ -104,18 +106,27 @@ extension OSLogInterpolation { guard argumentCount < maxOSLogArgumentCount else { return } formatString += format.formatSpecifier(for: T.self, align: align, privacy: privacy) - // If minimum column width is specified, append this value first. Note that the - // format specifier would use a '*' for width e.g. %*d. + + // If minimum column width is specified, append this value first. Note that + // the format specifier would use a '*' for width e.g. %*d. if let minColumns = align.minimumColumnWidth { - appendPrecisionArgument(minColumns) + appendAlignmentArgument(minColumns) } - // If minimum number of digits (precision) is specified, append the precision before - // the argument. Note that the format specifier would use a '*' for precision: %.*d. + // If the privacy has a mask, append the mask argument, which is a constant payload. + // Note that this should come after the width but before the precision. + if privacy.hasMask { + appendMaskArgument(privacy) + } + + // If minimum number of digits (precision) is specified, append the + // precision before the argument. Note that the format specifier would use + // a '*' for precision: %.*d. if let minDigits = format.minDigits { appendPrecisionArgument(minDigits) } + // Append the integer. addIntHeaders(privacy, sizeForEncoding(T.self)) arguments.append(number) argumentCount += 1 @@ -151,19 +162,57 @@ extension OSLogInterpolation { @inlinable @_optimize(none) internal mutating func appendPrecisionArgument(_ count: @escaping () -> Int) { - // Note that we don't have to update the preamble here. - let argumentHeader = getArgumentHeader(privacy: .auto, type: .count) + appendPrecisionAlignCount( + count, + getArgumentHeader(privacy: .auto, type: .count)) + } + + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal mutating func appendAlignmentArgument(_ count: @escaping () -> Int) { + appendPrecisionAlignCount( + count, + getArgumentHeader(privacy: .auto, type: .scalar)) + } + + // This is made transparent to minimize compile time overheads. The function's + // implementation also uses literals whenever possible for the same reason. + @_transparent + @inlinable + internal mutating func appendPrecisionAlignCount( + _ count: @escaping () -> Int, + _ argumentHeader: UInt8 + ) { arguments.append(argumentHeader) // Append number of bytes needed to serialize the argument. - let byteCount = sizeForEncoding(CInt.self) - arguments.append(UInt8(byteCount)) + arguments.append(4) // Increment total byte size by the number of bytes needed for this // argument, which is the sum of the byte size of the argument and // two bytes needed for the headers. - totalBytesForSerializingArguments += 2 + byteCount + totalBytesForSerializingArguments += 6 // The count is expected to be a CInt. arguments.append({ CInt(count()) }) argumentCount += 1 + // Note that we don't have to update the preamble here. + } + + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal mutating func appendMaskArgument(_ privacy: OSLogPrivacy) { + arguments.append(getArgumentHeader(privacy: .auto, type: .mask)) + // Append number of bytes needed to serialize the mask. Mask is 64 bit payload. + arguments.append(8) + // Increment total byte size by the number of bytes needed for this + // argument, which is the sum of the byte size of the argument and + // two bytes needed for the headers. + totalBytesForSerializingArguments += 10 + // Append the mask value. This is a compile-time constant. + let maskValue = privacy.maskValue + arguments.append({ maskValue }) + argumentCount += 1 + // Note that we don't have to update the preamble here. } } @@ -177,7 +226,7 @@ extension OSLogArguments { internal mutating func append( _ value: @escaping () -> T ) where T: FixedWidthInteger { - argumentClosures.append({ (position, _) in + argumentClosures.append({ (position, _, _) in serialize(value(), at: &position) }) } @@ -188,7 +237,7 @@ extension OSLogArguments { /// it is marked transparent instead of @inline(__always) as it is used in /// optimize(none) functions. @_transparent -@usableFromInline +@_alwaysEmitIntoClient internal func sizeForEncoding( _ type: T.Type ) -> Int where T : FixedWidthInteger { @@ -197,7 +246,6 @@ internal func sizeForEncoding( /// Serialize an integer at the buffer location that `position` points to and /// increment `position` by the byte size of `T`. -@inlinable @_alwaysEmitIntoClient @inline(__always) internal func serialize( diff --git a/stdlib/private/OSLog/OSLogMessage.swift b/stdlib/private/OSLog/OSLogMessage.swift index e49b2a1aa46be..99fd0e0bf3c1f 100644 --- a/stdlib/private/OSLog/OSLogMessage.swift +++ b/stdlib/private/OSLog/OSLogMessage.swift @@ -11,47 +11,31 @@ //===----------------------------------------------------------------------===// // This file contains data structures and helper functions that are used by -// the new OS log APIs. These are prototype implementations and should not be -// used outside of tests. - -/// Privacy qualifiers for indicating the privacy level of the logged data -/// to the logging system. These can be specified in the string interpolation -/// passed to the log APIs. -/// For Example, -/// log.info("Login request from user id \(userid, privacy: .private)") -/// -/// See `OSLogInterpolation.appendInterpolation` definitions for default options -/// for each supported type. -public enum OSLogPrivacy { - case `private` - case `public` - case auto -} +// the new OS log APIs. + +import ObjectiveC /// Maximum number of arguments i.e., interpolated expressions that can /// be used in the string interpolations passed to the log APIs. -/// This limit is imposed by the ABI of os_log. +/// This limit is imposed by the logging system. @_semantics("constant_evaluable") @inlinable @_optimize(none) public var maxOSLogArgumentCount: UInt8 { return 48 } -/// Note that this is marked transparent instead of @inline(__always) as it is -/// used in optimize(none) functions. +// Note that this is marked transparent instead of @inline(__always) as it is +// used in optimize(none) functions. @_transparent -@usableFromInline +@_alwaysEmitIntoClient internal var logBitsPerByte: Int { return 3 } /// Represents a string interpolation passed to the log APIs. /// /// This type converts (through its methods) the given string interpolation into -/// a C-style format string and a sequence of arguments, which is represented -/// by the type `OSLogArguments`. +/// a C-style format string and a sequence of arguments. /// -/// Do not create an instance of this type directly. It is used by the compiler -/// when you pass a string interpolation to the log APIs. -/// Extend this type with more `appendInterpolation` overloads to enable -/// interpolating additional types. +/// - Warning: Do not explicitly refer to this type. It will be implicitly created +/// by the compiler when you pass a string interpolation to the log APIs. @frozen public struct OSLogInterpolation : StringInterpolationProtocol { /// A format string constructed from the given string interpolation to be @@ -82,39 +66,14 @@ public struct OSLogInterpolation : StringInterpolationProtocol { @usableFromInline internal var arguments: OSLogArguments - /// The possible values for the argument flag, as defined by the os_log ABI, - /// which occupies four least significant bits of the first byte of the - /// argument header. The first two bits are used to indicate privacy and - /// the other two are reserved. - @usableFromInline - @frozen - internal enum ArgumentFlag { - case autoFlag - case privateFlag - case publicFlag - - @inlinable - internal var rawValue: UInt8 { - switch self { - case .autoFlag: - return 0 - case .privateFlag: - return 0x1 - case .publicFlag: - return 0x2 - } - } - } - /// The possible values for the argument type, as defined by the os_log ABI, /// which occupies four most significant bits of the first byte of the /// argument header. The rawValue of this enum must be constant evaluable. /// (Note that an auto-generated rawValue is not constant evaluable because /// it cannot be annotated so.) @usableFromInline - @frozen internal enum ArgumentType { - case scalar, count, string, pointer, object + case scalar, count, string, pointer, object, mask @inlinable internal var rawValue: UInt8 { @@ -127,7 +86,9 @@ public struct OSLogInterpolation : StringInterpolationProtocol { return 2 case .pointer: return 3 - case .object: + case .mask: + return 7 + default: //.object return 4 } } @@ -138,25 +99,18 @@ public struct OSLogInterpolation : StringInterpolationProtocol { @usableFromInline internal var preamble: UInt8 - /// Bit mask for setting bits in the peamble. The bits denoted by the bit - /// mask indicate whether there is an argument that is private, and whether - /// there is an argument that is non-scalar: String, NSObject or Pointer. - @usableFromInline - @frozen - internal enum PreambleBitMask { - case privateBitMask - case nonScalarBitMask + /// Denotes the bit that indicates whether there is private argument. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal var privateBitMask: UInt8 { 0x1 } - @inlinable - internal var rawValue: UInt8 { - switch self { - case .privateBitMask: - return 0x1 - case .nonScalarBitMask: - return 0x2 - } - } - } + /// Denotes the bit that indicates whether there is non-scalar argument: + /// String, NSObject or Pointer. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + internal var nonScalarBitMask: UInt8 { 0x2 } /// The second summary byte that denotes the number of arguments, which is /// also the number of interpolated expressions. This will be determined @@ -170,11 +124,24 @@ public struct OSLogInterpolation : StringInterpolationProtocol { @usableFromInline internal var totalBytesForSerializingArguments: Int + /// The number of arguments that are Strings. This count is used to create + /// auxiliary storage meant for extending the lifetime of the string arguments + /// until the log call completes. + @usableFromInline + internal var stringArgumentCount: Int + + /// The number of arguments that are NSObjects. This count is used to create + /// auxiliary storage meant for extending the lifetime of the NSObject + /// arguments until the log call completes. + @usableFromInline + internal var objectArgumentCount: Int + // Some methods defined below are marked @_optimize(none) to prevent inlining // of string internals (such as String._StringGuts) which will interfere with // constant evaluation and folding. Note that these methods will be inlined, // constant evaluated/folded and optimized in the context of a caller. + @_semantics("oslog.interpolation.init") @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -186,6 +153,8 @@ public struct OSLogInterpolation : StringInterpolationProtocol { preamble = 0 argumentCount = 0 totalBytesForSerializingArguments = 0 + stringArgumentCount = 0 + objectArgumentCount = 0 } @_semantics("constant_evaluable") @@ -197,23 +166,6 @@ public struct OSLogInterpolation : StringInterpolationProtocol { /// `appendInterpolation` conformances will be added by extensions to this type. - /// Return true if and only if the parameter is .private. - /// This function must be constant evaluable. - @inlinable - @_semantics("constant_evaluable") - @_effects(readonly) - @_optimize(none) - internal func getArugmentFlag(_ privacy: OSLogPrivacy) -> ArgumentFlag { - switch privacy { - case .public: - return .publicFlag - case .private: - return .privateFlag - default: - return .autoFlag - } - } - /// Compute a byte-sized argument header consisting of flag and type. /// Flag and type take up the least and most significant four bits /// of the header byte, respectively. @@ -226,9 +178,7 @@ public struct OSLogInterpolation : StringInterpolationProtocol { privacy: OSLogPrivacy, type: ArgumentType ) -> UInt8 { - let flag = getArugmentFlag(privacy) - let flagAndType: UInt8 = (type.rawValue &<< 4) | flag.rawValue - return flagAndType + return (type.rawValue &<< 4) | privacy.argumentFlag } /// Compute the new preamble based whether the current argument is private @@ -242,13 +192,11 @@ public struct OSLogInterpolation : StringInterpolationProtocol { isScalar: Bool ) -> UInt8 { var preamble = self.preamble - // Equality comparisions on enums is not yet supported by the constant - // evaluator. - if case .private = privacy { - preamble |= PreambleBitMask.privateBitMask.rawValue + if privacy.isAtleastPrivate { + preamble |= privateBitMask } - if !isScalar { - preamble |= PreambleBitMask.nonScalarBitMask.rawValue + if !isScalar || privacy.hasMask { + preamble |= nonScalarBitMask } return preamble } @@ -258,7 +206,8 @@ extension String { /// Replace all percents "%" in the string by "%%" so that the string can be /// interpreted as a C format string. This function is constant evaluable /// and its semantics is modeled within the evaluator. - public var percentEscapedString: String { + @inlinable + internal var percentEscapedString: String { @_semantics("string.escapePercent.get") @_effects(readonly) @_optimize(none) @@ -270,14 +219,17 @@ extension String { } } +/// Represents a message passed to the log APIs. This type should be created +/// from a string interpolation or a string literal. +/// +/// Do not explicitly refer to this type. It will be implicitly created +/// by the compiler when you pass a string interpolation to the log APIs. @frozen public struct OSLogMessage : ExpressibleByStringInterpolation, ExpressibleByStringLiteral { public let interpolation: OSLogInterpolation - /// Initializer for accepting string interpolations. This function must be - /// constant evaluable. @inlinable @_optimize(none) @_semantics("oslog.message.init_interpolation") @@ -286,8 +238,6 @@ public struct OSLogMessage : self.interpolation = stringInterpolation } - /// Initializer for accepting string literals. This function must be - /// constant evaluable. @inlinable @_optimize(none) @_semantics("oslog.message.init_stringliteral") @@ -298,19 +248,25 @@ public struct OSLogMessage : self.interpolation = s } - /// The byte size of the buffer that will be passed to the C os_log ABI. - /// It will contain the elements of `interpolation.arguments` and the two - /// summary bytes: preamble and argument count. + /// The byte size of the buffer that will be passed to the logging system. @_semantics("constant_evaluable") @inlinable @_optimize(none) public var bufferSize: Int { + // The two additional bytes is for the preamble and argument count. return interpolation.totalBytesForSerializingArguments + 2 } } -public typealias ByteBufferPointer = UnsafeMutablePointer -public typealias StorageObjects = [AnyObject] +@usableFromInline +internal typealias ByteBufferPointer = UnsafeMutablePointer +@usableFromInline +internal typealias ObjectStorage = UnsafeMutablePointer? +@usableFromInline +internal typealias ArgumentClosures = + [(inout ByteBufferPointer, + inout ObjectStorage, + inout ObjectStorage) -> ()] /// A representation of a sequence of arguments and headers (of possibly /// different types) that have to be serialized to a byte buffer. The arguments @@ -326,8 +282,7 @@ internal struct OSLogArguments { /// array of AnyObject to store references to auxiliary storage created during /// serialization. @usableFromInline - internal var argumentClosures: [(inout ByteBufferPointer, - inout StorageObjects) -> ()] + internal var argumentClosures: ArgumentClosures @_semantics("constant_evaluable") @inlinable @@ -342,7 +297,7 @@ internal struct OSLogArguments { @inlinable @_optimize(none) internal mutating func append(_ header: UInt8) { - argumentClosures.append({ (position, _) in + argumentClosures.append({ (position, _, _) in serialize(header, at: &position) }) } @@ -352,7 +307,6 @@ internal struct OSLogArguments { /// Serialize a UInt8 value at the buffer location pointed to by `bufferPosition`, /// and increment the `bufferPosition` with the byte size of the serialized value. -@inlinable @_alwaysEmitIntoClient @inline(__always) internal func serialize( @@ -362,3 +316,43 @@ internal func serialize( bufferPosition[0] = value bufferPosition += 1 } + +// The following code defines helper functions for creating and maintaining +// a buffer for holding a fixed number for instances of a type T. Such buffers +// are used to hold onto NSObjects and Strings that are interpolated in the log +// message until the end of the log call. + +@_alwaysEmitIntoClient +@inline(__always) +internal func createStorage( + capacity: Int, + type: T.Type +) -> ObjectStorage { + return + capacity == 0 ? + nil : + UnsafeMutablePointer.allocate(capacity: capacity) +} + +@_alwaysEmitIntoClient +@inline(__always) +internal func initializeAndAdvance( + _ storageOpt: inout ObjectStorage, + to value: T +) { + // This if statement should get optimized away. + if let storage = storageOpt { + storage.initialize(to: value) + storageOpt = storage.advanced(by: 1) + } +} + +@_alwaysEmitIntoClient +@inline(__always) +internal func destroyStorage(_ storageOpt: ObjectStorage, count: Int) { + // This if statement should get optimized away. + if let storage = storageOpt { + storage.deinitialize(count: count) + storage.deallocate() + } +} diff --git a/stdlib/private/OSLog/OSLogNSObjectType.swift b/stdlib/private/OSLog/OSLogNSObjectType.swift index 3942999a9c682..bcf1c7222f2f4 100644 --- a/stdlib/private/OSLog/OSLogNSObjectType.swift +++ b/stdlib/private/OSLog/OSLogNSObjectType.swift @@ -24,15 +24,18 @@ import ObjectiveC extension OSLogInterpolation { - /// Define interpolation for expressions of type NSObject. + /// Defines interpolation for expressions of type NSObject. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `NSObject` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - argumentObject: the interpolated expression of type NSObject, which is autoclosured. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - argumentObject: The interpolated expression of type NSObject, which is autoclosured. + /// - privacy: A privacy qualifier which is either private or public. It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ argumentObject: @autoclosure @escaping () -> NSObject, privacy: OSLogPrivacy = .auto @@ -40,10 +43,14 @@ extension OSLogInterpolation { guard argumentCount < maxOSLogArgumentCount else { return } formatString += getNSObjectFormatSpecifier(privacy) + // If the privacy has a mask, append the mask argument, which is a constant payload. + if privacy.hasMask { + appendMaskArgument(privacy) + } addNSObjectHeaders(privacy) - arguments.append(argumentObject) argumentCount += 1 + objectArgumentCount += 1 } /// Update preamble and append argument headers based on the parameters of @@ -76,14 +83,14 @@ extension OSLogInterpolation { @_effects(readonly) @_optimize(none) internal func getNSObjectFormatSpecifier(_ privacy: OSLogPrivacy) -> String { - switch privacy { - case .private: - return "%{private}@" - case .public: - return "%{public}@" - default: - return "%@" + var specifier = "%" + if let privacySpecifier = privacy.privacySpecifier { + specifier += "{" + specifier += privacySpecifier + specifier += "}" } + specifier += "@" + return specifier } } @@ -95,20 +102,20 @@ extension OSLogArguments { @inlinable @_optimize(none) internal mutating func append(_ value: @escaping () -> NSObject) { - argumentClosures.append({ (position, _) in - serialize(value(), at: &position) + argumentClosures.append({ (position, objectArguments, _) in + serialize(value(), at: &position, storingObjectsIn: &objectArguments) }) } } /// Serialize an NSObject pointer at the buffer location pointed by /// `bufferPosition`. -@inlinable @_alwaysEmitIntoClient @inline(__always) internal func serialize( _ object: NSObject, - at bufferPosition: inout ByteBufferPointer + at bufferPosition: inout ByteBufferPointer, + storingObjectsIn objectArguments: inout ObjectStorage ) { let byteCount = pointerSizeInBytes(); let dest = @@ -116,9 +123,11 @@ internal func serialize( // Get the address of this NSObject as an UnsafeRawPointer. let objectAddress = Unmanaged.passUnretained(object).toOpaque() // Copy the address into the destination buffer. Note that the input NSObject - // is an interpolated expression and is guaranteed to be alive until the - // os_log ABI call is completed by the implementation. Therefore, passing - // this address to the os_log ABI is safe. + // is kept alive until the os_log ABI call completes by storing in the + // objectArguments. withUnsafeBytes(of: objectAddress) { dest.copyMemory(from: $0) } bufferPosition += byteCount + // This object could be newly created by the auto-closure. Therefore, make + // sure it is alive until the log call completes. + initializeAndAdvance(&objectArguments, to: object) } diff --git a/stdlib/private/OSLog/OSLogPrivacy.swift b/stdlib/private/OSLog/OSLogPrivacy.swift new file mode 100644 index 0000000000000..e0646ed6395b7 --- /dev/null +++ b/stdlib/private/OSLog/OSLogPrivacy.swift @@ -0,0 +1,220 @@ +//===----------------- OSLogPrivacy.swift ---------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// This file defines the APIs for specifying privacy in the log messages and also +// the logic for encoding them in the byte buffer passed to the libtrace library. + +/// Privacy options for specifying privacy level of the interpolated expressions +/// in the string interpolations passed to the log APIs. +@frozen +public struct OSLogPrivacy { + + @usableFromInline + internal enum PrivacyOption { + case `private` + case `public` + case auto + } + + public enum Mask { + /// Applies a salted hashing transformation to an interpolated value to redact it in the logs. + /// + /// Its purpose is to permit the correlation of identical values across multiple log lines + /// without revealing the value itself. + case hash + case none + } + + @usableFromInline + internal var privacy: PrivacyOption + + @usableFromInline + internal var mask: Mask + + @_transparent + @usableFromInline + internal init(privacy: PrivacyOption, mask: Mask) { + self.privacy = privacy + self.mask = mask + } + + /// Sets the privacy level of an interpolated value to public. + /// + /// When the privacy level is public, the value will be displayed + /// normally without any redaction in the logs. + @_semantics("constant_evaluable") + @_optimize(none) + @inlinable + public static var `public`: OSLogPrivacy { + OSLogPrivacy(privacy: .public, mask: .none) + } + + /// Sets the privacy level of an interpolated value to private. + /// + /// When the privacy level is private, the value will be redacted in the logs, + /// subject to the privacy configuration of the logging system. + @_semantics("constant_evaluable") + @_optimize(none) + @inlinable + public static var `private`: OSLogPrivacy { + OSLogPrivacy(privacy: .private, mask: .none) + } + + /// Sets the privacy level of an interpolated value to private and + /// applies a `mask` to the interpolated value to redacted it. + /// + /// When the privacy level is private, the value will be redacted in the logs, + /// subject to the privacy configuration of the logging system. + /// + /// If the value need not be redacted in the logs, its full value is captured as normal. + /// Otherwise (i.e. if the value would be redacted) the `mask` is applied to + /// the argument value and the result of the transformation is recorded instead. + /// + /// - Parameters: + /// - mask: Mask to use with the privacy option. + @_semantics("constant_evaluable") + @_optimize(none) + @inlinable + public static func `private`(mask: Mask) -> OSLogPrivacy { + OSLogPrivacy(privacy: .private, mask: mask) + } + + /// Auto-infers a privacy level for an interpolated value. + /// + /// The system will automatically decide whether the value should + /// be captured fully in the logs or should be redacted. + @_semantics("constant_evaluable") + @_optimize(none) + @inlinable + public static var auto: OSLogPrivacy { + OSLogPrivacy(privacy: .auto, mask: .none) + } + + /// Auto-infers a privacy level for an interpolated value and applies a `mask` + /// to the interpolated value to redacted it when necessary. + /// + /// The system will automatically decide whether the value should + /// be captured fully in the logs or should be redacted. + /// If the value need not be redacted in the logs, its full value is captured as normal. + /// Otherwise (i.e. if the value would be redacted) the `mask` is applied to + /// the argument value and the result of the transformation is recorded instead. + /// + /// - Parameters: + /// - mask: Mask to use with the privacy option. + @_semantics("constant_evaluable") + @_optimize(none) + @inlinable + public static func auto(mask: Mask) -> OSLogPrivacy { + OSLogPrivacy(privacy: .auto, mask: mask) + } + + /// Return an argument flag for the privacy option., as defined by the + /// os_log ABI, which occupies four least significant bits of the first byte of the + /// argument header. The first two bits are used to indicate privacy and + /// the other two are reserved. + @inlinable + @_semantics("constant_evaluable") + @_optimize(none) + internal var argumentFlag: UInt8 { + switch privacy { + case .private: + return 0x1 + case .public: + return 0x2 + default: + return 0 + } + } + + @inlinable + @_semantics("constant_evaluable") + @_optimize(none) + internal var isAtleastPrivate: Bool { + switch privacy { + case .public: + return false + case .auto: + return false + default: + return true + } + } + + @inlinable + @_semantics("constant_evaluable") + @_optimize(none) + internal var needsPrivacySpecifier: Bool { + if case .hash = mask { + return true + } + switch privacy { + case .auto: + return false + default: + return true + } + } + + @inlinable + @_transparent + internal var hasMask: Bool { + if case .hash = mask { + return true + } + return false + } + + /// A 64-bit value obtained by interpreting the mask name as a little-endian unsigned + /// integer. + @inlinable + @_transparent + internal var maskValue: UInt64 { + // Return the value of + // 'h' | 'a' << 8 | 's' << 16 | 'h' << 24 which equals + // 104 | (97 << 8) | (115 << 16) | (104 << 24) + 1752392040 + } + + /// Return an os log format specifier for this `privacy` level. The + /// format specifier goes within curly braces e.g. %{private} in the format + /// string passed to the os log ABI. + @inlinable + @_semantics("constant_evaluable") + @_optimize(none) + internal var privacySpecifier: String? { + let hasMask = self.hasMask + var isAuto = false + if case .auto = privacy { + isAuto = true + } + if isAuto, !hasMask { + return nil + } + var specifier: String + switch privacy { + case .public: + specifier = "public" + case .private: + specifier = "private" + default: + specifier = "" + } + if hasMask { + if !isAuto { + specifier += "," + } + specifier += "mask.hash" + } + return specifier + } +} + diff --git a/stdlib/private/OSLog/OSLogStringAlignment.swift b/stdlib/private/OSLog/OSLogStringAlignment.swift index 05afc4f430964..a93388a9cfef9 100644 --- a/stdlib/private/OSLog/OSLogStringAlignment.swift +++ b/stdlib/private/OSLog/OSLogStringAlignment.swift @@ -13,8 +13,8 @@ // This file defines types and functions for specifying alignment of the // interpolations passed to the os log APIs. -@frozen -public enum OSLogCollectionBound { +@usableFromInline +internal enum OSLogCollectionBound { case start case end } @@ -23,20 +23,24 @@ public enum OSLogCollectionBound { public struct OSLogStringAlignment { /// Minimum number of characters to be displayed. If the value to be printed /// is shorter than this number, the result is padded with spaces. The value - /// is not truncated even if the result is larger.This value need not be a + /// is not truncated even if the result is larger. This value need not be a /// compile-time constant, and is therefore an autoclosure. - public var minimumColumnWidth: (() -> Int)? + @usableFromInline + internal var minimumColumnWidth: (() -> Int)? + /// This captures right/left alignment. - public var anchor: OSLogCollectionBound + @usableFromInline + internal var anchor: OSLogCollectionBound + /// Initiailzes stored properties. + /// /// - Parameters: /// - minimumColumnWidth: Minimum number of characters to be displayed. If the value to be /// printed is shorter than this number, the result is padded with spaces. The value is not truncated /// even if the result is larger. /// - anchor: Use `.end` for right alignment and `.start` for left. - @_semantics("constant_evaluable") - @inlinable - @_optimize(none) + @_transparent + @usableFromInline internal init( minimumColumnWidth: (() -> Int)? = nil, anchor: OSLogCollectionBound = .end @@ -45,29 +49,18 @@ public struct OSLogStringAlignment { self.anchor = anchor } - /// Right alignment formatter. - @_semantics("constant_evaluable") - @inlinable - @_optimize(none) - public static var right: OSLogStringAlignment { - OSLogStringAlignment(anchor: .end) - } - - /// Left alignment formatter. - @_semantics("constant_evaluable") - @inlinable - @_optimize(none) - public static var left: OSLogStringAlignment { - OSLogStringAlignment(anchor: .start) - } - - /// Use default alignment, which is right alignment. + /// Indicates no alignment. @_semantics("constant_evaluable") @inlinable @_optimize(none) - public static var none: OSLogStringAlignment { .right } + public static var none: OSLogStringAlignment { OSLogStringAlignment(anchor: .end) } - /// Right align and display at least`columns` characters. + /// Right align and display at least `columns` characters. + /// + /// The interpolated value would be padded with spaces, if necessary, to + /// meet the specified `columns` characters. + /// + /// - Parameter columns: minimum number of characters to display. @_semantics("constant_evaluable") @inlinable @_optimize(none) @@ -77,7 +70,12 @@ public struct OSLogStringAlignment { OSLogStringAlignment(minimumColumnWidth: columns, anchor: .end) } - /// Left align and display at least`columns` characters. + /// Left align and display at least `columns` characters. + /// + /// The interpolated value would be padded with spaces, if necessary, to + /// meet the specified `columns` characters. + /// + /// - Parameter columns: minimum number of characters to display. @_semantics("constant_evaluable") @inlinable @_optimize(none) diff --git a/stdlib/private/OSLog/OSLogStringTypes.swift b/stdlib/private/OSLog/OSLogStringTypes.swift index 8a90b03c40598..ef0a7961916ec 100644 --- a/stdlib/private/OSLog/OSLogStringTypes.swift +++ b/stdlib/private/OSLog/OSLogStringTypes.swift @@ -14,8 +14,7 @@ // It defines `appendInterpolation` function for String type. It also defines // extensions for serializing strings into the argument buffer passed to // os_log ABIs. Note that os_log requires passing a stable pointer to an -// interpolated string. The SPI: `_convertConstStringToUTF8PointerArgument` -// is used to construct a stable pointer to a (dynamic) string. +// interpolated string. // // The `appendInterpolation` function defined in this file accept privacy and // alignment options along with the interpolated expression as shown below: @@ -25,17 +24,21 @@ extension OSLogInterpolation { - /// Define interpolation for expressions of type String. + /// Defines interpolation for expressions of type String. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `String` in the string interpolations passed to the log APIs. + /// /// - Parameters: - /// - argumentString: the interpolated expression of type String, which is autoclosured. - /// - align: left or right alignment with the minimum number of columns as - /// defined by the type `OSLogStringAlignment`. - /// - privacy: a privacy qualifier which is either private or public. - /// It is auto-inferred by default. + /// - argumentString: The interpolated expression of type String, which is autoclosured. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. @_semantics("constant_evaluable") - @_semantics("oslog.requires_constant_arguments") @inlinable @_optimize(none) + @_semantics("oslog.requires_constant_arguments") public mutating func appendInterpolation( _ argumentString: @autoclosure @escaping () -> String, align: OSLogStringAlignment = .none, @@ -48,12 +51,20 @@ extension OSLogInterpolation { // If minimum column width is specified, append this value first. Note that the // format specifier would use a '*' for width e.g. %*s. if let minColumns = align.minimumColumnWidth { - appendPrecisionArgument(minColumns) + appendAlignmentArgument(minColumns) + } + + // If the privacy has a mask, append the mask argument, which is a constant payload. + // Note that this should come after the width but before the precision. + if privacy.hasMask { + appendMaskArgument(privacy) } + // Append the string argument. addStringHeaders(privacy) arguments.append(argumentString) argumentCount += 1 + stringArgumentCount += 1 } /// Update preamble and append argument headers based on the parameters of @@ -90,13 +101,10 @@ extension OSLogInterpolation { _ privacy: OSLogPrivacy ) -> String { var specifier = "%" - switch privacy { - case .private: - specifier += "{private}" - case .public: - specifier += "{public}" - default: - break + if let privacySpecifier = privacy.privacySpecifier { + specifier += "{" + specifier += privacySpecifier + specifier += "}" } if case .start = align.anchor { specifier += "-" @@ -117,7 +125,12 @@ extension OSLogArguments { @inlinable @_optimize(none) internal mutating func append(_ value: @escaping () -> String) { - argumentClosures.append({ serialize(value(), at: &$0, using: &$1) }) + argumentClosures.append({ (position, _, stringArgumentOwners) in + serialize( + value(), + at: &position, + storingStringOwnersIn: &stringArgumentOwners) + }) } } @@ -129,34 +142,48 @@ extension OSLogArguments { /// This function must be constant evaluable. Note that it is marked transparent /// instead of @inline(__always) as it is used in optimize(none) functions. @_transparent -@usableFromInline +@_alwaysEmitIntoClient internal func pointerSizeInBytes() -> Int { return Int.bitWidth &>> logBitsPerByte } /// Serialize a stable pointer to the string `stringValue` at the buffer location -/// pointed by `bufferPosition`. When necessary, this function would copy the -/// string contents to a storage with a stable pointer. If that happens, a reference -/// to the storage will be added to `storageObjects`. -@inlinable +/// pointed to by `bufferPosition`. @_alwaysEmitIntoClient @inline(__always) internal func serialize( _ stringValue: String, - at bufferPosition: inout ByteBufferPointer, - using storageObjects: inout StorageObjects + at bufferPosition: inout UnsafeMutablePointer, + storingStringOwnersIn stringArgumentOwners: inout ObjectStorage ) { - let (optionalStorage, bytePointer): (AnyObject?, UnsafeRawPointer) = - _convertConstStringToUTF8PointerArgument( - stringValue) - - if let storage = optionalStorage { - storageObjects.append(storage) - } + let stringPointer = + getNullTerminatedUTF8Pointer( + stringValue, + storingStringOwnersIn: &stringArgumentOwners) let byteCount = pointerSizeInBytes() let dest = UnsafeMutableRawBufferPointer(start: bufferPosition, count: byteCount) - withUnsafeBytes(of: bytePointer) { dest.copyMemory(from: $0) } + withUnsafeBytes(of: stringPointer) { dest.copyMemory(from: $0) } bufferPosition += byteCount } + +/// Return a pointer that points to a contiguous sequence of null-terminated, +/// UTF8 charcters. If necessary, extends the lifetime of `stringValue` by +/// using `stringArgumentOwners`. +@_alwaysEmitIntoClient +@inline(never) +internal func getNullTerminatedUTF8Pointer( + _ stringValue: String, + storingStringOwnersIn stringArgumentOwners: inout ObjectStorage +) -> UnsafeRawPointer { + let (optStorage, bytePointer, _, _, _): + (AnyObject?, UnsafeRawPointer, Int, Bool, Bool) = + stringValue._deconstructUTF8(scratch: nil) + if let storage = optStorage { + initializeAndAdvance(&stringArgumentOwners, to: storage) + } else { + initializeAndAdvance(&stringArgumentOwners, to: stringValue._guts) + } + return bytePointer +} diff --git a/stdlib/private/OSLog/OSLogSwiftProtocols.swift b/stdlib/private/OSLog/OSLogSwiftProtocols.swift new file mode 100644 index 0000000000000..f14ee3c99bef8 --- /dev/null +++ b/stdlib/private/OSLog/OSLogSwiftProtocols.swift @@ -0,0 +1,72 @@ +//===----------------- OSLogSwiftProtocols.swift -----------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// This file defines extensions for interpolating types conforming to common +// Swift protocols. It defines `appendInterpolation` overloads for these protocols. +// All overloads defined in this file, delegate to other appendInterpolation +// functions for types natively supported by os_log. + +extension OSLogInterpolation { + + /// Defines interpolation for values conforming to CustomStringConvertible. The values + /// are displayed using the description methods on them. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value conforming to CustomStringConvertible in the string interpolations passed + /// to the log APIs. + /// + /// - Parameters: + /// - value: The interpolated expression conforming to CustomStringConvertible. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. + @_optimize(none) + @_transparent + @_semantics("oslog.requires_constant_arguments") + public mutating func appendInterpolation( + _ value: @autoclosure @escaping () -> T, + align: OSLogStringAlignment = .none, + privacy: OSLogPrivacy = .auto + ) { + // TODO: Dead code elimination does not remove the call to the default value + // of alignment: .none. This function is made @_transparent to work around + // that. + appendInterpolation(value().description, align: align, privacy: privacy) + } + + /// Defines interpolation for meta-types. + /// + /// Do not call this function directly. It will be called automatically when interpolating + /// a value of type `Any.Type` in the string interpolations passed to the log APIs. + /// + /// - Parameters: + /// - value: An interpolated expression of type Any.Type, which is autoclosured. + /// - align: Left or right alignment with the minimum number of columns as + /// defined by the type `OSLogStringAlignment`. + /// - privacy: A privacy qualifier which is either private or public. + /// It is auto-inferred by default. + @_semantics("constant_evaluable") + @inlinable + @_optimize(none) + @_semantics("oslog.requires_constant_arguments") + public mutating func appendInterpolation( + _ value: @autoclosure @escaping () -> Any.Type, + align: OSLogStringAlignment = .none, + privacy: OSLogPrivacy = .auto + ) { + appendInterpolation( + _typeName(value(), qualified: false), + align: align, + privacy: privacy) + } +} diff --git a/stdlib/private/OSLog/OSLogTestHelper.swift b/stdlib/private/OSLog/OSLogTestHelper.swift index 85dde5ca81055..3d6e98dbaaad1 100644 --- a/stdlib/private/OSLog/OSLogTestHelper.swift +++ b/stdlib/private/OSLog/OSLogTestHelper.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import ObjectiveC + // This file contains test helpers for testing the compiler diagnostics and optimizations // of the new swift APIs for os log that accept string interpolations. @@ -51,41 +53,47 @@ func _osLogTestHelper( let preamble = message.interpolation.preamble let argumentCount = message.interpolation.argumentCount let bufferSize = message.bufferSize + let objectCount = message.interpolation.objectArgumentCount + let stringCount = message.interpolation.stringArgumentCount + let uint32bufferSize = UInt32(bufferSize) let argumentClosures = message.interpolation.arguments.argumentClosures + let formatStringPointer = _getGlobalStringTablePointer(formatString) // Code that will execute at runtime. if (!isLoggingEnabled()) { return } - - // Allocate a byte buffer to store the arguments. The buffer could be stack - // allocated as it is local to this function and also its size is a - // compile-time constant. let bufferMemory = UnsafeMutablePointer.allocate(capacity: bufferSize) - // Array of references to auxiliary storage created during serialization of - // strings. This array can be stack allocated. - var stringStorageObjects: [AnyObject] = [] + // Buffer for storing NSObjects and strings to keep them alive until the + // _os_log_impl_test call completes. + let objectArguments = createStorage(capacity: objectCount, type: NSObject.self) + let stringArgumentOwners = createStorage(capacity: stringCount, type: Any.self) var currentBufferPosition = bufferMemory + var objectArgumentsPosition = objectArguments + var stringArgumentOwnersPosition = stringArgumentOwners serialize(preamble, at: ¤tBufferPosition) serialize(argumentCount, at: ¤tBufferPosition) - argumentClosures.forEach { $0(¤tBufferPosition, &stringStorageObjects) } + argumentClosures.forEach { + $0(¤tBufferPosition, + &objectArgumentsPosition, + &stringArgumentOwnersPosition) + } _os_log_impl_test( assertion, formatString, formatStringPointer, bufferMemory, - UInt32(bufferSize)) + uint32bufferSize) - // The following operation extends the lifetime of argumentClosures, - // stringStorageObjects, and also of the objects stored in them, till this - // point. This is necessary because the assertion is passed internal pointers - // to the objects/strings stored in these arrays, as in the actual os log - // implementation. - _fixLifetime(argumentClosures) - _fixLifetime(stringStorageObjects) + // The following operation extends the lifetime of objectArguments and + // stringArgumentOwners till this point. This is necessary because the + // assertion is passed internal pointers to the objects/strings stored + // in these arrays, as in the actual os log implementation. + destroyStorage(objectArguments, count: objectCount) + destroyStorage(stringArgumentOwners, count: stringCount) bufferMemory.deallocate() } diff --git a/test/Frontend/PrivateFingerprints/class-fingerprint.swift b/test/Frontend/PrivateFingerprints/class-fingerprint.swift index 67b29178057e4..e244cc3f123a2 100644 --- a/test/Frontend/PrivateFingerprints/class-fingerprint.swift +++ b/test/Frontend/PrivateFingerprints/class-fingerprint.swift @@ -1,48 +1,6 @@ - // Test per-type-body fingerprints for classes // -// ============================================================================= -// Without the fingerprints -// ============================================================================= - -// Establish status quo - - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/class-fingerprint/* %t -// RUN: cp %t/definesAB{-before,}.swift - -// Seeing weird failure on CI, so set the mod times -// RUN: touch -t 200101010101 %t/*.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output1 - -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// Change one type, but uses of all types get recompiled - -// RUN: cp %t/definesAB{-after,}.swift - -// Seeing weird failure on CI, so ensure that definesAB.swift is newer -// RUN: touch -t 200201010101 %t/* -// RUN: touch -t 200101010101 %t/*.swift -// RUN: touch -t 200301010101 %t/definesAB.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output2 - -// Save for debugging: -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output2 - -// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} -// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} - -// ============================================================================= -// With the fingerprints -// ============================================================================= - // Establish status quo // RUN: %empty-directory(%t) @@ -71,3 +29,6 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 + +// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} +// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} diff --git a/test/Frontend/PrivateFingerprints/enum-fingerprint.swift b/test/Frontend/PrivateFingerprints/enum-fingerprint.swift index 138d16f211a88..a56b2443890a6 100644 --- a/test/Frontend/PrivateFingerprints/enum-fingerprint.swift +++ b/test/Frontend/PrivateFingerprints/enum-fingerprint.swift @@ -1,48 +1,6 @@ - // Test per-type-body fingerprints for enums // -// ============================================================================= -// Without the fingerprints -// ============================================================================= - -// Establish status quo - - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/enum-fingerprint/* %t -// RUN: cp %t/definesAB{-before,}.swift - -// Seeing weird failure on CI, so set the mod times -// RUN: touch -t 200101010101 %t/*.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output1 - -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// Change one type, but uses of all types get recompiled - -// RUN: cp %t/definesAB{-after,}.swift - -// Seeing weird failure on CI, so ensure that definesAB.swift is newer -// RUN: touch -t 200201010101 %t/* -// RUN: touch -t 200101010101 %t/*.swift -// RUN: touch -t 200301010101 %t/definesAB.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output2 - -// Save for debugging: -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output2 - -// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} -// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} - -// ============================================================================= -// With the fingerprints -// ============================================================================= - // Establish status quo // RUN: %empty-directory(%t) @@ -71,3 +29,6 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 + +// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} +// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} diff --git a/test/Frontend/PrivateFingerprints/extension-adds-member.swift b/test/Frontend/PrivateFingerprints/extension-adds-member.swift index 63726480b3c37..73a8e650dd340 100644 --- a/test/Frontend/PrivateFingerprints/extension-adds-member.swift +++ b/test/Frontend/PrivateFingerprints/extension-adds-member.swift @@ -1,56 +1,9 @@ - // Test per-type-body fingerprints using simple extensions // // If the parser is allowed to use a body fingerprint for an extension // this test will fail because usesA.swift won't be recompiled for the // last step. - -// ============================================================================= -// Without the fingerprints -// ============================================================================= - -// Establish status quo - - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/extension-adds-member/* %t -// RUN: cp %t/definesAB{-before,}.swift - -// Seeing weird failure on CI, so set the mod times -// RUN: touch -t 200101010101 %t/*.swift - - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >& %t/output1 - - -// Change one type, but uses of all types get recompiled - -// RUN: cp %t/definesAB{-after,}.swift - -// Seeing weird failure on CI, so ensure that definesAB.swift is newer -// RUN: touch -t 200201010101 %t/* -// RUN: touch -t 200101010101 %t/*.swift -// RUN: touch -t 200301010101 %t/definesAB.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >& %t/output2 - - -// This test checks for the status quo; it would be OK to be more conservative - -// RUN: %FileCheck -check-prefix=CHECK-RECOMPILED-WO %s < %t/output2 -// CHECK-RECOMPILED-WO: {compile: definesAB.o <= definesAB.swift} -// CHECK-RECOMPILED-WO: {compile: usesA.o <= usesA.swift} -// CHECK-RECOMPILED-WO: {compile: usesB.o <= usesB.swift} - -// RUN: %FileCheck -check-prefix=CHECK-NOT-RECOMPILED-WO %s < %t/output2 -// CHECK-NOT-RECOMPILED-WO-NOT: {compile: main.o <= main.swift} - - -// ============================================================================= -// With the fingerprints -// ============================================================================= - // Establish status quo // RUN: %empty-directory(%t) diff --git a/test/Frontend/PrivateFingerprints/protocol-fingerprint.swift b/test/Frontend/PrivateFingerprints/protocol-fingerprint.swift index a48649f0b11ee..10c62c62ed6fb 100644 --- a/test/Frontend/PrivateFingerprints/protocol-fingerprint.swift +++ b/test/Frontend/PrivateFingerprints/protocol-fingerprint.swift @@ -1,48 +1,6 @@ - // Test per-type-body fingerprints: the protocol case. // -// ============================================================================= -// Without the fingerprints -// ============================================================================= - -// Establish status quo - - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/protocol-fingerprint/* %t -// RUN: cp %t/definesAB{-before,}.swift - -// Seeing weird failure on CI, so set the mod times -// RUN: touch -t 200101010101 %t/*.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output1 - -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// Change one type, but uses of all types get recompiled - -// RUN: cp %t/definesAB{-after,}.swift - -// Seeing weird failure on CI, so ensure that definesAB.swift is newer -// RUN: touch -t 200201010101 %t/* -// RUN: touch -t 200101010101 %t/*.swift -// RUN: touch -t 200301010101 %t/definesAB.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output2 - -// Save for debugging: -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output2 - -// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} -// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} - -// ============================================================================= -// With the fingerprints -// ============================================================================= - // Establish status quo // RUN: %empty-directory(%t) @@ -71,3 +29,6 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 + +// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} +// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} diff --git a/test/Frontend/PrivateFingerprints/struct-fingerprint.swift b/test/Frontend/PrivateFingerprints/struct-fingerprint.swift index a02cef5fd649e..1010e8fcc7eb2 100644 --- a/test/Frontend/PrivateFingerprints/struct-fingerprint.swift +++ b/test/Frontend/PrivateFingerprints/struct-fingerprint.swift @@ -1,48 +1,6 @@ - // Test per-type-body fingerprints for structs // -// ============================================================================= -// Without the fingerprints -// ============================================================================= - -// Establish status quo - - -// RUN: %empty-directory(%t) -// RUN: cp %S/Inputs/struct-fingerprint/* %t -// RUN: cp %t/definesAB{-before,}.swift - -// Seeing weird failure on CI, so set the mod times -// RUN: touch -t 200101010101 %t/*.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output1 - -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// Change one type, but uses of all types get recompiled - -// RUN: cp %t/definesAB{-after,}.swift - -// Seeing weird failure on CI, so ensure that definesAB.swift is newer -// RUN: touch -t 200201010101 %t/* -// RUN: touch -t 200101010101 %t/*.swift -// RUN: touch -t 200301010101 %t/definesAB.swift - -// RUN: cd %t && %target-swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental main.swift definesAB.swift usesA.swift usesB.swift -module-name main -output-file-map ofm.json >&output2 - -// Save for debugging: -// only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB1.swiftdeps - -// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output2 - -// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} -// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} - -// ============================================================================= -// With the fingerprints -// ============================================================================= - // Establish status quo // RUN: %empty-directory(%t) @@ -71,3 +29,6 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 + +// CHECK-MAINAB-RECOMPILED: Queuing (initial): {compile: definesAB.o <= definesAB.swift} +// CHECK-MAINAB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} diff --git a/test/Incremental/Dependencies/reference-dependencies-fine.swift b/test/Incremental/Dependencies/reference-dependencies-fine.swift index 3c76ee51fa7a1..e2fba6628bf13 100644 --- a/test/Incremental/Dependencies/reference-dependencies-fine.swift +++ b/test/Incremental/Dependencies/reference-dependencies-fine.swift @@ -5,10 +5,9 @@ // RUN: %empty-directory(%t) // RUN: cp %s %t/main.swift -// Need -fine-grained-dependency-include-intrafile to be invarient wrt type-body-fingerprints enabled/disabled -// RUN: %target-swift-frontend -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps // Check that the output is deterministic. -// RUN: %target-swift-frontend -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps +// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps +// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps // Merge each entry onto one line and sort to overcome order differences // RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh %swift-dependency-tool %t.swiftdeps %t-processed.swiftdeps diff --git a/test/Incremental/Dependencies/reference-dependencies-members-fine.swift b/test/Incremental/Dependencies/reference-dependencies-members-fine.swift index 01e06c2dc6cb7..0fec187e1d91d 100644 --- a/test/Incremental/Dependencies/reference-dependencies-members-fine.swift +++ b/test/Incremental/Dependencies/reference-dependencies-members-fine.swift @@ -5,10 +5,9 @@ // RUN: %empty-directory(%t) // RUN: cp %s %t/main.swift -// Need -fine-grained-dependency-include-intrafile to be invarient wrt type-body-fingerprints enabled/disabled -// RUN: %target-swift-frontend -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps +// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps -// RUN: %target-swift-frontend -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps +// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/../Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps // RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh %swift-dependency-tool %t.swiftdeps %t-processed.swiftdeps // RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh %swift-dependency-tool %t-2.swiftdeps %t-2-processed.swiftdeps diff --git a/test/InterfaceHash/added_method-type-fingerprints.swift b/test/InterfaceHash/added_method-type.swift similarity index 86% rename from test/InterfaceHash/added_method-type-fingerprints.swift rename to test/InterfaceHash/added_method-type.swift index 6776e086a7559..0f7eb261f21b3 100644 --- a/test/InterfaceHash/added_method-type-fingerprints.swift +++ b/test/InterfaceHash/added_method-type.swift @@ -8,10 +8,10 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s // RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps // RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main // RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps // RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs diff --git a/test/InterfaceHash/added_method.swift b/test/InterfaceHash/added_method.swift deleted file mode 100644 index 28dd75f2d4329..0000000000000 --- a/test/InterfaceHash/added_method.swift +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash - -// BEGIN a.swift -class C { - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -class C { - func f2() -> Int { - return 0 - } - - func f3() -> Int { - return 1 - } -} diff --git a/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift deleted file mode 100644 index 5ba9627ce2731..0000000000000 --- a/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift +++ /dev/null @@ -1,53 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -private class C { - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -private class C { - func f2() -> Int { - return 0 - } - - private var x: Int = 0 -} - -// Since C is a type or extension, the interface hash ought to not get the -// changed token hash. - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_class_private_property.swift b/test/InterfaceHash/added_private_class_private_property.swift index e3ca285b2cb10..dfa6721eface6 100644 --- a/test/InterfaceHash/added_private_class_private_property.swift +++ b/test/InterfaceHash/added_private_class_private_property.swift @@ -1,8 +1,17 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift private class C { @@ -19,3 +28,26 @@ private class C { private var x: Int = 0 } + +// Since C is a type or extension, the interface hash ought to not get the +// changed token hash. + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_class_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_property-type-fingerprints.swift deleted file mode 100644 index d087848dd323f..0000000000000 --- a/test/InterfaceHash/added_private_class_property-type-fingerprints.swift +++ /dev/null @@ -1,53 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -class C { - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -class C { - func f2() -> Int { - return 0 - } - - private var x: Int = 0 -} - -// Since C is a type or extension, the interface hash ought to not get the -// changed token hash. - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_class_property.swift b/test/InterfaceHash/added_private_class_property.swift index cdeb03d8944a7..1734f85565ef4 100644 --- a/test/InterfaceHash/added_private_class_property.swift +++ b/test/InterfaceHash/added_private_class_property.swift @@ -1,8 +1,17 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift class C { @@ -19,3 +28,26 @@ class C { private var x: Int = 0 } + +// Since C is a type or extension, the interface hash ought to not get the +// changed token hash. + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift deleted file mode 100644 index ed898ffdce3d1..0000000000000 --- a/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift +++ /dev/null @@ -1,56 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - - -// BEGIN a.swift -private enum A { - case x, y - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -private enum A { - case x, y - func f2() -> Int { - return 0 - } - - var foo: Int { return 0 } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_private_property.swift b/test/InterfaceHash/added_private_enum_private_property.swift index a35d20b2928d0..078b78eef37ca 100644 --- a/test/InterfaceHash/added_private_enum_private_property.swift +++ b/test/InterfaceHash/added_private_enum_private_property.swift @@ -1,8 +1,21 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + // BEGIN a.swift private enum A { @@ -21,3 +34,23 @@ private enum A { var foo: Int { return 0 } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift deleted file mode 100644 index 0589feefd6214..0000000000000 --- a/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift +++ /dev/null @@ -1,55 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -enum A { - case x, y - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -enum A { - case x, y - func f2() -> Int { - return 0 - } - - private var foo: Int { return 0 } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_property.swift b/test/InterfaceHash/added_private_enum_property.swift index 370272d91d251..5993da28a924c 100644 --- a/test/InterfaceHash/added_private_enum_property.swift +++ b/test/InterfaceHash/added_private_enum_property.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift enum A { @@ -21,3 +33,23 @@ enum A { private var foo: Int { return 0 } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method-type-fingerprints.swift b/test/InterfaceHash/added_private_method-type-fingerprints.swift deleted file mode 100644 index f6b8236e94b64..0000000000000 --- a/test/InterfaceHash/added_private_method-type-fingerprints.swift +++ /dev/null @@ -1,55 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -class C { - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -class C { - func f2() -> Int { - return 0 - } - - private func f3() -> Int { - return 1 - } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method.swift b/test/InterfaceHash/added_private_method.swift index a07bed690cf16..77dcb2b0d2f68 100644 --- a/test/InterfaceHash/added_private_method.swift +++ b/test/InterfaceHash/added_private_method.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift class C { @@ -21,3 +33,23 @@ class C { return 1 } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift b/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift deleted file mode 100644 index 8499fbd0ea835..0000000000000 --- a/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift +++ /dev/null @@ -1,88 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -struct A { - func f2() -> Int { - return 0 - } -} - -enum B { - case x, y - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -struct A { - func f2() -> Int { - return 0 - } - - private func f3() -> Int { - return 1 - } -} - -enum B { - case x, y - func f2() -> Int { - return 0 - } - - private func f3() -> Int { - return 1 - } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' B true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' B true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' B true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' B true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1B{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1B{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1B{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method_value_types.swift b/test/InterfaceHash/added_private_method_value_types.swift index 29ff2314d0c1e..e685f9da9afcd 100644 --- a/test/InterfaceHash/added_private_method_value_types.swift +++ b/test/InterfaceHash/added_private_method_value_types.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift struct A { @@ -39,3 +51,38 @@ enum B { return 1 } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' B true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1B{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1B{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift deleted file mode 100644 index f029cdb8b803d..0000000000000 --- a/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift +++ /dev/null @@ -1,50 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -private protocol P { - func f2() -> Int - var y: Int { get set } -} - -// BEGIN b.swift -private protocol P { - func f2() -> Int - func f3() -> Int - var y: Int { get set } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_method.swift b/test/InterfaceHash/added_private_protocol_method.swift index 965c82b67af79..d7a03ef2dedd1 100644 --- a/test/InterfaceHash/added_private_protocol_method.swift +++ b/test/InterfaceHash/added_private_protocol_method.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift private protocol P { @@ -16,3 +28,23 @@ private protocol P { func f3() -> Int var y: Int { get set } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift deleted file mode 100644 index 4a51a0df7957b..0000000000000 --- a/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift +++ /dev/null @@ -1,50 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -private protocol P { - func f2() -> Int - var y: Int { get set } -} - -// BEGIN b.swift -private protocol P { - func f2() -> Int - var x: Int { get set } - var y: Int { get set } -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_property.swift b/test/InterfaceHash/added_private_protocol_property.swift index f47353d2d6521..ce76fffde3ff9 100644 --- a/test/InterfaceHash/added_private_protocol_property.swift +++ b/test/InterfaceHash/added_private_protocol_property.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift private protocol P { @@ -16,3 +28,23 @@ private protocol P { var x: Int { get set } var y: Int { get set } } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift deleted file mode 100644 index b5d20cf3b317c..0000000000000 --- a/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift +++ /dev/null @@ -1,56 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -struct S { - func f2() -> Int { - return 0 - } - - var y: Int = 0 -} - -// BEGIN b.swift -struct S { - func f2() -> Int { - return 0 - } - - private var x: Int = 0 - var y: Int = 0 -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_private_property.swift b/test/InterfaceHash/added_private_struct_private_property.swift index 7bba778652d58..94efb4498aa36 100644 --- a/test/InterfaceHash/added_private_struct_private_property.swift +++ b/test/InterfaceHash/added_private_struct_private_property.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift struct S { @@ -22,3 +34,23 @@ struct S { private var x: Int = 0 var y: Int = 0 } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift deleted file mode 100644 index f27418b9036ff..0000000000000 --- a/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift +++ /dev/null @@ -1,56 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs - -// BEGIN a.swift -private struct S { - func f2() -> Int { - return 0 - } - - var y: Int = 0 -} - -// BEGIN b.swift -private struct S { - func f2() -> Int { - return 0 - } - - var x: Int = 0 - var y: Int = 0 -} - -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH -// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT - -// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true - -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true -// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_property.swift b/test/InterfaceHash/added_private_struct_property.swift index 49e58b356b684..82611277f8d1c 100644 --- a/test/InterfaceHash/added_private_struct_property.swift +++ b/test/InterfaceHash/added_private_struct_property.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: not cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs // BEGIN a.swift private struct S { @@ -22,3 +34,23 @@ private struct S { var x: Int = 0 var y: Int = 0 } + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/edited_method_body-type-fingerprints.swift b/test/InterfaceHash/edited_method_body-type-fingerprints.swift deleted file mode 100644 index 726a36d8ba931..0000000000000 --- a/test/InterfaceHash/edited_method_body-type-fingerprints.swift +++ /dev/null @@ -1,31 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: cmp %t/{a,b}-processed.swiftdeps - -// BEGIN a.swift -class C { - func f2() -> Int { - return 0 - } -} - -// BEGIN b.swift -class C { - func f2() -> Int { - return 1 - } -} diff --git a/test/InterfaceHash/edited_method_body.swift b/test/InterfaceHash/edited_method_body.swift index b0aebce44e500..016a835646d1a 100644 --- a/test/InterfaceHash/edited_method_body.swift +++ b/test/InterfaceHash/edited_method_body.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: cmp %t/{a,b}-processed.swiftdeps // BEGIN a.swift class C { diff --git a/test/InterfaceHash/edited_property_getter-type-fingerprints.swift b/test/InterfaceHash/edited_property_getter-type-fingerprints.swift deleted file mode 100644 index 9024944bd865c..0000000000000 --- a/test/InterfaceHash/edited_property_getter-type-fingerprints.swift +++ /dev/null @@ -1,33 +0,0 @@ -// REQUIRES: shell -// Also uses awk: -// XFAIL OS=windows - -// When adding a private protocol method, the interface hash should stay the same -// The per-type fingerprint should change - -// RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s -// RUN: cp %t/{a,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps -// RUN: cp %t/{b,x}.swift -// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main -// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps - -// RUN: cmp %t/{a,b}-processed.swiftdeps - -// BEGIN a.swift -class C { - var p: Int { - return 0 - } -} - -// BEGIN b.swift -class C { - var p: Int { - let x = 1 - return x - } -} - diff --git a/test/InterfaceHash/edited_property_getter.swift b/test/InterfaceHash/edited_property_getter.swift index deaeb8ccc08dc..05d99baac6493 100644 --- a/test/InterfaceHash/edited_property_getter.swift +++ b/test/InterfaceHash/edited_property_getter.swift @@ -1,8 +1,20 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash -// RUN: cmp %t/a.hash %t/b.hash +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh %swift-dependency-tool %t/x.swiftdeps %t/b-processed.swiftdeps + +// RUN: cmp %t/{a,b}-processed.swiftdeps // BEGIN a.swift class C { @@ -18,3 +30,4 @@ class C { return x } } + diff --git a/test/NameLookup/edge-cases.swift b/test/NameLookup/edge-cases.swift new file mode 100644 index 0000000000000..cc0798480b43c --- /dev/null +++ b/test/NameLookup/edge-cases.swift @@ -0,0 +1,21 @@ +// RUN: %target-typecheck-verify-swift -disable-parser-lookup + +struct A {} +struct B {} + +func other() -> A {} + +func takesB(_: B) {} + +func multipleLocalResults1() { + func other() -> B {} + let result = other() + takesB(result) +} + +func multipleLocalResults2() { + func other() -> B {} + let result = other() + takesB(result) + let other: Int = 123 // expected-warning {{never used}} +} diff --git a/test/NameLookup/scope_map_top_level.swift b/test/NameLookup/scope_map_top_level.swift index eeee236dae731..014c920862e53 100644 --- a/test/NameLookup/scope_map_top_level.swift +++ b/test/NameLookup/scope_map_top_level.swift @@ -31,8 +31,8 @@ var i: Int = b.my_identity() // CHECK-EXPANDED-NEXT: `-NominalTypeBodyScope {{.*}}, [4:11 - 4:13] // CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [6:1 - 21:28] // CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [6:1 - 21:28] -// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [6:5 - 21:28] entry 0 'a' -// CHECK-EXPANDED-NEXT: |-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a' +// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [6:5 - 6:15] entry 0 'a' +// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [6:15 - 6:15] entry 0 'a' // CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [8:1 - 21:28] // CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [8:1 - 21:28] // CHECK-EXPANDED-NEXT: `-GuardStmtScope {{.*}}, [8:1 - 21:28] @@ -46,9 +46,9 @@ var i: Int = b.my_identity() // CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [11:18 - 11:19] // CHECK-EXPANDED-NEXT: `-TopLevelCodeScope {{.*}}, [13:1 - 21:28] // CHECK-EXPANDED-NEXT: `-BraceStmtScope {{.*}}, [13:1 - 21:28] -// CHECK-EXPANDED-NEXT: `-PatternEntryDeclScope {{.*}}, [13:5 - 21:28] entry 0 'c' -// CHECK-EXPANDED-NEXT: |-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c' -// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15] +// CHECK-EXPANDED-NEXT: |-PatternEntryDeclScope {{.*}}, [13:5 - 13:9] entry 0 'c' +// CHECK-EXPANDED-NEXT: `-PatternEntryInitializerScope {{.*}}, [13:9 - 13:9] entry 0 'c' +// CHECK-EXPANDED-NEXT: |-TypeAliasDeclScope {{.*}}, [15:1 - 15:15] // CHECK-EXPANDED-NEXT: |-ExtensionDeclScope {{.*}}, [17:14 - 19:1] // CHECK-EXPANDED-NEXT: `-ExtensionBodyScope {{.*}}, [17:15 - 19:1] // CHECK-EXPANDED-NEXT: `-AbstractFunctionDeclScope {{.*}}, [18:3 - 18:43] 'my_identity()' diff --git a/test/SILOptimizer/Inputs/OSLogConstantEvaluable.swift b/test/SILOptimizer/Inputs/OSLogConstantEvaluable.swift index f7a563f29582f..2207ea86c0c0b 100644 --- a/test/SILOptimizer/Inputs/OSLogConstantEvaluable.swift +++ b/test/SILOptimizer/Inputs/OSLogConstantEvaluable.swift @@ -45,3 +45,8 @@ func intValueWithPrecisionTest() -> OSLogMessage { \(10, format: .decimal(minDigits: 25), align: .right(columns: 10)) """ } + +@_semantics("test_driver") +func intValueWithPrivacyTest() -> OSLogMessage { + return "An integer value \(10, privacy: .private(mask: .hash))" +} diff --git a/test/SILOptimizer/OSLogFullOptTest.swift b/test/SILOptimizer/OSLogFullOptTest.swift index 8cc72d891f5e1..2d7a9b6812383 100644 --- a/test/SILOptimizer/OSLogFullOptTest.swift +++ b/test/SILOptimizer/OSLogFullOptTest.swift @@ -21,10 +21,6 @@ func testSimpleInterpolation() { // CHECK: tail call swiftcc i1 @"${{.*}}isLoggingEnabled{{.*}}"() // CHECK-NEXT: br i1 {{%.*}}, label %[[ENABLED:[0-9]+]], label %[[NOT_ENABLED:[0-9]+]] - // CHECK: [[NOT_ENABLED]]: - // CHECK-NEXT: tail call void @swift_release - // CHECK-NEXT: ret void - // CHECK: [[ENABLED]]: // // Header bytes. @@ -51,6 +47,10 @@ func testSimpleInterpolation() { // CHECK-32-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @{{.*}}, i32 0, i32 0), i8* {{(nonnull )?}}[[BUFFER]], i32 8) // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[BUFFER]] // CHECK-NEXT: br label %[[NOT_ENABLED]] + + // CHECK: [[NOT_ENABLED]]: + // CHECK-NEXT: tail call void @swift_release + // CHECK-NEXT: ret void } // CHECK-LABEL: define hidden swiftcc void @"${{.*}}testInterpolationWithMultipleArguments @@ -135,18 +135,15 @@ func testNSObjectInterpolation(nsArray: NSArray) { // CHECK-NEXT: tail call void @llvm.objc.release // CHECK-NEXT: br label %[[EXIT:[0-9]+]] - // CHECK: [[EXIT]]: - // CHECK-NEXT: tail call void @llvm.objc.release(i8* [[NSARRAY_ARG]]) - // CHECK-NEXT: tail call void @swift_release - // CHECK-NEXT: ret void - // CHECK: [[ENABLED]]: // // Header bytes. // // CHECK-64: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i64 12 // CHECK-32: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i32 8 - // CHECK-NEXT: store i8 2, i8* [[BUFFER]], align 1 + // CHECK-64: [[OBJ_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i64 8 + // CHECK-32: [[OBJ_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i32 4 + // CHECK: store i8 2, i8* [[BUFFER]], align 1 // CHECK-NEXT: [[OFFSET1:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 1 // CHECK-NEXT: store i8 1, i8* [[OFFSET1]], align 1 // @@ -157,18 +154,29 @@ func testNSObjectInterpolation(nsArray: NSArray) { // CHECK-NEXT: [[OFFSET3:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 3 // CHECK-64-NEXT: store i8 8, i8* [[OFFSET3]], align 1 // CHECK-32-NEXT: store i8 4, i8* [[OFFSET3]], align 1 - // CHECK-NEXT: tail call void @llvm.objc.release // CHECK-NEXT: bitcast %swift.refcounted* %{{.*}} to %swift.opaque* // CHECK-NEXT: [[OFFSET4:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 4 // CHECK-NEXT: [[BITCASTED_DEST:%.+]] = bitcast i8* [[OFFSET4]] to %TSo7NSArrayC** // CHECK-NEXT: [[BITCASTED_SRC:%.+]] = bitcast i8* [[NSARRAY_ARG]] to %TSo7NSArrayC* // CHECK-NEXT: store %TSo7NSArrayC* [[BITCASTED_SRC]], %TSo7NSArrayC** [[BITCASTED_DEST]], align 1 + // CHECK-NEXT: [[BITCASTED_DEST2:%.+]] = bitcast i8* [[OBJ_STORAGE]] to %TSo7NSArrayC** + // CHECK-NEXT: [[BITCASTED_SRC2:%.+]] = bitcast i8* [[NSARRAY_ARG]] to %TSo7NSArrayC* + // CHECK-64-NEXT: store %TSo7NSArrayC* [[BITCASTED_SRC2]], %TSo7NSArrayC** [[BITCASTED_DEST2]], align 8 + // CHECK-32-NEXT: store %TSo7NSArrayC* [[BITCASTED_SRC2]], %TSo7NSArrayC** [[BITCASTED_DEST2]], align 4 // CHECK-64-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @{{.*}}, i64 0, i64 0), i8* {{(nonnull )?}}[[BUFFER]], i32 12) // CHECK-32-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @{{.*}}, i32 0, i32 0), i8* {{(nonnull )?}}[[BUFFER]], i32 8) + // CHECK-NEXT: [[BITCASTED_OBJ_STORAGE:%.+]] = bitcast i8* [[OBJ_STORAGE]] to %swift.opaque* + // CHECK-NEXT: tail call void @swift_arrayDestroy(%swift.opaque* [[BITCASTED_OBJ_STORAGE]] + // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[OBJ_STORAGE]] // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[BUFFER]] // CHECK-NEXT: tail call void @swift_release // CHECK-NEXT: br label %[[EXIT]] + + // CHECK: [[EXIT]]: + // CHECK-NEXT: tail call void @llvm.objc.release(i8* [[NSARRAY_ARG]]) + // CHECK-NEXT: tail call void @swift_release + // CHECK-NEXT: ret void } // CHECK-LABEL: define hidden swiftcc void @"${{.*}}testFloatInterpolation @@ -178,10 +186,6 @@ func testFloatInterpolation(doubleValue: Double) { // CHECK: tail call swiftcc i1 @"${{.*}}isLoggingEnabled{{.*}}"() // CHECK-NEXT: br i1 {{%.*}}, label %[[ENABLED:[0-9]+]], label %[[NOT_ENABLED:[0-9]+]] - // CHECK: [[NOT_ENABLED]]: - // CHECK-NEXT: tail call void @swift_release - // CHECK-NEXT: ret void - // CHECK: [[ENABLED]]: // // Header bytes. @@ -204,6 +208,10 @@ func testFloatInterpolation(doubleValue: Double) { // CHECK-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @{{.*}}, i{{.*}} 0, i{{.*}} 0), i8* {{(nonnull )?}}[[BUFFER]], i32 12) // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[BUFFER]] // CHECK-NEXT: br label %[[NOT_ENABLED]] + + // CHECK: [[NOT_ENABLED]]: + // CHECK-NEXT: tail call void @swift_release + // CHECK-NEXT: ret void } // This test checks that the precision and alignment are optimally "stored" into the @@ -235,7 +243,7 @@ func testDynamicPrecisionAndAlignment() { // First argument bytes. // // CHECK-NEXT: [[OFFSET2:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 2 - // CHECK-NEXT: store i8 16, i8* [[OFFSET2]], align 1 + // CHECK-NEXT: store i8 0, i8* [[OFFSET2]], align 1 // CHECK-NEXT: [[OFFSET3:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 3 // CHECK-NEXT: store i8 4, i8* [[OFFSET3]], align 1 // CHECK-NEXT: [[OFFSET4:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 4 @@ -269,5 +277,110 @@ func testDynamicPrecisionAndAlignment() { // CHECK-NEXT: br label %[[NOT_ENABLED]] } -// TODO: add test for String. It is more complicated due to more complex logic -// in string serialization. +// CHECK-LABEL: define hidden swiftcc void @"${{.*}}testStringInterpolation +func testStringInterpolation(stringValue: String) { + _osLogTestHelper("String value: \(stringValue)") + // CHECK: entry: + // CHECK-64: call %swift.bridge* @swift_bridgeObjectRetain_n(%swift.bridge* %1 + // CHECK-32: tail call void @"$ss13_StringObjectV7VariantOWOy"(i32 %1 + // CHECK-32-NEXT: tail call void @"$ss13_StringObjectV7VariantOWOy"(i32 %1 + // CHECK: tail call swiftcc i1 @"${{.*}}isLoggingEnabled{{.*}}"() + // CHECK-NEXT: br i1 {{%.*}}, label %[[ENABLED:[0-9]+]], label %[[NOT_ENABLED:[0-9]+]] + + // CHECK: [[NOT_ENABLED]]: + // CHECK-64: call void @swift_bridgeObjectRelease_n(%swift.bridge* %1 + // CHECK-32: tail call void @"$ss13_StringObjectV7VariantOWOe"(i32 %1 + // CHECK-32-NEXT: tail call void @"$ss13_StringObjectV7VariantOWOe"(i32 %1 + // CHECK: br label %[[EXIT:[0-9]+]] + + // CHECK: [[ENABLED]]: + // + // Header bytes. + // + // CHECK-64: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 12 + // CHECK-32: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 8 + // CHECK-64-NEXT: [[STR_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 32 + // CHECK-32-NEXT: [[STR_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 16 + // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, i8* {{(nonnull )?}}[[STR_STORAGE_PTR:%.*]] + // CHECK: store i8 2, i8* [[BUFFER]], align 1 + // CHECK-NEXT: [[OFFSET1:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 1 + // CHECK-NEXT: store i8 1, i8* [[OFFSET1]], align 1 + + // Argument bytes. + // + // CHECK-NEXT: [[OFFSET2:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 2 + // CHECK-NEXT: store i8 32, i8* [[OFFSET2]], align 1 + // CHECK-NEXT: [[OFFSET3:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 3 + // CHECK-64-NEXT: store i8 8, i8* [[OFFSET3]], align 1 + // CHECK-32-NEXT: store i8 4, i8* [[OFFSET3]], align 1 + + // CHECK: [[STR_POINTER:%.*]] = call swiftcc i8* @"${{.*}}getNullTerminatedUTF8Pointer{{.*}}"(i{{.*}} %0, {{.*}} %1 + + // CHECK: [[OFFSET_BUFFER:%.*]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 4 + // CHECK-NEXT: [[OFFSET_BUFFER_PTR:%.*]] = bitcast i8* [[OFFSET_BUFFER]] to i8** + // CHECK-NEXT: store i8* [[STR_POINTER]], i8** [[OFFSET_BUFFER_PTR]] + + // os_log_impl call. + // CHECK-64-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @{{.*}}, i64 0, i64 0), i8* {{(nonnull )?}}[[BUFFER]], i32 12) + // CHECK-32-NEXT: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @{{.*}}, i32 0, i32 0), i8* {{(nonnull )?}}[[BUFFER]], i32 8) + // CHECK-NEXT: [[BITCASTED_STR_STORAGE:%.*]] = bitcast i8* [[STR_STORAGE]] to %swift.opaque* + // CHECK-NEXT: tail call void @swift_arrayDestroy(%swift.opaque* [[BITCASTED_STR_STORAGE]] + // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[STR_STORAGE]] + // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[BUFFER]] + // CHECK: call void @llvm.lifetime.end{{.*}}({{.*}}, i8* {{(nonnull )?}}[[STR_STORAGE_PTR]] + // CHECK-NEXT: br label %[[EXIT]] + + // CHECK: [[EXIT]]: + // CHECK-NEXT: ret void +} + +// CHECK-LABEL: define hidden swiftcc void @"${{.*}}testMetatypeInterpolation +func testMetatypeInterpolation(of type: T.Type) { + _osLogTestHelper("Metatype value: \(type)") + // CHECK: entry: + // CHECK: tail call swiftcc i1 @"${{.*}}isLoggingEnabled{{.*}}"() + // CHECK-NEXT: br i1 {{%.*}}, label %[[ENABLED:[0-9]+]], label %[[NOT_ENABLED:[0-9]+]] + + // CHECK: [[NOT_ENABLED]]: + // CHECK-NEXT: call void @swift_release + // CHECK-NEXT: br label %[[EXIT:[0-9]+]] + + // CHECK: [[ENABLED]]: + // + // Header bytes. + // + // CHECK-64: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 12 + // CHECK-32: [[BUFFER:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 8 + // CHECK-64-NEXT: [[STR_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 32 + // CHECK-32-NEXT: [[STR_STORAGE:%.+]] = tail call noalias i8* @swift_slowAlloc(i{{.*}} 16 + // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, i8* {{(nonnull )?}}[[STR_STORAGE_PTR:%.*]] + // CHECK: store i8 2, i8* [[BUFFER]], align 1 + // CHECK-NEXT: [[OFFSET1:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 1 + // CHECK-NEXT: store i8 1, i8* [[OFFSET1]], align 1 + + // Argument bytes. + // + // CHECK-NEXT: [[OFFSET2:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 2 + // CHECK-NEXT: store i8 32, i8* [[OFFSET2]], align 1 + // CHECK-NEXT: [[OFFSET3:%.+]] = getelementptr inbounds i8, i8* [[BUFFER]], i{{.*}} 3 + // CHECK-64-NEXT: store i8 8, i8* [[OFFSET3]], align 1 + // CHECK-32-NEXT: store i8 4, i8* [[OFFSET3]], align 1 + // CHECK-NEXT: [[TYPENAME:%.+]] = tail call swiftcc { i{{.*}}, {{.*}} } @"${{.*}}_typeName{{.*}}"({{.*}} %0 + // CHECK-NEXT: [[TYPENAME_0:%.+]] = extractvalue { i{{.*}}, {{.*}} } [[TYPENAME]], 0 + // CHECK-NEXT: [[TYPENAME_1:%.+]] = extractvalue { i{{.*}}, {{.*}} } [[TYPENAME]], 1 + + // CHECK: [[STR_POINTER:%.*]] = call swiftcc i8* @"${{.*}}getNullTerminatedUTF8Pointer{{.*}}"(i{{.*}} [[TYPENAME_0]], {{.*}} [[TYPENAME_1]] + + // os_log_impl call. + // CHECK-64: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @{{.*}}, i64 0, i64 0), i8* {{(nonnull )?}}[[BUFFER]], i32 12) + // CHECK-32: tail call swiftcc void @"${{.*}}_os_log_impl_test{{.*}}"({{.*}}, {{.*}}, {{.*}}, {{.*}}, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @{{.*}}, i32 0, i32 0), i8* {{(nonnull )?}}[[BUFFER]], i32 8) + // CHECK-NEXT: [[BITCASTED_STR_STORAGE:%.*]] = bitcast i8* [[STR_STORAGE]] to %swift.opaque* + // CHECK-NEXT: tail call void @swift_arrayDestroy(%swift.opaque* [[BITCASTED_STR_STORAGE]] + // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[STR_STORAGE]] + // CHECK-NEXT: tail call void @swift_slowDealloc(i8* {{(nonnull )?}}[[BUFFER]] + // CHECK: call void @llvm.lifetime.end{{.*}}({{.*}}, i8* {{(nonnull )?}}[[STR_STORAGE_PTR]] + // CHECK-NEXT: br label %[[EXIT]] + + // CHECK: [[EXIT]]: + // CHECK-NEXT: ret void +} diff --git a/test/SILOptimizer/OSLogMandatoryOptTest.swift b/test/SILOptimizer/OSLogMandatoryOptTest.swift index e5b2c9da9a946..8371053f21412 100644 --- a/test/SILOptimizer/OSLogMandatoryOptTest.swift +++ b/test/SILOptimizer/OSLogMandatoryOptTest.swift @@ -45,16 +45,16 @@ func testSimpleInterpolation() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // We need to wade through some borrows and copy values here. // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 3 } @@ -92,15 +92,15 @@ func testInterpolationWithFormatOptions() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 3 } @@ -140,15 +140,15 @@ func testInterpolationWithFormatOptionsAndPrivacy() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 3 } @@ -194,15 +194,15 @@ func testInterpolationWithMultipleArguments() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 9 } @@ -244,13 +244,13 @@ func testLogMessageWithoutData() { // Check whether argument array is folded. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[ARGSARRAY:%[0-9]+]] // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 0 } @@ -317,15 +317,15 @@ func testMessageWithTooManyArguments() { // Check whether argument array is folded. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 144 } @@ -402,15 +402,15 @@ func testDynamicStringArguments() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 6 } @@ -455,15 +455,15 @@ func testNSObjectInterpolation() { // the array which is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply {{.*}}<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply {{.*}}<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 6 } @@ -503,15 +503,15 @@ func testDoubleInterpolation() { // not checked here, but is checked by a different test suite. // CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF - // CHECK-DAG: try_apply [[FOREACH]], inout Array) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) + // CHECK-DAG: try_apply [[FOREACH]], inout Optional>, inout Optional>) -> ()>>({{%.*}}, [[ARGSARRAYADDR:%[0-9]+]]) // CHECK-DAG: store_borrow [[ARGSARRAY2:%[0-9]+]] to [[ARGSARRAYADDR]] // CHECK-DAG: [[ARGSARRAY2]] = begin_borrow [[ARGSARRAY3:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]] // CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]] // CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF - // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARGSARRAY:%[0-9]+]]) + // CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARGSARRAY:%[0-9]+]]) // CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]] - // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Array) -> ()>([[ARRAYSIZE:%[0-9]+]]) + // CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer, inout Optional>, inout Optional>) -> ()>([[ARRAYSIZE:%[0-9]+]]) // CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK-DAG: [[ARRAYSIZE]] = integer_literal $Builtin.Word, 3 } diff --git a/test/Sema/diag_constantness_check_os_log.swift b/test/Sema/diag_constantness_check_os_log.swift index 4caa166692b65..aba696db441bb 100644 --- a/test/Sema/diag_constantness_check_os_log.swift +++ b/test/Sema/diag_constantness_check_os_log.swift @@ -27,7 +27,7 @@ func testNonconstantFormatOption( func testNonconstantPrivacyOption(privacyOpt: OSLogPrivacy) { _osLogTestHelper("Integer: \(Int.max, privacy: privacyOpt)") - // expected-error@-1 {{argument must be a case of enum 'OSLogPrivacy'}} + // expected-error@-1 {{argument must be a static method or property of 'OSLogPrivacy'}} } func testNonconstantAlignmentOption(alignOpt: OSLogStringAlignment) { @@ -44,7 +44,7 @@ func testMultipleOptions( \(2, format: formatOpt, align: .right(columns: 10), privacy: privacyOpt) """) // expected-error@-2 {{argument must be a static method or property of 'OSLogIntegerFormatting'}} - // expected-error@-3 {{argument must be a case of enum 'OSLogPrivacy'}} + // expected-error@-3 {{argument must be a static method or property of 'OSLogPrivacy'}} } func testNoninlinedOSLogMessage() { diff --git a/test/Sema/redeclaration-checking.swift b/test/Sema/redeclaration-checking.swift index 9445d612f94b1..558c23faac717 100644 --- a/test/Sema/redeclaration-checking.swift +++ b/test/Sema/redeclaration-checking.swift @@ -93,4 +93,9 @@ func stmtTest() { // expected-error@-2 {{invalid redeclaration of 'x'}} // expected-warning@-3 2{{never used}} // expected-warning@-4 {{unreachable}} +} + +func fullNameTest() { + let x = 123 // expected-warning {{never used}} + func x() {} } \ No newline at end of file diff --git a/test/stdlib/OSLogExecutionTest.swift b/test/stdlib/OSLogExecutionTest.swift index 5e1eda880ac7c..b415579f6eaee 100644 --- a/test/stdlib/OSLogExecutionTest.swift +++ b/test/stdlib/OSLogExecutionTest.swift @@ -77,7 +77,7 @@ internal struct OSLogBufferChecker { /// This occupies four most significant bits of the first byte of the /// argument header. internal enum ArgumentType: UInt8 { - case scalar = 0, count, string, pointer, object + case scalar = 0, count = 1, string = 2, pointer = 3, object = 4, mask = 7 // TODO: include wide string and errno here if needed. } @@ -142,13 +142,13 @@ internal struct OSLogBufferChecker { /// Check whether the bytes starting from `startIndex` contain the encoding for a count. internal func checkCount( startIndex: Int, - flag: ArgumentFlag, - expectedCount: Int + expectedCount: Int, + precision: Bool ) { checkNumeric( startIndex: startIndex, - flag: flag, - type: .count, + flag: .autoFlag, + type: precision ? .count : .scalar, expectedValue: CInt(expectedCount)) } @@ -614,8 +614,8 @@ InterpolationTestSuite.test("Integer formatting with precision") { bufferChecker.checkArguments( { bufferChecker.checkCount( startIndex: $0, - flag: .autoFlag, - expectedCount: 10) + expectedCount: 10, + precision: true) }, { bufferChecker.checkInt( startIndex: $0, @@ -654,13 +654,13 @@ InterpolationTestSuite.test("Integer formatting with precision and alignment") { bufferChecker.checkArguments( { bufferChecker.checkCount( startIndex: $0, - flag: .autoFlag, - expectedCount: 7) + expectedCount: 7, + precision: false) }, { bufferChecker.checkCount( startIndex: $0, - flag: .autoFlag, - expectedCount: 10) + expectedCount: 10, + precision: true) }, { bufferChecker.checkInt( startIndex: $0, diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt index f045bc7fd8e6e..e9323a95c3c43 100644 --- a/unittests/Driver/CMakeLists.txt +++ b/unittests/Driver/CMakeLists.txt @@ -1,7 +1,6 @@ add_swift_unittest(SwiftDriverTests FineGrainedDependencyGraphTests.cpp MockingFineGrainedDependencyGraphs.cpp - TypeBodyFingerprintsDependencyGraphTests.cpp UnitTestSourceFileDepGraphFactory.cpp ) diff --git a/unittests/Driver/FineGrainedDependencyGraphTests.cpp b/unittests/Driver/FineGrainedDependencyGraphTests.cpp index becc5dd213d86..c0f49be7047d9 100644 --- a/unittests/Driver/FineGrainedDependencyGraphTests.cpp +++ b/unittests/Driver/FineGrainedDependencyGraphTests.cpp @@ -1,14 +1,33 @@ +//===--------------- FineGrainedDependencyGraphTests.cpp ------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + #include "MockingFineGrainedDependencyGraphs.h" #include "swift/Basic/ReferenceDependencyKeys.h" #include "swift/Driver/FineGrainedDependencyDriverGraph.h" #include "swift/Driver/Job.h" #include "gtest/gtest.h" -// 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. +// \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. + +// \c \c findExternallyDependentUntracedJobs may also return duplicates + +// 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 fine_grained_dependencies; @@ -38,8 +57,8 @@ static bool contains(const Range &range, const T &value) { std::end(range); } -TEST(ModuleDepGraphWithoutFingerprints, BasicLoad) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, BasicLoad) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"c->", "d->"}}}); @@ -57,8 +76,8 @@ TEST(ModuleDepGraphWithoutFingerprints, BasicLoad) { {NodeKind::topLevel, {"b", "c", "d->", "a->"}}}); } -TEST(ModuleDepGraphWithoutFingerprints, IndependentNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, IndependentNodes) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a0", "a->"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b0", "b->"}}}); @@ -86,8 +105,8 @@ TEST(ModuleDepGraphWithoutFingerprints, IndependentNodes) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, IndependentDepKinds) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "a->"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a", "b->"}}}); @@ -97,8 +116,8 @@ TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, IndependentDepKinds2) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a->", "b"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"b->", "a"}}}); @@ -108,8 +127,8 @@ TEST(ModuleDepGraphWithoutFingerprints, IndependentDepKinds2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, IndependentMembers) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, IndependentMembers) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa"}}}); simulateLoad(graph, &job1, {{NodeKind::member, {"a,bb->"}}}); @@ -125,8 +144,8 @@ TEST(ModuleDepGraphWithoutFingerprints, IndependentMembers) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job4)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); @@ -143,8 +162,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependentReverse) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a->", "b->", "c->"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x", "b", "z"}}}); @@ -166,8 +185,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentReverse) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent2) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); @@ -185,8 +204,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent3) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent3) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); @@ -205,8 +224,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent3) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent4) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent4) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); simulateLoad(graph, &job1, @@ -225,8 +244,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent4) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent5) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent5) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); @@ -247,8 +266,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent5) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent6) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependent6) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::dynamicLookup, {"a", "b", "c"}}}); simulateLoad(graph, &job1, @@ -266,8 +285,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependent6) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentMember) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleDependentMember) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::member, {"a,aa", "b,bb", "c,cc"}}}); simulateLoad(graph, &job1, @@ -286,8 +305,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleDependentMember) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsSame) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MultipleDependentsSame) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); @@ -309,8 +328,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsSame) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsDifferent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MultipleDependentsDifferent) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); @@ -332,8 +351,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MultipleDependentsDifferent) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedDependents) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z"}}}); @@ -355,8 +374,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedNoncascadingDependents) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "#z"}}}); @@ -378,8 +397,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedNoncascadingDependents2) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); simulateLoad( @@ -397,8 +416,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedNoncascadingDependents2) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkTwoNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkTwoNodes) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "z"}}}); @@ -435,8 +454,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkTwoNodes) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job12)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkOneNodeTwice) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); @@ -461,8 +480,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkOneNodeTwice2) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); @@ -487,8 +506,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkOneNodeTwice2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, ReloadDetectsChange) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ReloadDetectsChange) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); @@ -514,8 +533,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ReloadDetectsChange) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, NotTransitiveOnceMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, NotTransitiveOnceMarked) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); @@ -542,8 +561,8 @@ TEST(ModuleDepGraphWithoutFingerprints, NotTransitiveOnceMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, DependencyLoops) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, DependencyLoops) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c", "a->"}}}); simulateLoad(graph, &job1, @@ -569,8 +588,8 @@ TEST(ModuleDepGraphWithoutFingerprints, DependencyLoops) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitive) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkIntransitive) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); @@ -587,8 +606,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitive) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkIntransitiveTwice) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); @@ -597,8 +616,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveTwice) { EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveThenIndirect) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MarkIntransitiveThenIndirect) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b", "c"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"x->", "b->", "z->"}}}); @@ -616,8 +635,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MarkIntransitiveThenIndirect) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleExternal) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); @@ -637,8 +656,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, SimpleExternal2) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); @@ -650,8 +669,8 @@ TEST(ModuleDepGraphWithoutFingerprints, SimpleExternal2) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedExternal) { + ModuleDepGraph graph; simulateLoad( graph, &job0, @@ -680,8 +699,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedExternal) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedExternalReverse) { + ModuleDepGraph graph; simulateLoad( graph, &job0, @@ -711,8 +730,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalReverse) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalPreMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, ChainedExternalPreMarked) { + ModuleDepGraph graph; simulateLoad( graph, &job0, @@ -731,8 +750,8 @@ TEST(ModuleDepGraphWithoutFingerprints, ChainedExternalPreMarked) { EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); } -TEST(ModuleDepGraphWithoutFingerprints, MutualInterfaceHash) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, MutualInterfaceHash) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::topLevel, {"a", "b->"}}}); simulateLoad(graph, &job1, {{NodeKind::topLevel, {"a->", "b"}}}); @@ -740,8 +759,8 @@ TEST(ModuleDepGraphWithoutFingerprints, MutualInterfaceHash) { EXPECT_TRUE(contains(jobs, &job1)); } -TEST(ModuleDepGraphWithoutFingerprints, DisabledTypeBodyFingerprints) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, EnabledTypeBodyFingerprints) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"B2->"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "B2"}}}); @@ -756,8 +775,8 @@ TEST(ModuleDepGraphWithoutFingerprints, DisabledTypeBodyFingerprints) { } } -TEST(ModuleDepGraphWithoutFingerprints, BaselineForPrintsAndCrossType) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, BaselineForPrintsAndCrossType) { + ModuleDepGraph graph; // Because when A1 changes, B1 and not B2 is affected, only jobs1 and job2 // should be recompiled, except type fingerprints is off! @@ -778,16 +797,20 @@ TEST(ModuleDepGraphWithoutFingerprints, BaselineForPrintsAndCrossType) { } } -TEST(ModuleDepGraphWithoutFingerprints, LoadFailsWithFingerprint) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); - EXPECT_FALSE( +TEST(ModuleDepGraph, LoadPassesWithFingerprint) { + ModuleDepGraph graph; + EXPECT_TRUE( getChangesForSimulatedLoad(graph, &job0, {{NodeKind::nominal, {"A@1"}}})); } -TEST(ModuleDepGraphWithoutFingerprints, IgnoreFingerprints) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, UseFingerprints) { + ModuleDepGraph graph; - simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1", "A2"}}}); + // Because when A1 changes, B1 and not B2 is affected, only jobs1 and job2 + // should be recompiled, except type fingerprints is off! + // Include a dependency on A1, to ensure it does not muck things up. + + simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1@1", "A2@2", "A1->"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"B1", "A1->"}}}); simulateLoad(graph, &job2, {{NodeKind::nominal, {"C1", "A2->"}}}); simulateLoad(graph, &job3, {{NodeKind::nominal, {"D1"}}}); @@ -795,16 +818,16 @@ TEST(ModuleDepGraphWithoutFingerprints, IgnoreFingerprints) { { const auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); - EXPECT_EQ(4u, jobs.size()); + EXPECT_EQ(3u, jobs.size()); EXPECT_TRUE(contains(jobs, &job0)); EXPECT_TRUE(contains(jobs, &job1)); EXPECT_TRUE(contains(jobs, &job2)); - EXPECT_TRUE(contains(jobs, &job3)); + EXPECT_FALSE(contains(jobs, &job3)); } } -TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependencyBaseline) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, CrossTypeDependencyBaseline) { + ModuleDepGraph graph; simulateLoad(graph, &job0, {{NodeKind::nominal, {"A"}}}); simulateLoad(graph, &job1, {{NodeKind::nominal, {"B", "C", "A->"}}}); simulateLoad(graph, &job2, {{NodeKind::nominal, {"B->"}}}); @@ -817,8 +840,8 @@ TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependencyBaseline) { EXPECT_TRUE(contains(jobs, &job3)); } -TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependency) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/false); +TEST(ModuleDepGraph, CrossTypeDependency) { + ModuleDepGraph graph; // Because of the cross-type dependency, A->B, // when A changes, only B is dirtied in job1. @@ -833,3 +856,48 @@ TEST(ModuleDepGraphWithoutFingerprints, CrossTypeDependency) { EXPECT_TRUE(contains(jobs, &job2)); EXPECT_FALSE(contains(jobs, &job3)); } + +TEST(ModuleDepGraph, CrossTypeDependencyBaselineWithFingerprints) { + ModuleDepGraph graph; + 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; + // 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)); +} diff --git a/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp b/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp index 6ac82c50d45f2..549e3cb4af234 100644 --- a/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp +++ b/unittests/Driver/MockingFineGrainedDependencyGraphs.cpp @@ -26,11 +26,11 @@ 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, + StringRef interfaceHashIfNonEmpty, const bool hadCompilationError) { const auto changes = getChangesForSimulatedLoad( g, cmd, dependencyDescriptions, interfaceHashIfNonEmpty, - includePrivateDeps, hadCompilationError); + hadCompilationError); assert(changes && "simulated load should always succeed"); } @@ -38,7 +38,7 @@ ModuleDepGraph::Changes mocking_fine_grained_dependency_graphs::getChangesForSimulatedLoad( ModuleDepGraph &g, const driver::Job *cmd, const DependencyDescriptions &dependencyDescriptions, - StringRef interfaceHashIfNonEmpty, const bool includePrivateDeps, + StringRef interfaceHashIfNonEmpty, const bool hadCompilationError) { StringRef swiftDeps = cmd->getOutput().getAdditionalOutputForType(file_types::TY_SwiftDeps); @@ -51,7 +51,7 @@ mocking_fine_grained_dependency_graphs::getChangesForSimulatedLoad( auto sfdg = UnitTestSourceFileDepGraphFactory( - includePrivateDeps, hadCompilationError, swiftDeps, interfaceHash, + hadCompilationError, swiftDeps, interfaceHash, g.emitFineGrainedDependencyDotFileAfterEveryImport, dependencyDescriptions, diags) .construct(); @@ -63,11 +63,11 @@ std::vector mocking_fine_grained_dependency_graphs::simulateReload( ModuleDepGraph &g, const driver::Job *cmd, const DependencyDescriptions &dependencyDescriptions, - StringRef interfaceHashIfNonEmpty, const bool includePrivateDeps, + StringRef interfaceHashIfNonEmpty, const bool hadCompilationError) { const auto changedNodes = getChangesForSimulatedLoad( g, cmd, dependencyDescriptions, interfaceHashIfNonEmpty, - includePrivateDeps, hadCompilationError); + hadCompilationError); if (!changedNodes) return g.getAllJobs(); return g.findJobsToRecompileWhenNodesChange(changedNodes.getValue()); diff --git a/unittests/Driver/MockingFineGrainedDependencyGraphs.h b/unittests/Driver/MockingFineGrainedDependencyGraphs.h index 0bb5e298355b9..2bd042006bce1 100644 --- a/unittests/Driver/MockingFineGrainedDependencyGraphs.h +++ b/unittests/Driver/MockingFineGrainedDependencyGraphs.h @@ -35,9 +35,8 @@ namespace mocking_fine_grained_dependency_graphs { /// \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. +/// 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). @@ -68,7 +67,6 @@ namespace mocking_fine_grained_dependency_graphs { 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 @@ -78,7 +76,6 @@ 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. @@ -91,7 +88,6 @@ 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 diff --git a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp deleted file mode 100644 index 9e572b0c5fca4..0000000000000 --- a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp +++ /dev/null @@ -1,894 +0,0 @@ -#include "MockingFineGrainedDependencyGraphs.h" -#include "swift/Basic/ReferenceDependencyKeys.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, -// \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. - -// \c \c findExternallyDependentUntracedJobs may also return duplicates - -// 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 fine_grained_dependencies; -using namespace mocking_fine_grained_dependency_graphs; -using Job = driver::Job; - -static OutputFileMap OFM; - -static Job - job0(OFM, "0"), - job1(OFM, "1"), - job2(OFM, "2"), - job3(OFM, "3"), - job4(OFM, "4"), - job5(OFM, "5"), - job6(OFM, "6"), - job7(OFM, "7"), - job8(OFM, "8"), - job9(OFM, "9"), - job10(OFM, "10"), - job11(OFM, "11"), - job12(OFM, "12"); - -template -static bool contains(const Range &range, const T &value) { - return std::find(std::begin(range), std::end(range), value) != - std::end(range); -} - -TEST(ModuleDepGraph, BasicLoad) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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(ModuleDepGraph, IndependentNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - // Mark 0 again -- should be no change. - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job2).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(1u, graph.findJobsToRecompileWhenWholeJobChanges(&job1).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, IndependentDepKinds) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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=*/true); - - 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=*/true); - - 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)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job3)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job4)); -} - -TEST(ModuleDepGraph, SimpleDependent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependentReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependent2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"a", "b", "c"}}}); - simulateLoad(graph, &job1, {{NodeKind::nominal, {"x->", "b->", "z->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependent3) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, - {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); - simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependent4) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); - simulateLoad(graph, &job1, - {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependent5) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, - {{NodeKind::nominal, {"a"}}, {NodeKind::topLevel, {"a"}}}); - simulateLoad(graph, &job1, - {{NodeKind::nominal, {"a->"}}, {NodeKind::topLevel, {"a->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependent6) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleDependentMember) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, MultipleDependentsSame) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, MultipleDependentsDifferent) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, ChainedDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, ChainedNoncascadingDependents) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - EXPECT_EQ(0u, graph.findJobsToRecompileWhenWholeJobChanges(&job0).size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, ChainedNoncascadingDependents2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, MarkTwoNodes) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); //????? - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job10)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job11)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job12)); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job10); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job10)); - EXPECT_TRUE(contains(jobs, &job11)); - EXPECT_FALSE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job10)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job11)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job12)); -} - -TEST(ModuleDepGraph, MarkOneNodeTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); - simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); - simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - { - auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"b"}}}); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, MarkOneNodeTwice2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); - simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); - simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - { - auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"a", "b"}}}); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, ReloadDetectsChange) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - { - 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_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, NotTransitiveOnceMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"a"}}}); - simulateLoad(graph, &job1, {{NodeKind::nominal, {"a->"}}}); - simulateLoad(graph, &job2, {{NodeKind::nominal, {"b->"}}}); - - { - const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&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_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, DependencyLoops) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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); - EXPECT_EQ(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(contains(jobs, &job2)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(0u, jobs.size()); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job2)); -} - -TEST(ModuleDepGraph, MarkIntransitive) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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)); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, MarkIntransitiveTwice) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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=*/true); - - 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)); - - { - auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, SimpleExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, - {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); - - EXPECT_TRUE(contains(graph.getExternalDependencies(), "/foo")); - EXPECT_TRUE(contains(graph.getExternalDependencies(), "/bar")); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); - EXPECT_EQ(jobs.size(), 1u); - EXPECT_TRUE(contains(jobs, &job0)); - } - - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - - EXPECT_EQ(0u, graph.findExternallyDependentUntracedJobs("/foo").size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); -} - -TEST(ModuleDepGraph, SimpleExternal2) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad(graph, &job0, - {{NodeKind::externalDepend, {"/foo->", "/bar->"}}}); - - EXPECT_EQ(1u, graph.findExternallyDependentUntracedJobs("/bar").size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - - EXPECT_EQ(0u, graph.findExternallyDependentUntracedJobs("/bar").size()); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); -} - -TEST(ModuleDepGraph, ChainedExternal) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - 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")); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); - EXPECT_EQ(jobs.size(), 2u); - EXPECT_TRUE(contains(jobs, &job0)); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); - EXPECT_EQ(jobs.size(), 0u); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, ChainedExternalReverse) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad( - graph, &job0, - {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); - simulateLoad( - graph, &job1, - {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/bar"); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - EXPECT_EQ(0u, graph.findExternallyDependentUntracedJobs("/bar").size()); - EXPECT_FALSE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); - EXPECT_EQ(1u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -TEST(ModuleDepGraph, ChainedExternalPreMarked) { - ModuleDepGraph graph(/*EnableTypeFingerprints=*/true); - - simulateLoad( - graph, &job0, - {{NodeKind::externalDepend, {"/foo->"}}, {NodeKind::topLevel, {"a"}}}); - simulateLoad( - graph, &job1, - {{NodeKind::externalDepend, {"/bar->"}}, {NodeKind::topLevel, {"a->"}}}); - - { - auto jobs = graph.findExternallyDependentUntracedJobs("/foo"); - EXPECT_EQ(2u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - EXPECT_TRUE(contains(jobs, &job1)); - } - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job0)); - EXPECT_TRUE(graph.haveAnyNodesBeenTraversedIn(&job1)); -} - -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); - - 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)); - } -} - -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 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(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! - // Include a dependency on A1, to ensure it does not muck things up. - - simulateLoad(graph, &job0, {{NodeKind::nominal, {"A1@1", "A2@2", "A1->"}}}); - 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(3u, jobs.size()); - EXPECT_TRUE(contains(jobs, &job0)); - EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_TRUE(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)); -} diff --git a/unittests/Driver/UnitTestSourceFileDepGraphFactory.cpp b/unittests/Driver/UnitTestSourceFileDepGraphFactory.cpp index 34047395b1411..50cce1c47a95c 100644 --- a/unittests/Driver/UnitTestSourceFileDepGraphFactory.cpp +++ b/unittests/Driver/UnitTestSourceFileDepGraphFactory.cpp @@ -104,9 +104,7 @@ Optional UnitTestSourceFileDepGraphFactory::parseADefinedDecl( StringRef s, const NodeKind kind, const DeclAspect aspect) { static const char *privatePrefix = "#"; - const bool isPrivate = s.consume_front(privatePrefix); - if (isPrivate && !includePrivateDeps) - return None; + s.consume_front(privatePrefix); const std::string context = parseContext(s.split(fingerprintSeparator).first, kind); std::string name = parseName(s.split(fingerprintSeparator).first, kind); @@ -125,9 +123,7 @@ UnitTestSourceFileDepGraphFactory::parseAUsedDecl(const StringRef argString, // Someday, we might differentiate. const DeclAspect aspectOfDefUsed = DeclAspect::interface; - const bool isHolderPrivate = s.consume_front(privateHolderPrefix); - if (!includePrivateDeps && isHolderPrivate) - return None; + s.consume_front(privateHolderPrefix); const auto defUseStrings = s.split(defUseSeparator); const auto context = parseContext(defUseStrings.first, kind); const auto name = parseName(defUseStrings.first, kind); diff --git a/unittests/Driver/UnitTestSourceFileDepGraphFactory.h b/unittests/Driver/UnitTestSourceFileDepGraphFactory.h index 16b29321a2037..9298177aa39e7 100644 --- a/unittests/Driver/UnitTestSourceFileDepGraphFactory.h +++ b/unittests/Driver/UnitTestSourceFileDepGraphFactory.h @@ -27,12 +27,12 @@ class UnitTestSourceFileDepGraphFactory public: UnitTestSourceFileDepGraphFactory( - bool includePrivateDeps, bool hadCompilationError, StringRef swiftDeps, + bool hadCompilationError, StringRef swiftDeps, StringRef fileFingerprint, bool emitDotFileAfterConstruction, const DependencyDescriptions &dependencyDescriptions, DiagnosticEngine &diags) : AbstractSourceFileDepGraphFactory( - includePrivateDeps, hadCompilationError, swiftDeps, fileFingerprint, + hadCompilationError, swiftDeps, fileFingerprint, emitDotFileAfterConstruction, diags), dependencyDescriptions(dependencyDescriptions) {} diff --git a/utils/build-script-impl b/utils/build-script-impl index 0662f5961b754..2bb99c886a669 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -3049,7 +3049,7 @@ for host in "${ALL_HOSTS[@]}"; do grep -v '.py$' | \ grep -v '.a$' | \ grep -v 'swift-api-digester' | \ - xargs -n 1 -P 1 ${dsymutil_path}) + xargs -P 1 ${dsymutil_path}) # Strip executables, shared libraries and static libraries in # `host_install_destdir`. diff --git a/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift b/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift deleted file mode 100644 index 3eefcdd073ba8..0000000000000 --- a/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift +++ /dev/null @@ -1,61 +0,0 @@ -// RUN: %empty-directory(%t) - -// RUN: cp %s %t/main.swift -// RUN: cp %S/Inputs/rdar23148987/helper-1.swift %t/helper.swift -// RUN: touch -t 201401240005 %t/*.swift - -// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1 %s - -// CHECK-1-NOT: warning -// CHECK-1: {{^{$}} -// CHECK-1: "kind": "began" -// CHECK-1: "name": "compile" -// CHECK-1: ".\/main.swift" -// CHECK-1: {{^}$}} - -// CHECK-1: {{^{$}} -// CHECK-1: "kind": "began" -// CHECK-1: "name": "compile" -// CHECK-1: ".\/helper.swift" -// CHECK-1: {{^}$}} - -// RUN: ls %t/ | %FileCheck -check-prefix=CHECK-LS %s - -// CHECK-LS-DAG: main.o -// CHECK-LS-DAG: helper.o - -// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1-SKIPPED %s - -// CHECK-1-SKIPPED-NOT: warning -// CHECK-1-SKIPPED: {{^{$}} -// CHECK-1-SKIPPED: "kind": "skipped" -// CHECK-1-SKIPPED: "name": "compile" -// CHECK-1-SKIPPED: ".\/main.swift" -// CHECK-1-SKIPPED: {{^}$}} - -// CHECK-1-SKIPPED: {{^{$}} -// CHECK-1-SKIPPED: "kind": "skipped" -// CHECK-1-SKIPPED: "name": "compile" -// CHECK-1-SKIPPED: ".\/helper.swift" -// CHECK-1-SKIPPED: {{^}$}} - -// RUN: cp %S/Inputs/rdar23148987/helper-2.swift %t/helper.swift -// RUN: touch -t 201401240006 %t/helper.swift -// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 -driver-show-incremental -driver-show-job-lifecycle | %FileCheck -check-prefix=CHECK-2 %s - -// CHECK-2-NOT: warning -// CHECK-2: {{^{$}} -// CHECK-2: "kind": "began" -// CHECK-2: "name": "compile" -// CHECK-2: ".\/helper.swift" -// CHECK-2: {{^}$}} - -// CHECK-2: {{^{$}} -// CHECK-2: "kind": "began" -// CHECK-2: "name": "compile" -// CHECK-2: ".\/main.swift" -// CHECK-2: {{^}$}} - -func test(obj: Test) { - obj.foo() -} diff --git a/validation-test/Driver/Dependencies/rdar23148987.swift b/validation-test/Driver/Dependencies/rdar23148987.swift index 7ff7bcae38369..35aa9e75d74b6 100644 --- a/validation-test/Driver/Dependencies/rdar23148987.swift +++ b/validation-test/Driver/Dependencies/rdar23148987.swift @@ -4,7 +4,7 @@ // RUN: cp %S/Inputs/rdar23148987/helper-1.swift %t/helper.swift // RUN: touch -t 201401240005 %t/*.swift -// RUN: cd %t && %target-build-swift -disable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1 %s +// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1 %s // CHECK-1-NOT: warning // CHECK-1: {{^{$}} @@ -24,7 +24,7 @@ // CHECK-LS-DAG: main.o // CHECK-LS-DAG: helper.o -// RUN: cd %t && %target-build-swift -disable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1-SKIPPED %s +// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1-SKIPPED %s // CHECK-1-SKIPPED-NOT: warning // CHECK-1-SKIPPED: {{^{$}} @@ -41,7 +41,7 @@ // RUN: cp %S/Inputs/rdar23148987/helper-2.swift %t/helper.swift // RUN: touch -t 201401240006 %t/helper.swift -// RUN: cd %t && %target-build-swift -disable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-2 %s +// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 -driver-show-incremental -driver-show-job-lifecycle | %FileCheck -check-prefix=CHECK-2 %s // CHECK-2-NOT: warning // CHECK-2: {{^{$}}