diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 1e083e02c1ecc..665fcb0894313 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -748,11 +748,13 @@ class ASTContext final { /// \param methods The list of @objc methods in this class that have this /// selector and are instance/class methods as requested. This list will be /// extended with any methods found in subsequent generations. - void loadObjCMethods(ClassDecl *classDecl, - ObjCSelector selector, - bool isInstanceMethod, - unsigned previousGeneration, - llvm::TinyPtrVector &methods); + /// + /// \param swiftOnly If true, only loads methods from imported Swift modules, + /// skipping the Clang importer. + void loadObjCMethods(ClassDecl *classDecl, ObjCSelector selector, + bool isInstanceMethod, unsigned previousGeneration, + llvm::TinyPtrVector &methods, + bool swiftOnly = false); /// Load derivative function configurations for the given /// AbstractFunctionDecl. diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index eb6af822e7ab7..74af4727911a6 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -4117,8 +4117,8 @@ class ClassDecl final : public NominalTypeDecl { /// /// \param isInstance Whether we are looking for an instance method /// (vs. a class method). - MutableArrayRef lookupDirect(ObjCSelector selector, - bool isInstance); + TinyPtrVector lookupDirect(ObjCSelector selector, + bool isInstance); /// Record the presence of an @objc method with the given selector. void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector); @@ -5232,6 +5232,12 @@ class VarDecl : public AbstractStorageDecl { Optional getPropertyWrapperMutability() const; + /// Returns whether this property is the backing storage property or a storage + /// wrapper for wrapper instance's projectedValue. If this property is + /// neither, then it returns `None`. + Optional + getPropertyWrapperSynthesizedPropertyKind() const; + /// Retrieve the backing storage property for a property that has an /// attached property wrapper. /// diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index deeec88026f09..02ae15baf0630 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -557,6 +557,9 @@ ERROR(expr_keypath_mutating_getter,none, ERROR(expr_keypath_static_member,none, "%select{key path|dynamic key path member lookup}1 cannot refer to static member %0", (DeclName, bool)) +ERROR(expr_keypath_enum_case,none, + "%select{key path|dynamic key path member lookup}1 cannot refer to enum case %0", + (DeclName, bool)) ERROR(expr_keypath_empty,none, "empty key path does not refer to a property", ()) ERROR(expr_unsupported_objc_key_path_component,none, @@ -760,12 +763,20 @@ ERROR(invalid_redecl,none,"invalid redeclaration of %0", (DeclName)) ERROR(invalid_redecl_init,none, "invalid redeclaration of synthesized %select{|memberwise }1%0", (DeclName, bool)) +ERROR(invalid_redecl_implicit,none, + "invalid redeclaration of synthesized " + "%select{%0|implementation for protocol requirement}1 %2", + (DescriptiveDeclKind, bool, DeclName)) WARNING(invalid_redecl_swift5_warning,none, "redeclaration of %0 is deprecated and will be an error in Swift 5", (DeclName)) NOTE(invalid_redecl_prev,none, "%0 previously declared here", (DeclName)) +NOTE(invalid_redecl_implicit_wrapper,none, + "%0 synthesized for property wrapper " + "%select{projected value|backing storage}1", + (DeclName, bool)) ERROR(ambiguous_type_base,none, "%0 is ambiguous for type lookup in this context", (DeclNameRef)) diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 64eb1c1379421..d39c68ab1bcae 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -262,6 +262,12 @@ class Evaluator { void registerRequestFunctions(Zone zone, ArrayRef functions); + void enumerateReferencesInFile( + const SourceFile *SF, + evaluator::DependencyRecorder::ReferenceEnumerator f) const { + return recorder.enumerateReferencesInFile(SF, f); + } + /// Retrieve the result produced by evaluating a request that can /// be cached. template; struct DependencyRecorder; struct DependencyCollector { + friend DependencyRecorder; + struct Reference { public: enum class Kind { @@ -123,38 +125,41 @@ struct DependencyCollector { NominalTypeDecl *subject; DeclBaseName name; + bool cascades; private: - Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name) - : kind(kind), subject(subject), name(name) {} + Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name, + bool cascades) + : kind(kind), subject(subject), name(name), cascades(cascades) {} public: static Reference empty() { return {Kind::Empty, llvm::DenseMapInfo::getEmptyKey(), - llvm::DenseMapInfo::getEmptyKey()}; + llvm::DenseMapInfo::getEmptyKey(), false}; } static Reference tombstone() { - return {Kind::Empty, + return {Kind::Tombstone, llvm::DenseMapInfo::getTombstoneKey(), - llvm::DenseMapInfo::getTombstoneKey()}; + llvm::DenseMapInfo::getTombstoneKey(), false}; } public: - static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name) { - return {Kind::UsedMember, subject, name}; + static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name, + bool cascades) { + return {Kind::UsedMember, subject, name, cascades}; } - static Reference potentialMember(NominalTypeDecl *subject) { - return {Kind::PotentialMember, subject, DeclBaseName()}; + static Reference potentialMember(NominalTypeDecl *subject, bool cascades) { + return {Kind::PotentialMember, subject, DeclBaseName(), cascades}; } - static Reference topLevel(DeclBaseName name) { - return {Kind::TopLevel, nullptr, name}; + static Reference topLevel(DeclBaseName name, bool cascades) { + return {Kind::TopLevel, nullptr, name, cascades}; } - static Reference dynamic(DeclBaseName name) { - return {Kind::Dynamic, nullptr, name}; + static Reference dynamic(DeclBaseName name, bool cascades) { + return {Kind::Dynamic, nullptr, name, cascades}; } public: @@ -174,8 +179,12 @@ struct DependencyCollector { }; }; +public: + using ReferenceSet = llvm::DenseSet; + +private: DependencyRecorder &parent; - llvm::DenseSet scratch; + ReferenceSet scratch; public: explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {} @@ -226,11 +235,7 @@ struct DependencyCollector { /// particular \c DependencyScope during the course of request evaluation. struct DependencyRecorder { friend DependencyCollector; -private: - /// A stack of dependency sources in the order they were evaluated. - llvm::SmallVector dependencySources; -public: enum class Mode { // Enables the current "status quo" behavior of the dependency collector. // @@ -244,14 +249,19 @@ struct DependencyRecorder { // the primary file being acted upon instead of to the destination file. ExperimentalPrivateDependencies, }; - Mode mode; - llvm::DenseMap> + +private: + /// A stack of dependency sources in the order they were evaluated. + llvm::SmallVector dependencySources; + llvm::DenseMap + fileReferences; + llvm::DenseMap requestReferences; + Mode mode; bool isRecording; - explicit DependencyRecorder(Mode mode) - : mode{mode}, requestReferences{}, isRecording{false} {}; +public: + explicit DependencyRecorder(Mode mode) : mode{mode}, isRecording{false} {}; private: void realize(const DependencyCollector::Reference &ref); @@ -261,6 +271,12 @@ struct DependencyRecorder { void record(const llvm::SetVector &stack, llvm::function_ref rec); +public: + using ReferenceEnumerator = + llvm::function_ref; + void enumerateReferencesInFile(const SourceFile *SF, + ReferenceEnumerator f) const ; + public: /// Returns the scope of the current active scope. /// @@ -323,25 +339,6 @@ struct DependencyRecorder { return dependencySources.front().getPointer(); } - /// If there is an active dependency source, returns its - /// \c ReferencedNameTracker. Else, returns \c nullptr. - ReferencedNameTracker *getActiveDependencyTracker() const { - SourceFile *source = nullptr; - switch (mode) { - case Mode::StatusQuo: - source = getActiveDependencySourceOrNull(); - break; - case Mode::ExperimentalPrivateDependencies: - source = getFirstDependencySourceOrNull(); - break; - } - - if (!source) - return nullptr; - - return source->getRequestBasedReferencedNameTracker(); - } - /// Returns \c true if the scope of the current active source cascades. /// /// If there is no active scope, the result always cascades. diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 4d347fae5b9d8..271e07899698f 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -329,12 +329,12 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final /// Determine whether the given dependent type is equal to a concrete type. bool isConcreteType(Type type) const; - /// Return the concrete type that the given dependent type is constrained to, + /// Return the concrete type that the given type parameter is constrained to, /// or the null Type if it is not the subject of a concrete same-type /// constraint. Type getConcreteType(Type type) const; - /// Return the layout constraint that the given dependent type is constrained + /// Return the layout constraint that the given type parameter is constrained /// to, or the null LayoutConstraint if it is not the subject of layout /// constraint. LayoutConstraint getLayoutConstraint(Type type) const; diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 1a90d3572ba82..52ffcc34aca36 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -191,6 +191,7 @@ class IRGenOptions { unsigned DisableLLVMSLPVectorizer : 1; /// Disable frame pointer elimination? + unsigned DisableFPElimLeaf : 1; unsigned DisableFPElim : 1; /// Special codegen for playgrounds. @@ -319,6 +320,7 @@ class IRGenOptions { DisableClangModuleSkeletonCUs(false), UseJIT(false), DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false), DisableLLVMSLPVectorizer(false), + DisableFPElimLeaf(false), DisableFPElim(true), Playground(false), EmitStackPromotionChecks(false), FunctionSections(false), PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), HasValueNamesSetting(false), ValueNames(false), diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index c5a70a6e66773..f6a14683e0d9c 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -22,7 +22,6 @@ #include "swift/AST/Identifier.h" #include "swift/AST/LookupKinds.h" #include "swift/AST/RawComment.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/Type.h" #include "swift/Basic/Compiler.h" #include "swift/Basic/OptionSet.h" @@ -69,7 +68,6 @@ namespace swift { class ProtocolConformance; class ProtocolDecl; struct PrintOptions; - class ReferencedNameTracker; class Token; class TupleType; class Type; diff --git a/include/swift/AST/ReferencedNameTracker.h b/include/swift/AST/ReferencedNameTracker.h deleted file mode 100644 index cf61fe5c06b99..0000000000000 --- a/include/swift/AST/ReferencedNameTracker.h +++ /dev/null @@ -1,83 +0,0 @@ -//===--- ReferencedNameTracker.h - Records looked-up names ------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_REFERENCEDNAMETRACKER_H -#define SWIFT_REFERENCEDNAMETRACKER_H - -#include "swift/AST/Identifier.h" -#include "swift/Basic/ReferenceDependencyKeys.h" -#include "llvm/ADT/DenseMap.h" - -#include - -namespace swift { - -class NominalTypeDecl; -class DependencyTracker; - -class ReferencedNameTracker { -public: - using EnumerateUsedDecl = function_ref; - -private: -#define TRACKED_SET(KIND, NAME) \ -private: \ - llvm::DenseMap NAME##s; \ - \ -public: \ - void add##NAME(KIND new##NAME, bool isCascadingUse) { \ - NAME##s[new##NAME] |= isCascadingUse; \ - } \ - /* make private once ReferenceDependencies.cpp is gone */ \ - const decltype(NAME##s) &get##NAME##s() const { return NAME##s; } - - TRACKED_SET(DeclBaseName, TopLevelName) - TRACKED_SET(DeclBaseName, DynamicLookupName) - - using MemberPair = std::pair; - TRACKED_SET(MemberPair, UsedMember) - -#undef TRACKED_SET -public: - // Pushing the DependencyTracker through unifies external dependency - // enumeration. - void enumerateAllUses(bool includeIntrafileDeps, - const DependencyTracker &depTracker, - EnumerateUsedDecl enumerateUsedDecl) const; - -private: - template - void enumerateSimpleUses(llvm::DenseMap cascadesByName, - EnumerateUsedDecl enumerateUsedDecl) const; - - void enumerateExternalUses(const DependencyTracker &, - EnumerateUsedDecl enumerateUsedDecl) const; - - void enumerateCompoundUses(bool includeIntrafileDeps, - EnumerateUsedDecl enumerateUsedDecl) const; - - std::unordered_set - computeHoldersOfCascadingMembers(bool includeIntrafileDeps) const; - - void enumerateNominalUses( - bool includeIntrafileDeps, - const std::unordered_set &&holdersOfCascadingMembers, - EnumerateUsedDecl enumerateUsedDecl) const; - - void enumerateMemberUses(EnumerateUsedDecl enumerateUsedDecl) const; -}; - -} // end namespace swift - -#endif // LLVM_SWIFT_REFERENCEDNAMETRACKER_H diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 820af1095f4e9..06de45f082456 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -137,9 +137,6 @@ class SourceFile final : public FileUnit { /// This is set during type checking. TypeRefinementContext *TRC = nullptr; - /// If non-null, used to track name lookups that happen within this file. - Optional RequestReferencedNames; - /// Either the class marked \@NS/UIApplicationMain or the synthesized FuncDecl /// that calls main on the type marked @main. Decl *MainDecl = nullptr; @@ -439,25 +436,6 @@ class SourceFile final : public FileUnit { virtual bool walk(ASTWalker &walker) override; - ReferencedNameTracker *getRequestBasedReferencedNameTracker() { - return RequestReferencedNames ? RequestReferencedNames.getPointer() : nullptr; - } - const ReferencedNameTracker *getRequestBasedReferencedNameTracker() const { - return RequestReferencedNames ? RequestReferencedNames.getPointer() : nullptr; - } - - /// Creates and installs the referenced name trackers in this source file. - /// - /// This entrypoint must be called before incremental compilation can proceed, - /// else reference dependencies will not be registered. - void createReferencedNameTracker(); - - /// Retrieves the appropriate referenced name tracker instance. - /// - /// If incremental dependencies tracking is not enabled or \c createReferencedNameTracker() - /// has not been invoked on this source file, the result is \c nullptr. - const ReferencedNameTracker *getConfiguredReferencedNameTracker() const; - /// The buffer ID for the file that was imported, or None if there /// is no associated buffer. Optional getBufferID() const { diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 6cce6c7cf386a..016b16706ab3b 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -43,6 +43,12 @@ namespace clang { class Type; class VisibleDeclConsumer; class DeclarationName; + class CompilerInvocation; +namespace tooling { +namespace dependencies { + struct FullDependenciesResult; +} +} } namespace swift { @@ -148,6 +154,14 @@ class ClangImporter final : public ClangModuleLoader { std::string swiftPCHHash = "", DependencyTracker *tracker = nullptr, DWARFImporterDelegate *dwarfImporterDelegate = nullptr); + static std::vector + getClangArguments(ASTContext &ctx, const ClangImporterOptions &importerOpts); + + static std::unique_ptr + createClangInvocation(ClangImporter *importer, + const ClangImporterOptions &importerOpts, + ArrayRef invocationArgStrs, + std::vector *CC1Args = nullptr); ClangImporter(const ClangImporter &) = delete; ClangImporter(ClangImporter &&) = delete; ClangImporter &operator=(const ClangImporter &) = delete; @@ -369,6 +383,10 @@ class ClangImporter final : public ClangModuleLoader { void verifyAllModules() override; + void recordModuleDependencies( + ModuleDependenciesCache &cache, + const clang::tooling::dependencies::FullDependenciesResult &clangDependencies); + Optional getModuleDependencies( StringRef moduleName, ModuleDependenciesCache &cache, InterfaceSubContextDelegate &delegate) override; @@ -460,6 +478,12 @@ class ClangImporter final : public ClangModuleLoader { ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN, ArrayRef Exported); +/// Extract the specified-or-defaulted -module-cache-path that winds up in +/// the clang importer, for reuse as the .swiftmodule cache path when +/// building a ModuleInterfaceLoader. +std::string +getModuleCachePathFromClang(const clang::CompilerInstance &Instance); + } // end namespace swift #endif diff --git a/include/swift/Frontend/DiagnosticVerifier.h b/include/swift/Frontend/DiagnosticVerifier.h index 5671106996f6e..dcd62914e5e28 100644 --- a/include/swift/Frontend/DiagnosticVerifier.h +++ b/include/swift/Frontend/DiagnosticVerifier.h @@ -30,10 +30,8 @@ class SourceFile; // MARK: - DependencyVerifier -bool verifyDependencies(SourceManager &SM, const DependencyTracker &DT, - ArrayRef SFs); -bool verifyDependencies(SourceManager &SM, const DependencyTracker &DT, - ArrayRef SFs); +bool verifyDependencies(SourceManager &SM, ArrayRef SFs); +bool verifyDependencies(SourceManager &SM, ArrayRef SFs); // MARK: - DiagnosticVerifier struct ExpectedFixIt; diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 2a793922a1605..61d265d3a775b 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -198,12 +198,6 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock); }; -/// Extract the specified-or-defaulted -module-cache-path that winds up in -/// the clang importer, for reuse as the .swiftmodule cache path when -/// building a ModuleInterfaceLoader. -std::string -getModuleCachePathFromClang(const clang::CompilerInstance &Instance); - struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { private: SourceManager &SM; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a430124cc7f27..8a9971367dd69 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1010,6 +1010,10 @@ def enable_private_imports : Flag<["-"], "enable-private-imports">, Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>, HelpText<"Allows this module's internal and private API to be accessed">; +def disable_leaf_frame_pointer_elim : Flag<["-"], "no-omit-leaf-frame-pointer">, + Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>, + HelpText<"Don't omit the frame pointer for leaf functions">; + def sanitize_EQ : CommaJoined<["-"], "sanitize=">, Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"">, HelpText<"Turn on runtime checks for erroneous behavior.">; diff --git a/include/swift/Parse/ParseSILSupport.h b/include/swift/Parse/ParseSILSupport.h index 608812f4f4e0b..dc39168416a19 100644 --- a/include/swift/Parse/ParseSILSupport.h +++ b/include/swift/Parse/ParseSILSupport.h @@ -20,11 +20,11 @@ namespace swift { /// Interface between the Parse and ParseSIL libraries, to avoid circular /// dependencies. - class SILParserTUStateBase { + class SILParserStateBase { virtual void anchor(); protected: - SILParserTUStateBase() = default; - virtual ~SILParserTUStateBase() = default; + SILParserStateBase() = default; + virtual ~SILParserStateBase() = default; public: virtual bool parseDeclSIL(Parser &P) = 0; virtual bool parseDeclSILStage(Parser &P) = 0; diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 3c8eaf671f973..71e2f1819b2ae 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -50,7 +50,7 @@ namespace swift { class Lexer; class ParsedTypeSyntax; class PersistentParserState; - class SILParserTUStateBase; + class SILParserStateBase; class ScopeInfo; class SourceManager; class TupleType; @@ -114,7 +114,7 @@ class Parser { DiagnosticEngine &Diags; SourceFile &SF; Lexer *L; - SILParserTUStateBase *SIL; // Non-null when parsing SIL decls. + SILParserStateBase *SIL; // Non-null when parsing SIL decls. PersistentParserState *State; std::unique_ptr OwnedState; DeclContext *CurDeclContext; @@ -396,14 +396,13 @@ class Parser { public: Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags, - SILParserTUStateBase *SIL, - PersistentParserState *PersistentState, + SILParserStateBase *SIL, PersistentParserState *PersistentState, std::shared_ptr SPActions = nullptr); - Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL, + Parser(unsigned BufferID, SourceFile &SF, SILParserStateBase *SIL, PersistentParserState *PersistentState = nullptr, std::shared_ptr SPActions = nullptr); Parser(std::unique_ptr Lex, SourceFile &SF, - SILParserTUStateBase *SIL = nullptr, + SILParserStateBase *SIL = nullptr, PersistentParserState *PersistentState = nullptr, std::shared_ptr SPActions = nullptr); ~Parser(); diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index ca3abc64aea1b..ed5493376ab81 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -58,7 +58,6 @@ namespace swift { class SerializationOptions; class SILOptions; class SILModule; - class SILParserTUState; class SourceFile; enum class SourceFileKind; class SourceManager; @@ -74,17 +73,6 @@ namespace swift { class TypeConverter; } - /// Used to optionally maintain SIL parsing context for the parser. - /// - /// When not parsing SIL, this has no overhead. - class SILParserState { - public: - std::unique_ptr Impl; - - explicit SILParserState(SILModule *M); - ~SILParserState(); - }; - /// @{ /// \returns true if the declaration should be verified. This can return diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 79c73f3cb7b91..7a5f1bb2e7a48 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1484,14 +1484,16 @@ void ASTContext::loadExtensions(NominalTypeDecl *nominal, } void ASTContext::loadObjCMethods( - ClassDecl *classDecl, - ObjCSelector selector, - bool isInstanceMethod, - unsigned previousGeneration, - llvm::TinyPtrVector &methods) { + ClassDecl *classDecl, ObjCSelector selector, bool isInstanceMethod, + unsigned previousGeneration, + llvm::TinyPtrVector &methods, bool swiftOnly) { PrettyStackTraceSelector stackTraceSelector("looking for", selector); PrettyStackTraceDecl stackTraceDecl("...in", classDecl); for (auto &loader : getImpl().ModuleLoaders) { + // Ignore the Clang importer if we've been asked for Swift-only results. + if (swiftOnly && loader.get() == getClangModuleLoader()) + continue; + loader->loadObjCMethods(classDecl, selector, isInstanceMethod, previousGeneration, methods); } diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 5be2d5ae2bfd1..7645a0e5eb748 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -67,7 +67,6 @@ add_swift_host_library(swiftAST STATIC PrettyStackTrace.cpp ProtocolConformance.cpp RawComment.cpp - ReferencedNameTracker.cpp RequirementEnvironment.cpp SyntaxASTMap.cpp SILLayout.cpp diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 047b23bbe6234..71392bdb747cc 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5970,6 +5970,17 @@ VarDecl::getPropertyWrapperMutability() const { None); } +Optional +VarDecl::getPropertyWrapperSynthesizedPropertyKind() const { + if (getOriginalWrappedProperty( + PropertyWrapperSynthesizedPropertyKind::Backing)) + return PropertyWrapperSynthesizedPropertyKind::Backing; + if (getOriginalWrappedProperty( + PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) + return PropertyWrapperSynthesizedPropertyKind::StorageWrapper; + return None; +} + VarDecl *VarDecl::getPropertyWrapperBackingProperty() const { return getPropertyWrapperBackingPropertyInfo().backingVar; } @@ -6494,9 +6505,13 @@ ParamDecl::getDefaultValueStringRepresentation( return getASTContext().SourceMgr.extractText(charRange); } - // If there is no parent initializer, we used the default initializer. - auto parentInit = original->getParentInitializer(); - if (!parentInit) { + // If there is no initial wrapped value, we used the default initializer. + Expr *wrappedValue = nullptr; + if (auto *parentInit = original->getParentInitializer()) + if (auto *placeholder = findWrappedValuePlaceholder(parentInit)) + wrappedValue = placeholder->getOriginalWrappedValue(); + + if (!wrappedValue) { if (auto type = original->getPropertyWrapperBackingPropertyType()) { if (auto nominal = type->getAnyNominal()) { scratch.clear(); @@ -6511,9 +6526,8 @@ ParamDecl::getDefaultValueStringRepresentation( return ".init()"; } - auto init = - findWrappedValuePlaceholder(parentInit)->getOriginalWrappedValue(); - return extractInlinableText(getASTContext().SourceMgr, init, scratch); + auto &sourceMgr = getASTContext().SourceMgr; + return extractInlinableText(sourceMgr, wrappedValue, scratch); } } diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index d1e5b7aa16e1f..472a5387e0f5d 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -381,69 +381,60 @@ void Evaluator::dumpDependenciesGraphviz() const { void evaluator::DependencyRecorder::realize( const DependencyCollector::Reference &ref) { - auto *tracker = getActiveDependencyTracker(); - assert(tracker && "cannot realize dependency without name tracker!"); - - using Kind = evaluator::DependencyCollector::Reference::Kind; - switch (ref.kind) { - case Kind::Empty: - case Kind::Tombstone: - llvm_unreachable("cannot record empty dependency"); - case Kind::UsedMember: - tracker->addUsedMember({ref.subject, ref.name}, isActiveSourceCascading()); - break; - case Kind::PotentialMember: - tracker->addUsedMember({ref.subject, Identifier()}, - isActiveSourceCascading()); - break; - case Kind::TopLevel: - tracker->addTopLevelName(ref.name, isActiveSourceCascading()); - break; - case Kind::Dynamic: - tracker->addDynamicLookupName(ref.name, isActiveSourceCascading()); - break; + auto *source = getActiveDependencySourceOrNull(); + assert(source && "cannot realize dependency without associated file!"); + if (!source->hasInterfaceHash()) { + return; } + fileReferences[source].insert(ref); } void evaluator::DependencyCollector::addUsedMember(NominalTypeDecl *subject, DeclBaseName name) { if (parent.mode == DependencyRecorder::Mode::ExperimentalPrivateDependencies) { - scratch.insert(Reference::usedMember(subject, name)); + scratch.insert( + Reference::usedMember(subject, name, parent.isActiveSourceCascading())); } - return parent.realize(Reference::usedMember(subject, name)); + return parent.realize( + Reference::usedMember(subject, name, parent.isActiveSourceCascading())); } void evaluator::DependencyCollector::addPotentialMember( NominalTypeDecl *subject) { if (parent.mode == DependencyRecorder::Mode::ExperimentalPrivateDependencies) { - scratch.insert(Reference::potentialMember(subject)); + scratch.insert( + Reference::potentialMember(subject, parent.isActiveSourceCascading())); } - return parent.realize(Reference::potentialMember(subject)); + return parent.realize( + Reference::potentialMember(subject, parent.isActiveSourceCascading())); } void evaluator::DependencyCollector::addTopLevelName(DeclBaseName name) { if (parent.mode == DependencyRecorder::Mode::ExperimentalPrivateDependencies) { - scratch.insert(Reference::topLevel(name)); + scratch.insert(Reference::topLevel(name, parent.isActiveSourceCascading())); } - return parent.realize(Reference::topLevel(name)); + return parent.realize( + Reference::topLevel(name, parent.isActiveSourceCascading())); } void evaluator::DependencyCollector::addDynamicLookupName(DeclBaseName name) { if (parent.mode == DependencyRecorder::Mode::ExperimentalPrivateDependencies) { - scratch.insert(Reference::dynamic(name)); + scratch.insert(Reference::dynamic(name, parent.isActiveSourceCascading())); } - return parent.realize(Reference::dynamic(name)); + return parent.realize( + Reference::dynamic(name, parent.isActiveSourceCascading())); } void evaluator::DependencyRecorder::record( const llvm::SetVector &stack, llvm::function_ref rec) { assert(!isRecording && "Probably not a good idea to allow nested recording"); - if (!getActiveDependencyTracker()) { + auto *source = getActiveDependencySourceOrNull(); + if (!source || !source->hasInterfaceHash()) { return; } @@ -474,7 +465,8 @@ void evaluator::DependencyRecorder::record( void evaluator::DependencyRecorder::replay(const swift::ActiveRequest &req) { assert(!isRecording && "Probably not a good idea to allow nested recording"); - if (mode == Mode::StatusQuo || !getActiveDependencyTracker()) { + auto *source = getActiveDependencySourceOrNull(); + if (mode == Mode::StatusQuo || !source || !source->hasInterfaceHash()) { return; } @@ -491,3 +483,26 @@ void evaluator::DependencyRecorder::replay(const swift::ActiveRequest &req) { realize(ref); } } + +using namespace swift; + +void evaluator::DependencyRecorder::enumerateReferencesInFile( + const SourceFile *SF, ReferenceEnumerator f) const { + auto entry = fileReferences.find(SF); + if (entry == fileReferences.end()) { + return; + } + + for (const auto &ref : entry->getSecond()) { + switch (ref.kind) { + case DependencyCollector::Reference::Kind::Empty: + case DependencyCollector::Reference::Kind::Tombstone: + llvm_unreachable("Cannot enumerate dead reference!"); + case DependencyCollector::Reference::Kind::UsedMember: + case DependencyCollector::Reference::Kind::PotentialMember: + case DependencyCollector::Reference::Kind::TopLevel: + case DependencyCollector::Reference::Kind::Dynamic: + f(ref); + } + } +} diff --git a/lib/AST/FrontendSourceFileDepGraphFactory.cpp b/lib/AST/FrontendSourceFileDepGraphFactory.cpp index 1b74eddeb640d..fb87b49304026 100644 --- a/lib/AST/FrontendSourceFileDepGraphFactory.cpp +++ b/lib/AST/FrontendSourceFileDepGraphFactory.cpp @@ -551,24 +551,134 @@ void FrontendSourceFileDepGraphFactory::addAllDefinedDeclsOfAGivenType( // MARK: FrontendSourceFileDepGraphFactory - adding collections of used Decls //============================================================================== +namespace { +/// Extracts uses out of a SourceFile +class UsedDeclEnumerator { + SourceFile *SF; + const DependencyTracker &depTracker; + StringRef swiftDeps; + + /// Cache these for efficiency + 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), + sourceFileInterface(DependencyKey::createKeyForWholeSourceFile( + DeclAspect::interface, swiftDeps)), + sourceFileImplementation(DependencyKey::createKeyForWholeSourceFile( + DeclAspect::implementation, swiftDeps)), + includeIntrafileDeps(includeIntrafileDeps), createDefUse(createDefUse) { + } + +public: + void enumerateAllUses() { + auto &Ctx = SF->getASTContext(); + std::unordered_set holdersOfCascadingMembers; + Ctx.evaluator.enumerateReferencesInFile(SF, [&](const auto &ref) { + const auto cascades = ref.cascades; + std::string name = ref.name.userFacingName().str(); + const auto *nominal = ref.subject; + using Kind = evaluator::DependencyCollector::Reference::Kind; + + switch (ref.kind) { + case Kind::Empty: + case Kind::Tombstone: + llvm_unreachable("Cannot enumerate dead reference!"); + case Kind::TopLevel: + return enumerateUse("", name, cascades); + case Kind::Dynamic: + return enumerateUse("", name, cascades); + case Kind::PotentialMember: { + std::string context = DependencyKey::computeContextForProvidedEntity< + NodeKind::potentialMember>(nominal); + appendHolderOfCascadingMembers(holdersOfCascadingMembers, nominal, + cascades); + return enumerateUse(context, "", cascades); + } + case Kind::UsedMember: { + std::string context = + DependencyKey::computeContextForProvidedEntity( + nominal); + appendHolderOfCascadingMembers(holdersOfCascadingMembers, nominal, + cascades); + return enumerateUse(context, name, cascades); + } + } + }); + enumerateExternalUses(); + enumerateNominalUses(std::move(holdersOfCascadingMembers)); + } + +private: + template + void enumerateUse(StringRef context, StringRef name, bool isCascadingUse) { + // Assume that what is depended-upon is the interface + createDefUse( + DependencyKey(kind, DeclAspect::interface, context.str(), name.str()), + isCascadingUse ? sourceFileInterface : sourceFileImplementation); + } + + void appendHolderOfCascadingMembers(std::unordered_set &holders, + const NominalTypeDecl *subject, + bool isCascading) { + bool isPrivate = subject->isPrivateToEnclosingFile(); + if (isPrivate && !includeIntrafileDeps) + return; + + std::string context = + DependencyKey::computeContextForProvidedEntity( + subject); + if (isCascading) { + holders.insert(context); + } + } + + void enumerateNominalUses( + const std::unordered_set &&holdersOfCascadingMembers) { + auto &Ctx = SF->getASTContext(); + Ctx.evaluator.enumerateReferencesInFile(SF, [&](const auto &ref) { + const NominalTypeDecl *subject = ref.subject; + if (!subject) { + return; + } + + bool isPrivate = subject->isPrivateToEnclosingFile(); + if (isPrivate && !includeIntrafileDeps) { + return; + } + + std::string context = + DependencyKey::computeContextForProvidedEntity( + subject); + const bool isCascadingUse = holdersOfCascadingMembers.count(context) != 0; + enumerateUse(context, "", isCascadingUse); + }); + } + + void enumerateExternalUses() { + // external dependencies always cascade + for (StringRef s : depTracker.getDependencies()) + enumerateUse("", s, true); + } +}; +} // end namespace + void FrontendSourceFileDepGraphFactory::addAllUsedDecls() { - const DependencyKey sourceFileInterface = - DependencyKey::createKeyForWholeSourceFile(DeclAspect::interface, - swiftDeps); - - const DependencyKey sourceFileImplementation = - DependencyKey::createKeyForWholeSourceFile(DeclAspect::implementation, - swiftDeps); - - SF->getConfiguredReferencedNameTracker()->enumerateAllUses( - includePrivateDeps, depTracker, - [&](const fine_grained_dependencies::NodeKind kind, StringRef context, - StringRef name, const bool isCascadingUse) { - addAUsedDecl(DependencyKey(kind, DeclAspect::interface, context.str(), - name.str()), - isCascadingUse ? sourceFileInterface - : sourceFileImplementation); - }); + UsedDeclEnumerator(SF, depTracker, swiftDeps, includePrivateDeps, + [&](const DependencyKey &def, const DependencyKey &use) { + addAUsedDecl(def, use); + }) + .enumerateAllUses(); } //============================================================================== diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index ade97c2355846..a1a36e38096a4 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -428,7 +428,7 @@ Type GenericSignatureImpl::getSuperclassBound(Type type) const { /// required to conform. GenericSignature::RequiredProtocols GenericSignatureImpl::getRequiredProtocols(Type type) const { - if (!type->isTypeParameter()) return { }; + assert(type->isTypeParameter() && "Expected a type parameter"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = @@ -479,11 +479,11 @@ bool GenericSignatureImpl::isConcreteType(Type type) const { return bool(getConcreteType(type)); } -/// Return the concrete type that the given dependent type is constrained to, +/// Return the concrete type that the given type parameter is constrained to, /// or the null Type if it is not the subject of a concrete same-type /// constraint. Type GenericSignatureImpl::getConcreteType(Type type) const { - if (!type->isTypeParameter()) return Type(); + assert(type->isTypeParameter() && "Expected a type parameter"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = @@ -496,7 +496,8 @@ Type GenericSignatureImpl::getConcreteType(Type type) const { } LayoutConstraint GenericSignatureImpl::getLayoutConstraint(Type type) const { - if (!type->isTypeParameter()) return LayoutConstraint(); + assert(type->isTypeParameter() && + "Only type parameters can have layout constraints"); auto &builder = *getGenericSignatureBuilder(); auto equivClass = diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c8a667ebe38ab..7b44cb14704b5 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -36,7 +36,6 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PrintOptions.h" #include "swift/AST/ProtocolConformance.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/SourceFile.h" #include "swift/AST/SynthesizedFileUnit.h" #include "swift/AST/TypeCheckRequests.h" @@ -2638,16 +2637,6 @@ void SourceFile::setTypeRefinementContext(TypeRefinementContext *Root) { TRC = Root; } -void SourceFile::createReferencedNameTracker() { - assert(!RequestReferencedNames && "This file already has a name tracker."); - RequestReferencedNames.emplace(ReferencedNameTracker()); -} - -const ReferencedNameTracker * -SourceFile::getConfiguredReferencedNameTracker() const { - return getRequestBasedReferencedNameTracker(); -} - ArrayRef SourceFile::getOpaqueReturnTypeDecls() { for (auto *vd : UnvalidatedDeclsWithOpaqueReturnTypes.takeVector()) { if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) { diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index b6b2e577d00d6..51068ca10b41d 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -27,7 +27,6 @@ #include "swift/AST/ModuleNameLookup.h" #include "swift/AST/NameLookupRequests.h" #include "swift/AST/ParameterList.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/SourceFile.h" #include "swift/Basic/Debug.h" #include "swift/Basic/SourceManager.h" @@ -1309,7 +1308,7 @@ void ClassDecl::createObjCMethodLookup() { }); } -MutableArrayRef +TinyPtrVector ClassDecl::lookupDirect(ObjCSelector selector, bool isInstance) { if (!ObjCMethodLookup) { createObjCMethodLookup(); @@ -1325,7 +1324,7 @@ ClassDecl::lookupDirect(ObjCSelector selector, bool isInstance) { stored.Generation = ctx.getCurrentGeneration(); } - return { stored.Methods.begin(), stored.Methods.end() }; + return stored.Methods; } void ClassDecl::recordObjCMethod(AbstractFunctionDecl *method, diff --git a/lib/AST/ReferencedNameTracker.cpp b/lib/AST/ReferencedNameTracker.cpp deleted file mode 100644 index 601a69710f691..0000000000000 --- a/lib/AST/ReferencedNameTracker.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===---------------------------- ReferencedNameTracker.cpp ---------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -/// -/// This file implements unqualified lookup, which searches for an identifier -/// from a given context. -/// -//===----------------------------------------------------------------------===// - -#include "swift/AST/ReferencedNameTracker.h" - -#include "swift/AST/ASTContext.h" -#include "swift/AST/ASTMangler.h" -#include "swift/AST/Decl.h" -#include "swift/AST/DiagnosticEngine.h" -#include "swift/AST/DiagnosticsFrontend.h" -#include "swift/AST/FineGrainedDependencies.h" -#include "swift/AST/Module.h" -#include "swift/AST/ModuleLoader.h" -#include "swift/AST/NameLookup.h" -#include "swift/AST/SourceFile.h" -#include "swift/AST/Types.h" -#include "swift/Basic/FileSystem.h" -#include "swift/Basic/LLVM.h" -#include "swift/Basic/ReferenceDependencyKeys.h" -#include "swift/Demangling/Demangle.h" -#include "swift/Frontend/FrontendOptions.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" - -using namespace swift; -using NodeKind = fine_grained_dependencies::NodeKind; -using EnumerateUsedDecl = ReferencedNameTracker::EnumerateUsedDecl; -using DependencyKey = fine_grained_dependencies::DependencyKey; - -void ReferencedNameTracker::enumerateAllUses( - bool includeIntrafileDeps, const DependencyTracker &depTracker, - EnumerateUsedDecl enumerateUsedDecl) const { - enumerateSimpleUses(getTopLevelNames(), - enumerateUsedDecl); - enumerateSimpleUses(getDynamicLookupNames(), - enumerateUsedDecl); - enumerateExternalUses(depTracker, enumerateUsedDecl); - enumerateCompoundUses(includeIntrafileDeps, enumerateUsedDecl); -} - -template -void ReferencedNameTracker::enumerateSimpleUses( - llvm::DenseMap cascadesByName, - EnumerateUsedDecl enumerateUsedDecl) const { - for (const auto &p : cascadesByName) - enumerateUsedDecl(kind, "", p.getFirst().userFacingName(), p.getSecond()); -} - -void ReferencedNameTracker::enumerateExternalUses( - const DependencyTracker &depTracker, - EnumerateUsedDecl enumerateUsedDecl) const { - // external dependencies always cascade - for (StringRef s : depTracker.getDependencies()) - enumerateUsedDecl(NodeKind::externalDepend, "", s, true); -} - -void ReferencedNameTracker::enumerateCompoundUses( - bool includeIntrafileDeps, EnumerateUsedDecl enumerateUsedDecl) const { - enumerateNominalUses( - includeIntrafileDeps, - std::move(computeHoldersOfCascadingMembers(includeIntrafileDeps)), - enumerateUsedDecl); - enumerateMemberUses(enumerateUsedDecl); -} - -std::unordered_set -ReferencedNameTracker::computeHoldersOfCascadingMembers( - const bool includeIntrafileDeps) const { - std::unordered_set holdersOfCascadingMembers; - for (const auto &p : getUsedMembers()) { - { - bool isPrivate = p.getFirst().first->isPrivateToEnclosingFile(); - if (isPrivate && !includeIntrafileDeps) - continue; - } - std::string context = - DependencyKey::computeContextForProvidedEntity( - p.getFirst().first); - bool isCascading = p.getSecond(); - if (isCascading) - holdersOfCascadingMembers.insert(context); - } - return holdersOfCascadingMembers; -} - -void ReferencedNameTracker::enumerateNominalUses( - const bool includeIntrafileDeps, - const std::unordered_set &&holdersOfCascadingMembers, - EnumerateUsedDecl enumerateUsedDecl) const { - for (const auto &p : getUsedMembers()) { - { - bool isPrivate = p.getFirst().first->isPrivateToEnclosingFile(); - if (isPrivate && !includeIntrafileDeps) - continue; - } - - const NominalTypeDecl *nominal = p.getFirst().first; - - std::string context = - DependencyKey::computeContextForProvidedEntity( - nominal); - const bool isCascadingUse = holdersOfCascadingMembers.count(context) != 0; - enumerateUsedDecl(NodeKind::nominal, context, "", isCascadingUse); - } -} - -void ReferencedNameTracker::enumerateMemberUses( - EnumerateUsedDecl enumerateUsedDecl) const { - for (const auto &p : getUsedMembers()) { - const NominalTypeDecl *nominal = p.getFirst().first; - const auto rawName = p.getFirst().second; - const bool isPotentialMember = rawName.empty(); - const bool isCascadingUse = p.getSecond(); - if (isPotentialMember) { - std::string context = DependencyKey::computeContextForProvidedEntity< - NodeKind::potentialMember>(nominal); - enumerateUsedDecl(NodeKind::potentialMember, context, "", isCascadingUse); - } else { - std::string context = - DependencyKey::computeContextForProvidedEntity( - nominal); - std::string name = rawName.userFacingName().str(); - enumerateUsedDecl(NodeKind::member, context, name, isCascadingUse); - } - } -} diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 61d4695a4d9db..074e432f4893c 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -271,7 +271,7 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const { // The generic parameter may have been made concrete by the generic signature, // substitute into the concrete type. - if (auto concreteType = genericSig->getConcreteType(genericParam)){ + if (auto concreteType = genericSig->getConcreteType(genericParam)) { // Set the replacement type to an error, to block infinite recursion. replacementType = ErrorType::get(concreteType); diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 9658d53d9cd14..a138f4528039e 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -27,7 +27,6 @@ #include "swift/AST/NameLookup.h" #include "swift/AST/NameLookupRequests.h" #include "swift/AST/ParameterList.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/SourceFile.h" #include "swift/Basic/Debug.h" #include "swift/Basic/STLExtras.h" diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index dea2d51b7c7fa..0adaa6212d93d 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -909,15 +909,10 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions, return PCHFilename.getValue(); } -std::unique_ptr -ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, - std::string swiftPCHHash, DependencyTracker *tracker, - DWARFImporterDelegate *dwarfImporterDelegate) { - std::unique_ptr importer{ - new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)}; - +std::vector +ClangImporter::getClangArguments(ASTContext &ctx, + const ClangImporterOptions &importerOpts) { std::vector invocationArgStrs; - // Clang expects this to be like an actual command line. So we need to pass in // "clang" for argv[0] invocationArgStrs.push_back("clang"); @@ -931,6 +926,49 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, break; } addCommonInvocationArguments(invocationArgStrs, ctx, importerOpts); + return invocationArgStrs; +} + +std::unique_ptr +ClangImporter::createClangInvocation(ClangImporter *importer, + const ClangImporterOptions &importerOpts, + ArrayRef invocationArgStrs, + std::vector *CC1Args) { + std::vector invocationArgs; + invocationArgs.reserve(invocationArgStrs.size()); + for (auto &argStr : invocationArgStrs) + invocationArgs.push_back(argStr.c_str()); + // Set up a temporary diagnostic client to report errors from parsing the + // command line, which may be important for Swift clients if, for example, + // they're using -Xcc options. Unfortunately this diagnostic engine has to + // use the default options because the /actual/ options haven't been parsed + // yet. + // + // The long-term client for Clang diagnostics is set up below, after the + // clang::CompilerInstance is created. + llvm::IntrusiveRefCntPtr tempDiagOpts{ + new clang::DiagnosticOptions + }; + + ClangDiagnosticConsumer tempDiagClient{importer->Impl, *tempDiagOpts, + importerOpts.DumpClangDiagnostics}; + llvm::IntrusiveRefCntPtr tempClangDiags = + clang::CompilerInstance::createDiagnostics(tempDiagOpts.get(), + &tempDiagClient, + /*owned*/false); + + return clang::createInvocationFromCommandLine(invocationArgs, tempClangDiags, + nullptr, false, CC1Args); +} + +std::unique_ptr +ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, + std::string swiftPCHHash, DependencyTracker *tracker, + DWARFImporterDelegate *dwarfImporterDelegate) { + std::unique_ptr importer{ + new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)}; + importer->Impl.ClangArgs = getClangArguments(ctx, importerOpts); + ArrayRef invocationArgStrs = importer->Impl.ClangArgs; if (importerOpts.DumpClangDiagnostics) { llvm::errs() << "'"; @@ -940,10 +978,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, llvm::errs() << "'\n"; } - std::vector invocationArgs; - invocationArgs.reserve(invocationArgStrs.size()); - for (auto &argStr : invocationArgStrs) - invocationArgs.push_back(argStr.c_str()); + if (llvm::sys::path::extension(importerOpts.BridgingHeader) .endswith(file_types::getExtension(file_types::TY_PCH))) { @@ -961,27 +996,9 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, // Create a new Clang compiler invocation. { - // Set up a temporary diagnostic client to report errors from parsing the - // command line, which may be important for Swift clients if, for example, - // they're using -Xcc options. Unfortunately this diagnostic engine has to - // use the default options because the /actual/ options haven't been parsed - // yet. - // - // The long-term client for Clang diagnostics is set up below, after the - // clang::CompilerInstance is created. - llvm::IntrusiveRefCntPtr tempDiagOpts{ - new clang::DiagnosticOptions - }; - - ClangDiagnosticConsumer tempDiagClient{importer->Impl, *tempDiagOpts, - importerOpts.DumpClangDiagnostics}; - llvm::IntrusiveRefCntPtr tempClangDiags = - clang::CompilerInstance::createDiagnostics(tempDiagOpts.get(), - &tempDiagClient, - /*owned*/false); - - importer->Impl.Invocation = - clang::createInvocationFromCommandLine(invocationArgs, tempClangDiags); + importer->Impl.Invocation = createClangInvocation(importer.get(), + importerOpts, + invocationArgStrs); if (!importer->Impl.Invocation) return nullptr; } @@ -3049,11 +3066,6 @@ void ClangImporter::loadObjCMethods( bool isInstanceMethod, unsigned previousGeneration, llvm::TinyPtrVector &methods) { - // If we're currently looking for this selector, don't load any Objective-C - // methods. - if (Impl.ActiveSelectors.count({selector, isInstanceMethod})) - return; - const auto *objcClass = dyn_cast_or_null(classDecl->getClangDecl()); if (!objcClass) @@ -3086,10 +3098,7 @@ void ClangImporter::loadObjCMethods( // earlier, because we aren't tracking generation counts for Clang modules. // Filter out the duplicates. // FIXME: We shouldn't need to do this. - llvm::SmallPtrSet known; - known.insert(methods.begin(), methods.end()); - - if (known.insert(method).second) + if (!llvm::is_contained(methods, method)) methods.push_back(method); } @@ -4006,3 +4015,20 @@ bool ClangImporter::isInOverlayModuleForImportedModule( return !clangModule->ExportAsModule.empty() && clangModule->ExportAsModule == overlayModule->getName().str(); } + +/// Extract the specified-or-defaulted -module-cache-path that winds up in +/// the clang importer, for reuse as the .swiftmodule cache path when +/// building a ModuleInterfaceLoader. +std::string +swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) { + if (!Clang.hasPreprocessor()) + return ""; + std::string SpecificModuleCachePath = + Clang.getPreprocessor().getHeaderSearchInfo().getModuleCachePath().str(); + + // The returned-from-clang module cache path includes a suffix directory + // that is specific to the clang version and invocation; we want the + // directory above that. + return llvm::sys::path::parent_path(SpecificModuleCachePath).str(); +} + diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index d333d0e966ffb..d63601776f078 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -188,12 +188,48 @@ static ClangModuleDependenciesCacheImpl *getOrCreateClangImpl( return clangImpl; } +static std::string getModuleFilePath(StringRef moduleCacheDir, + StringRef moduleName, + StringRef contextHash) { + SmallString<128> outputPath(moduleCacheDir); + llvm::sys::path::append(outputPath, (llvm::Twine(moduleName) + + "-" + contextHash + ".pcm").str()); + return outputPath.str().str(); +} + +static std::string getModuleFilePath(StringRef moduleCacheDir, + const ModuleDeps &dep) { + return getModuleFilePath(moduleCacheDir, dep.ModuleName, dep.ContextHash); +} + /// Record the module dependencies we found by scanning Clang modules into /// the module dependencies cache. -static void recordModuleDependencies( +void ClangImporter::recordModuleDependencies( ModuleDependenciesCache &cache, const FullDependenciesResult &clangDependencies) { + struct ModuleInfo { + std::string PCMPath; + std::string ModuleMapPath; + }; + auto ModuleCacheDir = swift::getModuleCachePathFromClang(getClangInstance()); + + // A map keyed by module name and context hash. + llvm::StringMap> moduleInfoMap; + + // Traverse all Clang modules to populate moduleInfoMap for cross + // referencing later. + for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { + moduleInfoMap[clangModuleDep.ModuleName][clangModuleDep.ContextHash] = + { + // Keep track of pcm path for output. + getModuleFilePath(ModuleCacheDir, clangModuleDep), + // Keep track of modulemap file for input. + clangModuleDep.ClangModuleMapFile + }; + } for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { + assert(moduleInfoMap[clangModuleDep.ModuleName] + .count(clangModuleDep.ContextHash)); // If we've already cached this information, we're done. if (cache.hasDependencies(clangModuleDep.ModuleName, ModuleDependenciesKind::Clang)) @@ -204,14 +240,58 @@ static void recordModuleDependencies( for (const auto &fileDep : clangModuleDep.FileDeps) { fileDeps.push_back(fileDep.getKey().str()); } + // Inherit all Clang driver args when creating the clang importer. + std::vector allArgs = Impl.ClangArgs; + ClangImporterOptions Opts; + std::vector cc1Args; + + // Calling this to convert driver args to CC1 args. + createClangInvocation(this, Opts, allArgs, &cc1Args); + std::vector swiftArgs; + // We are using Swift frontend mode. + swiftArgs.push_back("-frontend"); + auto addClangArg = [&](StringRef arg) { + swiftArgs.push_back("-Xcc"); + swiftArgs.push_back("-Xclang"); + swiftArgs.push_back("-Xcc"); + swiftArgs.push_back(arg); + }; + // Add all args inheritted from creating the importer. + for (auto arg: cc1Args) { + addClangArg(arg); + } + // Add all args reported from the Clang dependencies scanner. + for(auto arg: clangModuleDep.NonPathCommandLine) { + addClangArg(arg); + } + // Add -fmodule-map-file and -fmodule-file for direct dependencies. + for (auto &dep: clangModuleDep.ClangModuleDeps) { + assert(moduleInfoMap[dep.ModuleName].count(dep.ContextHash)); + addClangArg((llvm::Twine("-fmodule-map-file=") + + moduleInfoMap[dep.ModuleName][dep.ContextHash].ModuleMapPath).str()); + addClangArg((llvm::Twine("-fmodule-file=") + + moduleInfoMap[dep.ModuleName][dep.ContextHash].PCMPath).str()); + } + // Swift frontend action: -emit-pcm + swiftArgs.push_back("-emit-pcm"); + swiftArgs.push_back("-module-name"); + swiftArgs.push_back(clangModuleDep.ModuleName); + + // Swift frontend option for output file path (Foo.pcm). + swiftArgs.push_back("-o"); + swiftArgs.push_back(moduleInfoMap[clangModuleDep.ModuleName] + [clangModuleDep.ContextHash].PCMPath); + + // Swift frontend option for input file path (Foo.modulemap). + swiftArgs.push_back(clangModuleDep.ClangModuleMapFile); // Module-level dependencies. llvm::StringSet<> alreadyAddedModules; auto dependencies = ModuleDependencies::forClangModule( clangModuleDep.ImplicitModulePCMPath, clangModuleDep.ClangModuleMapFile, clangModuleDep.ContextHash, - clangModuleDep.NonPathCommandLine, + swiftArgs, fileDeps); for (const auto &moduleName : clangModuleDep.ClangModuleDeps) { dependencies.addModuleDependency(moduleName.ModuleName, alreadyAddedModules); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 98dccac4e67fb..748c2df1e73c3 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2191,10 +2191,13 @@ namespace { if (fd->isInstanceMember() != decl->isInstanceProperty()) continue; - assert(fd->getName().getArgumentNames().empty()); + // We only care about methods with no arguments, because they can + // shadow imported properties. + if (!fd->getName().getArgumentNames().empty()) + continue; + foundMethod = true; - } else { - auto *var = cast(result); + } else if (auto *var = dyn_cast(result)) { if (var->isInstanceMember() != decl->isInstanceProperty()) continue; @@ -2280,7 +2283,7 @@ namespace { return getVersion() == getActiveSwiftVersion(); } - void recordMemberInContext(DeclContext *dc, ValueDecl *member) { + void recordMemberInContext(const DeclContext *dc, ValueDecl *member) { assert(member && "Attempted to record null member!"); auto *nominal = dc->getSelfNominalTypeDecl(); auto name = member->getBaseName(); @@ -4170,33 +4173,51 @@ namespace { bool isInstance, const DeclContext *dc, llvm::function_ref filter) { // We only need to perform this check for classes. - auto classDecl - = dc->getDeclaredInterfaceType()->getClassOrBoundGenericClass(); + auto *classDecl = dc->getSelfClassDecl(); if (!classDecl) return false; - // Make sure we don't search in Clang modules for this method. - ++Impl.ActiveSelectors[{selector, isInstance}]; - - // Look for a matching imported or deserialized member. - bool result = false; - for (auto decl : classDecl->lookupDirect(selector, isInstance)) { - if ((decl->getClangDecl() - || !decl->getDeclContext()->getParentSourceFile()) - && importedName.getDeclName() == decl->getName() - && filter(decl)) { - result = true; - break; + auto matchesImportedDecl = [&](Decl *member) -> bool { + auto *afd = dyn_cast(member); + if (!afd) + return false; + + // Instance-ness must match. + if (afd->isObjCInstanceMethod() != isInstance) + return false; + + // Both the selector and imported name must match. + if (afd->getObjCSelector() != selector || + importedName.getDeclName() != afd->getName()) { + return false; } - } - // Restore the previous active count in the active-selector mapping. - auto activeCount = Impl.ActiveSelectors.find({selector, isInstance}); - --activeCount->second; - if (activeCount->second == 0) - Impl.ActiveSelectors.erase(activeCount); + // Finally, the provided filter must match. + return filter(afd); + }; - return result; + // First check to see if we've already imported a method with the same + // selector. + auto importedMembers = Impl.MembersForNominal.find(classDecl); + if (importedMembers != Impl.MembersForNominal.end()) { + auto baseName = importedName.getDeclName().getBaseName(); + auto membersForName = importedMembers->second.find(baseName); + if (membersForName != importedMembers->second.end()) { + return llvm::any_of(membersForName->second, matchesImportedDecl); + } + } + + // Then, for a deserialized Swift class, check to see if it has brought in + // any matching @objc methods. + if (classDecl->wasDeserialized()) { + auto &ctx = Impl.SwiftContext; + TinyPtrVector deserializedMethods; + ctx.loadObjCMethods(classDecl, selector, isInstance, + /*prevGeneration*/ 0, deserializedMethods, + /*swiftOnly*/ true); + return llvm::any_of(deserializedMethods, matchesImportedDecl); + } + return false; } Decl *importObjCMethodDecl(const clang::ObjCMethodDecl *decl, @@ -4448,6 +4469,9 @@ namespace { // If this method overrides another method, mark it as such. recordObjCOverride(result); + // Make a note that we've imported this method into this context. + recordMemberInContext(dc, result); + // Record the error convention. if (errorConvention) { result->setForeignErrorConvention(*errorConvention); @@ -4484,14 +4508,6 @@ namespace { Impl.addAlternateDecl(result, cast(imported)); } } - - // We only care about recording methods with no arguments here, because - // they can shadow imported properties. - if (!isa(result) && - result->getName().getArgumentNames().empty()) { - recordMemberInContext(dc, result); - } - return result; } @@ -6461,6 +6477,7 @@ ConstructorDecl *SwiftDeclConverter::importConstructor( /*GenericParams=*/nullptr, const_cast(dc)); addObjCAttribute(result, selector); + recordMemberInContext(dc, result); Impl.recordImplicitUnwrapForDecl(result, importedType.isImplicitlyUnwrapped()); @@ -6668,14 +6685,24 @@ SwiftDeclConverter::importSubscript(Decl *decl, }; auto findCounterpart = [&](clang::Selector sel) -> FuncDecl * { - // If the declaration we're starting from is in a class, first - // look for a class member with the appropriate selector. + // If the declaration we're starting from is in a class, first check to see + // if we've already imported an instance method with a matching selector. if (auto classDecl = decl->getDeclContext()->getSelfClassDecl()) { auto swiftSel = Impl.importSelector(sel); - for (auto found : classDecl->lookupDirect(swiftSel, true)) { - if (auto foundFunc = dyn_cast(found)) - if (foundFunc->hasClangNode()) - return foundFunc; + auto importedMembers = Impl.MembersForNominal.find(classDecl); + if (importedMembers != Impl.MembersForNominal.end()) { + for (auto membersForName : importedMembers->second) { + for (auto *member : membersForName.second) { + // Must be an instance method. + auto *afd = dyn_cast(member); + if (!afd || !afd->isInstanceMember()) + continue; + + // Selector must match. + if (afd->getObjCSelector() == swiftSel) + return afd; + } + } } } diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 72de3a47bcde7..7963151dda780 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -390,6 +390,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Clang parser, which is used to load textual headers. std::unique_ptr Mangler; + /// Clang arguments used to create the Clang invocation. + std::vector ClangArgs; public: /// Mapping of already-imported declarations. llvm::DenseMap, Decl *> ImportedDecls; @@ -439,12 +441,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation llvm::DenseMap> ImportedMacroConstants; - /// Keeps track of active selector-based lookups, so that we don't infinitely - /// recurse when checking whether a method with a given selector has already - /// been imported. - llvm::DenseMap, unsigned> - ActiveSelectors; - // Mapping from imported types to their raw value types. llvm::DenseMap RawTypes; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 689d108faf8ed..52e1ac47f05d4 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -180,6 +180,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddAllArgs(arguments, options::OPT_I); inputArgs.AddAllArgs(arguments, options::OPT_F, options::OPT_Fsystem); + inputArgs.AddAllArgs(arguments, options::OPT_vfsoverlay); inputArgs.AddLastArg(arguments, options::OPT_AssertConfig); inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load); @@ -287,6 +288,8 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, arguments.push_back("-enable-anonymous-context-mangled-names"); } + inputArgs.AddLastArg(arguments, options::OPT_disable_leaf_frame_pointer_elim); + // Pass through any subsystem flags. inputArgs.AddAllArgs(arguments, options::OPT_Xllvm); inputArgs.AddAllArgs(arguments, options::OPT_Xcc); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 52d930029e5ae..4b9f1005a4133 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1498,6 +1498,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, getRuntimeCompatVersion(); } + if (Args.hasArg(OPT_disable_leaf_frame_pointer_elim)) + Opts.DisableFPElimLeaf = true; + return false; } diff --git a/lib/Frontend/DependencyVerifier.cpp b/lib/Frontend/DependencyVerifier.cpp index bfa77ad0126d5..b8950be51032d 100644 --- a/lib/Frontend/DependencyVerifier.cpp +++ b/lib/Frontend/DependencyVerifier.cpp @@ -279,11 +279,9 @@ struct Obligation { /// in the referenced name trackers associated with that file. class DependencyVerifier { SourceManager &SM; - const DependencyTracker &DT; public: - explicit DependencyVerifier(SourceManager &SM, const DependencyTracker &DT) - : SM(SM), DT(DT) {} + explicit DependencyVerifier(SourceManager &SM) : SM(SM) {} bool verifyFile(const SourceFile *SF); @@ -338,11 +336,11 @@ class DependencyVerifier { } private: - StringRef copyDemangledTypeName(ASTContext &Ctx, StringRef str) { - Demangle::DemangleOptions Opts; - Opts.ShowPrivateDiscriminators = false; - Opts.DisplayModuleNames = true; - return Ctx.AllocateCopy(Demangle::demangleTypeAsString(str, Opts)); + StringRef copyQualifiedTypeName(ASTContext &Ctx, NominalTypeDecl *subject) { + auto printOptions = PrintOptions(); + printOptions.FullyQualifiedTypes = true; + auto key = subject->getDeclaredInterfaceType()->getString(printOptions); + return Ctx.AllocateCopy(key); } private: @@ -428,34 +426,27 @@ bool DependencyVerifier::parseExpectations( bool DependencyVerifier::constructObligations(const SourceFile *SF, ObligationMap &Obligations) { - auto *tracker = SF->getConfiguredReferencedNameTracker(); - assert(tracker && "Constructed source file without referenced name tracker!"); - auto &Ctx = SF->getASTContext(); - tracker->enumerateAllUses( - /*includeIntrafileDeps*/ true, DT, - [&](const fine_grained_dependencies::NodeKind kind, StringRef context, - StringRef name, const bool isCascadingUse) { - using NodeKind = fine_grained_dependencies::NodeKind; - switch (kind) { - case NodeKind::externalDepend: - // We only care about the referenced name trackers for now. The set of - // external dependencies is often quite a large subset of the SDK. - return; - case NodeKind::nominal: - // Nominals duplicate member entries. We care about the member itself. - return; - case NodeKind::potentialMember: { - auto key = copyDemangledTypeName(Ctx, context); - auto nameCpy = Ctx.AllocateCopy(name); + Ctx.evaluator.enumerateReferencesInFile( + SF, [&](const auto &reference) { + const auto isCascadingUse = reference.cascades; + using NodeKind = evaluator::DependencyCollector::Reference::Kind; + switch (reference.kind) { + case NodeKind::Empty: + case NodeKind::Tombstone: + llvm_unreachable("Cannot enumerate dead dependency!"); + + case NodeKind::PotentialMember: { + auto key = copyQualifiedTypeName(Ctx, reference.subject); Obligations.insert({Obligation::Key::forPotentialMember(key), - {nameCpy, Expectation::Kind::PotentialMember, + {"", Expectation::Kind::PotentialMember, isCascadingUse ? Expectation::Scope::Cascading : Expectation::Scope::Private}}); } break; - case NodeKind::member: { - auto demContext = copyDemangledTypeName(Ctx, context); + case NodeKind::UsedMember: { + auto demContext = copyQualifiedTypeName(Ctx, reference.subject); + auto name = reference.name.userFacingName(); auto key = Ctx.AllocateCopy((demContext + "." + name).str()); Obligations.insert({Obligation::Key::forMember(key), {key, Expectation::Kind::Member, @@ -463,25 +454,21 @@ bool DependencyVerifier::constructObligations(const SourceFile *SF, : Expectation::Scope::Private}}); } break; - case NodeKind::dynamicLookup: { - auto contextCpy = Ctx.AllocateCopy(context); - auto key = Ctx.AllocateCopy(name); + case NodeKind::Dynamic: { + auto key = Ctx.AllocateCopy(reference.name.userFacingName()); Obligations.insert({Obligation::Key::forDynamicMember(key), - {contextCpy, Expectation::Kind::DynamicMember, + {"", Expectation::Kind::DynamicMember, isCascadingUse ? Expectation::Scope::Cascading : Expectation::Scope::Private}}); - break; } - case NodeKind::topLevel: - case NodeKind::sourceFileProvide: { - auto key = Ctx.AllocateCopy(name); + break; + case NodeKind::TopLevel: { + auto key = Ctx.AllocateCopy(reference.name.userFacingName()); Obligations.insert({Obligation::Key::forProvides(key), {key, Expectation::Kind::Provides, Expectation::Scope::None}}); - break; } - case NodeKind::kindCount: - llvm_unreachable("Given count node?"); + break; } }); @@ -491,8 +478,6 @@ bool DependencyVerifier::constructObligations(const SourceFile *SF, bool DependencyVerifier::verifyObligations( const SourceFile *SF, const std::vector &ExpectedDependencies, ObligationMap &OM, llvm::StringMap &NegativeExpectations) { - auto *tracker = SF->getConfiguredReferencedNameTracker(); - assert(tracker && "Constructed source file without referenced name tracker!"); auto &diags = SF->getASTContext().Diags; for (auto &expectation : ExpectedDependencies) { const bool wantsCascade = expectation.isCascading(); @@ -645,10 +630,9 @@ bool DependencyVerifier::verifyFile(const SourceFile *SF) { // MARK: Main entrypoints //===----------------------------------------------------------------------===// -bool swift::verifyDependencies(SourceManager &SM, const DependencyTracker &DT, - ArrayRef SFs) { +bool swift::verifyDependencies(SourceManager &SM, ArrayRef SFs) { bool HadError = false; - DependencyVerifier Verifier{SM, DT}; + DependencyVerifier Verifier{SM}; for (const auto *FU : SFs) { if (const auto *SF = dyn_cast(FU)) HadError |= Verifier.verifyFile(SF); @@ -656,10 +640,9 @@ bool swift::verifyDependencies(SourceManager &SM, const DependencyTracker &DT, return HadError; } -bool swift::verifyDependencies(SourceManager &SM, const DependencyTracker &DT, - ArrayRef SFs) { +bool swift::verifyDependencies(SourceManager &SM, ArrayRef SFs) { bool HadError = false; - DependencyVerifier Verifier{SM, DT}; + DependencyVerifier Verifier{SM}; for (const auto *SF : SFs) { HadError |= Verifier.verifyFile(SF); } diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 200f6765cfc52..950eb3e2c5a5c 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -893,7 +893,6 @@ SourceFile *CompilerInstance::createSourceFileForMainModule( if (isPrimary) { PrimarySourceFiles.push_back(inputFile); inputFile->enableInterfaceHash(); - inputFile->createReferencedNameTracker(); } if (bufferID == SourceMgr.getCodeCompletionBufferID()) { diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 6419b805edb90..884c5fa9f47bf 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -41,22 +41,6 @@ using namespace swift; using FileDependency = SerializationOptions::FileDependency; -/// Extract the specified-or-defaulted -module-cache-path that winds up in -/// the clang importer, for reuse as the .swiftmodule cache path when -/// building a ModuleInterfaceLoader. -std::string -swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) { - if (!Clang.hasPreprocessor()) - return ""; - std::string SpecificModuleCachePath = - Clang.getPreprocessor().getHeaderSearchInfo().getModuleCachePath().str(); - - // The returned-from-clang module cache path includes a suffix directory - // that is specific to the clang version and invocation; we want the - // directory above that. - return llvm::sys::path::parent_path(SpecificModuleCachePath).str(); -} - #pragma mark - Forwarding Modules namespace { @@ -1048,6 +1032,7 @@ void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames( void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface( const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts) { + GenericArgs.push_back("-frontend"); // Start with a SubInvocation that copies various state from our // invoking ASTContext. GenericArgs.push_back("-compile-module-from-interface"); diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 704aa40bf3a5c..8ce9b9df6fea9 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -35,7 +35,6 @@ #include "swift/AST/IRGenRequests.h" #include "swift/AST/NameLookup.h" #include "swift/AST/ASTMangler.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/TypeRefinementContext.h" #include "swift/Basic/Dwarf.h" #include "swift/Basic/Edit.h" @@ -692,11 +691,25 @@ static void countStatsPostSema(UnifiedStatsReporter &Stats, } for (auto SF : Instance.getPrimarySourceFiles()) { - if (auto *R = SF->getConfiguredReferencedNameTracker()) { - C.NumReferencedTopLevelNames += R->getTopLevelNames().size(); - C.NumReferencedDynamicNames += R->getDynamicLookupNames().size(); - C.NumReferencedMemberNames += R->getUsedMembers().size(); - } + auto &Ctx = SF->getASTContext(); + Ctx.evaluator.enumerateReferencesInFile(SF, [&C](const auto &ref) { + using NodeKind = evaluator::DependencyCollector::Reference::Kind; + switch (ref.kind) { + case NodeKind::Empty: + case NodeKind::Tombstone: + llvm_unreachable("Cannot enumerate dead dependency!"); + case NodeKind::TopLevel: + C.NumReferencedTopLevelNames += 1; + return; + case NodeKind::Dynamic: + C.NumReferencedDynamicNames += 1; + return; + case NodeKind::PotentialMember: + case NodeKind::UsedMember: + C.NumReferencedMemberNames += 1; + return; + } + }); } if (!Instance.getPrimarySourceFiles().empty()) { @@ -2169,11 +2182,10 @@ int swift::performFrontend(ArrayRef Args, if (Invocation.getFrontendOptions().EnableIncrementalDependencyVerifier) { if (!Instance->getPrimarySourceFiles().empty()) { HadError |= swift::verifyDependencies(Instance->getSourceMgr(), - *Instance->getDependencyTracker(), Instance->getPrimarySourceFiles()); } else { HadError |= swift::verifyDependencies( - Instance->getSourceMgr(), *Instance->getDependencyTracker(), + Instance->getSourceMgr(), Instance->getMainModule()->getFiles()); } } diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index a8288abf7a917..9b906ec2a8e74 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -656,13 +656,13 @@ class ExprContextAnalyzer { if (memberDC && ty->hasTypeParameter()) ty = memberDC->mapTypeIntoContext(ty); + bool canSkip = + paramList && (paramList->get(Pos)->isDefaultArgument() || + paramList->get(Pos)->isVariadic()); + if (paramType.hasLabel() && MayNeedName) { - bool isDefaulted = paramList && - paramList->get(Pos)->isDefaultArgument(); if (seenArgs.insert({paramType.getLabel(), ty.getPointer()}).second) - recordPossibleParam(¶mType, !isDefaulted); - if (isDefaulted) - continue; + recordPossibleParam(¶mType, !canSkip); } else { auto argTy = ty; if (paramType.isInOut()) @@ -670,7 +670,8 @@ class ExprContextAnalyzer { if (seenTypes.insert(argTy.getPointer()).second) recordPossibleType(argTy); } - break; + if (!canSkip) + break; } // If the argument position is out of expeceted number, indicate that // with optional nullptr param. @@ -980,11 +981,13 @@ class ExprContextAnalyzer { case ExprKind::Binary: case ExprKind::PrefixUnary: case ExprKind::Assign: - case ExprKind::Array: case ExprKind::Dictionary: case ExprKind::If: case ExprKind::UnresolvedMember: return true; + case ExprKind::Array: + return (!Parent.getAsExpr() || + !isa(Parent.getAsExpr())); case ExprKind::Tuple: { auto ParentE = Parent.getAsExpr(); return !ParentE || diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index cd6c494bce74e..d1027761e78d1 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -993,9 +993,14 @@ class ListAligner { SourceLoc AlignLoc; SourceLoc LastEndLoc; bool HasOutdent = false; + bool BreakAlignment = false; public: + /// Don't column-align if any element starts on the same line as IntroducerLoc + /// but ends on a later line. + bool BreakAlignmentIfSpanning = false; + /// Constructs a new \c ListAligner for a list bounded by separate opening and /// closing tokens, e.g. tuples, array literals, parameter lists, etc. /// @@ -1068,8 +1073,11 @@ class ListAligner { assert(Range.isValid()); LastEndLoc = Range.End; - HasOutdent |= isOnSameLine(SM, IntroducerLoc, Range.Start) && - OutdentChecker::hasOutdent(SM, Range, WalkableParent); + if (isOnSameLine(SM, IntroducerLoc, Range.Start)) { + HasOutdent |= OutdentChecker::hasOutdent(SM, Range, WalkableParent); + if (BreakAlignmentIfSpanning) + BreakAlignment |= !isOnSameLine(SM, IntroducerLoc, Range.End); + } if (HasOutdent || !SM.isBeforeInBuffer(Range.Start, TargetLoc)) return; @@ -1128,7 +1136,7 @@ class ListAligner { } bool ShouldIndent = shouldIndent(HasTrailingComma, TargetIsTrailing); - if (ShouldIndent && AlignLoc.isValid()) { + if (ShouldIndent && !BreakAlignment && AlignLoc.isValid()) { setAlignmentIfNeeded(Override); return IndentContext {AlignLoc, false, IndentContext::Exact}; } @@ -1140,7 +1148,7 @@ class ListAligner { /// This should be called before returning an \c IndentContext for a subrange /// of the list. void setAlignmentIfNeeded(ContextOverride &Override) { - if (HasOutdent || AlignLoc.isInvalid()) + if (HasOutdent || BreakAlignment || AlignLoc.isInvalid()) return; Override.setExact(SM, AlignLoc); } @@ -1676,6 +1684,36 @@ class FormatWalker : public ASTWalker { SourceLoc ContextLoc = PBD->getStartLoc(), IntroducerLoc = PBD->getLoc(); ListAligner Aligner(SM, TargetLocation, ContextLoc, IntroducerLoc); + + // Don't column align PBD entries if any entry spans from the same line as + // the IntroducerLoc (var/let) to another line. E.g. + // + // let foo = someItem + // .getValue(), // Column-alignment looks ok here, but... + // bar = otherItem + // .getValue() + // + // getAThing() + // .andDoStuffWithIt() + // let foo = someItem + // .getValue() // looks over-indented here, which is more common... + // getOtherThing() + // .andDoStuffWithIt() + // + // getAThing() + // .andDoStuffWithIt() + // let foo = someItem + // .getValue() // so break column alignment in this case... + // doOtherThing() + // + // let foo = someItem.getValue(), + // bar = otherItem.getValue() // but not in this case. + // + // Using this rule, rather than handling single and multi-entry PBDs + // differently, ensures that the as-typed-out indentation matches the + // re-indented indentation for multi-entry PBDs. + Aligner.BreakAlignmentIfSpanning = true; + for (auto I: range(PBD->getNumPatternEntries())) { SourceRange EntryRange = PBD->getEqualLoc(I); VarDecl *SingleVar = nullptr; diff --git a/lib/IDE/ModuleInterfacePrinting.cpp b/lib/IDE/ModuleInterfacePrinting.cpp index 2315576134277..8bccb61ed88cd 100644 --- a/lib/IDE/ModuleInterfacePrinting.cpp +++ b/lib/IDE/ModuleInterfacePrinting.cpp @@ -840,6 +840,16 @@ void swift::ide::printSwiftSourceInterface(SourceFile &File, File.print(Printer, Options); } +static Decl* getTopLevelDecl(Decl *D) { + while (!D->getDeclContext()->isModuleScopeContext()) { + auto *ParentD = D->getDeclContext()->getAsDecl(); + if (!ParentD) + break; + D = ParentD; + } + return D; +} + void swift::ide::printHeaderInterface( StringRef Filename, ASTContext &Ctx, @@ -858,10 +868,8 @@ void swift::ide::printHeaderInterface( SmallVector ClangDecls; llvm::SmallPtrSet SeenDecls; auto headerReceiver = [&](Decl *D) { - if (SeenDecls.count(D) == 0) { - SeenDecls.insert(D); + if (SeenDecls.insert(getTopLevelDecl(D)).second) ClangDecls.push_back(D); - } }; Importer.lookupDeclsFromHeader(Filename, headerFilter, headerReceiver); @@ -881,6 +889,10 @@ void swift::ide::printHeaderInterface( PrinterToUse = &RegularCommentPrinter; for (auto *D : ClangDecls) { + // Even though the corresponding clang decl should be top-level, its + // equivalent Swift decl may not be. E.g. a top-level function may be mapped + // to a property accessor in Swift. + D = getTopLevelDecl(D); ASTPrinter &Printer = *PrinterToUse; if (!AdjustedOptions.shouldPrint(D)) { Printer.callAvoidPrintDeclPost(D); diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 4dfd535594683..7c8423d1f357b 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -687,15 +687,26 @@ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload( llvm::Value *caseIndexFromValue = zero; if (fixedSize > Size(0)) { - // Read up to one pointer-sized 'chunk' of the payload. - // The size of the chunk does not have to be a power of 2. - auto *caseIndexType = llvm::IntegerType::get(Ctx, - fixedSize.getValueInBits()); - auto *caseIndexAddr = Builder.CreateBitCast(valueAddr, - caseIndexType->getPointerTo()); - caseIndexFromValue = Builder.CreateZExtOrTrunc( - Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), - IGM.Int32Ty); + // llvm only supports integer types upto a certain size (i.e selection dag + // will crash). + if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) { + // Read up to one pointer-sized 'chunk' of the payload. + // The size of the chunk does not have to be a power of 2. + auto *caseIndexType = + llvm::IntegerType::get(Ctx, fixedSize.getValueInBits()); + auto *caseIndexAddr = + Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo()); + caseIndexFromValue = Builder.CreateZExtOrTrunc( + Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), + IGM.Int32Ty); + } else { + auto *caseIndexType = llvm::IntegerType::get(Ctx, 32); + auto *caseIndexAddr = + Builder.CreateBitCast(valueAddr, caseIndexType->getPointerTo()); + caseIndexFromValue = Builder.CreateZExtOrTrunc( + Builder.CreateLoad(Address(caseIndexAddr, Alignment(1))), + IGM.Int32Ty); + } } auto *result1 = Builder.CreateAdd( @@ -867,11 +878,25 @@ void irgen::storeFixedTypeEnumTagSinglePayload( payloadIndex->addIncoming(payloadIndex0, payloadLT4BB); if (fixedSize > Size(0)) { - // Write the value to the payload as a zero extended integer. - auto *intType = Builder.getIntNTy(fixedSize.getValueInBits()); - Builder.CreateStore( - Builder.CreateZExtOrTrunc(payloadIndex, intType), - Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + if (fixedSize.getValueInBits() <= llvm::IntegerType::MAX_INT_BITS / 4) { + // Write the value to the payload as a zero extended integer. + auto *intType = Builder.getIntNTy(fixedSize.getValueInBits()); + Builder.CreateStore( + Builder.CreateZExtOrTrunc(payloadIndex, intType), + Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + } else { + // Write the value to the payload as a zero extended integer. + Size limit = IGM.getPointerSize(); + auto *intType = Builder.getIntNTy(limit.getValueInBits()); + Builder.CreateStore( + Builder.CreateZExtOrTrunc(payloadIndex, intType), + Builder.CreateBitCast(valueAddr, intType->getPointerTo())); + // Zero the remainder of the payload. + auto zeroAddr = Builder.CreateConstByteArrayGEP(valueAddr, limit); + auto zeroSize = Builder.CreateSub( + size, llvm::ConstantInt::get(size->getType(), limit.getValue())); + Builder.CreateMemSet(zeroAddr, Builder.getInt8(0), zeroSize); + } } // Write to the extra tag bytes, if any. emitSetTag(IGF, extraTagBitsAddr, extraTagIndex, numExtraTagBytes); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 96617c2a5273c..afaebcc924ad3 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -90,11 +90,26 @@ static llvm::PointerType *createStructPointerType(IRGenModule &IGM, return createStructType(IGM, name, types)->getPointerTo(DefaultAS); }; -static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, - llvm::LLVMContext &LLVMContext, - const IRGenOptions &Opts, - StringRef ModuleName, - StringRef PD) { +static clang::CodeGenOptions::FramePointerKind +shouldUseFramePointer(const IRGenOptions &Opts, const llvm::Triple &triple) { + if (Opts.DisableFPElim) { + // General frame pointer elimination is disabled. + // Should we at least eliminate in leaf functions? + // Currently we only do that on arm64 (this matches the behavior of clang). + return Opts.DisableFPElimLeaf + ? clang::CodeGenOptions::FramePointerKind::All + : triple.isAArch64() + ? clang::CodeGenOptions::FramePointerKind::NonLeaf + : clang::CodeGenOptions::FramePointerKind::All; + } + + return clang::CodeGenOptions::FramePointerKind::None; +} + +static clang::CodeGenerator * +createClangCodeGenerator(ASTContext &Context, llvm::LLVMContext &LLVMContext, + const IRGenOptions &Opts, StringRef ModuleName, + StringRef PD, const llvm::Triple &triple) { auto Loader = Context.getClangModuleLoader(); auto *Importer = static_cast(&*Loader); assert(Importer && "No clang module loader!"); @@ -102,9 +117,7 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context, auto &CGO = Importer->getClangCodeGenOpts(); CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0; - CGO.setFramePointer(Opts.DisableFPElim - ? clang::CodeGenOptions::FramePointerKind::All - : clang::CodeGenOptions::FramePointerKind::None); + CGO.setFramePointer(shouldUseFramePointer(Opts, triple)); CGO.DiscardValueNames = !Opts.shouldProvideValueNames(); switch (Opts.DebugInfoLevel) { case IRGenDebugInfoLevel::None: @@ -194,17 +207,17 @@ static void sanityCheckStdlib(IRGenModule &IGM) { IRGenModule::IRGenModule(IRGenerator &irgen, std::unique_ptr &&target, - SourceFile *SF, - StringRef ModuleName, StringRef OutputFilename, + SourceFile *SF, StringRef ModuleName, + StringRef OutputFilename, StringRef MainInputFilenameForDebugInfo, StringRef PrivateDiscriminator) - : LLVMContext(new llvm::LLVMContext()), - IRGen(irgen), Context(irgen.SIL.getASTContext()), + : LLVMContext(new llvm::LLVMContext()), IRGen(irgen), + Context(irgen.SIL.getASTContext()), // The LLVMContext (and the IGM itself) will get deleted by the IGMDeleter // as long as the IGM is registered with the IRGenerator. - ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext, - irgen.Opts, - ModuleName, PrivateDiscriminator)), + ClangCodeGen(createClangCodeGenerator(Context, *LLVMContext, irgen.Opts, + ModuleName, PrivateDiscriminator, + irgen.getEffectiveClangTriple())), Module(*ClangCodeGen->GetModule()), DataLayout(irgen.getClangDataLayout()), Triple(irgen.getEffectiveClangTriple()), TargetMachine(std::move(target)), @@ -1009,7 +1022,20 @@ bool swift::irgen::shouldRemoveTargetFeature(StringRef feature) { void IRGenModule::setHasFramePointer(llvm::AttrBuilder &Attrs, bool HasFramePointer) { - Attrs.addAttribute("frame-pointer", HasFramePointer ? "all" : "none"); + if (!HasFramePointer) { + Attrs.addAttribute("frame-pointer", "none"); + return; + } + if (IRGen.Opts.DisableFPElimLeaf) { + Attrs.addAttribute("frame-pointer", "all"); + return; + } + + // We omit frame pointers for leaf functions only for arm64 for now (matching + // clang's behavior). + auto framePointer = + IRGen.getEffectiveClangTriple().isAArch64() ? "non-leaf" : "all"; + Attrs.addAttribute("frame-pointer", framePointer); } void IRGenModule::setHasFramePointer(llvm::Function *F, @@ -1022,42 +1048,22 @@ void IRGenModule::setHasFramePointer(llvm::Function *F, /// Construct initial function attributes from options. void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs, OptimizationMode FuncOptMode) { + // Add the default attributes for the Clang configuration. + clang::CodeGen::addDefaultFunctionDefinitionAttributes(getClangCGM(), Attrs); + // Add frame pointer attributes. + // FIXME: why are we doing this? setHasFramePointer(Attrs, IRGen.Opts.DisableFPElim); - // Add target-cpu and target-features if they are non-null. - auto *Clang = static_cast(Context.getClangModuleLoader()); - clang::TargetOptions &ClangOpts = Clang->getTargetInfo().getTargetOpts(); - - std::string &CPU = ClangOpts.CPU; - if (CPU != "") - Attrs.addAttribute("target-cpu", CPU); - - std::vector Features; - for (auto &F : ClangOpts.Features) - if (!shouldRemoveTargetFeature(F)) - Features.push_back(F); - - if (!Features.empty()) { - SmallString<64> allFeatures; - // Sort so that the target features string is canonical. - std::sort(Features.begin(), Features.end()); - llvm::interleave(Features, [&](const std::string &s) { - allFeatures.append(s); - }, [&]{ - allFeatures.push_back(','); - }); - Attrs.addAttribute("target-features", allFeatures); - } + // Add/remove MinSize based on the appropriate setting. if (FuncOptMode == OptimizationMode::NotSet) FuncOptMode = IRGen.Opts.OptMode; - if (FuncOptMode == OptimizationMode::ForSize) + if (FuncOptMode == OptimizationMode::ForSize) { + Attrs.addAttribute(llvm::Attribute::OptimizeForSize); Attrs.addAttribute(llvm::Attribute::MinSize); - - auto triple = llvm::Triple(ClangOpts.Triple); - if (triple.getArchName() == "arm64e") { - Attrs.addAttribute("ptrauth-returns"); - Attrs.addAttribute("ptrauth-calls"); + } else { + Attrs.removeAttribute(llvm::Attribute::MinSize); + Attrs.removeAttribute(llvm::Attribute::OptimizeForSize); } } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index e0697741476dc..e5239778d7769 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -709,8 +709,10 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial( } if (IGM.getSILModule().isWholeModule()) { - if (nominal.isResilient(IGM.getSwiftModule(), - ResilienceExpansion::Maximal)) { + // Canonical prespecializations can only be emitted within the module where + // the generic type is itself defined, since it is the module where the + // metadata accessor is defined. + if (IGM.getSwiftModule() != nominal.getModuleContext()) { return false; } } else { @@ -727,6 +729,11 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial( } } + if (nominal.isResilient(IGM.getSwiftModule(), + ResilienceExpansion::Maximal)) { + return false; + } + if (isa(type) || isa(type)) { // TODO: Support classes. return false; diff --git a/lib/Parse/ParseRequests.cpp b/lib/Parse/ParseRequests.cpp index 8f1f9d23cd3b5..3890b5cb55ce8 100644 --- a/lib/Parse/ParseRequests.cpp +++ b/lib/Parse/ParseRequests.cpp @@ -96,8 +96,7 @@ BraceStmt *ParseAbstractFunctionBodyRequest::evaluate( SourceFile &sf = *afd->getDeclContext()->getParentSourceFile(); SourceManager &sourceMgr = sf.getASTContext().SourceMgr; unsigned bufferID = sourceMgr.findBufferContainingLoc(afd->getLoc()); - Parser parser(bufferID, sf, static_cast(nullptr), - nullptr, nullptr); + Parser parser(bufferID, sf, /*SIL*/ nullptr); parser.SyntaxContext->disable(); auto body = parser.parseAbstractFunctionBodyDelayed(afd); afd->setBodyKind(BodyKind::Parsed); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 118c59aee12dc..3b3a87d2e5c55 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -110,7 +110,7 @@ void tokenize(const LangOptions &LangOpts, const SourceManager &SM, using namespace swift; using namespace swift::syntax; -void SILParserTUStateBase::anchor() { } +void SILParserStateBase::anchor() { } void swift::performCodeCompletionSecondPass( SourceFile &SF, CodeCompletionCallbacksFactory &Factory) { @@ -379,14 +379,14 @@ static LexerMode sourceFileKindToLexerMode(SourceFileKind kind) { llvm_unreachable("covered switch"); } -Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL, +Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserStateBase *SIL, PersistentParserState *PersistentState, std::shared_ptr SPActions) : Parser(BufferID, SF, &SF.getASTContext().Diags, SIL, PersistentState, std::move(SPActions)) {} Parser::Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags, - SILParserTUStateBase *SIL, + SILParserStateBase *SIL, PersistentParserState *PersistentState, std::shared_ptr SPActions) : Parser( @@ -521,8 +521,7 @@ class TokenRecorder: public ConsumeTokenReceiver { } // End of an anonymous namespace. Parser::Parser(std::unique_ptr Lex, SourceFile &SF, - SILParserTUStateBase *SIL, - PersistentParserState *PersistentState, + SILParserStateBase *SIL, PersistentParserState *PersistentState, std::shared_ptr SPActions) : SourceMgr(SF.getASTContext().SourceMgr), Diags(SF.getASTContext().Diags), diff --git a/lib/PrintAsObjC/ModuleContentsWriter.cpp b/lib/PrintAsObjC/ModuleContentsWriter.cpp index a9b36541f31b2..ba703f28937cc 100644 --- a/lib/PrintAsObjC/ModuleContentsWriter.cpp +++ b/lib/PrintAsObjC/ModuleContentsWriter.cpp @@ -56,7 +56,7 @@ class ReferencedTypeFinder : public TypeDeclFinder { Action visitTypeAliasType(TypeAliasType *aliasTy) override { if (aliasTy->getDecl()->hasClangNode() && !aliasTy->getDecl()->isCompatibilityAlias()) { - assert(!aliasTy->getGenericSignature()); + assert(!aliasTy->getDecl()->isGeneric()); Callback(*this, aliasTy->getDecl()); } else { Type(aliasTy->getSinglyDesugaredType()).walk(*this); diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 1436ac2e085ce..d74cb490d61e8 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -46,13 +46,11 @@ using namespace swift::syntax; // SILParserState implementation //===----------------------------------------------------------------------===// -namespace swift { -// This has to be in the 'swift' namespace because it's forward-declared for -// SILParserState. -class SILParserTUState : public SILParserTUStateBase { +namespace { +class SILParserState : public SILParserStateBase { public: - explicit SILParserTUState(SILModule &M) : M(M) {} - ~SILParserTUState(); + explicit SILParserState(SILModule &M) : M(M) {} + ~SILParserState(); SILModule &M; @@ -80,9 +78,9 @@ class SILParserTUState : public SILParserTUStateBase { bool parseSILProperty(Parser &P) override; bool parseSILScope(Parser &P) override; }; -} // end namespace swift +} // end anonymous namespace -SILParserTUState::~SILParserTUState() { +SILParserState::~SILParserState() { if (!ForwardRefFns.empty()) { for (auto Entry : ForwardRefFns) { if (Entry.second.Loc.isValid()) { @@ -101,11 +99,6 @@ SILParserTUState::~SILParserTUState() { } } -SILParserState::SILParserState(SILModule *M) - : Impl(M ? std::make_unique(*M) : nullptr) {} - -SILParserState::~SILParserState() = default; - std::unique_ptr ParseSILModuleRequest::evaluate(Evaluator &evaluator, SILGenDescriptor desc) const { @@ -117,8 +110,8 @@ ParseSILModuleRequest::evaluate(Evaluator &evaluator, auto silMod = SILModule::createEmptyModule(desc.context, desc.conv, desc.opts); - SILParserState parserState(silMod.get()); - Parser parser(*bufferID, *SF, parserState.Impl.get()); + SILParserState parserState(*silMod.get()); + Parser parser(*bufferID, *SF, &parserState); PrettyStackTraceParser StackTrace(parser); auto hadError = parser.parseTopLevelSIL(); @@ -157,11 +150,11 @@ namespace { }; class SILParser { - friend SILParserTUState; + friend SILParserState; public: Parser &P; SILModule &SILMod; - SILParserTUState &TUState; + SILParserState &TUState; SILFunction *F = nullptr; GenericEnvironment *ContextGenericEnv = nullptr; @@ -193,8 +186,8 @@ namespace { public: SILParser(Parser &P) - : P(P), SILMod(static_cast(P.SIL)->M), - TUState(*static_cast(P.SIL)), + : P(P), SILMod(static_cast(P.SIL)->M), + TUState(*static_cast(P.SIL)), ParsedTypeCallback([](Type ty) {}) {} /// diagnoseProblems - After a function is fully parse, emit any diagnostics @@ -5638,7 +5631,7 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) { /// 'sil' sil-linkage '@' identifier ':' sil-type decl-sil-body? /// decl-sil-body: /// '{' sil-basic-block+ '}' -bool SILParserTUState::parseDeclSIL(Parser &P) { +bool SILParserState::parseDeclSIL(Parser &P) { // Inform the lexer that we're lexing the body of the SIL declaration. Do // this before we consume the 'sil' token so that all later tokens are // properly handled. @@ -5806,7 +5799,7 @@ bool SILParserTUState::parseDeclSIL(Parser &P) { /// decl-sil-stage: [[only in SIL mode]] /// 'sil_stage' ('raw' | 'canonical') -bool SILParserTUState::parseDeclSILStage(Parser &P) { +bool SILParserState::parseDeclSILStage(Parser &P) { SourceLoc stageLoc = P.consumeToken(tok::kw_sil_stage); if (!P.Tok.is(tok::identifier)) { P.diagnose(P.Tok, diag::expected_sil_stage_name); @@ -5887,7 +5880,7 @@ static Optional lookupGlobalDecl(Identifier GlobalName, /// decl-sil-global: [[only in SIL mode]] /// 'sil_global' sil-linkage @name : sil-type [external] -bool SILParserTUState::parseSILGlobal(Parser &P) { +bool SILParserState::parseSILGlobal(Parser &P) { // Inform the lexer that we're lexing the body of the SIL declaration. Lexer::SILBodyRAII Tmp(*P.L); @@ -5944,7 +5937,7 @@ bool SILParserTUState::parseSILGlobal(Parser &P) { /// decl-sil-property: [[only in SIL mode]] /// 'sil_property' sil-decl-ref '(' sil-key-path-pattern-component ')' -bool SILParserTUState::parseSILProperty(Parser &P) { +bool SILParserState::parseSILProperty(Parser &P) { Lexer::SILBodyRAII Tmp(*P.L); auto loc = P.consumeToken(tok::kw_sil_property); @@ -6017,7 +6010,7 @@ bool SILParserTUState::parseSILProperty(Parser &P) { /// '{' sil-vtable-entry* '}' /// sil-vtable-entry: /// SILDeclRef ':' SILFunctionName -bool SILParserTUState::parseSILVTable(Parser &P) { +bool SILParserState::parseSILVTable(Parser &P) { P.consumeToken(tok::kw_sil_vtable); SILParser VTableState(P); @@ -6545,7 +6538,7 @@ static bool parseSILVTableEntry( /// associated_type_protocol (AssocName: ProtocolName): /// protocol-conformance|dependent /// base_protocol ProtocolName: protocol-conformance -bool SILParserTUState::parseSILWitnessTable(Parser &P) { +bool SILParserState::parseSILWitnessTable(Parser &P) { P.consumeToken(tok::kw_sil_witness_table); SILParser WitnessState(P); @@ -6648,7 +6641,7 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) { /// sil-default-witness-entry: /// sil-witness-entry /// 'no_default' -bool SILParserTUState::parseSILDefaultWitnessTable(Parser &P) { +bool SILParserState::parseSILDefaultWitnessTable(Parser &P) { P.consumeToken(tok::kw_sil_default_witness_table); SILParser WitnessState(P); @@ -6715,7 +6708,7 @@ bool SILParserTUState::parseSILDefaultWitnessTable(Parser &P) { /// /// index-subset ::= /// [0-9]+ (' ' [0-9]+)* -bool SILParserTUState::parseSILDifferentiabilityWitness(Parser &P) { +bool SILParserState::parseSILDifferentiabilityWitness(Parser &P) { auto loc = P.consumeToken(tok::kw_sil_differentiability_witness); auto silLoc = RegularLocation(loc); SILParser State(P); @@ -6865,7 +6858,7 @@ llvm::Optional SILParser::parseSILCoverageExpr( /// StartLine ':' StartCol '->' EndLine ':' EndCol /// sil-coverage-expr: /// ... -bool SILParserTUState::parseSILCoverageMap(Parser &P) { +bool SILParserState::parseSILCoverageMap(Parser &P) { P.consumeToken(tok::kw_sil_coverage_map); SILParser State(P); @@ -6956,7 +6949,7 @@ bool SILParserTUState::parseSILCoverageMap(Parser &P) { /// scope-parent ::= sil-function-name ':' sil-type /// scope-parent ::= sil-scope-ref /// debug-loc ::= 'loc' string-literal ':' [0-9]+ ':' [0-9]+ -bool SILParserTUState::parseSILScope(Parser &P) { +bool SILParserState::parseSILScope(Parser &P) { P.consumeToken(tok::kw_sil_scope); SILParser ScopeState(P); diff --git a/lib/SILGen/Cleanup.cpp b/lib/SILGen/Cleanup.cpp index e92f5dbd443ce..20eb0cc3c8e7e 100644 --- a/lib/SILGen/Cleanup.cpp +++ b/lib/SILGen/Cleanup.cpp @@ -220,6 +220,21 @@ void CleanupManager::setCleanupState(CleanupsDepth depth, CleanupState state) { popTopDeadCleanups(); } +std::tuple> +CleanupManager::getFlagsAndWritebackBuffer(CleanupHandle depth) { + auto iter = stack.find(depth); + assert(iter != stack.end() && "can't change end of cleanups stack"); + assert(iter->getState() != CleanupState::Dead && + "Trying to get writeback buffer of a dead cleanup?!"); + + auto resultFlags = iter->getFlags(); + Optional result; + bool foundValue = iter->getWritebackBuffer([&](SILValue v) { result = v; }); + (void)foundValue; + assert(result.hasValue() == foundValue); + return std::make_tuple(resultFlags, result); +} + void CleanupManager::forwardCleanup(CleanupsDepth handle) { auto iter = stack.find(handle); assert(iter != stack.end() && "can't change end of cleanups stack"); @@ -344,7 +359,16 @@ void CleanupStateRestorationScope::pop() && { popImpl(); } //===----------------------------------------------------------------------===// CleanupCloner::CleanupCloner(SILGenFunction &SGF, const ManagedValue &mv) - : SGF(SGF), hasCleanup(mv.hasCleanup()), isLValue(mv.isLValue()) {} + : SGF(SGF), hasCleanup(mv.hasCleanup()), isLValue(mv.isLValue()), + writebackBuffer(None) { + if (hasCleanup) { + auto handle = mv.getCleanup(); + auto state = SGF.Cleanups.getFlagsAndWritebackBuffer(handle); + if (SILValue value = std::get<1>(state).getValueOr(SILValue())) { + writebackBuffer = value; + } + } +} CleanupCloner::CleanupCloner(SILGenBuilder &builder, const ManagedValue &mv) : CleanupCloner(builder.getSILGenFunction(), mv) {} @@ -372,6 +396,14 @@ ManagedValue CleanupCloner::clone(SILValue value) const { return ManagedValue::forUnmanaged(value); } + if (writebackBuffer.hasValue()) { + auto loc = RegularLocation::getAutoGeneratedLocation(); + auto cleanup = + SGF.enterOwnedValueWritebackCleanup(loc, *writebackBuffer, value); + return ManagedValue::forExclusivelyBorrowedOwnedObjectRValue(value, + cleanup); + } + if (value->getType().isAddress()) { return SGF.emitManagedBufferWithCleanup(value); } diff --git a/lib/SILGen/Cleanup.h b/lib/SILGen/Cleanup.h index 175b2cc6bb31a..cf8b98df606e3 100644 --- a/lib/SILGen/Cleanup.h +++ b/lib/SILGen/Cleanup.h @@ -19,6 +19,7 @@ #include "swift/Basic/DiverseStack.h" #include "swift/SIL/SILLocation.h" +#include "swift/SIL/SILValue.h" #include "llvm/ADT/SmallVector.h" namespace swift { @@ -75,10 +76,23 @@ llvm::raw_ostream &operator<<(raw_ostream &os, CleanupState state); class LLVM_LIBRARY_VISIBILITY Cleanup { friend class CleanupManager; + friend class CleanupCloner; - unsigned allocatedSize; +protected: + // A set of flags that categorize the type of cleanup such that it can be + // recreated via SILGenFunction methods based on the type of argument input. + // + // Example: Distinguishing in between @owned cleanups with a writeback buffer + // (ExclusiveBorrowCleanup) or ones that involve formal access cleanups. + enum class Flags : uint8_t { + None = 0, + ExclusiveBorrowCleanup = 1, + }; +private: CleanupState state; + unsigned allocatedSize : 24; + Flags flags : 8; protected: Cleanup() {} @@ -99,6 +113,16 @@ class LLVM_LIBRARY_VISIBILITY Cleanup { virtual void emit(SILGenFunction &SGF, CleanupLocation loc, ForUnwind_t forUnwind) = 0; virtual void dump(SILGenFunction &SGF) const = 0; + +protected: + Flags getFlags() const { return flags; } + + /// Call func passing in the SILValue address that this cleanup will write + /// back to if supported and any flags associated with the cleanup. Returns + /// false otherwise. + virtual bool getWritebackBuffer(function_ref func) { + return false; + } }; /// A cleanup depth is generally used to denote the set of cleanups @@ -117,6 +141,7 @@ typedef DiverseStackImpl::stable_iterator CleanupHandle; class LLVM_LIBRARY_VISIBILITY CleanupManager { friend class Scope; + friend class CleanupCloner; SILGenFunction &SGF; @@ -229,7 +254,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager { /// Set the state of the cleanup at the given depth. /// The transition must be non-trivial and legal. void setCleanupState(CleanupHandle depth, CleanupState state); - + /// True if there are any active cleanups in the scope between the two /// cleanup handles. bool hasAnyActiveCleanups(CleanupsDepth from, CleanupsDepth to); @@ -246,6 +271,12 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager { /// Verify that the given cleanup handle is valid. void checkIterator(CleanupHandle handle) const; + +private: + // Look up the flags and optionally the writeback address associated with the + // cleanup at \p depth. If + std::tuple> + getFlagsAndWritebackBuffer(CleanupHandle depth); }; /// An RAII object that allows the state of a cleanup to be @@ -274,10 +305,14 @@ class CleanupStateRestorationScope { void popImpl(); }; +/// Extract enough information from a managed value to reliably clone its +/// cleanup (if it has any) on a newly computed type. This includes modeling +/// writeback buffers. class CleanupCloner { SILGenFunction &SGF; bool hasCleanup; bool isLValue; + Optional writebackBuffer; public: CleanupCloner(SILGenFunction &SGF, const ManagedValue &mv); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index b72905eee45e9..778d7f1a3f42c 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -722,6 +722,7 @@ namespace { /// cleanup to take ownership of the value and thus prevent it form being /// written back. struct OwnedValueWritebackCleanup final : Cleanup { + using Flags = Cleanup::Flags; /// We store our own loc so that we can ensure that DI ignores our writeback. SILLocation loc; @@ -733,6 +734,11 @@ struct OwnedValueWritebackCleanup final : Cleanup { SILValue value) : loc(loc), lvalueAddress(lvalueAddress), value(value) {} + bool getWritebackBuffer(function_ref func) override { + func(lvalueAddress); + return true; + } + void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override { SILValue valueToStore = value; SILType lvalueObjTy = lvalueAddress->getType().getObjectType(); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 854fa87b50c0e..ca922d32de6bf 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -1188,6 +1188,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction CleanupHandle enterDeallocateUninitializedArrayCleanup(SILValue array); void emitUninitializedArrayDeallocation(SILLocation loc, SILValue array); + /// Emit a cleanup for an owned value that should be written back at end of + /// scope if the value is not forwarded. CleanupHandle enterOwnedValueWritebackCleanup(SILLocation loc, SILValue address, SILValue newValue); diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp index 4528e3ed2bc65..7d1f34ea07cc4 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp @@ -642,7 +642,6 @@ bool FunctionSignatureTransform::run(bool hasCaller) { TransformDescriptor.hasOnlyDirectInModuleCallers; SILFunction *F = TransformDescriptor.OriginalFunction; - // If we are asked to assume a caller for testing purposes, set the flag. hasCaller |= FSOOptimizeIfNotCalled; @@ -652,6 +651,16 @@ bool FunctionSignatureTransform::run(bool hasCaller) { return false; } + // Bail if we have a pseudo-generic function. We do not handle these today. If + // we let it through here we crash when attempting to compute the optimized + // function type. + // + // TODO: Add support for this. + if (F->getLoweredFunctionType()->isPseudogeneric()) { + LLVM_DEBUG(llvm::dbgs() << " function is pseudo-generic -> abort\n"); + return false; + } + // Run OwnedToGuaranteed optimization. if (OwnedToGuaranteedAnalyze()) { Changed = true; diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index 8bbb9d30ed1aa..b83872daea424 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -1639,6 +1639,7 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() { } // A store of a load from the box is ignored. + // // SILGen emits these if delegation to another initializer was // interrupted before the initializer was called. SILValue src = SI->getSrc(); @@ -1778,14 +1779,30 @@ void ClassInitElementUseCollector::collectClassInitSelfLoadUses( } } - // If this load's value is being stored back into the delegating - // mark_uninitialized buffer and it is a self init use, skip the - // use. This is to handle situations where due to usage of a metatype to - // allocate, we do not actually consume self. + // If this load's value is being stored immediately back into the delegating + // mark_uninitialized buffer, skip the use. + // + // This is to handle situations where we do not actually consume self as a + // result of situations such as: + // + // 1. The usage of a metatype to allocate the object. + // + // 2. If our self init call has a throwing function as an argument that + // actually throws. if (auto *SI = dyn_cast(User)) { - if (SI->getDest() == MUI && - (isSelfInitUse(User) || isSuperInitUse(User))) { - continue; + if (SI->getDest() == MUI) { + SILValue src = SI->getSrc(); + + // Look through conversions. + while (auto *conversion = dyn_cast(src)) { + src = conversion->getConverted(); + } + + if (auto *li = dyn_cast(src)) { + if (li->getOperand() == MUI) { + continue; + } + } } } diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 8250a4eba1993..65e5513dc1d7e 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -785,6 +785,7 @@ void LifetimeChecker::doIt() { break; case DIUseKind::LoadForTypeOfSelf: handleLoadForTypeOfSelfUse(Use); + break; } } diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index fbc44a776a78c..76f5586f2d147 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1088,12 +1088,22 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const { ConstraintFix *fix = nullptr; if (auto *GP = TypeVar->getImpl().getGenericParameter()) { - auto path = dstLocator->getPath(); - // Drop `generic parameter` locator element so that all missing - // generic parameters related to the same path can be coalesced later. - fix = DefaultGenericArgument::create( - cs, GP, - cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back())); + // If it is represetative for a key path root, let's emit a more + // specific diagnostic. + auto *keyPathRoot = + cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot); + if (keyPathRoot) { + fix = SpecifyKeyPathRootType::create( + cs, keyPathRoot->getImpl().getLocator()); + } else { + auto path = dstLocator->getPath(); + // Drop `generic parameter` locator element so that all missing + // generic parameters related to the same path can be coalesced later. + fix = DefaultGenericArgument::create( + cs, GP, + cs.getConstraintLocator(dstLocator->getAnchor(), + path.drop_back())); + } } else if (TypeVar->getImpl().isClosureParameterType()) { fix = SpecifyClosureParameterType::create(cs, dstLocator); } else if (TypeVar->getImpl().isClosureResultType()) { diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 6900f5bd38989..aa02e10370837 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -4859,6 +4859,12 @@ bool InvalidStaticMemberRefInKeyPath::diagnoseAsError() { return true; } +bool InvalidEnumCaseRefInKeyPath::diagnoseAsError() { + emitDiagnostic(diag::expr_keypath_enum_case, getName(), + isForKeyPathDynamicMemberLookup()); + return true; +} + bool InvalidMemberWithMutatingGetterInKeyPath::diagnoseAsError() { emitDiagnostic(diag::expr_keypath_mutating_getter, getName(), isForKeyPathDynamicMemberLookup()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 64428d227d763..73afab26d924d 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1524,6 +1524,25 @@ class InvalidStaticMemberRefInKeyPath final : public InvalidMemberRefInKeyPath { bool diagnoseAsError() override; }; +/// Diagnose an attempt to reference an enum case as a key path component +/// e.g. +/// +/// ```swift +/// enum E { +/// case foo +/// } +/// +/// _ = \E.Type.foo +/// ``` +class InvalidEnumCaseRefInKeyPath final : public InvalidMemberRefInKeyPath { +public: + InvalidEnumCaseRefInKeyPath(const Solution &solution, ValueDecl *member, + ConstraintLocator *locator) + : InvalidMemberRefInKeyPath(solution, member, locator) {} + + bool diagnoseAsError() override; +}; + /// Diagnose an attempt to reference a member which has a mutating getter as a /// key path component e.g. /// diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index c3875c5500cf9..55438f3440153 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -767,6 +767,11 @@ bool AllowInvalidRefInKeyPath::diagnose(const Solution &solution, return failure.diagnose(asNote); } + case RefKind::EnumCase: { + InvalidEnumCaseRefInKeyPath failure(solution, Member, getLocator()); + return failure.diagnose(asNote); + } + case RefKind::MutatingGetter: { InvalidMemberWithMutatingGetterInKeyPath failure(solution, Member, getLocator()); @@ -791,6 +796,12 @@ AllowInvalidRefInKeyPath::forRef(ConstraintSystem &cs, ValueDecl *member, return AllowInvalidRefInKeyPath::create(cs, RefKind::Method, member, locator); + // Referencing enum cases in key path is not currently allowed. + if (isa(member)) { + return AllowInvalidRefInKeyPath::create(cs, RefKind::EnumCase, member, + locator); + } + // Referencing initializers in key path is not currently allowed. if (isa(member)) return AllowInvalidRefInKeyPath::create(cs, RefKind::Initializer, diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 1decf4baa85d1..ad3b45633bc70 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -1330,6 +1330,8 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix { // Allow a reference to a initializer instance as a key path // component. Initializer, + // Allow a reference to an enum case as a key path component. + EnumCase, } Kind; ValueDecl *Member; @@ -1351,6 +1353,8 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix { return "allow reference to a method as a key path component"; case RefKind::Initializer: return "allow reference to an init method as a key path component"; + case RefKind::EnumCase: + return "allow reference to an enum case as a key path component"; } llvm_unreachable("covered switch"); } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 9b068b0c5947a..536b682c38798 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -903,6 +903,31 @@ Type ConstraintSystem::getFixedTypeRecursive(Type type, return type; } +TypeVariableType *ConstraintSystem::isRepresentativeFor( + TypeVariableType *typeVar, ConstraintLocator::PathElementKind kind) const { + // We only attempt to look for this if type variable is + // a representative. + if (getRepresentative(typeVar) != typeVar) + return nullptr; + + auto &CG = getConstraintGraph(); + auto result = CG.lookupNode(typeVar); + auto equivalence = result.first.getEquivalenceClass(); + auto member = llvm::find_if(equivalence, [=](TypeVariableType *eq) { + auto *loc = eq->getImpl().getLocator(); + if (!loc) + return false; + + auto path = loc->getPath(); + return !path.empty() && path.back().getKind() == kind; + }); + + if (member == equivalence.end()) + return nullptr; + + return *member; +} + /// Does a var or subscript produce an l-value? /// /// \param baseType - the type of the base on which this object @@ -4259,6 +4284,8 @@ void SolutionApplicationTarget::maybeApplyPropertyWrapper() { if (!outermostWrapperType) return; + bool isImplicit = false; + // Retrieve the outermost wrapper argument. If there isn't one, we're // performing default initialization. auto outermostArg = outermostWrapperAttr->getArg(); @@ -4266,6 +4293,7 @@ void SolutionApplicationTarget::maybeApplyPropertyWrapper() { SourceLoc fakeParenLoc = outermostWrapperAttr->getRange().End; outermostArg = TupleExpr::createEmpty( ctx, fakeParenLoc, fakeParenLoc, /*Implicit=*/true); + isImplicit = true; } auto typeExpr = TypeExpr::createImplicitHack( @@ -4276,7 +4304,7 @@ void SolutionApplicationTarget::maybeApplyPropertyWrapper() { outermostWrapperAttr->getArgumentLabels(), outermostWrapperAttr->getArgumentLabelLocs(), /*hasTrailingClosure=*/false, - /*implicit=*/false); + /*implicit=*/isImplicit); } wrapperAttrs[0]->setSemanticInit(backingInitializer); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 2b3148849ae19..28b68e4779354 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -3070,6 +3070,13 @@ class ConstraintSystem { return typeVar->getImpl().getRepresentative(getSavedBindings()); } + /// Find if the given type variable is representative for a type + /// variable which last locator path element is of the specified kind. + /// If true returns the type variable which it is the representative for. + TypeVariableType * + isRepresentativeFor(TypeVariableType *typeVar, + ConstraintLocator::PathElementKind kind) const; + /// Gets the VarDecl associateed with resolvedOverload, and the type of the /// storage wrapper if the decl has an associated storage wrapper. Optional> diff --git a/lib/Sema/IDETypeCheckingRequests.cpp b/lib/Sema/IDETypeCheckingRequests.cpp index 60fec61c517c4..739694f801205 100644 --- a/lib/Sema/IDETypeCheckingRequests.cpp +++ b/lib/Sema/IDETypeCheckingRequests.cpp @@ -65,6 +65,9 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy, static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy, const ValueDecl *VD) { + if (BaseTy->isExistentialType() && VD->isStatic()) + return false; + // We can't leak type variables into another constraint system. // We can't do anything if the base type has unbound generic parameters. if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType()|| diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e7c00c73fa87b..e6d251e5349c7 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -38,7 +38,6 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PropertyWrappers.h" #include "swift/AST/ProtocolConformance.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/SourceFile.h" #include "swift/AST/TypeWalker.h" #include "swift/Basic/Statistic.h" diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 21002610485e9..303624d42cc10 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -1886,12 +1886,7 @@ bool swift::fixDeclarationObjCName(InFlightDiagnostic &diag, const ValueDecl *de namespace { /// Produce a deterministic ordering of the given declarations. - class OrderDeclarations { - SourceManager &SrcMgr; - - public: - OrderDeclarations(SourceManager &srcMgr) : SrcMgr(srcMgr) { } - + struct OrderDeclarations { bool operator()(ValueDecl *lhs, ValueDecl *rhs) const { // If the declarations come from different modules, order based on the // module. @@ -1912,6 +1907,7 @@ namespace { } // Prefer the declaration that comes first in the source file. + const auto &SrcMgr = lhsSF->getASTContext().SourceMgr; return SrcMgr.isBeforeInBuffer(lhs->getLoc(), rhs->getLoc()); } @@ -1924,57 +1920,43 @@ namespace { } // end anonymous namespace /// Lookup for an Objective-C method with the given selector in the -/// given class or any of its superclasses. -static AbstractFunctionDecl *lookupObjCMethodInClass( - ClassDecl *classDecl, - ObjCSelector selector, - bool isInstanceMethod, - bool isInitializer, - SourceManager &srcMgr, - bool inheritingInits = true) { - if (!classDecl) - return nullptr; +/// given class or any of its superclasses. We intentionally don't respect +/// access control, since everything is visible to the Objective-C runtime. +static AbstractFunctionDecl * +lookupOverridenObjCMethod(ClassDecl *classDecl, AbstractFunctionDecl *method, + bool inheritingInits = true) { + assert(classDecl); // Look for an Objective-C method in this class. - auto methods = classDecl->lookupDirect(selector, isInstanceMethod); + auto methods = classDecl->lookupDirect(method->getObjCSelector(), + method->isObjCInstanceMethod()); if (!methods.empty()) { // If we aren't inheriting initializers, remove any initializers from the // list. - if (!inheritingInits && - std::find_if(methods.begin(), methods.end(), - [](AbstractFunctionDecl *func) { - return isa(func); - }) != methods.end()) { - SmallVector nonInitMethods; - std::copy_if(methods.begin(), methods.end(), - std::back_inserter(nonInitMethods), - [&](AbstractFunctionDecl *func) { - return !isa(func); - }); - if (nonInitMethods.empty()) + if (!inheritingInits) { + llvm::erase_if(methods, [](AbstractFunctionDecl *afd) { + return isa(afd); + }); + if (methods.empty()) return nullptr; - - return *std::min_element(nonInitMethods.begin(), nonInitMethods.end(), - OrderDeclarations(srcMgr)); } - return *std::min_element(methods.begin(), methods.end(), - OrderDeclarations(srcMgr)); + OrderDeclarations()); } - // Recurse into the superclass. + // If we've reached the bottom of the inheritance heirarchy, we're done. if (!classDecl->hasSuperclass()) return nullptr; // Determine whether we are (still) inheriting initializers. - inheritingInits = inheritingInits && - classDecl->inheritsSuperclassInitializers(); - if (isInitializer && !inheritingInits) + if (!classDecl->inheritsSuperclassInitializers()) + inheritingInits = false; + + if (isa(method) && !inheritingInits) return nullptr; - return lookupObjCMethodInClass(classDecl->getSuperclassDecl(), selector, - isInstanceMethod, isInitializer, srcMgr, - inheritingInits); + return lookupOverridenObjCMethod(classDecl->getSuperclassDecl(), method, + inheritingInits); } bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) { @@ -1986,7 +1968,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) { return false; // Sort the methods by declaration order. - std::sort(methods.begin(), methods.end(), OrderDeclarations(Ctx.SourceMgr)); + std::sort(methods.begin(), methods.end(), OrderDeclarations()); // For each Objective-C method declared in this file, check whether // it overrides something in one of its superclasses. We @@ -2022,18 +2004,13 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) { if (!classDecl->hasSuperclass()) continue; - // Look for a method that we have overridden in one of our - // superclasses. + // Look for a method that we have overridden in one of our superclasses by + // virtue of having the same selector. // Note: This should be treated as a lookup for intra-module dependency // purposes, but a subclass already depends on its superclasses and any // extensions for many other reasons. - auto selector = method->getObjCSelector(); - AbstractFunctionDecl *overriddenMethod - = lookupObjCMethodInClass(classDecl->getSuperclassDecl(), - selector, - method->isObjCInstanceMethod(), - isa(method), - Ctx.SourceMgr); + auto *overriddenMethod = + lookupOverridenObjCMethod(classDecl->getSuperclassDecl(), method); if (!overriddenMethod) continue; @@ -2051,18 +2028,18 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) { // Diagnose the override. auto methodDiagInfo = getObjCMethodDiagInfo(method); auto overriddenDiagInfo = getObjCMethodDiagInfo(overriddenMethod); - Ctx.Diags.diagnose(method, diag::objc_override_other, - methodDiagInfo.first, - methodDiagInfo.second, - overriddenDiagInfo.first, - overriddenDiagInfo.second, - selector, - overriddenMethod->getDeclContext() - ->getDeclaredInterfaceType()); + + Ctx.Diags.diagnose( + method, diag::objc_override_other, methodDiagInfo.first, + methodDiagInfo.second, overriddenDiagInfo.first, + overriddenDiagInfo.second, method->getObjCSelector(), + overriddenMethod->getDeclContext()->getDeclaredInterfaceType()); + const ValueDecl *overriddenDecl = overriddenMethod; if (overriddenMethod->isImplicit()) if (auto accessor = dyn_cast(overriddenMethod)) overriddenDecl = accessor->getStorage(); + Ctx.Diags.diagnose(overriddenDecl, diag::objc_declared_here, overriddenDiagInfo.first, overriddenDiagInfo.second); @@ -2073,7 +2050,7 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) { } /// Retrieve the source file for the given Objective-C member conflict. -static MutableArrayRef +static TinyPtrVector getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) { ClassDecl *classDecl = std::get<0>(conflict); ObjCSelector selector = std::get<1>(conflict); @@ -2082,45 +2059,13 @@ getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) { return classDecl->lookupDirect(selector, isInstanceMethod); } -/// Given a set of conflicting Objective-C methods, remove any methods -/// that are legitimately overridden in Objective-C, i.e., because -/// they occur in different modules, one is defined in the class, and -/// the other is defined in an extension (category) thereof. -static void removeValidObjCConflictingMethods( - MutableArrayRef &methods) { - // Erase any invalid or stub declarations. We don't want to complain about - // them, because we might already have complained about - // redeclarations based on Swift matching. - auto newEnd = std::remove_if(methods.begin(), methods.end(), - [&](AbstractFunctionDecl *method) { - if (method->isInvalid()) - return true; - - if (auto ad = dyn_cast(method)) { - return ad->getStorage()->isInvalid(); - } - - if (auto ctor - = dyn_cast(method)) { - if (ctor->hasStubImplementation()) - return true; - - return false; - } - - return false; - }); - methods = methods.slice(0, newEnd - methods.begin()); -} - bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) { // If there were no conflicts, we're done. if (sf.ObjCMethodConflicts.empty()) return false; auto &Ctx = sf.getASTContext(); - - OrderDeclarations ordering(Ctx.SourceMgr); + OrderDeclarations ordering; // Sort the set of conflicts so we get a deterministic order for // diagnostics. We use the first conflicting declaration in each set to @@ -2140,8 +2085,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) { auto methods = getObjCMethodConflictDecls(conflict); - // Prune out cases where it is acceptable to have a conflict. - removeValidObjCConflictingMethods(methods); + // Erase any invalid or stub declarations. We don't want to complain about + // them, because we might already have complained about redeclarations + // based on Swift matching. + llvm::erase_if(methods, [](AbstractFunctionDecl *afd) -> bool { + if (afd->isInvalid()) + return true; + + if (auto ad = dyn_cast(afd)) + return ad->getStorage()->isInvalid(); + + if (auto *ctor = dyn_cast(afd)) { + if (ctor->hasStubImplementation()) + return true; + } + return false; + }); + if (methods.size() < 2) continue; @@ -2150,22 +2110,23 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) { // If the first method is in an extension and the second is not, swap them // so the primary diagnostic is on the extension method. + MutableArrayRef methodsRef(methods); if (isa(methods[0]->getDeclContext()) && !isa(methods[1]->getDeclContext())) { - std::swap(methods[0], methods[1]); + std::swap(methodsRef[0], methodsRef[1]); // Within a source file, use our canonical ordering. } else if (methods[0]->getParentSourceFile() == methods[1]->getParentSourceFile() && !ordering(methods[0], methods[1])) { - std::swap(methods[0], methods[1]); + std::swap(methodsRef[0], methodsRef[1]); } // Otherwise, fall back to the order in which the declarations were type // checked. auto originalMethod = methods.front(); - auto conflictingMethods = methods.slice(1); + auto conflictingMethods = methodsRef.slice(1); auto origDiagInfo = getObjCMethodDiagInfo(originalMethod); for (auto conflictingDecl : conflictingMethods) { @@ -2182,12 +2143,9 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) { Ctx.Diags.diagnose(originalDecl, diag::invalid_redecl_prev, originalDecl->getBaseName()); } else { - Ctx.Diags.diagnose(conflictingDecl, diag::objc_redecl, - diagInfo.first, - diagInfo.second, - origDiagInfo.first, - origDiagInfo.second, - selector); + Ctx.Diags.diagnose(conflictingDecl, diag::objc_redecl, diagInfo.first, + diagInfo.second, origDiagInfo.first, + origDiagInfo.second, selector); Ctx.Diags.diagnose(originalDecl, diag::objc_declared_here, origDiagInfo.first, origDiagInfo.second); } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index f4fb62ce90c5e..5b887ae22b43b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -41,7 +41,6 @@ #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PropertyWrappers.h" #include "swift/AST/ProtocolConformance.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/SourceFile.h" #include "swift/AST/TypeWalker.h" #include "swift/Basic/Statistic.h" @@ -698,7 +697,75 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const { current->diagnose(diag::invalid_redecl_init, current->getName(), otherInit->isMemberwiseInitializer()); - } else if (!current->isImplicit() && !other->isImplicit()) { + } else if (current->isImplicit() || other->isImplicit()) { + // If both declarations are implicit, we do not diagnose anything + // as it would lead to misleading diagnostics and it's likely that + // there's nothing actionable about it due to its implicit nature. + // One special case for this is property wrappers. + // + // Otherwise, if 'current' is implicit, then we diagnose 'other' + // since 'other' is a redeclaration of 'current'. Similarly, if + // 'other' is implicit, we diagnose 'current'. + const Decl *declToDiagnose = nullptr; + if (current->isImplicit() && other->isImplicit()) { + // If 'current' is a property wrapper backing storage property + // or projected value property, then diagnose the wrapped + // property. + if (auto VD = dyn_cast(current)) { + if (auto originalWrappedProperty = + VD->getOriginalWrappedProperty()) { + declToDiagnose = originalWrappedProperty; + } + } + } else { + declToDiagnose = current->isImplicit() ? other : current; + } + + if (declToDiagnose) { + // Figure out if the the declaration we've redeclared is a + // synthesized witness for a protocol requirement. + bool isProtocolRequirement = false; + if (auto VD = dyn_cast(current->isImplicit() ? current + : other)) { + isProtocolRequirement = llvm::any_of( + VD->getSatisfiedProtocolRequirements(), [&](ValueDecl *req) { + return req->getName() == VD->getName(); + }); + } + declToDiagnose->diagnose(diag::invalid_redecl_implicit, + current->getDescriptiveKind(), + isProtocolRequirement, other->getName()); + } + + // Emit a specialized note if the one of the declarations is + // the backing storage property ('_foo') or projected value + // property ('$foo') for a wrapped property. The backing or + // projected var has the same source location as the wrapped + // property we diagnosed above, so we don't need to extract + // the original property. + const VarDecl *varToDiagnose = nullptr; + auto kind = PropertyWrapperSynthesizedPropertyKind::Backing; + if (auto currentVD = dyn_cast(current)) { + if (auto currentKind = + currentVD->getPropertyWrapperSynthesizedPropertyKind()) { + varToDiagnose = currentVD; + kind = *currentKind; + } + } + if (auto otherVD = dyn_cast(other)) { + if (auto otherKind = + otherVD->getPropertyWrapperSynthesizedPropertyKind()) { + varToDiagnose = otherVD; + kind = *otherKind; + } + } + + if (varToDiagnose) { + varToDiagnose->diagnose( + diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName(), + kind == PropertyWrapperSynthesizedPropertyKind::Backing); + } + } else { ctx.Diags.diagnoseWithNotes( current->diagnose(diag::invalid_redecl, current->getName()), [&]() { diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index b904be084ee33..b0c09e87d9d8b 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -34,7 +34,6 @@ #include "swift/AST/ParameterList.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" -#include "swift/AST/ReferencedNameTracker.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeDeclFinder.h" #include "swift/AST/TypeMatcher.h" @@ -2338,8 +2337,9 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance, diags.diagnose(witness, diag::protocol_witness_settable_conflict); if (auto VD = dyn_cast(witness)) { if (VD->hasStorage()) { - auto PBD = VD->getParentPatternBinding(); - diag.fixItReplace(PBD->getStartLoc(), getTokenText(tok::kw_var)); + if (auto PBD = VD->getParentPatternBinding()) { + diag.fixItReplace(PBD->getStartLoc(), getTokenText(tok::kw_var)); + } } } break; diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ef371a520ce13..f9992f5ff963b 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -4848,7 +4848,9 @@ class TypeDeserializer { auto substitutedType = substitutedTypeOrError.get(); // Read the substitutions. - auto subMap = MF.getSubstitutionMap(substitutionsID); + auto subMapOrError = MF.getSubstitutionMapChecked(substitutionsID); + if (!subMapOrError) + return subMapOrError.takeError(); auto parentTypeOrError = MF.getTypeChecked(parentTypeID); if (!parentTypeOrError) @@ -4858,11 +4860,12 @@ class TypeDeserializer { if (alias && alias->getAttrs().isUnavailable(ctx) && alias->isCompatibilityAlias()) { - return alias->getUnderlyingType().subst(subMap); + return alias->getUnderlyingType().subst(subMapOrError.get()); } auto parentType = parentTypeOrError.get(); - return TypeAliasType::get(alias, parentType, subMap, substitutedType); + return TypeAliasType::get(alias, parentType, subMapOrError.get(), + substitutedType); } Expected deserializeNominalType(ArrayRef scratch, @@ -5180,9 +5183,11 @@ class TypeDeserializer { return opaqueTypeOrError.takeError(); auto opaqueDecl = cast(opaqueTypeOrError.get()); - auto subs = MF.getSubstitutionMap(subsID); + auto subsOrError = MF.getSubstitutionMapChecked(subsID); + if (!subsOrError) + return subsOrError.takeError(); - return OpaqueTypeArchetypeType::get(opaqueDecl, subs); + return OpaqueTypeArchetypeType::get(opaqueDecl, subsOrError.get()); } Expected deserializeNestedArchetypeType(ArrayRef scratch, @@ -5317,8 +5322,11 @@ class TypeDeserializer { if (!layout) return nullptr; - auto subMap = MF.getSubstitutionMap(subMapID); - return SILBoxType::get(ctx, layout, subMap); + auto subMapOrError = MF.getSubstitutionMapChecked(subMapID); + if (!subMapOrError) + return subMapOrError.takeError(); + + return SILBoxType::get(ctx, layout, subMapOrError.get()); } Expected deserializeSILFunctionType(ArrayRef scratch, @@ -5503,16 +5511,19 @@ class TypeDeserializer { GenericSignature invocationSig = MF.getGenericSignature(rawInvocationGenericSig); - SubstitutionMap invocationSubs = - MF.getSubstitutionMap(rawInvocationSubs).getCanonical(); - SubstitutionMap patternSubs = - MF.getSubstitutionMap(rawPatternSubs).getCanonical(); + auto invocationSubsOrErr = MF.getSubstitutionMapChecked(rawInvocationSubs); + if (!invocationSubsOrErr) + return invocationSubsOrErr.takeError(); + auto patternSubsOrErr = MF.getSubstitutionMapChecked(rawPatternSubs); + if (!patternSubsOrErr) + return patternSubsOrErr.takeError(); return SILFunctionType::get(invocationSig, extInfo, coroutineKind.getValue(), calleeConvention.getValue(), allParams, allYields, allResults, errorResult, - patternSubs, invocationSubs, + patternSubsOrErr.get().getCanonical(), + invocationSubsOrErr.get().getCanonical(), ctx, witnessMethodConformance); } diff --git a/stdlib/CMakeLists.txt b/stdlib/CMakeLists.txt index bfeb17e2f2d2d..00f23b8a0f267 100644 --- a/stdlib/CMakeLists.txt +++ b/stdlib/CMakeLists.txt @@ -24,6 +24,10 @@ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN YES) + if(SWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER) if(NOT "${CMAKE_C_COMPILER_ID}" MATCHES "Clang") message(FATAL_ERROR "Building the swift runtime is not supported with ${CMAKE_C_COMPILER_ID}. Use the just-built clang instead.") diff --git a/stdlib/public/CMakeLists.txt b/stdlib/public/CMakeLists.txt index 5e3609d5cfc52..01879ce5cd5a1 100644 --- a/stdlib/public/CMakeLists.txt +++ b/stdlib/public/CMakeLists.txt @@ -48,13 +48,6 @@ if(CXX_SUPPORTS_EXIT_TIME_DESTRUCTORS_WARNING) list(APPEND SWIFT_RUNTIME_CORE_CXX_FLAGS "-Wexit-time-destructors") endif() -# We don't want runtime C++ code to export symbols we didn't explicitly -# choose to. -check_cxx_compiler_flag("-fvisibility=hidden" CXX_SUPPORTS_DEFAULT_HIDDEN_VISIBILITY) -if(CXX_SUPPORTS_DEFAULT_HIDDEN_VISIBILITY) - list(APPEND SWIFT_RUNTIME_CORE_CXX_FLAGS "-fvisibility=hidden") -endif() - add_subdirectory(SwiftShims) if(SWIFT_BUILD_STDLIB) diff --git a/stdlib/public/LLVMSupport/ErrorHandling.cpp b/stdlib/public/LLVMSupport/ErrorHandling.cpp index f40c614d46a6f..ed15bf4798f68 100644 --- a/stdlib/public/LLVMSupport/ErrorHandling.cpp +++ b/stdlib/public/LLVMSupport/ErrorHandling.cpp @@ -44,7 +44,7 @@ void error(const char *fmt, ...) { #if defined(__APPLE__) asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", buffer); #elif defined(__ANDROID__) - __android_log_printf(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", buffer); + __android_log_print(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", buffer); #elif defined(_WIN32) #define STDERR_FILENO 2 _write(STDERR_FILENO, buffer, strlen(buffer)); diff --git a/stdlib/toolchain/CMakeLists.txt b/stdlib/toolchain/CMakeLists.txt index 71462c3750698..9cda30ee3e91b 100644 --- a/stdlib/toolchain/CMakeLists.txt +++ b/stdlib/toolchain/CMakeLists.txt @@ -15,11 +15,7 @@ set(compile_flags # C++ code in the runtime and standard library should generally avoid # introducing static constructors or destructors. "-Wglobal-constructors" - "-Wexit-time-destructors" - - # We don't want runtime C++ code to export symbols we didn't explicitly - # choose to. - "-fvisibility=hidden") + "-Wexit-time-destructors") # Build the runtime with -Wall to catch, e.g., uninitialized variables diff --git a/test/AutoDiff/SILOptimizer/differentiation_activity_analysis.swift b/test/AutoDiff/SILOptimizer/activity_analysis.swift similarity index 97% rename from test/AutoDiff/SILOptimizer/differentiation_activity_analysis.swift rename to test/AutoDiff/SILOptimizer/activity_analysis.swift index 92cc3329dc2bd..6c1fc31f23cf4 100644 --- a/test/AutoDiff/SILOptimizer/differentiation_activity_analysis.swift +++ b/test/AutoDiff/SILOptimizer/activity_analysis.swift @@ -289,7 +289,7 @@ extension Mut { mutating func mutatingMethod(_ x: Mut) {} } -// CHECK-LABEL: [AD] Activity info for $s33differentiation_activity_analysis3MutV14mutatingMethodyyACF at (source=0 parameters=(0)) +// CHECK-LABEL: [AD] Activity info for ${{.*}}3MutV14mutatingMethodyyACF at (source=0 parameters=(0)) // CHECK: [VARIED] %0 = argument of bb0 : $Mut // CHECK: [USEFUL] %1 = argument of bb0 : $*Mut @@ -301,7 +301,7 @@ func nonActiveInoutArg(_ nonactive: inout Mut, _ x: Mut) { nonactive = x } -// CHECK-LABEL: [AD] Activity info for $s33differentiation_activity_analysis17nonActiveInoutArgyyAA3MutVz_ADtF at (source=0 parameters=(1)) +// CHECK-LABEL: [AD] Activity info for ${{.*}}17nonActiveInoutArgyyAA3MutVz_ADtF at (source=0 parameters=(1)) // CHECK: [ACTIVE] %0 = argument of bb0 : $*Mut // CHECK: [ACTIVE] %1 = argument of bb0 : $Mut // CHECK: [ACTIVE] %4 = begin_access [modify] [static] %0 : $*Mut @@ -316,7 +316,7 @@ func activeInoutArgMutatingMethod(_ x: Mut) -> Mut { return result } -// CHECK-LABEL: [AD] Activity info for $s33differentiation_activity_analysis28activeInoutArgMutatingMethodyAA3MutVADF at (source=0 parameters=(0)) +// CHECK-LABEL: [AD] Activity info for ${{.*}}28activeInoutArgMutatingMethodyAA3MutVADF at (source=0 parameters=(0)) // CHECK: [ACTIVE] %0 = argument of bb0 : $Mut // CHECK: [ACTIVE] %2 = alloc_stack $Mut, var, name "result" // CHECK: [ACTIVE] %4 = begin_access [read] [static] %2 : $*Mut @@ -334,14 +334,14 @@ func activeInoutArgMutatingMethodVar(_ nonactive: inout Mut, _ x: Mut) { nonactive = result } -// CHECK_LABEL: [AD] Activity info for $s33differentiation_activity_analysis31activeInoutArgMutatingMethodVaryyAA3MutVz_ADtF at (source=0 parameters=(1)) +// CHECK_LABEL: [AD] Activity info for ${{.*}}31activeInoutArgMutatingMethodVaryyAA3MutVz_ADtF at (source=0 parameters=(1)) // CHECK: [ACTIVE] %0 = argument of bb0 : $*Mut // CHECK: [ACTIVE] %1 = argument of bb0 : $Mut // CHECK: [ACTIVE] %4 = alloc_stack $Mut, var, name "result" // CHECK: [ACTIVE] %5 = begin_access [read] [static] %0 : $*Mut // CHECK: [ACTIVE] %8 = begin_access [modify] [static] %4 : $*Mut // CHECK: [NONE] // function_ref Mut.mutatingMethod(_:) -// CHECK: %9 = function_ref @$s33differentiation_activity_analysis3MutV14mutatingMethodyyACF : $@convention(method) (Mut, @inout Mut) -> () +// CHECK: %9 = function_ref @${{.*}}3MutV14mutatingMethodyyACF : $@convention(method) (Mut, @inout Mut) -> () // CHECK: [NONE] %10 = apply %9(%1, %8) : $@convention(method) (Mut, @inout Mut) -> () // CHECK: [ACTIVE] %12 = begin_access [read] [static] %4 : $*Mut // CHECK: [ACTIVE] %13 = load [trivial] %12 : $*Mut @@ -355,7 +355,7 @@ func activeInoutArgMutatingMethodTuple(_ nonactive: inout Mut, _ x: Mut) { nonactive = result.0 } -// CHECK-LABEL: [AD] Activity info for $s33differentiation_activity_analysis33activeInoutArgMutatingMethodTupleyyAA3MutVz_ADtF at (source=0 parameters=(1)) +// CHECK-LABEL: [AD] Activity info for ${{.*}}33activeInoutArgMutatingMethodTupleyyAA3MutVz_ADtF at (source=0 parameters=(1)) // CHECK: [ACTIVE] %0 = argument of bb0 : $*Mut // CHECK: [ACTIVE] %1 = argument of bb0 : $Mut // CHECK: [ACTIVE] %4 = alloc_stack $(Mut, Mut), var, name "result" @@ -466,7 +466,7 @@ func testAccessorCoroutines(_ x: HasCoroutineAccessors) -> HasCoroutineAccessors // CHECK: [ACTIVE] %11 = load [trivial] %9 : $*Float // CHECK: [ACTIVE] %14 = begin_access [modify] [static] %2 : $*HasCoroutineAccessors // CHECK: [NONE] // function_ref HasCoroutineAccessors.computed.modify -// CHECK: %15 = function_ref @$s33differentiation_activity_analysis21HasCoroutineAccessorsV8computedSfvM : $@yield_once @convention(method) (@inout HasCoroutineAccessors) -> @yields @inout Float +// CHECK: %15 = function_ref @${{.*}}21HasCoroutineAccessorsV8computedSfvM : $@yield_once @convention(method) (@inout HasCoroutineAccessors) -> @yields @inout Float // CHECK: [ACTIVE] (**%16**, %17) = begin_apply %15(%14) : $@yield_once @convention(method) (@inout HasCoroutineAccessors) -> @yields @inout Float // CHECK: [VARIED] (%16, **%17**) = begin_apply %15(%14) : $@yield_once @convention(method) (@inout HasCoroutineAccessors) -> @yields @inout Float // CHECK: [ACTIVE] %22 = begin_access [read] [static] %2 : $*HasCoroutineAccessors diff --git a/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift b/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift index cd3d05554820e..5a922cad39f82 100644 --- a/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift +++ b/test/AutoDiff/SILOptimizer/semantic_member_accessors_sil.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -emit-sil -Xllvm -sil-print-after=differentiation %s -o /dev/null 2>&1 | %FileCheck %s +// RUN: %target-swift-frontend -emit-sil -Xllvm -sil-print-after=differentiation %s -module-name null -o /dev/null 2>&1 | %FileCheck %s // Test differentiation of semantic member accessors: // - Stored property accessors. diff --git a/test/AutoDiff/compiler_crashers_fixed/sr12642-differentiable-derivation-redeclared-property.swift b/test/AutoDiff/compiler_crashers_fixed/sr12642-differentiable-derivation-redeclared-property.swift index fdcace744089f..ff75fb345dce3 100644 --- a/test/AutoDiff/compiler_crashers_fixed/sr12642-differentiable-derivation-redeclared-property.swift +++ b/test/AutoDiff/compiler_crashers_fixed/sr12642-differentiable-derivation-redeclared-property.swift @@ -16,10 +16,12 @@ struct Generic {} extension Generic: Differentiable where T: Differentiable {} struct WrappedProperties: Differentiable { - // expected-note @+2 {{'int' previously declared here}} - // expected-warning @+1 {{stored property 'int' has no derivative because 'Generic' does not conform to 'Differentiable'; add an explicit '@noDerivative' attribute}} @Wrapper var int: Generic + // expected-note@-1 {{'int' previously declared here}} + // expected-note@-2 {{'_int' synthesized for property wrapper backing storage}} + // expected-warning@-3 {{stored property 'int' has no derivative because 'Generic' does not conform to 'Differentiable'; add an explicit '@noDerivative' attribute}} - // expected-error @+1 {{invalid redeclaration of 'int'}} @Wrapper var int: Generic + // expected-error@-1 {{invalid redeclaration of 'int'}} + // expected-error@-2 {{invalid redeclaration of synthesized property '_int'}} } diff --git a/test/Constraints/keyword_arguments.swift b/test/Constraints/argument_matching.swift similarity index 81% rename from test/Constraints/keyword_arguments.swift rename to test/Constraints/argument_matching.swift index 8ea73b96d2033..f93366259302a 100644 --- a/test/Constraints/keyword_arguments.swift +++ b/test/Constraints/argument_matching.swift @@ -66,6 +66,13 @@ class GenericCtor { } GenericCtor() // expected-error{{missing argument for parameter 't' in call}} +func secondArgumentNotLabeled(a: Int, _ b: Int) { } +secondArgumentNotLabeled(10, 20) +// expected-error@-1 {{missing argument label 'a:' in call}} + +func f_31849281(x: Int, y: Int, z: Int) {} +f_31849281(42, y: 10, x: 20) // expected-error {{incorrect argument labels in call (have '_:y:x:', expected 'x:y:z:')}} {{12-12=x: }} {{23-24=z}} + // ------------------------------------------- // Extraneous keywords // ------------------------------------------- @@ -82,12 +89,51 @@ somekeywords1(x: 1, y: 2, z: 3) // expected-error{{extraneous argument label 'x: somekeywords1(1, 2, 3) // expected-error{{missing argument labels 'y:z:' in call}}{{18-18=y: }}{{21-21=z: }} somekeywords1(x: 1, 2, z: 3) // expected-error{{incorrect argument labels in call (have 'x:_:z:', expected '_:y:z:')}}{{15-18=}}{{21-21=y: }} +// SR-2242: poor diagnostic when argument label is omitted + +func r27212391(x: Int, _ y: Int) { + let _: Int = x + y +} + +func r27212391(a: Int, x: Int, _ y: Int) { + let _: Int = a + x + y +} + +r27212391(3, 5) // expected-error {{missing argument label 'x:' in call}} +r27212391(3, y: 5) // expected-error {{incorrect argument labels in call (have '_:y:', expected 'x:_:')}} +r27212391(3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #1}} {{11-11=x: 5, }} {{12-18=}} +r27212391(y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'y:x:', expected 'x:_:')}} {{11-12=x}} {{17-20=}} +r27212391(y: 3, 5) // expected-error {{incorrect argument label in call (have 'y:_:', expected 'x:_:')}} +r27212391(x: 3, x: 5) // expected-error {{extraneous argument label 'x:' in call}} +r27212391(a: 1, 3, y: 5) // expected-error {{incorrect argument labels in call (have 'a:_:y:', expected 'a:x:_:')}} +r27212391(1, x: 3, y: 5) // expected-error {{incorrect argument labels in call (have '_:x:y:', expected 'a:x:_:')}} +r27212391(a: 1, y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'a:y:x:', expected 'a:x:_:')}} +r27212391(a: 1, 3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #2}} {{17-17=x: 5, }} {{18-24=}} // ------------------------------------------- // Out-of-order keywords // ------------------------------------------- allkeywords1(y: 1, x: 2) // expected-error{{argument 'x' must precede argument 'y'}} {{14-14=x: 2, }} {{18-24=}} +// rdar://problem/31849281 - Let's play "bump the argument" + +struct rdar31849281 { var foo, a, b, c: Int } +_ = rdar31849281(a: 101, b: 102, c: 103, foo: 104) // expected-error {{argument 'foo' must precede argument 'a'}} {{18-18=foo: 104, }} {{40-50=}} + +_ = rdar31849281(a: 101, c: 103, b: 102, foo: 104) // expected-error {{argument 'foo' must precede argument 'a'}} {{18-18=foo: 104, }} {{40-50=}} +_ = rdar31849281(foo: 104, a: 101, c: 103, b: 102) // expected-error {{argument 'b' must precede argument 'c'}} {{36-36=b: 102, }} {{42-50=}} + +_ = rdar31849281(b: 102, c: 103, a: 101, foo: 104) // expected-error {{incorrect argument labels in call (have 'b:c:a:foo:', expected 'foo:a:b:c:')}} {{18-19=foo}} {{26-27=a}} {{34-35=b}} {{42-45=c}} +_ = rdar31849281(foo: 104, b: 102, c: 103, a: 101) // expected-error {{argument 'a' must precede argument 'b'}} {{28-28=a: 101, }} {{42-50=}} + +func fun_31849281(a: (Bool) -> Bool, b: (Int) -> (String), c: [Int?]) {} +fun_31849281(c: [nil, 42], a: { !$0 }, b: { (num: Int) -> String in return "\(num)" }) +// expected-error @-1 {{incorrect argument labels in call (have 'c:a:b:', expected 'a:b:c:')}} {{14-15=a}} {{28-29=b}} {{40-41=c}} +fun_31849281(a: { !$0 }, c: [nil, 42], b: { (num: Int) -> String in return String(describing: num) }) +// expected-error @-1 {{argument 'b' must precede argument 'c'}} {{26-26=b: { (num: Int) -> String in return String(describing: num) }, }} {{38-101=}} +fun_31849281(a: { !$0 }, c: [nil, 42], b: { "\($0)" }) +// expected-error @-1 {{argument 'b' must precede argument 'c'}} {{26-26=b: { "\\($0)" }, }} {{38-54=}} + // ------------------------------------------- // Default arguments // ------------------------------------------- @@ -127,6 +173,9 @@ defargs2(first: 1, z: 3, y: 2, last: 4) // expected-error{{argument 'y' must pre defargs2(x: 1, first: 1, last: 4) // expected-error{{argument 'first' must precede argument 'x'}} {{10-10=first: 1, }} {{14-24=}} defargs2(first: 1, last: 4, x: 1) // expected-error{{argument 'x' must precede argument 'last'}} {{20-20=x: 1, }} {{27-33=}} +func rdar43525641(_ a: Int, _ b: Int = 0, c: Int = 0, _ d: Int) {} +rdar43525641(1, c: 2, 3) // Ok + // ------------------------------------------- // Variadics // ------------------------------------------- @@ -334,6 +383,9 @@ struct Variadics8 { } } +func var_31849281(_ a: Int, _ b: Int..., c: Int) {} +var_31849281(1, c: 10, 3, 4, 5, 6, 7, 8, 9) // expected-error {{unnamed argument #3 must precede argument 'c'}} {{17-17=3, 4, 5, 6, 7, 8, 9, }} {{22-43=}} + // ------------------------------------------- // Positions around defaults and variadics // ------------------------------------------- @@ -630,6 +682,18 @@ mismatch1(foo: 5) // expected-error {{extra argument 'foo' in call}} mismatch1(baz: 1, wobble: 2) // expected-error{{incorrect argument labels in call (have 'baz:wobble:', expected 'bar:wibble:')}} {{11-14=bar}} {{19-25=wibble}} mismatch1(food: 1, zap: 2) // expected-error{{extra arguments at positions #1, #2 in call}} +// QoI: FailureDiagnosis doesn't look through 'try' +struct rdar27891805 { + init(contentsOf: String, encoding: String) throws {} + init(contentsOf: String, usedEncoding: inout String) throws {} + init(_ t: T) {} +} + +try rdar27891805(contentsOfURL: nil, usedEncoding: nil) +// expected-error@-1 {{incorrect argument label in call (have 'contentsOfURL:usedEncoding:', expected 'contentsOf:usedEncoding:')}} +// expected-error@-2 {{'nil' is not compatible with expected argument type 'String'}} +// expected-error@-3 {{'nil' is not compatible with expected argument type 'String'}} + // ------------------------------------------- // Out of order and default // ------------------------------------------- @@ -874,3 +938,100 @@ func generic_and_missing_label(x: T) {} generic_and_missing_label(42) // expected-error@-1 {{missing argument label 'x:' in call}} {{27-27=x: }} + +// ------------------------------------------- +// Curried functions +// ------------------------------------------- + +func f7(_ a: Int) -> (_ b: Int) -> Int { + return { b in a+b } +} + +_ = f7(1)(1) +f7(1.0)(2) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} + +f7(1)(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +f7(1)(b: 1.0) // expected-error{{extraneous argument label 'b:' in call}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} + +let f10 = f7(2) +_ = f10(1) +f10(10) // expected-warning {{result of call to function returning 'Int' is unused}} +f10(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +f10(b: 1.0) // expected-error {{extraneous argument label 'b:' in call}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} + + +class CurriedClass { + func method1() {} + func method2(_ a: Int) -> (_ b : Int) -> () { return { b in () } } + func method3(_ a: Int, b : Int) {} // expected-note 3 {{'method3(_:b:)' declared here}} +} + +let c = CurriedClass() +_ = c.method1 +c.method1(1) // expected-error {{argument passed to call that takes no arguments}} +_ = c.method2(1) +_ = c.method2(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +c.method2(1)(2) +c.method2(1)(c: 2) // expected-error {{extraneous argument label 'c:' in call}} +c.method2(1)(c: 2.0) // expected-error {{extraneous argument label 'c:' in call}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} +c.method2(1)(2.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +c.method2(1.0)(2) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +c.method2(1.0)(2.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} + +CurriedClass.method1(c)() +_ = CurriedClass.method1(c) +CurriedClass.method1(c)(1) // expected-error {{argument passed to call that takes no arguments}} +CurriedClass.method1(2.0)(1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'CurriedClass'}} +// expected-error@-1:27 {{argument passed to call that takes no arguments}} + +CurriedClass.method2(c)(32)(b: 1) // expected-error{{extraneous argument label 'b:' in call}} +_ = CurriedClass.method2(c) +_ = CurriedClass.method2(c)(32) +_ = CurriedClass.method2(1,2) // expected-error {{extra argument in call}} +// expected-error@-1 {{instance member 'method2' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} +CurriedClass.method2(c)(1.0)(b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +// expected-error@-1 {{extraneous argument label 'b:' in call}} +CurriedClass.method2(c)(1)(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +CurriedClass.method2(c)(2)(c: 1.0) // expected-error {{extraneous argument label 'c:'}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} + +CurriedClass.method3(c)(32, b: 1) +_ = CurriedClass.method3(c) +_ = CurriedClass.method3(c)(1, 2) // expected-error {{missing argument label 'b:' in call}} {{32-32=b: }} +_ = CurriedClass.method3(c)(1, b: 2)(32) // expected-error {{cannot call value of non-function type '()'}} +_ = CurriedClass.method3(1, 2) // expected-error {{instance member 'method3' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} +// expected-error@-1 {{missing argument label 'b:' in call}} +CurriedClass.method3(c)(1.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +CurriedClass.method3(c)(1) // expected-error {{missing argument for parameter 'b' in call}} +CurriedClass.method3(c)(c: 1.0) // expected-error {{incorrect argument labels in call (have 'c:', expected '_:b:')}} +// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} +// expected-error@-2 {{missing argument for parameter #1 in call}} + + +extension CurriedClass { + func f() { + method3(1, b: 2) + method3() // expected-error {{missing arguments for parameters #1, 'b' in call}} {{13-13=<#Int#>, b: <#Int#>}} + method3(42) // expected-error {{missing argument for parameter 'b' in call}} + method3(self) + // expected-error@-1:13 {{cannot convert value of type 'CurriedClass' to expected argument type 'Int'}} + // expected-error@-2:17 {{missing argument for parameter 'b' in call}} {{17-17=, b: <#Int#>}} + } +} + +extension CurriedClass { + func m1(_ a : Int, b : Int) {} + + func m2(_ a : Int) {} +} + +// QoI: "Extra argument" error when accidentally currying a method +CurriedClass.m1(2, b: 42) // expected-error {{instance member 'm1' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} + + +// QoI: Confusing error message when calling an instance method as a class method +CurriedClass.m2(12) // expected-error {{instance member 'm2' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index c10f96ad1e126..003387b8829e6 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -391,103 +391,6 @@ func rdar19804707() { _ = knownOps } - -func f7(_ a: Int) -> (_ b: Int) -> Int { - return { b in a+b } -} - -_ = f7(1)(1) -f7(1.0)(2) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} - -f7(1)(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -f7(1)(b: 1.0) // expected-error{{extraneous argument label 'b:' in call}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} - -let f10 = f7(2) -_ = f10(1) -f10(10) // expected-warning {{result of call to function returning 'Int' is unused}} -f10(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -f10(b: 1.0) // expected-error {{extraneous argument label 'b:' in call}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} - - -class CurriedClass { - func method1() {} - func method2(_ a: Int) -> (_ b : Int) -> () { return { b in () } } - func method3(_ a: Int, b : Int) {} // expected-note 3 {{'method3(_:b:)' declared here}} -} - -let c = CurriedClass() -_ = c.method1 -c.method1(1) // expected-error {{argument passed to call that takes no arguments}} -_ = c.method2(1) -_ = c.method2(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -c.method2(1)(2) -c.method2(1)(c: 2) // expected-error {{extraneous argument label 'c:' in call}} -c.method2(1)(c: 2.0) // expected-error {{extraneous argument label 'c:' in call}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} -c.method2(1)(2.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -c.method2(1.0)(2) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -c.method2(1.0)(2.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} - -CurriedClass.method1(c)() -_ = CurriedClass.method1(c) -CurriedClass.method1(c)(1) // expected-error {{argument passed to call that takes no arguments}} -CurriedClass.method1(2.0)(1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'CurriedClass'}} -// expected-error@-1:27 {{argument passed to call that takes no arguments}} - -CurriedClass.method2(c)(32)(b: 1) // expected-error{{extraneous argument label 'b:' in call}} -_ = CurriedClass.method2(c) -_ = CurriedClass.method2(c)(32) -_ = CurriedClass.method2(1,2) // expected-error {{extra argument in call}} -// expected-error@-1 {{instance member 'method2' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} -CurriedClass.method2(c)(1.0)(b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -// expected-error@-1 {{extraneous argument label 'b:' in call}} -CurriedClass.method2(c)(1)(1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -CurriedClass.method2(c)(2)(c: 1.0) // expected-error {{extraneous argument label 'c:'}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} - -CurriedClass.method3(c)(32, b: 1) -_ = CurriedClass.method3(c) -_ = CurriedClass.method3(c)(1, 2) // expected-error {{missing argument label 'b:' in call}} {{32-32=b: }} -_ = CurriedClass.method3(c)(1, b: 2)(32) // expected-error {{cannot call value of non-function type '()'}} -_ = CurriedClass.method3(1, 2) // expected-error {{instance member 'method3' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} -// expected-error@-1 {{missing argument label 'b:' in call}} -CurriedClass.method3(c)(1.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} -CurriedClass.method3(c)(1) // expected-error {{missing argument for parameter 'b' in call}} -CurriedClass.method3(c)(c: 1.0) // expected-error {{incorrect argument labels in call (have 'c:', expected '_:b:')}} -// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Int'}} -// expected-error@-2 {{missing argument for parameter #1 in call}} - - -extension CurriedClass { - func f() { - method3(1, b: 2) - method3() // expected-error {{missing arguments for parameters #1, 'b' in call}} {{13-13=<#Int#>, b: <#Int#>}} - method3(42) // expected-error {{missing argument for parameter 'b' in call}} - method3(self) - // expected-error@-1:13 {{cannot convert value of type 'CurriedClass' to expected argument type 'Int'}} - // expected-error@-2:17 {{missing argument for parameter 'b' in call}} {{17-17=, b: <#Int#>}} - } -} - -extension CurriedClass { - func m1(_ a : Int, b : Int) {} - - func m2(_ a : Int) {} -} - -// QoI: "Extra argument" error when accidentally currying a method -CurriedClass.m1(2, b: 42) // expected-error {{instance member 'm1' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} - - -// QoI: Confusing error message when calling an instance method as a class method -CurriedClass.m2(12) // expected-error {{instance member 'm2' cannot be used on type 'CurriedClass'; did you mean to use a value of this type instead?}} - - - - // Error message does not tell me what the problem is enum Color { case Red @@ -847,10 +750,6 @@ func nilComparison(i: Int, o: AnyObject) { _ = o !== nil // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns true}} } -func secondArgumentNotLabeled(a: Int, _ b: Int) { } -secondArgumentNotLabeled(10, 20) -// expected-error@-1 {{missing argument label 'a:' in call}} - // QoI: incorrect ambiguity error due to implicit conversion func testImplConversion(a : Float?) -> Bool {} func testImplConversion(a : Int?) -> Bool { @@ -910,18 +809,6 @@ let sr1752: SR1752? true ? nil : sr1752?.foo() // don't generate a warning about unused result since foo returns Void -// QoI: FailureDiagnosis doesn't look through 'try' -struct rdar27891805 { - init(contentsOf: String, encoding: String) throws {} - init(contentsOf: String, usedEncoding: inout String) throws {} - init(_ t: T) {} -} - -try rdar27891805(contentsOfURL: nil, usedEncoding: nil) -// expected-error@-1 {{incorrect argument label in call (have 'contentsOfURL:usedEncoding:', expected 'contentsOf:usedEncoding:')}} -// expected-error@-2 {{'nil' is not compatible with expected argument type 'String'}} -// expected-error@-3 {{'nil' is not compatible with expected argument type 'String'}} - // Make sure RawRepresentable fix-its don't crash in the presence of type variables class NSCache { func object(forKey: K) -> V? {} @@ -937,27 +824,6 @@ func valueForKey(_ key: K) -> CacheValue? { return cache.object(forKey: key)?.value // expected-error {{no exact matches in reference to instance method 'value'}} } -// SR-2242: poor diagnostic when argument label is omitted - -func r27212391(x: Int, _ y: Int) { - let _: Int = x + y -} - -func r27212391(a: Int, x: Int, _ y: Int) { - let _: Int = a + x + y -} - -r27212391(3, 5) // expected-error {{missing argument label 'x:' in call}} -r27212391(3, y: 5) // expected-error {{incorrect argument labels in call (have '_:y:', expected 'x:_:')}} -r27212391(3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #1}} {{11-11=x: 5, }} {{12-18=}} -r27212391(y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'y:x:', expected 'x:_:')}} {{11-12=x}} {{17-20=}} -r27212391(y: 3, 5) // expected-error {{incorrect argument label in call (have 'y:_:', expected 'x:_:')}} -r27212391(x: 3, x: 5) // expected-error {{extraneous argument label 'x:' in call}} -r27212391(a: 1, 3, y: 5) // expected-error {{incorrect argument labels in call (have 'a:_:y:', expected 'a:x:_:')}} -r27212391(1, x: 3, y: 5) // expected-error {{incorrect argument labels in call (have '_:x:y:', expected 'a:x:_:')}} -r27212391(a: 1, y: 3, x: 5) // expected-error {{incorrect argument labels in call (have 'a:y:x:', expected 'a:x:_:')}} -r27212391(a: 1, 3, x: 5) // expected-error {{argument 'x' must precede unnamed argument #2}} {{17-17=x: 5, }} {{18-24=}} - // SR-1255 func foo1255_1() { return true || false @@ -1216,31 +1082,6 @@ class ListExpr_28456467 : AST_28456467, Expr_28456467 { } } -// rdar://problem/31849281 - Let's play "bump the argument" - -struct rdar31849281 { var foo, a, b, c: Int } -_ = rdar31849281(a: 101, b: 102, c: 103, foo: 104) // expected-error {{argument 'foo' must precede argument 'a'}} {{18-18=foo: 104, }} {{40-50=}} - -_ = rdar31849281(a: 101, c: 103, b: 102, foo: 104) // expected-error {{argument 'foo' must precede argument 'a'}} {{18-18=foo: 104, }} {{40-50=}} -_ = rdar31849281(foo: 104, a: 101, c: 103, b: 102) // expected-error {{argument 'b' must precede argument 'c'}} {{36-36=b: 102, }} {{42-50=}} - -_ = rdar31849281(b: 102, c: 103, a: 101, foo: 104) // expected-error {{incorrect argument labels in call (have 'b:c:a:foo:', expected 'foo:a:b:c:')}} {{18-19=foo}} {{26-27=a}} {{34-35=b}} {{42-45=c}} -_ = rdar31849281(foo: 104, b: 102, c: 103, a: 101) // expected-error {{argument 'a' must precede argument 'b'}} {{28-28=a: 101, }} {{42-50=}} - -func var_31849281(_ a: Int, _ b: Int..., c: Int) {} -var_31849281(1, c: 10, 3, 4, 5, 6, 7, 8, 9) // expected-error {{unnamed argument #3 must precede argument 'c'}} {{17-17=3, 4, 5, 6, 7, 8, 9, }} {{22-43=}} - -func fun_31849281(a: (Bool) -> Bool, b: (Int) -> (String), c: [Int?]) {} -fun_31849281(c: [nil, 42], a: { !$0 }, b: { (num: Int) -> String in return "\(num)" }) -// expected-error @-1 {{incorrect argument labels in call (have 'c:a:b:', expected 'a:b:c:')}} {{14-15=a}} {{28-29=b}} {{40-41=c}} -fun_31849281(a: { !$0 }, c: [nil, 42], b: { (num: Int) -> String in return String(describing: num) }) -// expected-error @-1 {{argument 'b' must precede argument 'c'}} {{26-26=b: { (num: Int) -> String in return String(describing: num) }, }} {{38-101=}} -fun_31849281(a: { !$0 }, c: [nil, 42], b: { "\($0)" }) -// expected-error @-1 {{argument 'b' must precede argument 'c'}} {{26-26=b: { "\\($0)" }, }} {{38-54=}} - -func f_31849281(x: Int, y: Int, z: Int) {} -f_31849281(42, y: 10, x: 20) // expected-error {{incorrect argument labels in call (have '_:y:x:', expected 'x:y:z:')}} {{12-12=x: }} {{23-24=z}} - func sr5081() { var a = ["1", "2", "3", "4", "5"] var b = [String]() @@ -1286,9 +1127,6 @@ func unresolvedTypeExistential() -> Bool { // expected-error@-1 {{'_' can only appear in a pattern or on the left side of an assignment}} } -func rdar43525641(_ a: Int, _ b: Int = 0, c: Int = 0, _ d: Int) {} -rdar43525641(1, c: 2, 3) // Ok - do { struct Array {} let foo: Swift.Array = Array() // expected-error {{cannot convert value of type 'Array' to specified type 'Array'}} diff --git a/test/Driver/vfs.swift b/test/Driver/vfs.swift new file mode 100644 index 0000000000000..21409e5d276d2 --- /dev/null +++ b/test/Driver/vfs.swift @@ -0,0 +1,9 @@ +// Verifies that the driver passes the -vfsoverlay flag to the frontend (SR-12834). +// RUN: %swiftc_driver -driver-print-jobs -c -vfsoverlay overlay.yaml %s | %FileCheck --check-prefix=CHECK-ONE %s + +// CHECK-ONE: bin{{/|\\\\}}swift{{c?(\.exe)?"?}} -frontend{{.*}}-c{{.*}}-vfsoverlay overlay.yaml + +// Verifies that multiple occurrences are passed in order. +// RUN: %swiftc_driver -driver-print-jobs -c -vfsoverlay overlay1.yaml -vfsoverlay overlay2.yaml -vfsoverlay overlay3.yaml %s | %FileCheck --check-prefix=CHECK-MULTIPLE %s + +// CHECK-MULTIPLE: bin{{/|\\\\}}swift{{c?(\.exe)?"?}} -frontend{{.*}}-c{{.*}}-vfsoverlay overlay1.yaml -vfsoverlay overlay2.yaml -vfsoverlay overlay3.yaml diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index 4e297bf18e338..609b1847543ce 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -106,6 +106,10 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=KEYPATH_THUNK_BASE | %FileCheck %s -check-prefix=KEYPATH_THUNK_BASE +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VARIADIC_1 | %FileCheck %s -check-prefix=VARIADIC_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VARIADIC_2 | %FileCheck %s -check-prefix=VARIADIC_2 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VARIADIC_3 | %FileCheck %s -check-prefix=VARIADIC_2 + var i1 = 1 var i2 = 2 var oi1 : Int? @@ -848,3 +852,19 @@ func testKeyPathThunkInBase() { // KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: baz[#SimpleEnum#]; name=baz // KEYPATH_THUNK_BASE: End completions } + +func testVariadic(_ arg: Any..., option1: Int = 0, option2: String = 1) { + testVariadic(#^VARIADIC_1^#) +// VARIADIC_1: Begin completions +// VARIADIC_1-DAG: Decl[FreeFunction]/CurrModule: ['(']{#(arg): Any...#}, {#option1: Int#}, {#option2: String#}[')'][#Void#]; +// VARIADIC_1-DAG: Decl[GlobalVar]/CurrModule: i1[#Int#]; +// VARIADIC_1: End completions + testVariadic(1, #^VARIADIC_2^#) +// VARIADIC_2: Begin completions +// VARIADIC_2-DAG: Pattern/ExprSpecific: {#option1: Int#}[#Int#]; +// VARIADIC_2-DAG: Pattern/ExprSpecific: {#option2: String#}[#String#]; +// VARIADIC_2-DAG: Decl[GlobalVar]/CurrModule: i1[#Int#]; +// VARIADIC_2: End completions + testVariadic(1, 2, #^VARIADIC_3^#) +// Same as VARIADIC_2. +} diff --git a/test/IDE/complete_value_expr.swift b/test/IDE/complete_value_expr.swift index eabd01144a73a..d6164eb7868cc 100644 --- a/test/IDE/complete_value_expr.swift +++ b/test/IDE/complete_value_expr.swift @@ -202,6 +202,10 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE_CALL_RESULT | %FileCheck %s -check-prefix=COMPLETE_CALL_RESULT // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-keywords=false -code-completion-token=BROKEN_CONFORMANCE | %FileCheck %s -check-prefix=BROKEN_CONFORMANCE +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOLMETA_1 | %FileCheck %s -check-prefix=PROTOCOLMETA_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOLMETA_2 | %FileCheck %s -check-prefix=PROTOCOLMETA_2 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOLMETA_3 | %FileCheck %s -check-prefix=PROTOCOLMETA_3 + // Test code completion of expressions that produce a value. struct FooStruct { @@ -2202,3 +2206,38 @@ func testBrokenConformance(arg: BrokenConformanceS) { // BROKEN_CONFORMANCE: Decl[InstanceMethod]/Super: instanceFunc()[#Void#]; // BROKEN_CONFORMANCE: End completions } + +protocol MetaProto { + static func staticFunc() -> Int + static var staticVar: Int { get } + func instanceFunc() -> Int + var intanceVar: Int { get } +} +extension MetaProto { + static func staticFuncExtension() -> Int { 1 } + static var staticVarExtension: Int { 1 } + func instanceFuncExtension() -> Int { 1 } + var intanceVarExtension: Int { 1 } +} +func testProtocolMetatype(protoProto: MetaProto.Protocol, protoType: MetaProto.Type) { + let _ = BrokenConformanceP.#^PROTOCOLMETA_1^# +// PROTOCOLMETA_1: Begin completions, 3 items +// PROTOCOLMETA_1-DAG: Keyword[self]/CurrNominal: self[#BrokenConformanceP.Protocol#]; name=self +// PROTOCOLMETA_1-DAG: Keyword/CurrNominal: Protocol[#BrokenConformanceP.Protocol#]; name=Protocol +// PROTOCOLMETA_1-DAG: Keyword/CurrNominal: Type[#BrokenConformanceP.Type#]; name=Type +// PROTOCOLMETA_1: End completions + let _ = protoProto.#^PROTOCOLMETA_2^# +// PROTOCOLMETA_2: Begin completions, 1 items +// PROTOCOLMETA_2-DAG: Keyword[self]/CurrNominal: self[#MetaProto.Protocol#]; name=self +// PROTOCOLMETA_2: End completions + let _ = protoType.#^PROTOCOLMETA_3^# +// PROTOCOLMETA_3: Begin completions, 7 items +// PROTOCOLMETA_3-DAG: Keyword[self]/CurrNominal: self[#MetaProto.Type#]; name=self +// PROTOCOLMETA_3-DAG: Decl[StaticMethod]/CurrNominal: staticFunc()[#Int#]; name=staticFunc() +// PROTOCOLMETA_3-DAG: Decl[StaticVar]/CurrNominal: staticVar[#Int#]; name=staticVar +// PROTOCOLMETA_3-DAG: Decl[InstanceMethod]/CurrNominal: instanceFunc({#(self): Self#})[#() -> Int#]; name=instanceFunc(self: Self) +// PROTOCOLMETA_3-DAG: Decl[StaticMethod]/CurrNominal: staticFuncExtension()[#Int#]; name=staticFuncExtension() +// PROTOCOLMETA_3-DAG: Decl[StaticVar]/CurrNominal: staticVarExtension[#Int#]; name=staticVarExtension +// PROTOCOLMETA_3-DAG: Decl[InstanceMethod]/CurrNominal: instanceFuncExtension({#(self): Self#})[#() -> Int#]; name=instanceFuncExtension(self: Self) +// PROTOCOLMETA_3: End completions +} diff --git a/test/IRGen/Inputs/huge_c_type.h b/test/IRGen/Inputs/huge_c_type.h new file mode 100644 index 0000000000000..2afde356161e4 --- /dev/null +++ b/test/IRGen/Inputs/huge_c_type.h @@ -0,0 +1,31 @@ +#include + +typedef uint8_t bool; + +#define CREATE_ARRAY(T, N) \ + struct { \ + T data[N]; \ + uint64_t size; \ + } + +typedef struct { + int32_t a; + double b[16]; +} Thing; + +typedef struct { + uint64_t a; + bool b; + CREATE_ARRAY(Thing, 16) c; + uint32_t d; + uint64_t e; + uint64_t f; + CREATE_ARRAY(uint32_t, 4) g; + CREATE_ARRAY(uint64_t, 4) h; + CREATE_ARRAY(uint64_t, 4) i; +} Thing2; + +typedef struct { + int64_t a; + CREATE_ARRAY(Thing2, 512) c; +} Thing3; diff --git a/test/IRGen/c_globals.swift b/test/IRGen/c_globals.swift index 20cdca7519981..0f55f9bb4d173 100644 --- a/test/IRGen/c_globals.swift +++ b/test/IRGen/c_globals.swift @@ -32,4 +32,4 @@ public func testCaptureGlobal() { } // CHECK-DAG: attributes [[CLANG_FUNC_ATTR]] = { noinline nounwind {{.*}}"frame-pointer"="all"{{.*}} -// CHECK-DAG: attributes [[SWIFT_FUNC_ATTR]] = { "frame-pointer"="all" {{.*}}"target-cpu" +// CHECK-DAG: attributes [[SWIFT_FUNC_ATTR]] = { {{.*}}"frame-pointer"="all" {{.*}}"target-cpu" diff --git a/test/IRGen/framepointer.sil b/test/IRGen/framepointer.sil new file mode 100644 index 0000000000000..ab1d393011a36 --- /dev/null +++ b/test/IRGen/framepointer.sil @@ -0,0 +1,64 @@ +// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK +// RUN: %target-swift-frontend -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL +// RUN: %target-swift-frontend -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM --check-prefix=CHECKASM-%target-os-%target-cpu + +// REQUIRES: CPU=x86_64 + +sil_stage canonical + +import Swift + +sil @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 { +entry(%i : $Int32): + return %i : $Int32 +} + +sil @non_leaf_function_with_frame_pointer : $@convention(thin) (Int32) -> Int32 { +entry(%i : $Int32): + %f = function_ref @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 + %r = apply %f(%i) : $@convention(thin) (Int32) -> Int32 + return %r : $Int32 +} + +// CHECK: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// CHECK: entry: +// CHECK: ret i32 %0 +// CHECK: } + +// CHECK: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// CHECK: entry: +// CHECK: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// CHECK: ret i32 %1 +// CHECK: } + +// CHECK: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" + +// CHECK-ALL: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// CHECK-ALL: entry: +// CHECK-ALL: ret i32 %0 +// CHECK-ALL: } + +// CHECK-ALL: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// CHECK-ALL: entry: +// CHECK-ALL: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// CHECK-ALL: ret i32 %1 +// CHECK-ALL: } + +// CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" + +// Silence other os-archs. +// CHECKASM: {{.*}} + +// CHECKASM-macosx-x86_64-LABEL: _leaf_function_no_frame_pointer: +// CHECKASM-macosx-x86_64: push +// CHECKASM-macosx-x86_64: movl %edi, %eax +// CHECKASM-macosx-x86_64: pop +// CHECKASM-macosx-x86_64: ret + + +// CHECKASM-macosx-x86_64-LABEL: _non_leaf_function_with_frame_pointer: +// CHECKASM-macosx-x86_64: pushq %rbp +// CHECKASM-macosx-x86_64: movq %rsp, %rbp +// CHECKASM-macosx-x86_64: callq _leaf_function_no_frame_pointer +// CHECKASM-macosx-x86_64: popq %rbp +// CHECKASM-macosx-x86_64: ret diff --git a/test/IRGen/framepointer_arm64.sil b/test/IRGen/framepointer_arm64.sil new file mode 100644 index 0000000000000..e82a1dabf4ef4 --- /dev/null +++ b/test/IRGen/framepointer_arm64.sil @@ -0,0 +1,73 @@ +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -emit-ir -no-omit-leaf-frame-pointer| %FileCheck %s --check-prefix=CHECK-ALL +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S | %FileCheck %s --check-prefix=CHECKASM +// RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S -no-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECKASM-ALL + +// REQUIRES: CODEGENERATOR=AArch64 + +// UNSUPPORTED: OS=linux-gnu +// UNSUPPORTED: OS=windows + +sil_stage canonical + +import Swift + +sil @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 { +entry(%i : $Int32): + return %i : $Int32 +} + +sil @non_leaf_function_with_frame_pointer : $@convention(thin) (Int32) -> Int32 { +entry(%i : $Int32): + %f = function_ref @leaf_function_no_frame_pointer : $@convention(thin) (Int32) -> Int32 + %r = apply %f(%i) : $@convention(thin) (Int32) -> Int32 + return %r : $Int32 +} + +// CHECK: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// CHECK: entry: +// CHECK: ret i32 %0 +// CHECK: } + +// CHECK: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// CHECK: entry: +// CHECK: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// CHECK: ret i32 %1 +// CHECK: } + +// CHECK: attributes [[ATTR]] = {{{.*}}"frame-pointer"="non-leaf" + +// CHECK-ALL: define{{.*}} swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) [[ATTR:#.*]] { +// CHECK-ALL: entry: +// CHECK-ALL: ret i32 %0 +// CHECK-ALL: } + +// CHECK-ALL: define{{.*}} swiftcc i32 @non_leaf_function_with_frame_pointer(i32 %0) [[ATTR]] { +// CHECK-ALL: entry: +// CHECK-ALL: %1 = call swiftcc i32 @leaf_function_no_frame_pointer(i32 %0) +// CHECK-ALL: ret i32 %1 +// CHECK-ALL: } + +// CHECK-ALL: attributes [[ATTR]] = {{{.*}}"frame-pointer"="all" + +// CHECKASM-LABEL: _leaf_function_no_frame_pointer: +// CHECKASM-NOT: stp +// CHECKASM-NOT: ldp +// CHECKASM: ret + +// CHECKASM-LABEL: _non_leaf_function_with_frame_pointer: +// CHECKASM: stp +// CHECKASM: _leaf_function_no_frame_pointer +// CHECKASM: ldp +// CHECKASM: ret + +// CHECKASM-ALL-LABEL: _leaf_function_no_frame_pointer: +// CHECKASM-ALL: stp +// CHECKASM-ALL: ldp +// CHECKASM-ALL: ret + +// CHECKASM-ALL-LABEL: _non_leaf_function_with_frame_pointer: +// CHECKASM-ALL: stp +// CHECKASM-ALL: _leaf_function_no_frame_pointer +// CHECKASM-ALL: ldp +// CHECKASM-ALL: ret diff --git a/test/IRGen/generic_metatypes.swift b/test/IRGen/generic_metatypes.swift index 2bc67e77b6321..c6033e3680034 100644 --- a/test/IRGen/generic_metatypes.swift +++ b/test/IRGen/generic_metatypes.swift @@ -146,4 +146,4 @@ func makeGenericMetatypes() { // CHECK: ret %swift.metadata_response // CHECK-DAG: attributes [[NOUNWIND_READNONE]] = { nounwind readnone } -// CHECK-DAG: attributes [[NOUNWIND_OPT]] = { noinline nounwind "frame-pointer"="none" "target-cpu" +// CHECK-DAG: attributes [[NOUNWIND_OPT]] = { noinline nounwind " diff --git a/test/IRGen/generic_metatypes_future.swift b/test/IRGen/generic_metatypes_future.swift index 4cfaab336ad8a..3e9fb48513d35 100644 --- a/test/IRGen/generic_metatypes_future.swift +++ b/test/IRGen/generic_metatypes_future.swift @@ -176,4 +176,4 @@ func makeGenericMetatypes() { // CHECK: ret %swift.metadata_response // CHECK-DAG: attributes [[NOUNWIND_READNONE]] = { nounwind readnone } -// CHECK-DAG: attributes [[NOUNWIND_OPT]] = { noinline nounwind "frame-pointer"="none" "target-cpu" +// CHECK-DAG: attributes [[NOUNWIND_OPT]] = { noinline nounwind " diff --git a/test/IRGen/huge_c_type.swift b/test/IRGen/huge_c_type.swift new file mode 100644 index 0000000000000..ebbed0263aeda --- /dev/null +++ b/test/IRGen/huge_c_type.swift @@ -0,0 +1,10 @@ +// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -disable-llvm-optzns -emit-ir | %FileCheck %s +// Make sure that this does not crash during LLVM's ISel. It does not like huge +// llvm::IntegerTypes. +// RUN: %target-swift-frontend -import-objc-header %S/Inputs/huge_c_type.h %s -c + +// CHECK-NOT:i9535616 + +public func doIt(a: Thing3) { + print(a) +} diff --git a/test/IRGen/prespecialized-metadata/Inputs/enum-public-nonfrozen-1argument.swift b/test/IRGen/prespecialized-metadata/Inputs/enum-public-nonfrozen-1argument.swift new file mode 100644 index 0000000000000..9b069a3af60d7 --- /dev/null +++ b/test/IRGen/prespecialized-metadata/Inputs/enum-public-nonfrozen-1argument.swift @@ -0,0 +1,3 @@ +public enum OneArgument { + case first(First) +} diff --git a/test/IRGen/prespecialized-metadata/Inputs/struct-public-nonfrozen-1argument.swift b/test/IRGen/prespecialized-metadata/Inputs/struct-public-nonfrozen-1argument.swift new file mode 100644 index 0000000000000..4300ae8ddca0d --- /dev/null +++ b/test/IRGen/prespecialized-metadata/Inputs/struct-public-nonfrozen-1argument.swift @@ -0,0 +1,17 @@ +public struct OneArgument { + public let first: First + + public let line: UInt + + public init(_ first: First, line: UInt = #line) { + self.first = first + self.line = line + } +} + +extension OneArgument : CustomStringConvertible { + public var description: String { + "\(first) @ \(line)" + } +} + diff --git a/test/IRGen/prespecialized-metadata/enum-outmodule-1argument-1distinct_use-struct-inmodule.swift b/test/IRGen/prespecialized-metadata/enum-outmodule-1argument-1distinct_use-struct-inmodule.swift new file mode 100644 index 0000000000000..360ff61dc64d5 --- /dev/null +++ b/test/IRGen/prespecialized-metadata/enum-outmodule-1argument-1distinct_use-struct-inmodule.swift @@ -0,0 +1,28 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/enum-public-nonfrozen-1argument.swift -emit-library -o %t/libArgument.dylib -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule +// RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment + +// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// UNSUPPORTED: CPU=i386 && OS=ios +// UNSUPPORTED: CPU=armv7 && OS=ios +// UNSUPPORTED: CPU=armv7s && OS=ios + +// CHECK-NOT: @"$s8Argument03OneA0Oy4main03TheA0VGMf" = + +@inline(never) +func consume(_ t: T) { + withExtendedLifetime(t) { t in + } +} + +import Argument + +struct TheArgument { + let value: Int +} + +func doit() { + consume( Argument.OneArgument.first(TheArgument(value: 13)) ) +} +doit() + diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-inmodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-inmodule.swift new file mode 100644 index 0000000000000..d85345483bf30 --- /dev/null +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-inmodule.swift @@ -0,0 +1,28 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift -emit-library -o %t/libArgument.dylib -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule +// RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment + +// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// UNSUPPORTED: CPU=i386 && OS=ios +// UNSUPPORTED: CPU=armv7 && OS=ios +// UNSUPPORTED: CPU=armv7s && OS=ios + +// CHECK-NOT: @"$s8Argument03OneA0Vy4main03TheA0VGMf" = + +@inline(never) +func consume(_ t: T) { + withExtendedLifetime(t) { t in + } +} + +import Argument + +struct TheArgument { + let value: Int +} + +func doit() { + consume( OneArgument(TheArgument(value: 13)) ) +} +doit() + diff --git a/test/IRGen/ptrauth-functions.sil b/test/IRGen/ptrauth-functions.sil index 9606671228345..80f9e43227584 100644 --- a/test/IRGen/ptrauth-functions.sil +++ b/test/IRGen/ptrauth-functions.sil @@ -87,4 +87,4 @@ bb0(%0 : $T): sil_vtable F { } -// CHECK: #[[ATTRS]] = {{{.*}} "ptrauth-calls" "ptrauth-returns" +// CHECK: #[[ATTRS]] = {{{.*}} "ptrauth-auth-traps" "ptrauth-calls" "ptrauth-indirect-gotos" "ptrauth-returns" diff --git a/test/Incremental/Verifier/multi-file/Inputs/Base.swift b/test/Incremental/Verifier/multi-file/Inputs/Base.swift index b9d87e10c8b4c..d58f36b2ec9a1 100644 --- a/test/Incremental/Verifier/multi-file/Inputs/Base.swift +++ b/test/Incremental/Verifier/multi-file/Inputs/Base.swift @@ -1,14 +1,14 @@ open class OpenBase {} // expected-provides {{OpenBase}} // expected-cascading-member {{main.OpenBase.init}} -// expected-cascading-member {{main.OpenBase.deinit}} +// expected-private-member {{main.OpenBase.deinit}} public class PublicBase {} // expected-provides {{PublicBase}} // expected-cascading-member {{main.PublicBase.init}} -// expected-cascading-member {{main.PublicBase.deinit}} +// expected-private-member {{main.PublicBase.deinit}} internal class InternalBase {} // expected-provides {{InternalBase}} // expected-cascading-member {{main.InternalBase.init}} -// expected-cascading-member {{main.InternalBase.deinit}} +// expected-private-member {{main.InternalBase.deinit}} fileprivate class FilePrivateBase {} // expected-provides {{FilePrivateBase}} // expected-cascading-member {{main.FilePrivateBase.init}} diff --git a/test/Incremental/Verifier/multi-file/Inputs/Derived.swift b/test/Incremental/Verifier/multi-file/Inputs/Derived.swift index d60a46fb15250..1246ad927544c 100644 --- a/test/Incremental/Verifier/multi-file/Inputs/Derived.swift +++ b/test/Incremental/Verifier/multi-file/Inputs/Derived.swift @@ -2,19 +2,19 @@ final public class OpenSubclass: OpenBase {} // expected-provides {{OpenSubclass // expected-provides {{OpenBase}} // expected-cascading-member {{main.OpenBase.init}} // expected-cascading-member {{main.OpenSubclass.init}} -// expected-cascading-member {{main.OpenSubclass.deinit}} +// expected-private-member {{main.OpenSubclass.deinit}} final public class PublicSubclass: PublicBase {} // expected-provides {{PublicSubclass}} expected-cascading-superclass {{main.PublicBase}} // expected-provides {{PublicBase}} // expected-cascading-member {{main.PublicBase.init}} // expected-cascading-member {{main.PublicSubclass.init}} -// expected-cascading-member {{main.PublicSubclass.deinit}} +// expected-private-member {{main.PublicSubclass.deinit}} final internal class InternalSubclass: InternalBase {} // expected-provides {{InternalSubclass}} expected-cascading-superclass {{main.InternalBase}} // expected-provides {{InternalBase}} // expected-cascading-member {{main.InternalBase.init}} // expected-cascading-member {{main.InternalSubclass.init}} -// expected-cascading-member {{main.InternalSubclass.deinit}} +// expected-private-member {{main.InternalSubclass.deinit}} public protocol PublicProtocol: PublicBaseProtocol {} // expected-provides {{PublicProtocol}} diff --git a/test/Incremental/Verifier/single-file-private/AnyObject.swift b/test/Incremental/Verifier/single-file-private/AnyObject.swift index d7cac96fdffa1..63aaaac49d028 100644 --- a/test/Incremental/Verifier/single-file-private/AnyObject.swift +++ b/test/Incremental/Verifier/single-file-private/AnyObject.swift @@ -15,7 +15,8 @@ import Foundation // expected-provides {{LookupFactory}} // expected-provides {{NSObject}} -// expected-private-superclass {{__C.NSObject}} +// expected-private-superclass {{ObjectiveC.NSObject}} +// expected-private-conformance {{ObjectiveC.NSObjectProtocol}} // expected-private-conformance {{Foundation._KeyValueCodingAndObserving}} // expected-private-conformance {{Foundation._KeyValueCodingAndObservingPublishing}} // expected-private-conformance {{Swift.Hashable}} @@ -30,14 +31,18 @@ import Foundation // expected-provides {{IntegerLiteralType}} // expected-provides {{FloatLiteralType}} // expected-provides {{Int}} - // expected-private-member {{__C.NSObject.someMember}} - // expected-private-member {{__C.NSObject.Int}} + // expected-private-member {{ObjectiveC.NSObject.someMember}} + // expected-private-member {{ObjectiveC.NSObject.Int}} + // expected-private-member {{ObjectiveC.NSObjectProtocol.someMember}} + // expected-private-member {{ObjectiveC.NSObjectProtocol.Int}} // expected-private-member {{main.LookupFactory.Int}} @objc var someMember: Int = 0 - // expected-private-member {{__C.NSObject.someMethod}} + // expected-private-member {{ObjectiveC.NSObject.someMethod}} + // expected-private-member {{ObjectiveC.NSObjectProtocol.someMethod}} @objc func someMethod() {} - // expected-private-member {{__C.NSObject.init}} + // expected-private-member {{ObjectiveC.NSObject.init}} + // expected-private-member {{ObjectiveC.NSObjectProtocol.init}} // expected-private-member {{main.LookupFactory.init}} // expected-private-member {{main.LookupFactory.deinit}} // expected-private-member {{main.LookupFactory.someMember}} @@ -47,7 +52,7 @@ import Foundation // expected-private-member {{Swift.ExpressibleByNilLiteral.callAsFunction}} // expected-private-member {{Swift.CustomReflectable.callAsFunction}} // expected-private-member {{Swift._ObjectiveCBridgeable.callAsFunction}} -// expected-private-member {{Swift.Optional.callAsFunction}} +// expected-private-member {{Swift.Optional.callAsFunction}} // expected-private-member {{Swift.CustomDebugStringConvertible.callAsFunction}} // expected-private-member {{Swift.Equatable.callAsFunction}} // expected-private-member {{Swift.Hashable.callAsFunction}} diff --git a/test/Incremental/Verifier/single-file/AnyObject.swift b/test/Incremental/Verifier/single-file/AnyObject.swift index eccf877fbd05e..cc7cd837a0828 100644 --- a/test/Incremental/Verifier/single-file/AnyObject.swift +++ b/test/Incremental/Verifier/single-file/AnyObject.swift @@ -15,7 +15,8 @@ import Foundation // expected-provides {{LookupFactory}} // expected-provides {{NSObject}} -// expected-private-superclass {{__C.NSObject}} +// expected-private-superclass {{ObjectiveC.NSObject}} +// expected-private-conformance {{ObjectiveC.NSObjectProtocol}} // expected-private-conformance {{Foundation._KeyValueCodingAndObserving}} // expected-private-conformance {{Foundation._KeyValueCodingAndObservingPublishing}} // expected-private-conformance {{Swift.Hashable}} @@ -30,14 +31,18 @@ import Foundation // expected-provides {{IntegerLiteralType}} // expected-provides {{FloatLiteralType}} // expected-provides {{Int}} - // expected-cascading-member {{__C.NSObject.someMember}} - // expected-cascading-member {{__C.NSObject.Int}} + // expected-cascading-member {{ObjectiveC.NSObject.someMember}} + // expected-cascading-member {{ObjectiveC.NSObject.Int}} + // expected-cascading-member {{ObjectiveC.NSObjectProtocol.someMember}} + // expected-cascading-member {{ObjectiveC.NSObjectProtocol.Int}} // expected-cascading-member {{main.LookupFactory.Int}} @objc var someMember: Int = 0 - // expected-cascading-member {{__C.NSObject.someMethod}} + // expected-cascading-member {{ObjectiveC.NSObject.someMethod}} + // expected-cascading-member {{ObjectiveC.NSObjectProtocol.someMethod}} @objc func someMethod() {} - // expected-cascading-member {{__C.NSObject.init}} + // expected-cascading-member {{ObjectiveC.NSObject.init}} + // expected-cascading-member {{ObjectiveC.NSObjectProtocol.init}} // expected-cascading-member {{main.LookupFactory.init}} // expected-private-member {{main.LookupFactory.deinit}} // expected-cascading-member {{main.LookupFactory.someMember}} @@ -47,7 +52,7 @@ import Foundation // expected-private-member {{Swift.ExpressibleByNilLiteral.callAsFunction}} // expected-private-member {{Swift.CustomReflectable.callAsFunction}} // expected-private-member {{Swift._ObjectiveCBridgeable.callAsFunction}} -// expected-private-member {{Swift.Optional.callAsFunction}} +// expected-private-member {{Swift.Optional.callAsFunction}} // expected-private-member {{Swift.CustomDebugStringConvertible.callAsFunction}} // expected-private-member {{Swift.Equatable.callAsFunction}} // expected-private-member {{Swift.Hashable.callAsFunction}} diff --git a/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift b/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift new file mode 100644 index 0000000000000..9a365a5b687f6 --- /dev/null +++ b/test/Interpreter/objc_failable_composed_with_throwing_initializers.swift @@ -0,0 +1,678 @@ +// RUN: %empty-directory(%t) +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// RUN: %empty-directory(%t) +// +// target-build-swift assumes we want -swift-version 4. Behavior in initializers +// changed in swift 5, so we want to explicitly check it as well. +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out -swift-version 5 +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +// These tests are failable tests that compose with throwing initializers. They +// all catch the throw on failure and return None. + +import Foundation +import ObjCClasses +import StdlibUnittest + +var FailableComposedWithThrowingInitTestSuite = TestSuite("FailableInitObjCComposedWithThrowingInits") +defer { runAllTests() } + +enum E : Error { + case X +} + +func maybeThrow(_ shouldThrow: Bool, _ result: Int? = nil) throws -> Int { + if shouldThrow { + throw E.X + } + return result ?? 0 +} + +func mustFail(f: () -> T?) { + if f() != nil { + preconditionFailure("Didn't fail") + } +} + +class Bear : NSLifetimeTracked { + let x: LifetimeTracked + + /* Designated */ + init(n: Int) { + x = LifetimeTracked(0) + } + + init?(n: Int, before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + } + + init?(n: Int, after: Bool) { + self.x = LifetimeTracked(0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, after: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Convenience */ + convenience init?(before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.init(n: v) + } + + convenience init?(during: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + convenience init?(before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + convenience init?(after: Bool) { + self.init(n: 0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(before: Bool, after: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.init(n: value) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(during: Bool, after: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + convenience init?(before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Exotic */ + convenience init!(IUO: Bool) { + self.init(before: IUO) + } + + convenience init(force: Bool) { + self.init(before: force)! + } +} + +class PolarBear : Bear { + let y: LifetimeTracked + + /* Designated */ + override init(n: Int) { + self.y = LifetimeTracked(0) + super.init(n: n) + } + + override init?(n: Int, before: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: value) + } + + init?(n: Int, during: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + override init?(n: Int, after: Bool) { + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, during: Bool, after: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + override init?(n: Int, before: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + init?(n: Int, before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } +} + +class GuineaPig : Bear { + let y: LifetimeTracked + let t: T + + init?(t: T, during: Bool) { + self.y = LifetimeTracked(0) + self.t = t + super.init(n: 0, before: during) + } +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Root") { + mustFail { Bear(n: 0, before: true) } + mustFail { Bear(n: 0, after: true) } + mustFail { Bear(n: 0, before: true, after: false) } + mustFail { Bear(n: 0, before: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Derived") { + mustFail { PolarBear(n: 0, before: true) } + mustFail { PolarBear(n: 0, during: true) } + mustFail { PolarBear(n: 0, before: true, during: false) } + mustFail { PolarBear(n: 0, before: false, during: true) } + mustFail { PolarBear(n: 0, after: true) } + mustFail { PolarBear(n: 0, during: true, after: false) } + mustFail { PolarBear(n: 0, during: false, after: true) } + mustFail { PolarBear(n: 0, before: true, after: false) } + mustFail { PolarBear(n: 0, before: false, after: true) } + mustFail { PolarBear(n: 0, before: true, during: false, after: false) } + mustFail { PolarBear(n: 0, before: false, during: true, after: false) } + mustFail { PolarBear(n: 0, before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("DesignatedInitFailure_DerivedGeneric") { + mustFail { GuineaPig(t: LifetimeTracked(0), during: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Root") { + mustFail { Bear(before: true) } + mustFail { Bear(during: true) } + mustFail { Bear(before: true, during: false) } + mustFail { Bear(before: false, during: true) } + mustFail { Bear(after: true) } + mustFail { Bear(before: true, after: false) } + mustFail { Bear(before: false, after: true) } + mustFail { Bear(during: true, after: false) } + mustFail { Bear(during: false, after: true) } + mustFail { Bear(before: true, during: false, after: false) } + mustFail { Bear(before: false, during: true, after: false) } + mustFail { Bear(before: false, during: false, after: true) } + + _ = Bear(IUO: false) + _ = Bear(force: false) + + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Derived") { + mustFail { PolarBear(before: true) } + mustFail { PolarBear(during: true) } + mustFail { PolarBear(before: true, during: false) } + mustFail { PolarBear(before: false, during: true) } + mustFail { PolarBear(after: true) } + mustFail { PolarBear(before: true, after: false) } + mustFail { PolarBear(before: false, after: true) } + mustFail { PolarBear(during: true, after: false) } + mustFail { PolarBear(during: false, after: true) } + mustFail { PolarBear(before: true, during: false, after: false) } + mustFail { PolarBear(before: false, during: true, after: false) } + mustFail { PolarBear(before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +// @objc + +class AtObjCBear : NSLifetimeTracked { + let x: LifetimeTracked + + /* Designated */ + @objc init(n: Int) { + x = LifetimeTracked(0) + } + + @objc init?(n: Int, before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + } + + @objc init?(n: Int, after: Bool) { + self.x = LifetimeTracked(0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, after: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.x = LifetimeTracked(v) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Convenience */ + @objc convenience init?(before: Bool) { + let v: Int + do { + v = try maybeThrow(before) + } catch { + return nil + } + self.init(n: v) + } + + @objc convenience init?(during: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc convenience init?(after: Bool) { + self.init(n: 0) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, after: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.init(n: value) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(during: Bool, after: Bool) { + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc convenience init?(before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + do { + try self.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + /* Exotic */ + @objc convenience init!(IUO: Bool) { + self.init(before: IUO) + } + + @objc convenience init(force: Bool) { + self.init(before: force)! + } +} + +class AtObjCPolarBear : AtObjCBear { + let y: LifetimeTracked + + /* Designated */ + @objc override init(n: Int) { + self.y = LifetimeTracked(0) + super.init(n: n) + } + + @objc override init?(n: Int, before: Bool) { + let value: Int + do { + value = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: value) + } + + @objc init?(n: Int, during: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, during: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + } + + @objc override init?(n: Int, after: Bool) { + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, during: Bool, after: Bool) { + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc override init?(n: Int, before: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + self.y = LifetimeTracked(0) + super.init(n: n) + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } + + @objc init?(n: Int, before: Bool, during: Bool, after: Bool) { + do { + let _ = try maybeThrow(before) + } catch { + return nil + } + + self.y = LifetimeTracked(0) + do { + try super.init(n: maybeThrow(during)) + } catch { + return nil + } + + do { + let _ = try maybeThrow(after) + } catch { + return nil + } + } +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Root") { + mustFail { AtObjCBear(n: 0, before: true) } + mustFail { AtObjCBear(n: 0, after: true) } + mustFail { AtObjCBear(n: 0, before: true, after: false) } + mustFail { AtObjCBear(n: 0, before: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("FailableInitFailure_Derived") { + mustFail { AtObjCPolarBear(n: 0, before: true) } + mustFail { AtObjCPolarBear(n: 0, during: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, during: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: true) } + mustFail { AtObjCPolarBear(n: 0, after: true) } + mustFail { AtObjCPolarBear(n: 0, during: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, during: false, after: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, after: true) } + mustFail { AtObjCPolarBear(n: 0, before: true, during: false, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: true, after: false) } + mustFail { AtObjCPolarBear(n: 0, before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Root") { + mustFail { AtObjCBear(before: true) } + mustFail { AtObjCBear(during: true) } + mustFail { AtObjCBear(before: true, during: false) } + mustFail { AtObjCBear(before: false, during: true) } + mustFail { AtObjCBear(after: true) } + mustFail { AtObjCBear(before: true, after: false) } + mustFail { AtObjCBear(before: false, after: true) } + mustFail { AtObjCBear(during: true, after: false) } + mustFail { AtObjCBear(during: false, after: true) } + mustFail { AtObjCBear(before: true, during: false, after: false) } + mustFail { AtObjCBear(before: false, during: true, after: false) } + mustFail { AtObjCBear(before: false, during: false, after: true) } + + _ = AtObjCBear(IUO: false) + _ = AtObjCBear(force: false) + + expectEqual(NSLifetimeTracked.count(), 0) +} + +FailableComposedWithThrowingInitTestSuite.test("ConvenienceInitFailure_Derived") { + mustFail { AtObjCPolarBear(before: true) } + mustFail { AtObjCPolarBear(during: true) } + mustFail { AtObjCPolarBear(before: true, during: false) } + mustFail { AtObjCPolarBear(before: false, during: true) } + mustFail { AtObjCPolarBear(after: true) } + mustFail { AtObjCPolarBear(before: true, after: false) } + mustFail { AtObjCPolarBear(before: false, after: true) } + mustFail { AtObjCPolarBear(during: true, after: false) } + mustFail { AtObjCPolarBear(during: false, after: true) } + mustFail { AtObjCPolarBear(before: true, during: false, after: false) } + mustFail { AtObjCPolarBear(before: false, during: true, after: false) } + mustFail { AtObjCPolarBear(before: false, during: false, after: true) } + expectEqual(NSLifetimeTracked.count(), 0) +} diff --git a/test/Interpreter/objc_throwing_initializers.swift b/test/Interpreter/objc_throwing_initializers.swift index ea6aaca8c2bbb..f8cf7dfd0e24f 100644 --- a/test/Interpreter/objc_throwing_initializers.swift +++ b/test/Interpreter/objc_throwing_initializers.swift @@ -5,6 +5,16 @@ // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out +// RUN: %empty-directory(%t) +// +// target-build-swift assumes we want -swift-version 4. Behavior in initializers +// changed in swift 5, so we want to explicitly check it as well. +// +// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o +// RUN: %target-build-swift -I %S/Inputs/ObjCClasses/ -Xlinker %t/ObjCClasses.o %s -o %t/a.out -swift-version 5 +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + // REQUIRES: executable_test // REQUIRES: objc_interop diff --git a/test/Misc/tbi.sil b/test/Misc/tbi.sil index 0fd2274c7ff40..f22555d8c0aad 100644 --- a/test/Misc/tbi.sil +++ b/test/Misc/tbi.sil @@ -19,19 +19,13 @@ // NO_TBI-LABEL: .globl _testTBI // NO_TBI: _testTBI -// NO_TBI-NEXT: stp -// NO_TBI-NEXT: mov // NO_TBI-NEXT: and // NO_TBI-NEXT: ldr -// NO_TBI-NEXT: ldp // NO_TBI-NEXT: ret // TBI-LABEL: .globl _testTBI // TBI: _testTBI: -// TBI-NEXT: stp -// TBI-NEXT: mov // TBI-NEXT: ldr -// TBI-NEXT: ldp // TBI-NEXT: ret sil_stage canonical diff --git a/test/PrintAsObjC/Inputs/imported-generic-typealias.h b/test/PrintAsObjC/Inputs/imported-generic-typealias.h new file mode 100644 index 0000000000000..f25f2bec8e323 --- /dev/null +++ b/test/PrintAsObjC/Inputs/imported-generic-typealias.h @@ -0,0 +1,11 @@ +@interface NSObject +- (void) init; +@end; + +@interface Horse : NSObject +@end + +@interface Barn : NSObject +@end + +typedef int Hay __attribute__((swift_name("Horse.Hay"))); diff --git a/test/PrintAsObjC/imported-generic-typealias.swift b/test/PrintAsObjC/imported-generic-typealias.swift new file mode 100644 index 0000000000000..dc442656c33b6 --- /dev/null +++ b/test/PrintAsObjC/imported-generic-typealias.swift @@ -0,0 +1,14 @@ +// REQUIRES: objc_interop + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -parse-as-library %s -typecheck -emit-objc-header-path %t/imported-generic-typealias.h -import-objc-header %S/Inputs/imported-generic-typealias.h -disable-objc-attr-requires-foundation-module +// RUN: %FileCheck -check-prefix=CHECK -check-prefix=CHECK-PUBLIC %s < %t/imported-generic-typealias.h + +@objc public class MyRedBarn : Barn { + @objc public func feed(_: Horse.Hay) {} +} + +// CHECK-LABEL: SWIFT_CLASS("_TtC4main9MyRedBarn") +// CHECK-NEXT: @interface MyRedBarn : Barn +// CHECK-NEXT: - (void)feed:(Hay)_; +// CHECK-NEXT: @end diff --git a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil index 2f71618c1e085..b41c5bab7eb6d 100644 --- a/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil +++ b/test/SILOptimizer/definite_init_markuninitialized_delegatingself.sil @@ -31,6 +31,8 @@ class DerivedClassWithNontrivialStoredProperties : RootClassWithNontrivialStored override init() } +sil @getThrowingValue : $@convention(thin) () -> (Int, @error Error) + // CHECK-LABEL: @self_init_assert_instruction // CHECK: apply // CHECK-NEXT: store @@ -323,5 +325,50 @@ bb4: br bb5(%24 : $Optional) bb5(%26 : $Optional): - return %26 : $Optional + return %26 : $Optional +} + +sil @selfinit_derivedclass_peerconvenience_init : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + +// Make sure that we do not error when we store back in the fail block here. +sil hidden [ossa] @convenience_init_with_throwing_argument : $@convention(method) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned Optional { +bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties): + %1 = alloc_stack $DerivedClassWithNontrivialStoredProperties, let, name "self" + %2 = mark_uninitialized [delegatingselfallocated] %1 : $*DerivedClassWithNontrivialStoredProperties + store %0 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + %6 = load [take] %2 : $*DerivedClassWithNontrivialStoredProperties + %7 = function_ref @getThrowingValue : $@convention(thin) () -> (Int, @error Error) + try_apply %7() : $@convention(thin) () -> (Int, @error Error), normal bb1, error bb5 + +bb1(%9 : $Int): + %10 = function_ref @selfinit_derivedclass_peerconvenience_init : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + %11 = apply %10(%6) : $@convention (thin) (@owned DerivedClassWithNontrivialStoredProperties) -> @owned DerivedClassWithNontrivialStoredProperties + store %11 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + %13 = load [copy] %2 : $*DerivedClassWithNontrivialStoredProperties + %14 = enum $Optional, #Optional.some!enumelt, %13 : $DerivedClassWithNontrivialStoredProperties + destroy_addr %2 : $*DerivedClassWithNontrivialStoredProperties + dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties + br bb3(%14 : $Optional) + +bb2: + destroy_addr %2 : $*DerivedClassWithNontrivialStoredProperties + dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties + %20 = enum $Optional, #Optional.none!enumelt + br bb3(%20 : $Optional) + +bb3(%22 : @owned $Optional): + return %22 : $Optional + +bb4(%24 : @owned $Error): + %25 = begin_borrow %24 : $Error + %26 = copy_value %25 : $Error + debug_value %26 : $Error, let, name "error" + destroy_value %26 : $Error + end_borrow %25 : $Error + destroy_value %24 : $Error + br bb2 + +bb5(%32 : @owned $Error): + store %6 to [init] %2 : $*DerivedClassWithNontrivialStoredProperties + br bb4(%32 : $Error) } diff --git a/test/SILOptimizer/funcsig_pseudogenerics.sil b/test/SILOptimizer/funcsig_pseudogenerics.sil new file mode 100644 index 0000000000000..25ab67676d6ba --- /dev/null +++ b/test/SILOptimizer/funcsig_pseudogenerics.sil @@ -0,0 +1,31 @@ +// RUN: %empty-directory(%t) +// RUN: %build-clang-importer-objc-overlays +// RUN: %target-sil-opt(mock-sdk: %clang-importer-sdk-nosource -I %t) -function-signature-opts -sil-fso-optimize-if-not-called %s | %FileCheck %s + +// Make sure that we do not try to specialize pseudo-generics with FSO. + +// REQUIRES: objc_interop + +sil_stage canonical + +import Swift +import Foundation +import objc_generics + +// CHECK: sil [signature_optimized_thunk] [always_inline] @non_pseudo_method : +sil @non_pseudo_method : $@convention(thin) (Int64) -> () { +entry(%0 : $Int64): + return undef : $() +} + +// CHECK: sil @method : +sil @method : $@convention(method) @pseudogeneric (Int64, @guaranteed GenericClass) -> () { +entry(%0 : $Int64, %1 : $GenericClass): + return undef : $() +} + +// CHECK: sil @objcMethod : +sil @objcMethod : $@convention(objc_method) @pseudogeneric (Int64, @guaranteed GenericClass) -> () { +entry(%0 : $Int64, %1 : $GenericClass): + return undef : $() +} diff --git a/test/SILOptimizer/opt_mode.swift b/test/SILOptimizer/opt_mode.swift index cfe34c25aea42..35a6f8f8bcbe0 100644 --- a/test/SILOptimizer/opt_mode.swift +++ b/test/SILOptimizer/opt_mode.swift @@ -47,5 +47,5 @@ func test_ospeed(_ a: A) -> Int { } -// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize " +// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize optsize " // CHECK-IR: attributes [[NOSIZE_ATTR]] = { " diff --git a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift new file mode 100644 index 0000000000000..bd6e5057b9a47 --- /dev/null +++ b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift @@ -0,0 +1,46 @@ +//===--------------- BuildModulesFromGraph.swift --------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// +import Foundation + +let fileName = CommandLine.arguments[1] +let swiftPath = CommandLine.arguments[2] +let moduleName = CommandLine.arguments[3] +let data = try! Data(contentsOf: URL(fileURLWithPath: fileName)) + +let decoder = JSONDecoder() +let moduleDependencyGraph = try! decoder.decode( + ModuleDependencyGraph.self, from: data) + +func findModuleBuildingCommand(_ moduleName: String) -> [String]? { + for (_, dep) in moduleDependencyGraph.modules { + if dep.modulePath.hasSuffix(moduleName) { + switch dep.details { + case .swift(let details): + return details.commandLine + case .clang(let details): + return details.commandLine + } + } else { + continue + } + } + return nil +} + +if let command = findModuleBuildingCommand(moduleName) { + var result = swiftPath + command.forEach { result += " \($0)"} + print(result) + exit(0) +} else { + fatalError("cannot find module building commands for \(moduleName)") +} diff --git a/test/ScanDependencies/Inputs/CHeaders/B.h b/test/ScanDependencies/Inputs/CHeaders/B.h index dedb1b5524f7f..f065892fde57a 100644 --- a/test/ScanDependencies/Inputs/CHeaders/B.h +++ b/test/ScanDependencies/Inputs/CHeaders/B.h @@ -1,4 +1,4 @@ -#include +#include "A.h" void funcB(void); diff --git a/test/ScanDependencies/Inputs/CHeaders/C.h b/test/ScanDependencies/Inputs/CHeaders/C.h index 8a5a9b119ec9d..ec830425f36c5 100644 --- a/test/ScanDependencies/Inputs/CHeaders/C.h +++ b/test/ScanDependencies/Inputs/CHeaders/C.h @@ -1,3 +1,3 @@ -#include +#include "B.h" void funcC(void); diff --git a/test/ScanDependencies/Inputs/CommandRunner.py b/test/ScanDependencies/Inputs/CommandRunner.py new file mode 100755 index 0000000000000..c54adba3fce2c --- /dev/null +++ b/test/ScanDependencies/Inputs/CommandRunner.py @@ -0,0 +1,7 @@ +#!/usr/bin/python + +import subprocess +import sys + +for line in sys.stdin: + subprocess.check_call(line.split()) diff --git a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift index 127126b58aeae..bfcb553fabb03 100644 --- a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift +++ b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift @@ -65,6 +65,10 @@ struct SwiftModuleDetails: Codable { /// The bridging header, if any. var bridgingHeader: BridgingHeader? + + /// The Swift command line arguments that need to be passed through + /// to the -compile-module-from-interface action to build this module. + var commandLine: [String]? } /// Details specific to Clang modules. @@ -144,11 +148,3 @@ struct ModuleDependencyGraph: Codable { /// Information about the main module. var mainModule: ModuleDependencies { modules[.swift(mainModuleName)]! } } - -let fileName = CommandLine.arguments[1] -let data = try! Data(contentsOf: URL(fileURLWithPath: fileName)) - -let decoder = JSONDecoder() -let moduleDependencyGraph = try! decoder.decode( - ModuleDependencyGraph.self, from: data) -print(moduleDependencyGraph) diff --git a/test/ScanDependencies/Inputs/PrintGraph.swift b/test/ScanDependencies/Inputs/PrintGraph.swift new file mode 100644 index 0000000000000..98ecf6acb5881 --- /dev/null +++ b/test/ScanDependencies/Inputs/PrintGraph.swift @@ -0,0 +1,9 @@ +import Foundation + +let fileName = CommandLine.arguments[1] +let data = try! Data(contentsOf: URL(fileURLWithPath: fileName)) + +let decoder = JSONDecoder() +let moduleDependencyGraph = try! decoder.decode( + ModuleDependencyGraph.self, from: data) +print(moduleDependencyGraph) diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index 641f622efcc16..84ff06c2b4c58 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -11,10 +11,32 @@ // Check that the JSON parses correctly into the canonical Swift data // structures. -// RUN: %target-build-swift %S/Inputs/ModuleDependencyGraph.swift -o %t/main +// RUN: mkdir -p %t/PrintGraph +// RUN: cp %S/Inputs/PrintGraph.swift %t/main.swift +// RUN: %target-build-swift %S/Inputs/ModuleDependencyGraph.swift %t/main.swift -o %t/main // RUN: %target-codesign %t/main // RUN: %target-run %t/main %t/deps.json +// RUN: mkdir -p %t/BuildModules +// RUN: cp %S/Inputs/BuildModulesFromGraph.swift %t/BuildModules/main.swift +// RUN: %target-build-swift %S/Inputs/ModuleDependencyGraph.swift %t/BuildModules/main.swift -o %t/ModuleBuilder +// RUN: %target-codesign %t/ModuleBuilder + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A-*.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path B.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/B-*.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path C.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/C-*.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.swiftmodule | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A-*.swiftmodule +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path E.swiftmodule | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/E-*.swiftmodule +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path F.swiftmodule | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/F-*.swiftmodule +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path G.swiftmodule | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/G-*.swiftmodule + // REQUIRES: executable_test // REQUIRES: objc_interop @@ -82,7 +104,12 @@ import G // CHECK-SAME: "{{.*}}" // CHECK: "commandLine": [ -// CHECK-NEXT: "-remove-preceeding-explicit-module-build-incompatible-options" +// CHECK-NEXT: "-frontend" +// CHECK-NEXT: "-Xcc" +// CHECK-NEXT: "-Xclang" +// CHECK-NEXT: "-Xcc" +// CHECK-NEXT: "-cc1" +// CHECK: "-remove-preceeding-explicit-module-build-incompatible-options" /// --------Swift module E // CHECK: "swift": "E" diff --git a/test/Sema/enum_conformance_synthesis.swift b/test/Sema/enum_conformance_synthesis.swift index b6e348c84c80c..b823bf99eb021 100644 --- a/test/Sema/enum_conformance_synthesis.swift +++ b/test/Sema/enum_conformance_synthesis.swift @@ -61,7 +61,7 @@ func customHashable() { enum InvalidCustomHashable { case A, B - var hashValue: String { return "" } + var hashValue: String { return "" } // expected-error {{invalid redeclaration of synthesized implementation for protocol requirement 'hashValue'}} } func ==(x: InvalidCustomHashable, y: InvalidCustomHashable) -> String { return "" @@ -369,7 +369,6 @@ func canEatHotChip(_ birthyear:Birthyear) -> Bool { return birthyear > .nineties(3) } // FIXME: Remove -verify-ignore-unknown. -// :0: error: unexpected error produced: invalid redeclaration of 'hashValue' // :0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool' // :0: error: unexpected note produced: candidate has non-matching type ' (Generic, Generic) -> Bool' // :0: error: unexpected note produced: candidate has non-matching type '(InvalidCustomHashable, InvalidCustomHashable) -> Bool' diff --git a/test/SourceKit/CodeFormat/indent-multiline-string.swift b/test/SourceKit/CodeFormat/indent-multiline-string.swift index 701aac483dff3..bab0eb7c80f32 100644 --- a/test/SourceKit/CodeFormat/indent-multiline-string.swift +++ b/test/SourceKit/CodeFormat/indent-multiline-string.swift @@ -17,4 +17,4 @@ this is line1, // CHECK: key.sourcetext: "this is line1," // CHECK: key.sourcetext: " this is line2," // CHECK: key.sourcetext: "\"\"\"" -// CHECK: key.sourcetext: " \"content\"" +// CHECK: key.sourcetext: " \"content\"" diff --git a/test/SourceKit/CodeFormat/rdar_32789463.swift b/test/SourceKit/CodeFormat/rdar_32789463.swift index b940e6aadfc41..ec803b91f814e 100644 --- a/test/SourceKit/CodeFormat/rdar_32789463.swift +++ b/test/SourceKit/CodeFormat/rdar_32789463.swift @@ -12,5 +12,5 @@ $ // CHECK: key.sourcetext: "struct $ {" // CHECK: key.sourcetext: " let $: <#Type#>" -// CHECK: key.sourcetext: " = foo(\"foo \\($) bar\") {" +// CHECK: key.sourcetext: " = foo(\"foo \\($) bar\") {" // CHECK: key.sourcetext: " $" diff --git a/test/SourceKit/InterfaceGen/Inputs/header3.h b/test/SourceKit/InterfaceGen/Inputs/header3.h new file mode 100644 index 0000000000000..8008adf5dcc2f --- /dev/null +++ b/test/SourceKit/InterfaceGen/Inputs/header3.h @@ -0,0 +1,10 @@ +#define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type +#define NS_ENUM(_type, _name) CF_ENUM(_type, _name) +#define NS_OPTIONS(_type, _name) CF_OPTIONS(_type, _name) +#define CF_SWIFT_NAME(_name) __attribute__((swift_name(#_name))) +#define NS_SWIFT_NAME(_name) CF_SWIFT_NAME(_name) + +typedef NS_ENUM(unsigned, SKFuelKind) { SKFuelKindH2, SKFuelKindCH4, SKFuelKindC12H26 }; +unsigned SKFuelKindIsCryogenic(SKFuelKind kind) NS_SWIFT_NAME(getter:SKFuelKind.isCryogenic(self:)); +unsigned SKFuelKindIsNotCryogenic(SKFuelKind kind) NS_SWIFT_NAME(getter:SKFuelKind.isNotCryogenic(self:)); diff --git a/test/SourceKit/InterfaceGen/gen_header.swift b/test/SourceKit/InterfaceGen/gen_header.swift index 1d25285167656..e6a675b051d74 100644 --- a/test/SourceKit/InterfaceGen/gen_header.swift +++ b/test/SourceKit/InterfaceGen/gen_header.swift @@ -21,3 +21,7 @@ // RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=5 -pass-version-as-string -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.swift4.response // RUN: %FileCheck -input-file %t.header2.swift4.response %s -check-prefix=SWIFT4-STR // SWIFT4-STR: public func show_only_for_swift_4() + +// RUN: echo '#include "header3.h"' > %t.m +// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header3.h -swift-version=5 -- -fsyntax-only %t.m -I %S/Inputs > %t.header3.response +// RUN: %diff -u %s.header3.response %t.header3.response diff --git a/test/SourceKit/InterfaceGen/gen_header.swift.header3.response b/test/SourceKit/InterfaceGen/gen_header.swift.header3.response new file mode 100644 index 0000000000000..15b680fa6d966 --- /dev/null +++ b/test/SourceKit/InterfaceGen/gen_header.swift.header3.response @@ -0,0 +1,328 @@ + +public enum SKFuelKind : UInt32 { + + + case H2 = 0 + + case CH4 = 1 + + case C12H26 = 2 +} +extension SKFuelKind { + + public var isCryogenic: UInt32 { get } + + public var isNotCryogenic: UInt32 { get } +} + +[ + { + key.kind: source.lang.swift.syntaxtype.attribute.builtin, + key.offset: 1, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 8, + key.length: 4 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 13, + key.length: 10 + }, + { + key.kind: source.lang.swift.syntaxtype.typeidentifier, + key.offset: 26, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 45, + key.length: 4 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 50, + key.length: 2 + }, + { + key.kind: source.lang.swift.syntaxtype.number, + key.offset: 55, + key.length: 1 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 62, + key.length: 4 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 67, + key.length: 3 + }, + { + key.kind: source.lang.swift.syntaxtype.number, + key.offset: 73, + key.length: 1 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 80, + key.length: 4 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 85, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.number, + key.offset: 94, + key.length: 1 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 98, + key.length: 9 + }, + { + key.kind: source.lang.swift.syntaxtype.typeidentifier, + key.offset: 108, + key.length: 10 + }, + { + key.kind: source.lang.swift.syntaxtype.attribute.builtin, + key.offset: 126, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 133, + key.length: 3 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 137, + key.length: 11 + }, + { + key.kind: source.lang.swift.syntaxtype.typeidentifier, + key.offset: 150, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 159, + key.length: 3 + }, + { + key.kind: source.lang.swift.syntaxtype.attribute.builtin, + key.offset: 170, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 177, + key.length: 3 + }, + { + key.kind: source.lang.swift.syntaxtype.identifier, + key.offset: 181, + key.length: 14 + }, + { + key.kind: source.lang.swift.syntaxtype.typeidentifier, + key.offset: 197, + key.length: 6 + }, + { + key.kind: source.lang.swift.syntaxtype.keyword, + key.offset: 206, + key.length: 3 + } +] +[ + { + key.kind: source.lang.swift.ref.struct, + key.offset: 26, + key.length: 6, + key.is_system: 1 + }, + { + key.kind: source.lang.swift.ref.enum, + key.offset: 108, + key.length: 10 + }, + { + key.kind: source.lang.swift.ref.struct, + key.offset: 150, + key.length: 6, + key.is_system: 1 + }, + { + key.kind: source.lang.swift.ref.struct, + key.offset: 197, + key.length: 6, + key.is_system: 1 + } +] +[ + { + key.kind: source.lang.swift.decl.enum, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "SKFuelKind", + key.offset: 8, + key.length: 89, + key.nameoffset: 13, + key.namelength: 10, + key.bodyoffset: 34, + key.bodylength: 62, + key.inheritedtypes: [ + { + key.name: "UInt32" + } + ], + key.attributes: [ + { + key.offset: 1, + key.length: 6, + key.attribute: source.decl.attribute.public + } + ], + key.elements: [ + { + key.kind: source.lang.swift.structure.elem.typeref, + key.offset: 26, + key.length: 6 + } + ], + key.substructure: [ + { + key.kind: source.lang.swift.decl.enumcase, + key.offset: 45, + key.length: 11, + key.nameoffset: 0, + key.namelength: 0, + key.substructure: [ + { + key.kind: source.lang.swift.decl.enumelement, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "H2", + key.offset: 50, + key.length: 6, + key.nameoffset: 50, + key.namelength: 2, + key.elements: [ + { + key.kind: source.lang.swift.structure.elem.init_expr, + key.offset: 55, + key.length: 1 + } + ] + } + ] + }, + { + key.kind: source.lang.swift.decl.enumcase, + key.offset: 62, + key.length: 12, + key.nameoffset: 0, + key.namelength: 0, + key.substructure: [ + { + key.kind: source.lang.swift.decl.enumelement, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "CH4", + key.offset: 67, + key.length: 7, + key.nameoffset: 67, + key.namelength: 3, + key.elements: [ + { + key.kind: source.lang.swift.structure.elem.init_expr, + key.offset: 73, + key.length: 1 + } + ] + } + ] + }, + { + key.kind: source.lang.swift.decl.enumcase, + key.offset: 80, + key.length: 15, + key.nameoffset: 0, + key.namelength: 0, + key.substructure: [ + { + key.kind: source.lang.swift.decl.enumelement, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "C12H26", + key.offset: 85, + key.length: 10, + key.nameoffset: 85, + key.namelength: 6, + key.elements: [ + { + key.kind: source.lang.swift.structure.elem.init_expr, + key.offset: 94, + key.length: 1 + } + ] + } + ] + } + ] + }, + { + key.kind: source.lang.swift.decl.extension, + key.name: "SKFuelKind", + key.offset: 98, + key.length: 115, + key.nameoffset: 108, + key.namelength: 10, + key.bodyoffset: 120, + key.bodylength: 92, + key.substructure: [ + { + key.kind: source.lang.swift.decl.var.instance, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "isCryogenic", + key.offset: 133, + key.length: 31, + key.typename: "UInt32", + key.nameoffset: 137, + key.namelength: 11, + key.bodyoffset: 158, + key.bodylength: 5, + key.attributes: [ + { + key.offset: 126, + key.length: 6, + key.attribute: source.decl.attribute.public + } + ] + }, + { + key.kind: source.lang.swift.decl.var.instance, + key.accessibility: source.lang.swift.accessibility.public, + key.name: "isNotCryogenic", + key.offset: 177, + key.length: 34, + key.typename: "UInt32", + key.nameoffset: 181, + key.namelength: 14, + key.bodyoffset: 205, + key.bodylength: 5, + key.attributes: [ + { + key.offset: 170, + key.length: 6, + key.attribute: source.decl.attribute.public + } + ] + } + ] + } +] diff --git a/test/attr/ApplicationMain/attr_main_throws_prints_error.swift b/test/attr/ApplicationMain/attr_main_throws_prints_error.swift index 6f87bb65eac3a..2333737782256 100644 --- a/test/attr/ApplicationMain/attr_main_throws_prints_error.swift +++ b/test/attr/ApplicationMain/attr_main_throws_prints_error.swift @@ -1,9 +1,11 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -parse-as-library %s -o %t/main // RUN: %target-codesign %t/main -// RUN: not --crash %t/main 2>&1 | %FileCheck %s +// RUN: %target-run %t/main > %t/log 2>&1 || true +// RUN: %FileCheck %s < %t/log + // REQUIRES: executable_test -// REQUIRES: OS=macosx +// REQUIRES: OS=macosx || OS=ios enum Err : Error { case or } diff --git a/test/attr/Inputs/SymbolMove/LowLevel.swift b/test/attr/Inputs/SymbolMove/LowLevel.swift index fcc17c74e7f5f..6e848ec43caac 100644 --- a/test/attr/Inputs/SymbolMove/LowLevel.swift +++ b/test/attr/Inputs/SymbolMove/LowLevel.swift @@ -1,11 +1,11 @@ -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) public func printMessageMoved() { print("Hello from LowLevel") } -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) public struct Entity { public let value = "LowLevel" public init() {} @@ -13,8 +13,8 @@ public struct Entity { } // =================== Move protocol =================================// -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) public protocol Box { associatedtype Item var ItemKind: String { get } @@ -22,22 +22,22 @@ public protocol Box { func shape() -> String } -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) extension Box { public func shape() -> String { return "round"} } -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) public struct Candy { public var kind = "candy" public init() {} } // =================== Move enum ============================ // -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) public enum LanguageKind: Int { case Cpp = 1 case Swift = 2 @@ -45,8 +45,8 @@ public enum LanguageKind: Int { } // =================== Move class ============================ // -@available(OSX 10.7, *) -@_originallyDefinedIn(module: "HighLevel", OSX 10.9) +@available(OSX 10.7, iOS 7.0, *) +@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0) open class Vehicle { public init() {} public var currentSpeed = 40.0 diff --git a/test/attr/attr_originally_definedin_backward_compatibility.swift b/test/attr/attr_originally_definedin_backward_compatibility.swift index 7529089a4fd99..6df3f56170f4b 100644 --- a/test/attr/attr_originally_definedin_backward_compatibility.swift +++ b/test/attr/attr_originally_definedin_backward_compatibility.swift @@ -1,5 +1,6 @@ -// REQUIRES: OS=macosx // REQUIRES: executable_test +// REQUIRES: OS=macosx || OS=ios +// REQUIRES: rdar63546363 // // RUN: %empty-directory(%t) // @@ -16,10 +17,10 @@ // --- Build an executable using the original high level framework // RUN: %target-build-swift -emit-executable %s -g -o %t/HighlevelRunner -F %t/SDK/Frameworks/ -framework HighLevel \ -// RUN: -Xlinker -rpath -Xlinker %t/SDK/Frameworks +// RUN: %target-rpath(@executable_path/SDK/Frameworks) // --- Run the executable -// RUN: %t/HighlevelRunner | %FileCheck %s -check-prefix=BEFORE_MOVE +// RUN: %target-run %t/HighlevelRunner %t/SDK/Frameworks/HighLevel.framework/HighLevel | %FileCheck %s -check-prefix=BEFORE_MOVE // --- Build low level framework. // RUN: mkdir -p %t/SDK/Frameworks/LowLevel.framework/Modules/LowLevel.swiftmodule @@ -34,7 +35,7 @@ // RUN: %S/Inputs/SymbolMove/HighLevel.swift -F %t/SDK/Frameworks -Xlinker -reexport_framework -Xlinker LowLevel -enable-library-evolution // --- Run the executable -// RUN: %t/HighlevelRunner | %FileCheck %s -check-prefix=AFTER_MOVE +// RUN: %target-run %t/HighlevelRunner %t/SDK/Frameworks/HighLevel.framework/HighLevel %t/SDK/Frameworks/LowLevel.framework/LowLevel | %FileCheck %s -check-prefix=AFTER_MOVE import HighLevel diff --git a/test/decl/protocol/req/Inputs/witness_fix_its_other_module.swift b/test/decl/protocol/req/Inputs/witness_fix_its_other_module.swift new file mode 100644 index 0000000000000..1a55e31ebac54 --- /dev/null +++ b/test/decl/protocol/req/Inputs/witness_fix_its_other_module.swift @@ -0,0 +1,7 @@ +public protocol OtherOS { + var name: String { get } +} + +public struct Linux: OtherOS { + public let name = "Linux" +} diff --git a/test/decl/protocol/req/witness_fix_its.swift b/test/decl/protocol/req/witness_fix_its.swift index bfb2405ce8c0e..3b7d6f2e9afce 100644 --- a/test/decl/protocol/req/witness_fix_its.swift +++ b/test/decl/protocol/req/witness_fix_its.swift @@ -1,8 +1,12 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -o %t/OtherOS.swiftmodule -module-name OtherOS %S/Inputs/witness_fix_its_other_module.swift -parse-as-library +// RUN: %target-typecheck-verify-swift -I %t/ prefix operator ^^^ postfix operator ^^^^ +import OtherOS + protocol Foo { var bar1: Int { get set } // expected-note {{protocol requires property 'bar1' with type 'Int'; do you want to add a stub?}} static var bar2: Int { get set } // expected-note {{protocol requires property 'bar2' with type 'Int'; do you want to add a stub?}} @@ -34,3 +38,12 @@ protocol Foo1 { struct ConformsToFoo1: Foo1 { // expected-error {{type 'ConformsToFoo1' does not conform to protocol 'Foo1'}} subscript(value: Bool) -> Bool { return false } // expected-note {{candidate is not settable, but protocol requires it}}{{none}} } + +// Don't crash or try to fixup get/set mismatches in other modules +// This protocol requirement must conflict with the one in +// witness_fix_its_other_module.swift. +protocol RenameableProtocol { + var name: String { get set } // expected-note {{protocol requires property 'name' with type 'String'; do you want to add a stub?}} +} + +extension Linux: RenameableProtocol {} // expected-error {{type 'Linux' does not conform to protocol 'RenameableProtocol'}} diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 5d173b1864acb..51c06e93ecfcb 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -849,11 +849,28 @@ struct WrapperWithProjectedValue { var projectedValue: T { return wrappedValue } } -class TestInvalidRedeclaration { +class TestInvalidRedeclaration1 { + @WrapperWithProjectedValue var i = 17 // expected-note@-1 {{'i' previously declared here}} + // expected-note@-2 {{'$i' synthesized for property wrapper projected value}} + // expected-note@-3 {{'_i' synthesized for property wrapper backing storage}} + @WrapperWithProjectedValue var i = 39 // expected-error@-1 {{invalid redeclaration of 'i'}} + // expected-error@-2 {{invalid redeclaration of synthesized property '$i'}} + // expected-error@-3 {{invalid redeclaration of synthesized property '_i'}} +} + +// SR-12839 +struct TestInvalidRedeclaration2 { + var _foo1 = 123 // expected-error {{invalid redeclaration of synthesized property '_foo1'}} + @WrapperWithInitialValue var foo1 = 123 // expected-note {{'_foo1' synthesized for property wrapper backing storage}} +} + +struct TestInvalidRedeclaration3 { + @WrapperWithInitialValue var foo1 = 123 // expected-note {{'_foo1' synthesized for property wrapper backing storage}} + var _foo1 = 123 // expected-error {{invalid redeclaration of synthesized property '_foo1'}} } // --------------------------------------------------------------------------- diff --git a/test/decl/var/property_wrappers_default_init.swift b/test/decl/var/property_wrappers_default_init.swift new file mode 100644 index 0000000000000..80f40e3a4b81b --- /dev/null +++ b/test/decl/var/property_wrappers_default_init.swift @@ -0,0 +1,17 @@ +// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s + +@propertyWrapper +struct Wrapper { + init() {} + + var wrappedValue: Int = 0 +} + +// CHECK-LABEL: internal struct UseWrapperDefaultInit +struct UseWrapperDefaultInit { + @Wrapper var value + // CHECK: internal init(value: Wrapper = Wrapper()) +} + +let _ = UseWrapperDefaultInit() + diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift index c3a7b9e9e9a07..449876f2c8b98 100644 --- a/test/expr/unary/keypath/keypath.swift +++ b/test/expr/unary/keypath/keypath.swift @@ -906,16 +906,15 @@ func testKeyPathHole() { f(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}} f(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}} - // FIXME(SR-12827): Instead of "generic parameter 'T' could not be inferred", - // we should offer the same diagnostic as above. - func provideValueButNotRoot(_ fn: (T) -> String) {} // expected-note 2{{in call to function 'provideValueButNotRoot'}} - provideValueButNotRoot(\.x) // expected-error {{generic parameter 'T' could not be inferred}} - provideValueButNotRoot(\.x.y) // expected-error {{generic parameter 'T' could not be inferred}} + func provideValueButNotRoot(_ fn: (T) -> String) {} + provideValueButNotRoot(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} + provideValueButNotRoot(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} provideValueButNotRoot(\String.foo) // expected-error {{value of type 'String' has no member 'foo'}} - func provideKPValueButNotRoot(_ kp: KeyPath) {} // expected-note 3{{in call to function 'provideKPValueButNotRoot'}} - provideKPValueButNotRoot(\.x) // expected-error {{generic parameter 'T' could not be inferred}} - provideKPValueButNotRoot(\.x.y) // expected-error {{generic parameter 'T' could not be inferred}} + func provideKPValueButNotRoot(_ kp: KeyPath) {} // expected-note {{in call to function 'provideKPValueButNotRoot'}} + provideKPValueButNotRoot(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} + provideKPValueButNotRoot(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} + provideKPValueButNotRoot(\String.foo) // expected-error@-1 {{value of type 'String' has no member 'foo'}} // expected-error@-2 {{generic parameter 'T' could not be inferred}} diff --git a/test/lit.cfg b/test/lit.cfg index 801cc485d0281..79086fa0e640c 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -409,6 +409,7 @@ config.substitutions.append( ('%Benchmark_O', config.benchmark_o) ) config.substitutions.append( ('%Benchmark_Driver', config.benchmark_driver) ) config.substitutions.append( ('%llvm-strings', config.llvm_strings) ) config.substitutions.append( ('%target-ptrauth', run_ptrauth ) ) +config.substitutions.append( ('%swift-path', config.swift) ) # This must come after all substitutions containing "%swift". config.substitutions.append( @@ -962,6 +963,11 @@ if run_vendor == 'apple': config.target_sil_opt = ( "%s %s %s %s" % (xcrun_prefix, config.sil_opt, target_options, config.sil_test_options)) + subst_target_sil_opt_mock_sdk = ( + "%s %s" % + (config.sil_opt, target_options_for_mock_sdk)) + subst_target_sil_opt_mock_sdk_after = \ + target_options_for_mock_sdk_after config.target_swift_symbolgraph_extract = ( "%s %s %s" % (xcrun_prefix, config.swift_symbolgraph_extract, target_options)) @@ -1042,6 +1048,8 @@ elif run_os in ['windows-msvc']: ('%r -target %s %s %s %s' % (config.sil_opt, config.variant_triple, \ resource_dir_opt, mcp_opt, \ config.sil_test_options)) + subst_target_sil_opt_mock_sdk = config.target_sil_opt + subst_target_sil_opt_mock_sdk_after = '' config.target_swift_symbolgraph_extract = \ ('%r -target %s %s' % (config.swift_symbolgraph_extract, \ config.variant_triple, \ @@ -1151,6 +1159,8 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows- config.target_sil_opt = ( '%s -target %s %s %s %s' % (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options)) + subst_target_sil_opt_mock_sdk = config.target_sil_opt + subst_target_sil_opt_mock_sdk_after = "" config.target_swift_symbolgraph_extract = ( '%s -target %s %s' % (config.swift_symbolgraph_extract, config.variant_triple, mcp_opt)) @@ -1272,6 +1282,8 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': '-target', config.variant_triple, android_include_paths_opt, resource_dir_opt, mcp_opt, config.sil_test_options]) + subst_target_sil_opt_mock_sdk = config.target_sil_opt + subst_target_sil_opt_mock_sdk_after = "" config.target_swift_symbolgraph_extract = ' '.join([ config.swift_symbolgraph_extract, '-target', config.variant_triple, @@ -1310,10 +1322,7 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': elif run_os == 'wasi': tools_directory = pipes.quote(make_path(config.wasi_sdk_path, "bin")) - if run_cpu == 'wasm32': - lit_config.note("Testing WebAssembly/WASI " + config.variant_triple) - else: - lit_config.fatal("Unknown environment %s %s" % (run_os, run_cpu)) + lit_config.note("Testing WebAssembly/WASI " + config.variant_triple) config.target_object_format = "wasm" config.target_shared_library_prefix = 'lib' @@ -1373,6 +1382,8 @@ elif run_os == 'wasi': config.target_sil_opt = ( '%s -target %s %s %s %s' % (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt, config.sil_test_options)) + subst_target_sil_opt_mock_sdk = config.target_sil_opt + subst_target_sil_opt_mock_sdk_after = "" config.target_swift_symbolgraph_extract = ' '.join([ config.swift_symbolgraph_extract, '-target', config.variant_triple, @@ -1821,7 +1832,13 @@ config.substitutions.append(('%scale-test', config.substitutions.append(('%empty-directory\(([^)]+)\)', SubstituteCaptures(r'rm -rf "\1" && mkdir -p "\1"'))) +config.substitutions.append(('%target-sil-opt\(mock-sdk:([^)]+)\)', + SubstituteCaptures(r'%s \1 %s' % (subst_target_sil_opt_mock_sdk, + subst_target_sil_opt_mock_sdk_after)))) +# NOTE: This needs to be appended after the mock-sdk expansion to ensure that we +# first expand the mock-sdk when lit is processing. config.substitutions.append(('%target-sil-opt', config.target_sil_opt)) + config.substitutions.append(('%target-sil-func-extractor', config.target_sil_func_extractor)) config.substitutions.append(('%target-sil-llvm-gen', config.target_sil_llvm_gen)) config.substitutions.append(('%target-sil-nm', config.target_sil_nm)) diff --git a/test/swift-indent/basic.swift b/test/swift-indent/basic.swift index 93ed10331d1ba..c4e160d818de2 100644 --- a/test/swift-indent/basic.swift +++ b/test/swift-indent/basic.swift @@ -68,9 +68,9 @@ test(arg1: 1, } let x = [1, 2, 3] - .filter {$0 < $1} - .filter {$0 < $1} - .filter {$0 < $1} + .filter {$0 < $1} + .filter {$0 < $1} + .filter {$0 < $1} bax(34949494949) .foo(a: Int, @@ -141,11 +141,11 @@ if #available( // do the same. // let _ = [] - .map { - f { - print() - } ?? 0 - } + .map { + f { + print() + } ?? 0 + } basename .foo(a: Int, @@ -234,10 +234,10 @@ let arrayC = [2] let arrayD = [3] let array1 = - arrayA + - arrayB + - arrayC + - arrayD + arrayA + + arrayB + + arrayC + + arrayD array1 = arrayA + @@ -254,9 +254,9 @@ arrayC + arrayD let array2 = arrayA + - arrayB + - arrayC + - arrayD + arrayB + + arrayC + + arrayD // Comments should not break exact alignment, and leading comments should be aligned, rather than the label. @@ -867,7 +867,7 @@ func foo( ) {} var (d, e): - (Int, Int) = (1, 3), + (Int, Int) = (1, 3), (f, g): ( Int, Int @@ -1015,3 +1015,24 @@ catch MyErr.a(let code, let message), { print("ahhh!") } + +// Pattern binding decls should only column-align if no element spans from the first line to beyond it. + +public let x = 10, + y = 20 + +private var firstThing = 20, + secondThing = item + .filter {}, + thirdThing = 42 + +public let myVar = itemWithALongName + .filter { $0 >= $1 && $0 - $1 < 50} + +public let first = 45, second = itemWithALongName + .filter { $0 >= $1 && $0 - $1 < 50} + +private var secondThing = item + .filter {}, + firstThing = 20, + thirdThing = 56 diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 32902979906c0..dfb54f841c8ea 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -1697,13 +1697,13 @@ class PlaceholderExpansionScanner { struct ParamClosureInfo { Optional placeholderClosure; - bool isNonPlacholderClosure = false; + bool isNonPlaceholderClosure = false; bool isWrappedWithBraces = false; }; /// Scan the given TupleExpr collecting parameter closure information and /// returning the index of the given target placeholder (if found). - Optional scanTupleExpr(TupleExpr *TE, SourceLoc targetPlacholderLoc, + Optional scanTupleExpr(TupleExpr *TE, SourceLoc targetPlaceholderLoc, std::vector &outParams) { if (TE->getElements().empty()) return llvm::None; @@ -1711,7 +1711,7 @@ class PlaceholderExpansionScanner { outParams.clear(); outParams.reserve(TE->getNumElements()); - Optional targetPlacholderIndex; + Optional targetPlaceholderIndex; for (Expr *E : TE->getElements()) { outParams.emplace_back(); @@ -1720,8 +1720,8 @@ class PlaceholderExpansionScanner { if (auto CE = dyn_cast(E)) { if (CE->hasSingleExpressionBody() && CE->getSingleExpressionBody()->getStartLoc() == - targetPlacholderLoc) { - targetPlacholderIndex = outParams.size() - 1; + targetPlaceholderLoc) { + targetPlaceholderIndex = outParams.size() - 1; if (auto *PHE = dyn_cast( CE->getSingleExpressionBody())) { outParam.isWrappedWithBraces = true; @@ -1732,7 +1732,7 @@ class PlaceholderExpansionScanner { } } // else... - outParam.isNonPlacholderClosure = true; + outParam.isNonPlaceholderClosure = true; continue; } @@ -1741,15 +1741,15 @@ class PlaceholderExpansionScanner { if (scanClosureType(PHE, info)) outParam.placeholderClosure = info; } else if (containClosure(E)) { - outParam.isNonPlacholderClosure = true; + outParam.isNonPlaceholderClosure = true; } - if (E->getStartLoc() == targetPlacholderLoc) { - targetPlacholderIndex = outParams.size() - 1; + if (E->getStartLoc() == targetPlaceholderLoc) { + targetPlaceholderIndex = outParams.size() - 1; } } - return targetPlacholderIndex; + return targetPlaceholderIndex; } public: @@ -1785,21 +1785,21 @@ class PlaceholderExpansionScanner { // and if the call parens can be removed in that case. // We'll first find the enclosing CallExpr, and then do further analysis. std::vector params; - Optional targetPlacholderIndex; + Optional targetPlaceholderIndex; auto ECE = enclosingCallExprArg(SF, PlaceholderStartLoc); Expr *Args = ECE.first; if (Args && ECE.second) { if (isa(Args)) { params.emplace_back(); params.back().placeholderClosure = TargetClosureInfo; - targetPlacholderIndex = 0; + targetPlaceholderIndex = 0; } else if (auto *TE = dyn_cast(Args)) { - targetPlacholderIndex = scanTupleExpr(TE, PlaceholderStartLoc, params); + targetPlaceholderIndex = scanTupleExpr(TE, PlaceholderStartLoc, params); } } // If there was no appropriate parent call expression, it's non-trailing. - if (!targetPlacholderIndex.hasValue()) { + if (!targetPlaceholderIndex.hasValue()) { OneClosureCallback(Args, /*useTrailingClosure=*/false, /*isWrappedWithBraces=*/false, TargetClosureInfo); return true; @@ -1811,23 +1811,23 @@ class PlaceholderExpansionScanner { // Find the first parameter eligible to be trailing. while (firstTrailingIndex != 0) { unsigned i = firstTrailingIndex - 1; - if (params[i].isNonPlacholderClosure || + if (params[i].isNonPlaceholderClosure || !params[i].placeholderClosure.hasValue()) break; firstTrailingIndex = i; } - if (firstTrailingIndex > targetPlacholderIndex) { + if (firstTrailingIndex > targetPlaceholderIndex) { // Target comes before the eligible trailing closures. OneClosureCallback(Args, /*isTrailing=*/false, - params[*targetPlacholderIndex].isWrappedWithBraces, + params[*targetPlaceholderIndex].isWrappedWithBraces, TargetClosureInfo); return true; - } else if (targetPlacholderIndex == end - 1 && + } else if (targetPlaceholderIndex == end - 1 && firstTrailingIndex == end - 1) { // Target is the only eligible trailing closure. OneClosureCallback(Args, /*isTrailing=*/true, - params[*targetPlacholderIndex].isWrappedWithBraces, + params[*targetPlaceholderIndex].isWrappedWithBraces, TargetClosureInfo); return true; } diff --git a/utils/build-presets.ini b/utils/build-presets.ini index cc72681723bc2..e80d899319a6b 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -2437,67 +2437,39 @@ no-assertions [preset: webassembly] +wasm release +verbose cmake-c-launcher=%(C_CXX_LAUNCHER)s cmake-cxx-launcher=%(C_CXX_LAUNCHER)s skip-build-benchmarks -llvm-targets-to-build=X86;WebAssembly -install-destdir=%(INSTALL_DESTDIR)s -swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;sdk-overlay;parser-lib;editor-integration;tools;testsuite-tools;toolchain-tools;license;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers;clang-resource-dir-symlink -llvm-install-components=clang -install-swift -install-prefix=/%(TOOLCHAIN_NAME)s/usr - -[preset: webassembly-host] - -mixin-preset=webassembly -extra-cmake-options= - -DSWIFT_BUILD_SOURCEKIT=FALSE - -DSWIFT_ENABLE_SOURCEKIT_TESTS=FALSE - -DSWIFT_BUILD_SYNTAXPARSERLIB=FALSE - -llbuild -swiftpm - -install-swift -install-llbuild -install-swiftpm - -[preset: webassembly-linux-host] - -mixin-preset=webassembly-host - -libdispatch -libicu -foundation -xctest - -install-libicu -install-foundation -install-libdispatch -install-xctest - -skip-test-libicu -skip-test-foundation -skip-test-libdispatch -skip-test-xctest - -[preset: webassembly-target] - -mixin-preset=webassembly -wasm -verbose build-stdlib-deployment-targets=wasi-wasm32 build-swift-dynamic-sdk-overlay=false build-swift-dynamic-stdlib=false build-swift-static-sdk-overlay build-swift-static-stdlib +llvm-targets-to-build=X86;WebAssembly stdlib-deployment-targets=wasi-wasm32 wasi-sdk=%(SOURCE_PATH)s/wasi-sdk -[preset: webassembly-linux-target] +[preset: webassembly-installable] -mixin-preset=webassembly-target +install_destdir=%(SOURCE_PATH)s/install +installable_package=%(INSTALLABLE_PACKAGE)s +install-prefix=/%(TOOLCHAIN_NAME)s/usr +swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;sdk-overlay;parser-lib;editor-integration;tools;testsuite-tools;toolchain-tools;license;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers;clang-resource-dir-symlink +llvm-install-components=clang +install-swift +darwin-toolchain-bundle-identifier=%(BUNDLE_IDENTIFIER)s +darwin-toolchain-display-name=%(DISPLAY_NAME)s +darwin-toolchain-display-name-short=%(DISPLAY_NAME_SHORT)s +darwin-toolchain-name=%(TOOLCHAIN_NAME)s +darwin-toolchain-version=%(TOOLCHAIN_VERSION)s +darwin-toolchain-alias=swift + +[preset: webassembly-linux] + +mixin-preset=webassembly extra-cmake-options= -DWASI_ICU_URL:STRING="https://github.com/swiftwasm/icu4c-wasi/releases/download/0.5.0/icu4c-wasi.tar.xz" -DWASI_ICU_MD5:STRING="25943864ebbfff15cf5aee8d9d5cc4d7" @@ -2510,9 +2482,9 @@ extra-cmake-options= -DCMAKE_AR="%(SOURCE_PATH)s/wasi-sdk/bin/llvm-ar" -DCMAKE_RANLIB="%(SOURCE_PATH)s/wasi-sdk/bin/llvm-ranlib" -[preset: webassembly-macos-target] +[preset: webassembly-macos] -mixin-preset=webassembly-target +mixin-preset=webassembly extra-cmake-options= -DWASI_ICU_URL:STRING="https://github.com/swiftwasm/icu4c-wasi/releases/download/0.5.0/icu4c-wasi.tar.xz" -DWASI_ICU_MD5:STRING="25943864ebbfff15cf5aee8d9d5cc4d7" @@ -2524,3 +2496,15 @@ extra-cmake-options= -DSWIFT_BUILD_SYNTAXPARSERLIB=FALSE -DCMAKE_AR='/usr/local/opt/llvm/bin/llvm-ar' -DCMAKE_RANLIB='/usr/local/opt/llvm/bin/llvm-ranlib' + +[preset: webassembly-linux-installable] + +mixin-preset= + webassembly-linux + webassembly-installable + +[preset: webassembly-macos-installable] + +mixin-preset= + webassembly-macos + webassembly-installable diff --git a/utils/build-script-impl b/utils/build-script-impl index af06dc936c43c..a1616ef0797e5 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -2385,7 +2385,7 @@ for host in "${ALL_HOSTS[@]}"; do if [[ "${ENABLE_ASAN}" ]] ; then # Limit the number of parallel tests - LLVM_LIT_ARGS="${LLVM_LIT_ARGS} -j $(sysctl hw.physicalcpu | awk -v N=${BUILD_JOBS} '{ print (N < $2) ? N : $2 }')" + LLVM_LIT_ARGS="${LLVM_LIT_ARGS} -j $(sysctl hw.physicalcpu | awk -v N=${BUILD_JOBS} '{ print (N < $2) ? N : int($2/2) }')" fi FILTER_SWIFT_OPTION="--filter=[sS]wift" diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index e746211f7bead..c5ebc8a4b976b 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -424,7 +424,7 @@ is_optional=True), Child('AdditionalTrailingClosures', kind='MultipleTrailingClosureElementList', - collection_element_name='AdditionalTralingClosure', + collection_element_name='AdditionalTrailingClosure', is_optional=True), ]), @@ -440,7 +440,7 @@ is_optional=True), Child('AdditionalTrailingClosures', kind='MultipleTrailingClosureElementList', - collection_element_name='AdditionalTralingClosure', + collection_element_name='AdditionalTrailingClosure', is_optional=True), ]), diff --git a/utils/webassembly/build-swiftpm.sh b/utils/webassembly/build-swiftpm.sh new file mode 100755 index 0000000000000..5a7899166c7d7 --- /dev/null +++ b/utils/webassembly/build-swiftpm.sh @@ -0,0 +1,60 @@ +#!/bin/bash +set -e +DESTINATION_TOOLCHAIN=$1 +SOURCE_PATH="$(cd "$(dirname $0)/../../.." && pwd)" +NIGHTLY_TOOLCHAIN=${SOURCE_PATH}/swift-nightly-toolchain + +export PATH=$NIGHTLY_TOOLCHAIN/usr/bin:$PATH + +SWIFT_BUILD_FLAGS="-c release" +SWIFT_BUILD=${NIGHTLY_TOOLCHAIN}/usr/bin/swift-build + +build_swiftpm() { + local build_flags=$SWIFT_BUILD_FLAGS + if [[ "$(uname)" == "Darwin" ]]; then + rpath_prefix='@executable_path/../lib/swift/macosx' + else + rpath_prefix='$ORIGIN/../lib/swift/linux' + fi + build_flags="${build_flags} -Xlinker -rpath -Xlinker ${rpath_prefix}" + cd ${SOURCE_PATH}/swiftpm + ${SWIFT_BUILD} ${build_flags} +} + +install_binary() { + local src=$1 + local dest=${DESTINATION_TOOLCHAIN}/usr/bin + echo "Installing ${src} to ${dest}" + cp ${src} ${dest} +} + +install_runtime_file() { + local src=$1 + local dest=${DESTINATION_TOOLCHAIN}/usr/lib/swift/pm + echo "Installing ${src} to ${dest}/{4,4_2}" + for runtime in "4" "4_2" + do + mkdir -p ${dest}/${runtime} + cp ${src} ${dest}/${runtime} + done +} + +install_swiftpm() { + cd ${SOURCE_PATH}/swiftpm + local bin_path=$(${SWIFT_BUILD} ${SWIFT_BUILD_FLAGS} --show-bin-path) + for binary in ${bin_path}/{swift-build,swift-test,swift-run,swift-package} + do + install_binary ${binary} + done + + if [[ "$(uname)" == "Linux" ]]; then + install_runtime_file "${bin_path}/libPackageDescription.so" + else + install_runtime_file "${bin_path}/libPackageDescription.dylib" + fi + install_runtime_file "${bin_path}/PackageDescription.swiftmodule" + install_runtime_file "${bin_path}/PackageDescription.swiftdoc" +} + +build_swiftpm +install_swiftpm diff --git a/utils/webassembly/build-toolchain.sh b/utils/webassembly/build-toolchain.sh index eec7d8f068108..fbfceedb83afe 100755 --- a/utils/webassembly/build-toolchain.sh +++ b/utils/webassembly/build-toolchain.sh @@ -9,13 +9,11 @@ WASI_SDK_PATH=$SOURCE_PATH/wasi-sdk case $(uname -s) in Darwin) OS_SUFFIX=osx - HOST_PRESET=webassembly-host - TARGET_PRESET=webassembly-macos-target + PRESET_NAME=webassembly-macos-installable ;; Linux) OS_SUFFIX=linux - HOST_PRESET=webassembly-linux-host - TARGET_PRESET=webassembly-linux-target + PRESET_NAME=webassembly-linux-installable ;; *) echo "Unrecognised platform $(uname -s)" @@ -37,29 +35,9 @@ BUNDLE_IDENTIFIER="swiftwasm.${YEAR}${MONTH}${DAY}" DISPLAY_NAME_SHORT="Swift for WebAssembly Development Snapshot" DISPLAY_NAME="${DISPLAY_NAME_SHORT} ${YEAR}-${MONTH}-${DAY}" -HOST_TOOLCHAIN_DESTDIR=$SOURCE_PATH/host-toolchain-sdk -HOST_TOOLCHAIN_SDK=$HOST_TOOLCHAIN_DESTDIR/$TOOLCHAIN_NAME - -# Avoid clang headers symlink issues -mkdir -p $HOST_TOOLCHAIN_SDK/usr/lib/clang/10.0.0 - -# Build the host toolchain and SDK first. -$SOURCE_PATH/swift/utils/build-script \ - --preset=$HOST_PRESET \ - INSTALL_DESTDIR="$HOST_TOOLCHAIN_DESTDIR" \ - TOOLCHAIN_NAME="$TOOLCHAIN_NAME" \ - C_CXX_LAUNCHER="$(which sccache)" - -# Clean up the host toolchain build directory so that the next -# `build-script` invocation doesn't pick up wrong CMake config files. -# For some reason passing `--reconfigure` to `build-script` won't do this. -rm -rf $SOURCE_PATH/build/Ninja-ReleaseAssert/swift-* - -# build the cross-compilled toolchain -$SOURCE_PATH/swift/utils/build-script \ - --preset=$TARGET_PRESET \ - INSTALL_DESTDIR="$SOURCE_PATH/install" \ +$SOURCE_PATH/swift/utils/build-script --preset=$PRESET_NAME \ SOURCE_PATH="$SOURCE_PATH" \ + INSTALLABLE_PACKAGE="$INSTALLABLE_PACKAGE" \ BUNDLE_IDENTIFIER="${BUNDLE_IDENTIFIER}" \ DISPLAY_NAME="${DISPLAY_NAME}" \ DISPLAY_NAME_SHORT="${DISPLAY_NAME_SHORT}" \ @@ -67,24 +45,37 @@ $SOURCE_PATH/swift/utils/build-script \ TOOLCHAIN_VERSION="${TOOLCHAIN_VERSION}" \ C_CXX_LAUNCHER="$(which sccache)" -# Merge wasi-sdk and the toolchain -cp -a $WASI_SDK_PATH/lib/clang $HOST_TOOLCHAIN_SDK/usr/lib -cp -a $WASI_SDK_PATH/bin/{*ld,llvm-ar} $HOST_TOOLCHAIN_SDK/usr/bin -cp -r $WASI_SDK_PATH/share/wasi-sysroot $HOST_TOOLCHAIN_SDK/usr/share + +NIGHTLY_TOOLCHAIN=$SOURCE_PATH/swift-nightly-toolchain +if [ ! -e $NIGHTLY_TOOLCHAIN ]; then + $UTILS_PATH/install-nightly-toolchain.sh +fi + +TMP_DIR=$(mktemp -d) +cd $TMP_DIR +tar xfz $INSTALLABLE_PACKAGE $TOOLCHAIN_NAME +cd $TMP_DIR/$TOOLCHAIN_NAME + +# Merge wasi-sdk and toolchain +cp -r $WASI_SDK_PATH/lib/clang usr/lib +cp -a $WASI_SDK_PATH/bin/{*ld,llvm-ar} usr/bin +cp -r $WASI_SDK_PATH/share/wasi-sysroot usr/share + +# Build SwiftPM and install it into toolchain +$UTILS_PATH/build-swiftpm.sh $TMP_DIR/$TOOLCHAIN_NAME # Replace absolute sysroot path with relative path -sed -i -e "s@\".*/include@\"../../../../share/wasi-sysroot/include@g" $SOURCE_PATH/install/$TOOLCHAIN_NAME/usr/lib/swift/wasi/wasm32/glibc.modulemap +sed -i -e "s@\".*/include@\"../../../../share/wasi-sysroot/include@g" $TMP_DIR/$TOOLCHAIN_NAME/usr/lib/swift/wasi/wasm32/glibc.modulemap -# Copy the target environment stdlib into the toolchain +# Copy nightly-toolchain's host environment stdlib into toolchain if [[ "$(uname)" == "Linux" ]]; then - # Avoid copying usr/lib/swift/clang because our toolchain's one is a directory - # but nightly's one is symbolic link. A simple copy fails to merge them. - rsync -v -a $SOURCE_PATH/install/$TOOLCHAIN_NAME/usr/lib/ $HOST_TOOLCHAIN_SDK/usr/lib/ --exclude 'swift/clang' + # Avoid to copy usr/lib/swift/clang because our toolchain's one is a directory + # but nightly's one is symbolic link, so fail to merge them. + rsync -a $NIGHTLY_TOOLCHAIN/usr/lib/ $TMP_DIR/$TOOLCHAIN_NAME/usr/lib/ --exclude 'swift/clang' else - cp -v -a $SOURCE_PATH/install/$TOOLCHAIN_NAME/usr/lib/swift_static $HOST_TOOLCHAIN_SDK/usr/lib/swift_static - cp -v -a $SOURCE_PATH/install/$TOOLCHAIN_NAME/usr/lib/swift/wasi $HOST_TOOLCHAIN_SDK/usr/lib/swift + cp -r $NIGHTLY_TOOLCHAIN/usr/lib/swift/macosx $TMP_DIR/$TOOLCHAIN_NAME/usr/lib/swift fi -cd $HOST_TOOLCHAIN_DESTDIR +cd $TMP_DIR tar cfz $PACKAGE_ARTIFACT $TOOLCHAIN_NAME diff --git a/utils/webassembly/install-nightly-toolchain.sh b/utils/webassembly/install-nightly-toolchain.sh new file mode 100755 index 0000000000000..cb0b814aad75b --- /dev/null +++ b/utils/webassembly/install-nightly-toolchain.sh @@ -0,0 +1,50 @@ +set -x + +SOURCE_DIR="$(cd "$(dirname $0)/../../.." && pwd)" +DESTINATION="${SOURCE_DIR}/swift-nightly-toolchain" + +mkdir -p $DESTINATION + +install_linux() { + WORKSPACE=$(mktemp -d) + + pushd ${WORKSPACE} + + BASE_URL=https://swift.org/builds/development/ubuntu1804 + export $(/usr/bin/curl ${BASE_URL}/latest-build.yml | grep 'download:' | sed 's/:[^:\/\/]/=/g') + + DOWNLOAD_DIR=$(echo $download | sed "s/-ubuntu18.04.tar.gz//g") + DOWNLOAD_URL=${BASE_URL}/${DOWNLOAD_DIR}/${download} + /usr/bin/curl ${BASE_URL}/${DOWNLOAD_DIR}/${download} > ${WORKSPACE}/latest_toolchain.tar.gz + + mkdir -p ${WORKSPACE}/latest_toolchain + tar xzf ${WORKSPACE}/latest_toolchain.tar.gz -C ${WORKSPACE}/latest_toolchain + mv ${WORKSPACE}/latest_toolchain/${DOWNLOAD_DIR}-ubuntu18.04/usr ${DESTINATION}/usr + + popd +} + +install_macos() { + WORKSPACE=$(mktemp -d) + + pushd ${WORKSPACE} + + BASE_URL=https://swift.org/builds/development/ + export $(/usr/bin/curl --silent ${BASE_URL}/xcode/latest-build.yml | grep 'download:' | sed 's/:[^:\/\/]/=/g') + + DOWNLOAD_DIR=$(echo $download | sed "s/-osx.pkg//g") + DOWNLOAD_URL=${BASE_URL}/xcode/${DOWNLOAD_DIR}/${download} + + /usr/bin/curl --silent ${DOWNLOAD_URL} > ${WORKSPACE}/latest_xcode_toolchain.pkg + pkgutil --expand ${WORKSPACE}/latest_xcode_toolchain.pkg ${WORKSPACE}/latest_xcode_toolchain + tar xf latest_xcode_toolchain/${DOWNLOAD_DIR}-osx-package.pkg/Payload + mv ${WORKSPACE}/usr ${DESTINATION}/usr + + popd +} + +if [[ "$(uname)" == "Linux" ]]; then + install_linux +else + install_macos +fi diff --git a/validation-test/compiler_crashers_2_fixed/sr12863.swift b/validation-test/compiler_crashers_2_fixed/sr12863.swift new file mode 100644 index 0000000000000..c32e20276d66a --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr12863.swift @@ -0,0 +1,14 @@ +// RUN: %target-swift-frontend -typecheck %s -verify + +enum E { + case bar +} + +@dynamicMemberLookup +struct S { + subscript(dynamicMember key: KeyPath) -> Bool { true } +} + + +let s = S() +let e = s.bar // expected-error {{dynamic key path member lookup cannot refer to enum case 'bar'}} diff --git a/validation-test/stdlib/NewArray.swift.gyb b/validation-test/stdlib/NewArray.swift.gyb index 2e9d4eb7d36c7..4bfb174b34905 100644 --- a/validation-test/stdlib/NewArray.swift.gyb +++ b/validation-test/stdlib/NewArray.swift.gyb @@ -10,13 +10,11 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// -// RUN-DISABLED: %target-run-simple-swift | %FileCheck %s // RUN: %empty-directory(%t) // RUN: %gyb %s -o %t/NewArray.swift // RUN: %line-directive %t/NewArray.swift -- %target-build-swift %t/NewArray.swift -o %t/a.out -Xfrontend -disable-access-control // RUN: %target-run %t/a.out 2>&1 | %line-directive %t/NewArray.swift -- %FileCheck %t/NewArray.swift --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // REQUIRES: executable_test -// XFAIL: * import StdlibUnittest import StdlibCollectionUnittest @@ -40,15 +38,14 @@ protocol MyArrayProtocol : RandomAccessCollection, RangeReplaceableCollection, MutableCollection, - ArrayLiteralConvertible { - - associatedtype Iterator : IteratorProtocol - + ExpressibleByArrayLiteral + where ArrayLiteralElement == Element +{ var _owner: AnyObject? { get } var capacity: Int { get } - func += < + static func += < S : Sequence >(lhs: inout Self, rhs: S) where S.Iterator.Element == Iterator.Element @@ -89,8 +86,7 @@ func test< T : MyArrayProtocol >(_: T.Type, _ label: String) where -T.Iterator.Element == LifetimeTracked, -T.Iterator.Element == T.Element, +T.Element == LifetimeTracked, T.Index == Int { print("test: \(label)...", terminator: "") @@ -113,15 +109,15 @@ T.Index == Int { x += LifetimeTracked(0).. Array { +func nsArrayOfStrings() -> NSArray { let src: ContiguousArray = ["foo", "bar", "baz"] return src.withUnsafeBufferPointer { - let ns = NSArray( + return NSArray( objects: unsafeBitCast($0.baseAddress!, to: UnsafeMutablePointer.self), count: $0.count) - return ns as! [NSString] } } +func swiftArrayWithNSArrayOfStrings() -> Array { + return nsArrayOfStrings() as! [NSString] +} + func testCocoa() { print("== Cocoa ==") // CHECK-objc: == Cocoa == - var a = nsArrayOfStrings() + var a = swiftArrayWithNSArrayOfStrings() printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -232,7 +231,7 @@ func testCocoa() { printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz, qux] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -246,12 +245,12 @@ func testCocoa() { printSequence(b) // CHECK-objc-NEXT: [foo, bar, baz] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() a.insert("bag", at: 2) printSequence(a) // CHECK-objc-NEXT: [foo, bar, bag, baz] - a = nsArrayOfStrings() + a = swiftArrayWithNSArrayOfStrings() a.reserveCapacity(30) printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -269,12 +268,6 @@ func testCocoa() { testCocoa() #endif // _runtime(_ObjC) -extension ArraySlice { - mutating func qsort(_ compare: @escaping (Element, Element) -> Bool) { - _introSort(&self, subRange: Range(self.indices), by: compare) - } -} - func testSlice() { print("== ArraySlice ==") // CHECK: == ArraySlice == @@ -301,14 +294,13 @@ func testSlice() { printSequence(b) // CHECK-NEXT: [0, 1, 2, 3, 41, 5, 6, 7, 8, 9] let c = b - b[b.startIndex..( - _ArrayBuffer(nsArray: nsArrayOfStrings()._buffer._asCocoaArray())) + let a = Array(_buffer: _ArrayBuffer(nsArray: nsArrayOfStrings())) printSequence(a) // CHECK-objc-NEXT: [foo, bar, baz] @@ -456,8 +448,8 @@ func testIsEmptyFirstLast${A}() { print("<\(${A}(3..<43).first!)>") // CHECK-NEXT: <3> print("<\(${A}(3..<43).last!)>") // CHECK-NEXT: <42> - print("<\(${A}().first)>") // CHECK-NEXT: nil - print("<\(${A}().last)>") // CHECK-NEXT: nil + print("<\(String(describing: ${A}().first))>") // CHECK-NEXT: nil + print("<\(String(describing:${A}().last))>") // CHECK-NEXT: nil var a = ${A}(LifetimeTracked(0)..