diff --git a/CMakeLists.txt b/CMakeLists.txt index 524a9981d77b1..baeb525d1f737 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,12 +148,22 @@ set(CLANG_COMPILER_VERSION "" CACHE STRING "The internal version of the Clang compiler") # Indicate whether Swift should attempt to use the lld linker. -set(SWIFT_ENABLE_LLD_LINKER TRUE CACHE BOOL +if(CMAKE_SYSTEM_NAME STREQUAL Windows AND NOT CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) + set(SWIFT_ENABLE_LLD_LINKER_default TRUE) +else() + set(SWIFT_ENABLE_LLD_LINKER_default FALSE) +endif() +set(SWIFT_ENABLE_LLD_LINKER ${SWIFT_ENABLE_LLD_LINKER_default} CACHE BOOL "Enable using the lld linker when available") # Indicate whether Swift should attempt to use the gold linker. # This is not used on Darwin. -set(SWIFT_ENABLE_GOLD_LINKER TRUE CACHE BOOL +if(CMAKE_SYSTEM_NAME STREQUAL Darwin OR CMAKE_SYSTEM_NAME STREQUAL Windows) + set(SWIFT_ENABLE_GOLD_LINKER_default FALSE) +else() + set(SWIFT_ENABLE_GOLD_LINKER_default TRUE) +endif() +set(SWIFT_ENABLE_GOLD_LINKER ${SWIFT_ENABLE_GOLD_LINKER_default} CACHE BOOL "Enable using the gold linker when available") set(SWIFT_TOOLS_ENABLE_LTO OFF CACHE STRING "Build Swift tools with LTO. One diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 09abb13345bb4..ae109498abce4 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -368,18 +368,12 @@ function(_add_host_variant_link_flags target) endif() if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - # FIXME: On Apple platforms, find_program needs to look for "ld64.lld" - find_program(LDLLD_PATH "ld.lld") - if((SWIFT_ENABLE_LLD_LINKER AND LDLLD_PATH AND NOT APPLE) OR - (SWIFT_HOST_VARIANT_SDK STREQUAL WINDOWS AND NOT CMAKE_SYSTEM_NAME STREQUAL WINDOWS)) - target_link_options(${target} PRIVATE -fuse-ld=lld) - elseif(SWIFT_ENABLE_GOLD_LINKER AND - "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_OBJECT_FORMAT}" STREQUAL "ELF") - if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) - target_link_options(${target} PRIVATE -fuse-ld=gold.exe) - else() - target_link_options(${target} PRIVATE -fuse-ld=gold) - endif() + if(SWIFT_ENABLE_LLD_LINKER) + target_link_options(${target} PRIVATE + -fuse-ld=lld$<$:.exe>) + elseif(SWIFT_ENABLE_GOLD_LINKER) + target_link_options(${target} PRIVATE + -fuse-ld=gold$<$:.exe>) endif() endif() diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 4c8e9660a31f2..8409c8dcd724e 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -1012,9 +1012,12 @@ struct TargetAnyClassMetadata : public TargetHeapMetadata { constexpr TargetAnyClassMetadata(TargetClassMetadata *superclass) : TargetHeapMetadata(MetadataKind::Class), - Superclass(superclass), - CacheData{nullptr, nullptr}, - Data(SWIFT_CLASS_IS_SWIFT_MASK) {} + Superclass(superclass) +#if SWIFT_OBJC_INTEROP + , CacheData{nullptr, nullptr}, + Data(SWIFT_CLASS_IS_SWIFT_MASK) +#endif + {} #if SWIFT_OBJC_INTEROP // Allow setting the metadata kind to a class ISA on class metadata. @@ -1027,8 +1030,7 @@ struct TargetAnyClassMetadata : public TargetHeapMetadata { /// The metadata for the superclass. This is null for the root class. ConstTargetMetadataPointer Superclass; - // TODO: remove the CacheData and Data fields in non-ObjC-interop builds. - +#if SWIFT_OBJC_INTEROP /// The cache data is used for certain dynamic lookups; it is owned /// by the runtime and generally needs to interoperate with /// Objective-C's use. @@ -1043,11 +1045,16 @@ struct TargetAnyClassMetadata : public TargetHeapMetadata { static constexpr StoredPointer offsetToData() { return offsetof(TargetAnyClassMetadata, Data); } +#endif /// Is this object a valid swift type metadata? That is, can it be /// safely downcast to ClassMetadata? bool isTypeMetadata() const { +#if SWIFT_OBJC_INTEROP return (Data & SWIFT_CLASS_IS_SWIFT_MASK); +#else + return true; +#endif } /// A different perspective on the same bit bool isPureObjC() const { @@ -1270,6 +1277,7 @@ struct TargetClassMetadata : public TargetAnyClassMetadata { return bounds; } +#if SWIFT_OBJC_INTEROP /// Given a statically-emitted metadata template, this sets the correct /// "is Swift" bit for the current runtime. Depending on the deployment /// target a binary was compiled for, statically emitted metadata templates @@ -1294,6 +1302,7 @@ struct TargetClassMetadata : public TargetAnyClassMetadata { assert(isTypeMetadata()); } +#endif bool isCanonicalStaticallySpecializedGenericMetadata() const { auto *description = getDescription(); diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 74af4727911a6..cd09aa7aee8eb 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -7054,6 +7054,10 @@ class PrecedenceGroupDecl : public Decl { return Name; } + // This is needed to allow templated code to work with both ValueDecls and + // PrecedenceGroupDecls. + DeclBaseName getBaseName() const { return Name; } + SourceLoc getLBraceLoc() const { return LBraceLoc; } SourceLoc getRBraceLoc() const { return RBraceLoc; } @@ -7211,6 +7215,10 @@ class OperatorDecl : public Decl { SourceLoc getNameLoc() const { return NameLoc; } Identifier getName() const { return name; } + // This is needed to allow templated code to work with both ValueDecls and + // OperatorDecls. + DeclBaseName getBaseName() const { return name; } + /// Get the list of identifiers after the colon in the operator declaration. /// /// This list includes the names of designated types. For infix operators, the @@ -7271,12 +7279,6 @@ class InfixOperatorDecl : public OperatorDecl { PrecedenceGroupDecl *getPrecedenceGroup() const; - /// True if this decl's attributes conflict with those declared by another - /// operator. - bool conflictsWith(InfixOperatorDecl *other) { - return getPrecedenceGroup() != other->getPrecedenceGroup(); - } - static bool classof(const Decl *D) { return D->getKind() == DeclKind::InfixOperator; } @@ -7305,12 +7307,6 @@ class PrefixOperatorDecl : public OperatorDecl { return { getOperatorLoc(), getNameLoc() }; } - /// True if this decl's attributes conflict with those declared by another - /// PrefixOperatorDecl. - bool conflictsWith(PrefixOperatorDecl *other) { - return false; - } - static bool classof(const Decl *D) { return D->getKind() == DeclKind::PrefixOperator; } @@ -7338,12 +7334,6 @@ class PostfixOperatorDecl : public OperatorDecl { SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; } - - /// True if this decl's attributes conflict with those declared by another - /// PostfixOperatorDecl. - bool conflictsWith(PostfixOperatorDecl *other) { - return false; - } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PostfixOperator; diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index cd7fc9e22c6aa..36e1f07a2db56 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -55,6 +55,9 @@ namespace swift { class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; + class InfixOperatorDecl; + class InfixOperatorLookupResult; + class PrecedenceGroupDecl; class ProtocolDecl; class Requirement; class SourceFile; @@ -62,6 +65,9 @@ namespace swift { class ModuleDecl; class GenericTypeDecl; class NominalTypeDecl; + class PrecedenceGroupLookupResult; + class PostfixOperatorDecl; + class PrefixOperatorDecl; class ProtocolConformance; class ValueDecl; class Initializer; @@ -562,6 +568,29 @@ class alignas(1 << DeclContextAlignInBits) DeclContext { ObjCSelector selector, SmallVectorImpl &results) const; + /// Looks up an infix operator with a given \p name. + /// + /// This returns a vector of results, as it's possible to find multiple infix + /// operators with different precedence groups. + InfixOperatorLookupResult lookupInfixOperator(Identifier name) const; + + /// Looks up an prefix operator with a given \p name. + /// + /// If multiple results are found, one is chosen in a stable manner, as + /// prefix operator decls cannot differ other than in name. If no results are + /// found, returns \c nullptr. + PrefixOperatorDecl *lookupPrefixOperator(Identifier name) const; + + /// Looks up an postfix operator with a given \p name. + /// + /// If multiple results are found, one is chosen in a stable manner, as + /// postfix operator decls cannot differ other than in name. If no results are + /// found, returns \c nullptr. + PostfixOperatorDecl *lookupPostfixOperator(Identifier name) const; + + /// Looks up a precedence group with a given \p name. + PrecedenceGroupLookupResult lookupPrecedenceGroup(Identifier name) const; + /// Return the ASTContext for a specified DeclContext by /// walking up to the enclosing module and returning its ASTContext. LLVM_READONLY diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index f6a14683e0d9c..9cd688373bbbf 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -590,21 +590,6 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// FIXME: Remove the integrated REPL. void clearLookupCache(); - /// @{ - - /// Look up the given operator in this module. - /// - /// If the operator is not found, or if there is an ambiguity, returns null. - InfixOperatorDecl *lookupInfixOperator(Identifier name, - SourceLoc diagLoc = {}); - PrefixOperatorDecl *lookupPrefixOperator(Identifier name, - SourceLoc diagLoc = {}); - PostfixOperatorDecl *lookupPostfixOperator(Identifier name, - SourceLoc diagLoc = {}); - PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name, - SourceLoc diagLoc = {}); - /// @} - /// Finds all class members defined in this module. /// /// This does a simple local lookup, not recursively looking through imports. diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 911a259dd0135..544b5b9bdf54c 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -455,6 +455,26 @@ bool removeOverriddenDecls(SmallVectorImpl &decls); bool removeShadowedDecls(SmallVectorImpl &decls, const DeclContext *dc); +/// Remove any operators in the given set that are shadowed by +/// other operators in that set. +/// +/// \param decls The set of operators being considered. +/// \param dc The DeclContext from which the lookup was performed. +/// +/// \returns true if any shadowed declarations were removed. +bool removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc); + +/// Remove any precedence groups in the given set that are shadowed by +/// other precedence groups in that set. +/// +/// \param decls The set of precedence groups being considered. +/// \param dc The DeclContext from which the lookup was performed. +/// +/// \returns true if any shadowed declarations were removed. +bool removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc); + /// Finds decls visible in the given context and feeds them to the given /// VisibleDeclConsumer. If the current DeclContext is nested in a function, /// the SourceLoc is used to determine which declarations in that function diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index e15c8b787dce1..e71c789fbfb0a 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -594,14 +594,10 @@ class OperatorLookupDescriptor final { using Storage = llvm::PointerUnion; Storage fileOrModule; Identifier name; - bool isCascading; - SourceLoc diagLoc; private: - OperatorLookupDescriptor(Storage fileOrModule, Identifier name, - bool isCascading, SourceLoc diagLoc) - : fileOrModule(fileOrModule), name(name), isCascading(isCascading), - diagLoc(diagLoc) {} + OperatorLookupDescriptor(Storage fileOrModule, Identifier name) + : fileOrModule(fileOrModule), name(name) {} public: /// Retrieves the files to perform lookup in. @@ -613,14 +609,20 @@ class OperatorLookupDescriptor final { return fileOrModule.dyn_cast(); } + /// Retrieve the file or module for the lookup, as a DeclContext. + DeclContext *getDC() const { + if (auto *module = getModule()) + return module; + return fileOrModule.get(); + } + friend llvm::hash_code hash_value(const OperatorLookupDescriptor &desc) { - return llvm::hash_combine(desc.fileOrModule, desc.name, desc.isCascading); + return llvm::hash_combine(desc.fileOrModule, desc.name); } friend bool operator==(const OperatorLookupDescriptor &lhs, const OperatorLookupDescriptor &rhs) { - return lhs.fileOrModule == rhs.fileOrModule && lhs.name == rhs.name && - lhs.isCascading == rhs.isCascading; + return lhs.fileOrModule == rhs.fileOrModule && lhs.name == rhs.name; } friend bool operator!=(const OperatorLookupDescriptor &lhs, @@ -628,16 +630,15 @@ class OperatorLookupDescriptor final { return !(lhs == rhs); } - static OperatorLookupDescriptor forFile(FileUnit *file, Identifier name, - bool isCascading, SourceLoc diagLoc) { - return OperatorLookupDescriptor(file, name, isCascading, diagLoc); + static OperatorLookupDescriptor forFile(FileUnit *file, Identifier name) { + return OperatorLookupDescriptor(file, name); } - static OperatorLookupDescriptor forModule(ModuleDecl *mod, Identifier name, - bool isCascading, - SourceLoc diagLoc) { - return OperatorLookupDescriptor(mod, name, isCascading, diagLoc); + static OperatorLookupDescriptor forModule(ModuleDecl *mod, Identifier name) { + return OperatorLookupDescriptor(mod, name); } + + static OperatorLookupDescriptor forDC(const DeclContext *DC, Identifier name); }; void simple_display(llvm::raw_ostream &out, @@ -645,34 +646,6 @@ void simple_display(llvm::raw_ostream &out, SourceLoc extractNearestSourceLoc(const OperatorLookupDescriptor &desc); -template -class LookupOperatorRequest - : public SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached> { - using SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached>::SimpleRequest; - -private: - friend SimpleRequest, - OperatorType *(OperatorLookupDescriptor), - RequestFlags::Cached>; - - // Evaluation. - OperatorType *evaluate(Evaluator &evaluator, - OperatorLookupDescriptor desc) const; - -public: - // Cached. - bool isCached() const { return true; } -}; - -using LookupPrefixOperatorRequest = LookupOperatorRequest; -using LookupInfixOperatorRequest = LookupOperatorRequest; -using LookupPostfixOperatorRequest = LookupOperatorRequest; -using LookupPrecedenceGroupRequest = LookupOperatorRequest; - /// Looks up an operator in a given file or module without looking through /// imports. class DirectOperatorLookupRequest @@ -770,6 +743,84 @@ class LookupConformanceInModuleRequest ProtocolConformanceRef result) const; }; +/// Look up an 'infix operator' decl by name. +class LookupInfixOperatorRequest + : public SimpleRequest( + OperatorLookupDescriptor), + RequestFlags::Cached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + TinyPtrVector + evaluate(Evaluator &evaluator, OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up an 'prefix operator' decl by name. +class LookupPrefixOperatorRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + PrefixOperatorDecl *evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up an 'postfix operator' decl by name. +class LookupPostfixOperatorRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + PostfixOperatorDecl *evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + +/// Look up a precedencegroup decl by name. +class LookupPrecedenceGroupRequest + : public SimpleRequest( + OperatorLookupDescriptor), + RequestFlags::Cached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + TinyPtrVector + evaluate(Evaluator &evaluator, OperatorLookupDescriptor descriptor) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + #define SWIFT_TYPEID_ZONE NameLookup #define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/AST/NameLookupTypeIDZone.def b/include/swift/AST/NameLookupTypeIDZone.def index de346c54f8806..b67a2bbabe078 100644 --- a/include/swift/AST/NameLookupTypeIDZone.def +++ b/include/swift/AST/NameLookupTypeIDZone.def @@ -89,11 +89,11 @@ SWIFT_REQUEST(NameLookup, LookupPrefixOperatorRequest, PrefixOperatorDecl *(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupInfixOperatorRequest, - InfixOperatorDecl *(OperatorLookupDescriptor), + TinyPtrVector(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupPostfixOperatorRequest, PostfixOperatorDecl *(OperatorLookupDescriptor), Cached, NoLocationInfo) SWIFT_REQUEST(NameLookup, LookupPrecedenceGroupRequest, - PrecedenceGroupDecl *(OperatorLookupDescriptor), + TinyPtrVector(OperatorLookupDescriptor), Cached, NoLocationInfo) diff --git a/include/swift/AST/OperatorNameLookup.h b/include/swift/AST/OperatorNameLookup.h new file mode 100644 index 0000000000000..6cea9e69e7d26 --- /dev/null +++ b/include/swift/AST/OperatorNameLookup.h @@ -0,0 +1,127 @@ +//===--- OperatorNameLookup.h - Operator and Precedence Lookup --*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces for looking up operator and precedence group +// declarations. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_AST_OPERATOR_NAME_LOOKUP_H +#define SWIFT_AST_OPERATOR_NAME_LOOKUP_H + +#include "swift/AST/Identifier.h" +#include "swift/AST/Module.h" +#include "llvm/ADT/TinyPtrVector.h" + +namespace swift { + +/// Base class for infix operator and precedence group lookup results. +template +class OperatorLookupResultBase { +protected: + const DeclContext *ModuleDC; + Identifier Name; + TinyPtrVector Results; + +private: + const Derived &asDerived() const { + return *static_cast(this); + } + +public: + OperatorLookupResultBase(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : ModuleDC(moduleDC), Name(name), Results(std::move(results)) {} + + /// Retrieve the underlying results vector. + TinyPtrVector get() && { return std::move(Results); } + + /// If the lookup produced a single result, returns it. Otherwise returns + /// \c nullptr. + DeclTy *getSingle() const { + return Results.size() == 1 ? Results[0] : nullptr; + } + + /// If the lookup produced a single result, returns it. Otherwise, emits an + /// ambiguity or missing decl diagnostic, and returns \c nullptr. + DeclTy *getSingleOrDiagnose(SourceLoc loc, bool forBuiltin = false) const { + if (auto single = getSingle()) + return single; + + if (isAmbiguous()) { + asDerived().diagnoseAmbiguity(loc); + } else { + assert(!hasResults()); + asDerived().diagnoseMissing(loc, forBuiltin); + } + return nullptr; + } + + using const_iterator = typename decltype(Results)::const_iterator; + const_iterator begin() const { return Results.begin(); } + const_iterator end() const { return Results.end(); } + + /// Whether the lookup produced at least one result. + bool hasResults() const { return !Results.empty(); } + + /// Whether the lookup produced multiple ambiguous results. + bool isAmbiguous() const { return Results.size() > 1; } + + friend bool operator==(const OperatorLookupResultBase &lhs, + const OperatorLookupResultBase &rhs) { + return lhs.Results == rhs.Results; + } + friend bool operator!=(const OperatorLookupResultBase &lhs, + const OperatorLookupResultBase &rhs) { + return !(lhs == rhs); + } + friend void simple_display(llvm::raw_ostream &out, + const OperatorLookupResultBase &result) { + simple_display(out, result.Results); + } +}; + +/// The result of a precedence group lookup. +class PrecedenceGroupLookupResult final + : public OperatorLookupResultBase { + friend class OperatorLookupResultBase; + +public: + PrecedenceGroupLookupResult(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} + + void diagnoseAmbiguity(SourceLoc loc) const; + void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; +}; + +/// The result of an infix operator lookup. +class InfixOperatorLookupResult final + : public OperatorLookupResultBase { + friend class OperatorLookupResultBase; + +public: + InfixOperatorLookupResult(const DeclContext *moduleDC, Identifier name, + TinyPtrVector &&results) + : OperatorLookupResultBase(moduleDC, name, std::move(results)) {} + + void diagnoseAmbiguity(SourceLoc loc) const; + void diagnoseMissing(SourceLoc loc, bool forBuiltin) const; +}; + +} // end namespace swift + +#endif diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 06de45f082456..7265512843e73 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -30,7 +30,6 @@ class SourceFile final : public FileUnit { friend class ParseSourceFileRequest; public: - class Impl; struct SourceFileSyntaxInfo; /// Possible attributes for imports in source files. @@ -195,7 +194,6 @@ class SourceFile final : public FileUnit { ParserStatePtr(/*ptr*/ nullptr, /*deleter*/ nullptr); friend ASTContext; - friend Impl; public: /// Appends the given declaration to the end of the top-level decls list. Do diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 200663d00cb80..2d8f1bb7f7257 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1531,7 +1531,8 @@ void simple_display(llvm::raw_ostream &out, const PrecedenceGroupDescriptor &d); class ValidatePrecedenceGroupRequest : public SimpleRequest( + PrecedenceGroupDescriptor), RequestFlags::Cached> { public: using SimpleRequest::SimpleRequest; @@ -1540,7 +1541,7 @@ class ValidatePrecedenceGroupRequest friend SimpleRequest; // Evaluation. - PrecedenceGroupDecl * + TinyPtrVector evaluate(Evaluator &evaluator, PrecedenceGroupDescriptor descriptor) const; public: diff --git a/include/swift/AST/TypeLoc.h b/include/swift/AST/TypeLoc.h index 50218e2844ede..9eefeed82e529 100644 --- a/include/swift/AST/TypeLoc.h +++ b/include/swift/AST/TypeLoc.h @@ -65,8 +65,6 @@ class alignas(1 << TypeLocAlignInBits) TypeLoc { void setInvalidType(ASTContext &C); void setType(Type Ty); - TypeLoc clone(ASTContext &ctx) const; - friend llvm::hash_code hash_value(const TypeLoc &owner) { return llvm::hash_combine(owner.Ty.getPointer(), owner.TyR); } diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index 14e99ea6225e9..57cb8c6b73011 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -163,9 +163,6 @@ class alignas(8) TypeRepr { void print(raw_ostream &OS, const PrintOptions &Opts = PrintOptions()) const; void print(ASTPrinter &Printer, const PrintOptions &Opts) const; SWIFT_DEBUG_DUMP; - - /// Clone the given type representation. - TypeRepr *clone(const ASTContext &ctx) const; }; /// A TypeRepr for a type with a syntax error. Can be used both as a diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index d193f011a8824..9e4a053e972d4 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -267,6 +267,10 @@ namespace swift { /// Build the ASTScope tree lazily bool LazyASTScopes = true; + /// Whether to enable the new operator decl and precedencegroup lookup + /// behavior. This is a staging flag, and will be removed in the future. + bool EnableNewOperatorLookup = false; + /// Use Clang function types for computing canonical types. /// If this option is false, the clang function types will still be computed /// but will not be used for checking type equality. diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def index d00a337f4eb21..415db666c919d 100644 --- a/include/swift/IDE/DigesterEnums.def +++ b/include/swift/IDE/DigesterEnums.def @@ -132,6 +132,7 @@ KEY_BOOL(HasStorage, hasStorage) KEY_BOOL(ReqNewWitnessTableEntry, reqNewWitnessTableEntry) KEY_BOOL(IsABIPlaceholder, isABIPlaceholder) KEY_BOOL(IsExternal, isExternal) +KEY_BOOL(IsEnumExhaustive, isEnumExhaustive) KEY_BOOL(HasMissingDesignatedInitializers, hasMissingDesignatedInitializers) KEY_BOOL(InheritsConvenienceInitializers, inheritsConvenienceInitializers) diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c8168fde7d545..5f21197687f34 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -483,6 +483,14 @@ def disable_invalid_ephemeralness_as_error : def switch_checking_invocation_threshold_EQ : Joined<["-"], "switch-checking-invocation-threshold=">; +def enable_new_operator_lookup : + Flag<["-"], "enable-new-operator-lookup">, + HelpText<"Enable the new operator decl and precedencegroup lookup behavior">; + +def disable_new_operator_lookup : + Flag<["-"], "disable-new-operator-lookup">, + HelpText<"Disable the new operator decl and precedencegroup lookup behavior">; + def enable_source_import : Flag<["-"], "enable-source-import">, HelpText<"Enable importing of Swift source files">; diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 171ebd491cfe2..cb7b3393735fc 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -2623,6 +2623,7 @@ class MetadataReader { // WARNING: the following algorithm works on current modern Apple // runtimes but is not actually ABI. But it is pretty reliable. +#if SWIFT_OBJC_INTEROP StoredPointer dataPtr; if (!Reader->readInteger(RemoteAddress(classAddress + TargetClassMetadata::offsetToData()), @@ -2665,6 +2666,9 @@ class MetadataReader { } return dataPtr; +#else + return StoredPointer(); +#endif } IsaEncodingKind getIsaEncoding() { diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 7645a0e5eb748..bc655a43df383 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -61,6 +61,7 @@ add_swift_host_library(swiftAST STATIC ModuleNameLookup.cpp NameLookup.cpp NameLookupRequests.cpp + OperatorNameLookup.cpp Parameter.cpp Pattern.cpp PlatformKind.cpp diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 71392bdb747cc..6e4be31422f3f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -924,53 +924,13 @@ GenericParamList::clone(DeclContext *dc) const { GenericTypeParamDecl::InvalidDepth, param->getIndex()); params.push_back(newParam); - - SmallVector inherited; - for (auto loc : param->getInherited()) - inherited.push_back(loc.clone(ctx)); - newParam->setInherited(ctx.AllocateCopy(inherited)); - } - - SmallVector requirements; - for (auto reqt : getRequirements()) { - switch (reqt.getKind()) { - case RequirementReprKind::TypeConstraint: { - auto first = reqt.getSubjectLoc(); - auto second = reqt.getConstraintLoc(); - reqt = RequirementRepr::getTypeConstraint( - first.clone(ctx), - reqt.getSeparatorLoc(), - second.clone(ctx)); - break; - } - case RequirementReprKind::SameType: { - auto first = reqt.getFirstTypeLoc(); - auto second = reqt.getSecondTypeLoc(); - reqt = RequirementRepr::getSameType( - first.clone(ctx), - reqt.getSeparatorLoc(), - second.clone(ctx)); - break; - } - case RequirementReprKind::LayoutConstraint: { - auto first = reqt.getSubjectLoc(); - auto layout = reqt.getLayoutConstraintLoc(); - reqt = RequirementRepr::getLayoutConstraint( - first.clone(ctx), - reqt.getSeparatorLoc(), - layout); - break; - } - } - - requirements.push_back(reqt); } return GenericParamList::create(ctx, getLAngleLoc(), params, getWhereLoc(), - requirements, + /*requirements=*/{}, getRAngleLoc()); } @@ -6152,8 +6112,6 @@ ParamDecl *ParamDecl::cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD) { nullptr, PD->DefaultValueAndFlags.getInt()); Clone->Bits.ParamDecl.defaultArgumentKind = PD->Bits.ParamDecl.defaultArgumentKind; - if (auto *repr = PD->getTypeRepr()) - Clone->setTypeRepr(repr->clone(Ctx)); Clone->setSpecifier(PD->getSpecifier()); Clone->setImplicitlyUnwrappedOptional(PD->isImplicitlyUnwrappedOptional()); diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 7b44cb14704b5..cdd196cb5ca05 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1050,72 +1050,6 @@ LookupConformanceInModuleRequest::evaluate( return ProtocolConformanceRef(conformance); } -namespace { - template - struct OperatorLookup { - // Don't fold this into the static_assert: this would trigger an MSVC bug - // that causes the assertion to fail. - static constexpr T* ptr = static_cast(nullptr); - static_assert(ptr, "Only usable with operators"); - }; - - template <> - struct OperatorLookup { - static PrefixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // We can return the first prefix operator. All prefix operators of the - // same name are equivalent. - DirectOperatorLookupRequest req{desc, OperatorFixity::Prefix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static InfixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // Return the first result if it exists. - DirectOperatorLookupRequest req{desc, OperatorFixity::Infix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static PostfixOperatorDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // We can return the first postfix operator. All postfix operators of the - // same name are equivalent. - DirectOperatorLookupRequest req{desc, OperatorFixity::Postfix}; - auto results = evaluateOrDefault(eval, req, {}); - return results.empty() ? nullptr : cast(results[0]); - } - }; - - template <> - struct OperatorLookup { - static PrecedenceGroupDecl *lookup(Evaluator &eval, - const OperatorLookupDescriptor &desc) { - // Return the first result if it exists. - auto results = - evaluateOrDefault(eval, DirectPrecedenceGroupLookupRequest{desc}, {}); - return results.empty() ? nullptr : results[0]; - } - }; -} // end anonymous namespace - -/// A helper class to sneak around C++ access control rules. -class SourceFile::Impl { -public: - /// Only intended for use by lookupOperatorDeclForName. - static ArrayRef - getImportsForSourceFile(const SourceFile &SF) { - return *SF.Imports; - } -}; - struct SourceFile::SourceFileSyntaxInfo { const bool Enable; /// The root of the syntax tree representing the source file. @@ -1136,180 +1070,6 @@ void SourceFile::setSyntaxRoot(syntax::SourceFileSyntax &&Root) { SyntaxInfo->SyntaxRoot.emplace(Root); } -template -static Optional -lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name, - bool isCascading); - -template -using ImportedOperatorsMap = llvm::SmallDenseMap; - -template -static typename ImportedOperatorsMap::iterator -checkOperatorConflicts(const SourceFile &SF, SourceLoc loc, - ImportedOperatorsMap &importedOperators) { - // Check for conflicts. - auto i = importedOperators.begin(), end = importedOperators.end(); - auto start = i; - for (++i; i != end; ++i) { - if (i->first->conflictsWith(start->first)) { - if (loc.isValid()) { - ASTContext &C = SF.getASTContext(); - C.Diags.diagnose(loc, diag::ambiguous_operator_decls); - start->first->diagnose(diag::found_this_operator_decl); - i->first->diagnose(diag::found_this_operator_decl); - } - return end; - } - } - return start; -} - -template<> -typename ImportedOperatorsMap::iterator -checkOperatorConflicts(const SourceFile &SF, SourceLoc loc, - ImportedOperatorsMap &importedGroups) { - if (importedGroups.size() == 1) - return importedGroups.begin(); - - // Any sort of ambiguity is an error. - if (loc.isValid()) { - ASTContext &C = SF.getASTContext(); - C.Diags.diagnose(loc, diag::ambiguous_precedence_groups); - for (auto &entry : importedGroups) { - entry.first->diagnose(diag::found_this_precedence_group); - } - } - return importedGroups.end(); -} - -// Returns None on error, Optional(nullptr) if no operator decl found, or -// Optional(decl) if decl was found. -template -static Optional -lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc, - Identifier Name, bool includePrivate, - bool isCascading) { - auto &eval = File.getASTContext().evaluator; - auto desc = OperatorLookupDescriptor::forFile(const_cast(&File), - Name, isCascading, - /*diagLoc*/ SourceLoc()); - switch (File.getKind()) { - case FileUnitKind::Builtin: - // The Builtin module declares no operators. - return nullptr; - case FileUnitKind::Synthesized: - // Synthesized files currently declare no operators. - return nullptr; - case FileUnitKind::Source: - break; - case FileUnitKind::SerializedAST: - case FileUnitKind::ClangModule: - case FileUnitKind::DWARFModule: - return OperatorLookup::lookup(eval, desc); - } - - auto &SF = cast(File); - assert(SF.ASTStage >= SourceFile::ImportsResolved); - - // Check if the decl exists on the file. - if (auto *op = OperatorLookup::lookup(eval, desc)) - return op; - - // Look for imported operator decls. - // Record whether they come from re-exported modules. - // FIXME: We ought to prefer operators elsewhere in this module before we - // check imports. - auto ownModule = SF.getParentModule(); - ImportedOperatorsMap importedOperators; - for (auto &imported : SourceFile::Impl::getImportsForSourceFile(SF)) { - // Protect against source files that contrive to import their own modules. - if (imported.module.importedModule == ownModule) - continue; - - bool isExported = - imported.importOptions.contains(SourceFile::ImportFlags::Exported); - if (!includePrivate && !isExported) - continue; - - Optional maybeOp = lookupOperatorDeclForName( - imported.module.importedModule, Loc, Name, isCascading); - if (!maybeOp) - return None; - - if (OP_DECL *op = *maybeOp) - importedOperators[op] |= isExported; - } - - llvm::PointerIntPair result = {nullptr, - true}; - - if (!importedOperators.empty()) { - auto start = checkOperatorConflicts(SF, Loc, importedOperators); - if (start == importedOperators.end()) - return None; - result = { start->first, start->second }; - } - - if (includePrivate || result.getInt()) - return result.getPointer(); - return nullptr; -} - -template -static Optional -lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name, - bool isCascading) { - OP_DECL *result = nullptr; - for (const FileUnit *File : M->getFiles()) { - auto next = lookupOperatorDeclForName(*File, Loc, Name, false, - isCascading); - if (!next.hasValue()) - return next; - - // FIXME: Diagnose ambiguity. - if (*next && result) - return None; - if (*next) - result = *next; - } - return result; -} - -template -OperatorType *LookupOperatorRequest::evaluate( - Evaluator &evaluator, OperatorLookupDescriptor desc) const { - auto *file = desc.fileOrModule.get(); - auto result = - lookupOperatorDeclForName(*file, desc.diagLoc, desc.name, - /*includePrivate*/ true, - desc.isCascading); - if (!result.hasValue()) - return nullptr; - - if (!result.getValue()) { - result = lookupOperatorDeclForName(file->getParentModule(), - desc.diagLoc, desc.name, - desc.isCascading); - } - return result.hasValue() ? result.getValue() : nullptr; -} - -#define LOOKUP_OPERATOR(Kind) \ - Kind##Decl *ModuleDecl::lookup##Kind(Identifier name, SourceLoc loc) { \ - auto result = lookupOperatorDeclForName( \ - this, loc, name, /*isCascading*/ false); \ - return result ? *result : nullptr; \ - } \ - template Kind##Decl *LookupOperatorRequest::evaluate( \ - Evaluator &e, OperatorLookupDescriptor) const; - -LOOKUP_OPERATOR(PrefixOperator) -LOOKUP_OPERATOR(InfixOperator) -LOOKUP_OPERATOR(PostfixOperator) -LOOKUP_OPERATOR(PrecedenceGroup) -#undef LOOKUP_OPERATOR - void DirectOperatorLookupRequest::writeDependencySink( evaluator::DependencyCollector &reqTracker, TinyPtrVector ops) const { diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 51068ca10b41d..5afc70b7d9bce 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -246,10 +246,10 @@ static ConstructorComparison compareConstructors(ConstructorDecl *ctor1, /// Given a set of declarations whose names and signatures have matched, /// figure out which of these declarations have been shadowed by others. -static void recordShadowedDeclsAfterSignatureMatch( - ArrayRef decls, - const DeclContext *dc, - llvm::SmallPtrSetImpl &shadowed) { +template +static void +recordShadowedDeclsAfterSignatureMatch(ArrayRef decls, const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { assert(decls.size() > 1 && "Nothing collided"); // Compare each declaration to every other declaration. This is @@ -353,9 +353,9 @@ static void recordShadowedDeclsAfterSignatureMatch( // This is due to the fact that in Swift 4, we only gave custom overload // types to properties in extensions of generic types, otherwise we // used the null type. - if (!ctx.isSwiftVersionAtLeast(5)) { - auto secondSig = secondDecl->getOverloadSignature(); - auto firstSig = firstDecl->getOverloadSignature(); + if (!ctx.isSwiftVersionAtLeast(5) && isa(firstDecl)) { + auto secondSig = cast(secondDecl)->getOverloadSignature(); + auto firstSig = cast(firstDecl)->getOverloadSignature(); if (firstSig.IsVariable && secondSig.IsVariable) if (firstSig.InExtensionOfGenericType != secondSig.InExtensionOfGenericType) @@ -582,8 +582,8 @@ static void recordShadowedDecls(ArrayRef decls, // Check whether we have shadowing for signature collisions. for (auto signature : collisionTypes) { - recordShadowedDeclsAfterSignatureMatch(collisions[signature], dc, - shadowed); + ArrayRef collidingDecls = collisions[signature]; + recordShadowedDeclsAfterSignatureMatch(collidingDecls, dc, shadowed); } // Check whether we have shadowing for imported initializer collisions. @@ -593,11 +593,25 @@ static void recordShadowedDecls(ArrayRef decls, } } -bool swift::removeShadowedDecls(SmallVectorImpl &decls, - const DeclContext *dc) { +static void +recordShadowedDecls(ArrayRef decls, const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { + // Always considered to have the same signature. + recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed); +} + +static void +recordShadowedDecls(ArrayRef decls, + const DeclContext *dc, + llvm::SmallPtrSetImpl &shadowed) { + // Always considered to have the same signature. + recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed); +} + +template +static bool removeShadowedDeclsImpl(Container &decls, const DeclContext *dc) { // Collect declarations with the same (full) name. - llvm::SmallDenseMap> - collidingDeclGroups; + llvm::SmallDenseMap> collidingDeclGroups; bool anyCollisions = false; for (auto decl : decls) { // Record this declaration based on its full name. @@ -613,7 +627,7 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, return false; // Walk through the declarations again, marking any declarations that shadow. - llvm::SmallPtrSet shadowed; + llvm::SmallPtrSet shadowed; for (auto decl : decls) { auto known = collidingDeclGroups.find(decl->getName()); if (known == collidingDeclGroups.end()) { @@ -632,8 +646,8 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, // Remove shadowed declarations from the list of declarations. bool anyRemoved = false; decls.erase(std::remove_if(decls.begin(), decls.end(), - [&](ValueDecl *vd) { - if (shadowed.count(vd) > 0) { + [&](T decl) { + if (shadowed.count(decl) > 0) { anyRemoved = true; return true; } @@ -645,6 +659,28 @@ bool swift::removeShadowedDecls(SmallVectorImpl &decls, return anyRemoved; } +bool swift::removeShadowedDecls(SmallVectorImpl &decls, + const DeclContext *dc) { + return removeShadowedDeclsImpl(decls, dc); +} + +bool swift::removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc) { +#ifndef NDEBUG + // Make sure all the operators have the same fixity. + if (decls.size() > 1) { + for (auto *op : decls) + assert(op->getFixity() == decls[0]->getFixity()); + } +#endif + return removeShadowedDeclsImpl(decls, dc); +} + +bool swift::removeShadowedDecls(TinyPtrVector &decls, + const DeclContext *dc) { + return removeShadowedDeclsImpl(decls, dc); +} + namespace { enum class DiscriminatorMatch { NoDiscriminator, diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 5b44f7fa0dce2..0e3f41f6aee43 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -281,6 +281,17 @@ SourceLoc swift::extractNearestSourceLoc(const DirectLookupDescriptor &desc) { // LookupOperatorRequest computation. //----------------------------------------------------------------------------// +OperatorLookupDescriptor OperatorLookupDescriptor::forDC(const DeclContext *DC, + Identifier name) { + auto *moduleDC = DC->getModuleScopeContext(); + if (auto *file = dyn_cast(moduleDC)) { + return OperatorLookupDescriptor::forFile(file, name); + } else { + auto *mod = cast(moduleDC->getAsDecl()); + return OperatorLookupDescriptor::forModule(mod, name); + } +} + ArrayRef OperatorLookupDescriptor::getFiles() const { if (auto *module = getModule()) return module->getFiles(); @@ -298,7 +309,7 @@ void swift::simple_display(llvm::raw_ostream &out, } SourceLoc swift::extractNearestSourceLoc(const OperatorLookupDescriptor &desc) { - return desc.diagLoc; + return extractNearestSourceLoc(desc.fileOrModule); } void DirectLookupRequest::writeDependencySink( diff --git a/lib/AST/OperatorNameLookup.cpp b/lib/AST/OperatorNameLookup.cpp new file mode 100644 index 0000000000000..b074fbf30f630 --- /dev/null +++ b/lib/AST/OperatorNameLookup.cpp @@ -0,0 +1,243 @@ +//===--- OperatorNameLookup.cpp - Operator and Precedence Lookup *- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file implements interfaces for performing operator and precedence group +// declaration lookup. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/OperatorNameLookup.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/DiagnosticsSema.h" +#include "swift/AST/ImportCache.h" +#include "swift/AST/NameLookupRequests.h" + +#define DEBUG_TYPE "operator-name-lookup" + +using namespace swift; +using namespace swift::namelookup; + +template +static TinyPtrVector lookupOperatorImpl( + DeclContext *moduleDC, Identifier name, + llvm::function_ref &)> + lookupDirect) { + assert(moduleDC->isModuleScopeContext()); + auto &ctx = moduleDC->getASTContext(); + + // First try to use the new operator lookup logic. + { + TinyPtrVector results; + for (auto &import : getAllImports(moduleDC)) { + auto *mod = import.importedModule; + lookupDirect(OperatorLookupDescriptor::forModule(mod, name), results); + } + + // If there aren't multiple results, or the new logic is completely enabled, + // perform shadowing checks and return. Otherwise fall through to the old + // logic. + if (results.size() <= 1 || ctx.LangOpts.EnableNewOperatorLookup) { + removeShadowedDecls(results, moduleDC); + return std::move(results); + } + } + + // There are three stages to the old operator lookup: + // 1) Lookup directly in the file. + // 2) Lookup in the file's direct imports (not looking through exports). + // 3) Lookup in other files. + // If any step yields results, we return them without performing the next + // steps. Note that this means when we come to look in other files, we can + // accumulate ambiguities across files, unlike when looking in the original + // file, where we can bail early. + + TinyPtrVector results; + SmallPtrSet visitedModules; + + // Protect against source files that contrive to import their own modules. + visitedModules.insert(moduleDC->getParentModule()); + + auto lookupInFileAndImports = [&](FileUnit *file, + bool includePrivate) -> bool { + // If we find something in the file itself, bail without checking imports. + lookupDirect(OperatorLookupDescriptor::forFile(file, name), results); + if (!results.empty()) + return true; + + // Only look into SourceFile imports. + auto *SF = dyn_cast(file); + if (!SF) + return false; + + for (auto &import : SF->getImports()) { + auto *mod = import.module.importedModule; + if (!visitedModules.insert(mod).second) + continue; + + bool isExported = + import.importOptions.contains(SourceFile::ImportFlags::Exported); + if (!includePrivate && !isExported) + continue; + + lookupDirect(OperatorLookupDescriptor::forModule(mod, name), results); + } + return !results.empty(); + }; + + // If we have a SourceFile context, search it and its private imports. + auto *SF = dyn_cast(moduleDC); + if (SF && lookupInFileAndImports(SF, /*includePrivate*/ true)) + return std::move(results); + + // Search all the other files of the module, this time excluding private + // imports. + auto *mod = moduleDC->getParentModule(); + for (auto *file : mod->getFiles()) { + if (file != SF) + lookupInFileAndImports(file, /*includePrivate*/ false); + } + return std::move(results); +} + +static TinyPtrVector +lookupOperator(DeclContext *moduleDC, Identifier name, OperatorFixity fixity) { + auto &eval = moduleDC->getASTContext().evaluator; + return lookupOperatorImpl( + moduleDC, name, + [&](OperatorLookupDescriptor desc, + TinyPtrVector &results) { + auto ops = evaluateOrDefault( + eval, DirectOperatorLookupRequest{desc, fixity}, {}); + for (auto *op : ops) + results.push_back(op); + }); +} + +void InfixOperatorLookupResult::diagnoseAmbiguity(SourceLoc loc) const { + auto &ctx = ModuleDC->getASTContext(); + ctx.Diags.diagnose(loc, diag::ambiguous_operator_decls); + for (auto *op : *this) + op->diagnose(diag::found_this_operator_decl); +} + +void InfixOperatorLookupResult::diagnoseMissing(SourceLoc loc, + bool forBuiltin) const { + ModuleDC->getASTContext().Diags.diagnose(loc, diag::unknown_binop); +} + +TinyPtrVector +LookupInfixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Infix); + + // If we have a single result, return it directly. This avoids having to look + // up its precedence group. + if (ops.size() == 1) + return {cast(ops[0])}; + + // Otherwise take the first infix operator we see with a particular precedence + // group. This avoids an ambiguity if two different modules declare the same + // operator with the same precedence. + TinyPtrVector results; + SmallPtrSet groups; + for (auto *op : ops) { + auto *infix = cast(op); + if (groups.insert(infix->getPrecedenceGroup()).second) + results.push_back(infix); + } + return results; +} + +InfixOperatorLookupResult +DeclContext::lookupInfixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + auto ops = evaluateOrDefault(getASTContext().evaluator, + LookupInfixOperatorRequest{desc}, {}); + // Wrap the result in a InfixOperatorLookupResult. The request doesn't + // return this directly to avoid unnecessarily caching the name and context. + return InfixOperatorLookupResult(this, name, std::move(ops)); +} + +PrefixOperatorDecl * +LookupPrefixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Prefix); + if (ops.empty()) + return nullptr; + + // We can return the first prefix operator. All prefix operators of the same + // name are equivalent. + return cast(ops[0]); +} + +PrefixOperatorDecl *DeclContext::lookupPrefixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + return evaluateOrDefault(getASTContext().evaluator, + LookupPrefixOperatorRequest{desc}, nullptr); +} + +PostfixOperatorDecl * +LookupPostfixOperatorRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + auto ops = lookupOperator(desc.getDC(), desc.name, OperatorFixity::Postfix); + if (ops.empty()) + return nullptr; + + // We can return the first postfix operator. All postfix operators of the same + // name are equivalent. + return cast(ops[0]); +} + +PostfixOperatorDecl *DeclContext::lookupPostfixOperator(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + return evaluateOrDefault(getASTContext().evaluator, + LookupPostfixOperatorRequest{desc}, nullptr); +} + +void PrecedenceGroupLookupResult::diagnoseAmbiguity(SourceLoc loc) const { + auto &ctx = ModuleDC->getASTContext(); + ctx.Diags.diagnose(loc, diag::ambiguous_precedence_groups); + for (auto *group : *this) + group->diagnose(diag::found_this_precedence_group); +} + +void PrecedenceGroupLookupResult::diagnoseMissing(SourceLoc loc, + bool forBuiltin) const { + auto &ctx = ModuleDC->getASTContext(); + auto diagID = forBuiltin ? diag::missing_builtin_precedence_group + : diag::unknown_precedence_group; + ctx.Diags.diagnose(loc, diagID, Name); +} + +TinyPtrVector +LookupPrecedenceGroupRequest::evaluate(Evaluator &evaluator, + OperatorLookupDescriptor desc) const { + return lookupOperatorImpl( + desc.getDC(), desc.name, + [&](OperatorLookupDescriptor desc, + TinyPtrVector &results) { + auto groups = evaluateOrDefault( + evaluator, DirectPrecedenceGroupLookupRequest{desc}, {}); + for (auto *group : groups) + results.push_back(group); + }); +} + +PrecedenceGroupLookupResult +DeclContext::lookupPrecedenceGroup(Identifier name) const { + auto desc = OperatorLookupDescriptor::forDC(this, name); + auto groups = evaluateOrDefault(getASTContext().evaluator, + LookupPrecedenceGroupRequest{desc}, {}); + // Wrap the result in a PrecedenceGroupLookupResult. The request doesn't + // return this directly to avoid unnecessarily caching the name and context. + return PrecedenceGroupLookupResult(this, name, std::move(groups)); +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index df297b9793478..7532ea5bbefcc 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -90,13 +90,6 @@ SourceRange TypeLoc::getSourceRange() const { return SourceRange(); } -TypeLoc TypeLoc::clone(ASTContext &ctx) const { - if (TyR) { - return TypeLoc(TyR->clone(ctx), Ty); - } - return *this; -} - SourceLoc TypeLoc::getLoc() const { if (TyR) return TyR->getLoc(); return SourceLoc(); diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index dbcae80ad7db0..61cfbee4f91bd 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -116,158 +116,6 @@ void TypeRepr::print(ASTPrinter &Printer, const PrintOptions &Opts) const { llvm_unreachable("unknown kind!"); } -namespace { - class CloneVisitor : public TypeReprVisitor { - const ASTContext &Ctx; - - public: - explicit CloneVisitor(const ASTContext &ctx) : Ctx(ctx) { } - -#define TYPEREPR(CLASS, PARENT) \ - TypeRepr *visit##CLASS##TypeRepr(CLASS##TypeRepr* type); -#include "swift/AST/TypeReprNodes.def" - }; -} // end anonymous namespace - -TypeRepr *CloneVisitor::visitErrorTypeRepr(ErrorTypeRepr *T) { - return new (Ctx) ErrorTypeRepr(T->getSourceRange()); -} - -TypeRepr *CloneVisitor::visitAttributedTypeRepr(AttributedTypeRepr *T) { - return new (Ctx) AttributedTypeRepr(T->getAttrs(), visit(T->getTypeRepr())); -} - -TypeRepr *CloneVisitor::visitSimpleIdentTypeRepr(SimpleIdentTypeRepr *T) { - return new (Ctx) SimpleIdentTypeRepr(T->getNameLoc(), T->getNameRef()); -} - -TypeRepr *CloneVisitor::visitGenericIdentTypeRepr(GenericIdentTypeRepr *T) { - // Clone the generic arguments. - SmallVector genericArgs; - genericArgs.reserve(T->getGenericArgs().size()); - for (auto &arg : T->getGenericArgs()) { - genericArgs.push_back(visit(arg)); - } - return GenericIdentTypeRepr::create(Ctx, T->getNameLoc(), T->getNameRef(), - genericArgs, T->getAngleBrackets()); -} - -TypeRepr *CloneVisitor::visitCompoundIdentTypeRepr(CompoundIdentTypeRepr *T) { - // Clone the components. - SmallVector components; - components.reserve(T->getComponents().size()); - for (auto &component : T->getComponents()) { - components.push_back(cast(visit(component))); - } - return CompoundIdentTypeRepr::create(Ctx, components); -} - -TypeRepr *CloneVisitor::visitFunctionTypeRepr(FunctionTypeRepr *T) { - return new (Ctx) FunctionTypeRepr( - /*FIXME: Clone?*/T->getGenericParams(), - cast(visit(T->getArgsTypeRepr())), - T->getThrowsLoc(), - T->getArrowLoc(), - visit(T->getResultTypeRepr())); -} - -TypeRepr *CloneVisitor::visitArrayTypeRepr(ArrayTypeRepr *T) { - return new (Ctx) ArrayTypeRepr(visit(T->getBase()), T->getBrackets()); -} - -TypeRepr *CloneVisitor::visitDictionaryTypeRepr(DictionaryTypeRepr *T) { - return new (Ctx) DictionaryTypeRepr(visit(T->getKey()), visit(T->getValue()), - T->getColonLoc(), T->getBrackets()); -} - -TypeRepr *CloneVisitor::visitOptionalTypeRepr(OptionalTypeRepr *T) { - return new (Ctx) OptionalTypeRepr(visit(T->getBase()), T->getQuestionLoc()); -} - -TypeRepr * CloneVisitor::visitImplicitlyUnwrappedOptionalTypeRepr( - ImplicitlyUnwrappedOptionalTypeRepr *T) { - return new (Ctx) ImplicitlyUnwrappedOptionalTypeRepr(visit(T->getBase()), - T->getExclamationLoc()); -} - -TypeRepr *CloneVisitor::visitTupleTypeRepr(TupleTypeRepr *T) { - SmallVector elements; - elements.reserve(T->getNumElements()); - for (auto arg : T->getElements()) { - arg.Type = visit(arg.Type); - elements.push_back(arg); - } - return TupleTypeRepr::create(Ctx, elements, - T->getParens(), - T->getEllipsisLoc(), - T->getEllipsisIndex()); -} - -TypeRepr *CloneVisitor::visitCompositionTypeRepr(CompositionTypeRepr *T) { - // Clone the protocols. - SmallVector types; - types.reserve(T->getTypes().size()); - for (auto &type : T->getTypes()) { - types.push_back(cast(visit(type))); - } - - return CompositionTypeRepr::create(Ctx, types, T->getStartLoc(), - T->getCompositionRange()); -} - -TypeRepr *CloneVisitor::visitMetatypeTypeRepr(MetatypeTypeRepr *T) { - return new (Ctx) MetatypeTypeRepr(visit(T->getBase()), T->getMetaLoc()); -} - -TypeRepr *CloneVisitor::visitProtocolTypeRepr(ProtocolTypeRepr *T) { - return new (Ctx) ProtocolTypeRepr(visit(T->getBase()), T->getProtocolLoc()); -} - -TypeRepr *CloneVisitor::visitInOutTypeRepr(InOutTypeRepr *T) { - return new (Ctx) InOutTypeRepr(visit(T->getBase()), T->getSpecifierLoc()); -} - -TypeRepr *CloneVisitor::visitSharedTypeRepr(SharedTypeRepr *T) { - return new (Ctx) SharedTypeRepr(visit(T->getBase()), T->getSpecifierLoc()); -} - -TypeRepr *CloneVisitor::visitOwnedTypeRepr(OwnedTypeRepr *T) { - return new (Ctx) OwnedTypeRepr(visit(T->getBase()), T->getSpecifierLoc()); -} - -TypeRepr *CloneVisitor::visitFixedTypeRepr(FixedTypeRepr *T) { - return new (Ctx) FixedTypeRepr(T->getType(), T->getLoc()); -} - -TypeRepr *CloneVisitor::visitSILBoxTypeRepr(SILBoxTypeRepr *type) { - SmallVector cloneFields; - SmallVector cloneArgs; - - for (auto &field : type->getFields()) - cloneFields.push_back({field.getLoc(), field.isMutable(), - visit(field.getFieldType())}); - for (auto *arg : type->getGenericArguments()) - cloneArgs.push_back(visit(arg)); - - return new (Ctx) SILBoxTypeRepr(/*FIXME: Clone?*/type->getGenericParams(), - type->getLBraceLoc(), - Ctx.AllocateCopy(cloneFields), - type->getRBraceLoc(), - type->getArgumentLAngleLoc(), - Ctx.AllocateCopy(cloneArgs), - type->getArgumentRAngleLoc()); -} - -TypeRepr *CloneVisitor::visitOpaqueReturnTypeRepr(OpaqueReturnTypeRepr *type) { - return new (Ctx) OpaqueReturnTypeRepr(type->getOpaqueLoc(), - visit(type->getConstraint())); -} - -TypeRepr *TypeRepr::clone(const ASTContext &ctx) const { - CloneVisitor visitor(ctx); - return visitor.visit(const_cast(this)); -} - void ErrorTypeRepr::printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const { Printer << "<>"; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9db77ec33b219..c5bf8daeec430 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -409,6 +409,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.StressASTScopeLookup |= Args.hasArg(OPT_stress_astscope_lookup); Opts.WarnIfASTScopeLookup |= Args.hasArg(OPT_warn_if_astscope_lookup); Opts.LazyASTScopes |= Args.hasArg(OPT_lazy_astscopes); + Opts.EnableNewOperatorLookup = Args.hasFlag(OPT_enable_new_operator_lookup, + OPT_disable_new_operator_lookup, + /*default*/ false); Opts.UseClangFunctionTypes |= Args.hasArg(OPT_use_clang_function_types); Opts.NamedLazyMemberLoading &= !Args.hasArg(OPT_disable_named_lazy_member_loading); diff --git a/lib/IRGen/ClassMetadataVisitor.h b/lib/IRGen/ClassMetadataVisitor.h index 0b9b5e145d30c..a7453f8dad37c 100644 --- a/lib/IRGen/ClassMetadataVisitor.h +++ b/lib/IRGen/ClassMetadataVisitor.h @@ -58,15 +58,13 @@ template class ClassMetadataVisitor // Metadata header. super::layout(); - // ClassMetadata header. In ObjCInterop mode, this must be - // layout-compatible with an Objective-C class. The superclass - // pointer is useful regardless of mode, but the rest of the data - // isn't necessary. - // FIXME: Figure out what can be removed altogether in non-objc-interop - // mode and remove it. rdar://problem/18801263 + // ClassMetadata header. This must be layout-compatible with Objective-C + // classes when interoperability is enabled. asImpl().addSuperclass(); - asImpl().addClassCacheData(); - asImpl().addClassDataPointer(); + if (IGM.ObjCInterop) { + asImpl().addClassCacheData(); + asImpl().addClassDataPointer(); + } asImpl().addClassFlags(); asImpl().addInstanceAddressPoint(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 7e3e7bf14f2ba..6cacdd41d8a97 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -29,6 +29,7 @@ #include "swift/AST/Initializer.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericSignature.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" @@ -7637,8 +7638,10 @@ bool swift::exprNeedsParensOutsideFollowingOperator( bool swift::exprNeedsParensBeforeAddingNilCoalescing(DeclContext *DC, Expr *expr) { + auto &ctx = DC->getASTContext(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); + DC, ctx.Id_NilCoalescingPrecedence, SourceLoc()) + .getSingle(); if (!asPG) return true; return exprNeedsParensInsideFollowingOperator(DC, expr, asPG); @@ -7647,9 +7650,12 @@ bool swift::exprNeedsParensBeforeAddingNilCoalescing(DeclContext *DC, bool swift::exprNeedsParensAfterAddingNilCoalescing(DeclContext *DC, Expr *expr, Expr *rootExpr) { + auto &ctx = DC->getASTContext(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); - if (!asPG) return true; + DC, ctx.Id_NilCoalescingPrecedence, SourceLoc()) + .getSingle(); + if (!asPG) + return true; return exprNeedsParensOutsideFollowingOperator(DC, expr, rootExpr, asPG); } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 73afab26d924d..72670b9f3fd4e 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -25,6 +25,7 @@ #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/Expr.h" #include "swift/AST/Identifier.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/Types.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/ArrayRef.h" @@ -813,7 +814,7 @@ class MissingExplicitConversionFailure final : public ContextualFailure { bool exprNeedsParensBeforeAddingAs(const Expr *expr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); + DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()).getSingle(); if (!asPG) return true; return exprNeedsParensInsideFollowingOperator(DC, const_cast(expr), @@ -823,7 +824,7 @@ class MissingExplicitConversionFailure final : public ContextualFailure { bool exprNeedsParensAfterAddingAs(const Expr *expr, const Expr *rootExpr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( - DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); + DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()).getSingle(); if (!asPG) return true; diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 400aa93578030..dc9cba57590bd 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -991,13 +991,8 @@ void ConstraintSystem::shrink(Expr *expr) { auto typeRepr = castTypeLoc.getTypeRepr(); if (typeRepr && isSuitableCollection(typeRepr)) { - // Clone representative to avoid modifying in-place, - // FIXME: We should try and silently resolve the type here, - // instead of cloning representative. - auto coercionRepr = typeRepr->clone(CS.getASTContext()); - // Let's try to resolve coercion type from cloned representative. auto resolution = TypeResolution::forContextual(CS.DC, None); - auto coercionType = resolution.resolveType(coercionRepr); + auto coercionType = resolution.resolveType(typeRepr); // Looks like coercion type is invalid, let's skip this sub-tree. if (coercionType->hasError()) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e6d251e5349c7..146b59ee3117f 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -35,6 +35,7 @@ #include "swift/AST/GenericSignatureBuilder.h" #include "swift/AST/Initializer.h" #include "swift/AST/NameLookup.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PropertyWrappers.h" #include "swift/AST/ProtocolConformance.h" @@ -1320,21 +1321,6 @@ static void checkPrecedenceCircularity(DiagnosticEngine &D, } while (!stack.empty()); } -static PrecedenceGroupDecl * -lookupPrecedenceGroup(const PrecedenceGroupDescriptor &descriptor) { - auto *dc = descriptor.dc; - if (auto sf = dc->getParentSourceFile()) { - auto desc = OperatorLookupDescriptor::forFile( - sf, descriptor.ident, dc->isCascadingContextForLookup(false), - descriptor.nameLoc); - return evaluateOrDefault(sf->getASTContext().evaluator, - LookupPrecedenceGroupRequest{desc}, nullptr); - } else { - return dc->getParentModule()->lookupPrecedenceGroup(descriptor.ident, - descriptor.nameLoc); - } -} - static PrecedenceGroupDecl *lookupPrecedenceGroupForRelation( DeclContext *dc, PrecedenceGroupDecl::Relation rel, PrecedenceGroupDescriptor::PathDirection direction) { @@ -1349,10 +1335,8 @@ static PrecedenceGroupDecl *lookupPrecedenceGroupForRelation( llvm::handleAllErrors(result.takeError(), [](const Error &E) {}); return nullptr; } - if (!result.get()) { - ctx.Diags.diagnose(rel.NameLoc, diag::unknown_precedence_group, rel.Name); - } - return result.get(); + return PrecedenceGroupLookupResult(dc, rel.Name, std::move(*result)) + .getSingleOrDiagnose(rel.NameLoc); } void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { @@ -1391,10 +1375,8 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { // If we didn't find anything, try doing a raw lookup for the group before // diagnosing the 'lowerThan' within the same-module restriction. This can // allow us to diagnose even if we have a precedence group cycle. - if (!group) { - group = lookupPrecedenceGroup(PrecedenceGroupDescriptor{ - dc, rel.Name, rel.NameLoc, PrecedenceGroupDescriptor::LowerThan}); - } + if (!group) + group = dc->lookupPrecedenceGroup(rel.Name).getSingle(); if (group && group->getDeclContext()->getParentModule() == dc->getParentModule()) { @@ -1415,22 +1397,25 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) { checkPrecedenceCircularity(Diags, PGD); } -PrecedenceGroupDecl * ValidatePrecedenceGroupRequest::evaluate( +TinyPtrVector ValidatePrecedenceGroupRequest::evaluate( Evaluator &eval, PrecedenceGroupDescriptor descriptor) const { - if (auto *group = lookupPrecedenceGroup(descriptor)) { + auto groups = descriptor.dc->lookupPrecedenceGroup(descriptor.ident); + for (auto *group : groups) validatePrecedenceGroup(group); - return group; - } - return nullptr; + // Return the raw results vector, which will get wrapped back in a + // PrecedenceGroupLookupResult by the TypeChecker entry point. This dance + // avoids unnecessarily caching the name and context for the lookup. + return std::move(groups).get(); } -PrecedenceGroupDecl *TypeChecker::lookupPrecedenceGroup(DeclContext *dc, - Identifier name, - SourceLoc nameLoc) { - return evaluateOrDefault( +PrecedenceGroupLookupResult +TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, + SourceLoc nameLoc) { + auto groups = evaluateOrDefault( dc->getASTContext().evaluator, - ValidatePrecedenceGroupRequest({dc, name, nameLoc, None}), nullptr); + ValidatePrecedenceGroupRequest({dc, name, nameLoc, None}), {}); + return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } static NominalTypeDecl *resolveSingleNominalTypeDecl( @@ -1479,7 +1464,6 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto enableOperatorDesignatedTypes = ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes; - auto &Diags = ctx.Diags; PrecedenceGroupDecl *group = nullptr; auto identifiers = IOD->getIdentifiers(); @@ -1487,20 +1471,18 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto name = identifiers[0].Item; auto loc = identifiers[0].Loc; - group = TypeChecker::lookupPrecedenceGroup(dc, name, loc); - - if (group) { + auto canResolveType = [&]() -> bool { + return enableOperatorDesignatedTypes && + resolveSingleNominalTypeDecl(dc, loc, name, ctx, + TypeResolutionFlags::SilenceErrors); + }; + + // Make sure not to diagnose in the case where we failed to find a + // precedencegroup, but we could resolve a type instead. + auto groups = TypeChecker::lookupPrecedenceGroup(dc, name, loc); + if (groups.hasResults() || !canResolveType()) { + group = groups.getSingleOrDiagnose(loc); identifiers = identifiers.slice(1); - } else { - // If we're either not allowing types, or we are allowing them - // and this identifier is not a type, emit an error as if it's - // a precedence group. - if (!(enableOperatorDesignatedTypes && - resolveSingleNominalTypeDecl(dc, loc, name, ctx, - TypeResolutionFlags::SilenceErrors))) { - Diags.diagnose(loc, diag::unknown_precedence_group, name); - identifiers = identifiers.slice(1); - } } } @@ -1510,13 +1492,9 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, assert(identifiers.empty() || enableOperatorDesignatedTypes); if (!group) { - group = TypeChecker::lookupPrecedenceGroup(dc, ctx.Id_DefaultPrecedence, - SourceLoc()); - } - - if (!group) { - Diags.diagnose(IOD->getLoc(), diag::missing_builtin_precedence_group, - ctx.Id_DefaultPrecedence); + auto groups = TypeChecker::lookupPrecedenceGroup( + dc, ctx.Id_DefaultPrecedence, SourceLoc()); + group = groups.getSingleOrDiagnose(IOD->getLoc(), /*forBuiltin*/ true); } auto nominalTypes = IOD->getDesignatedNominalTypes(); @@ -1796,24 +1774,15 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { FD->diagnose(diag::operator_in_local_scope); } - auto desc = OperatorLookupDescriptor::forFile( - FD->getDeclContext()->getParentSourceFile(), operatorName, - FD->isCascadingContextForLookup(false), FD->getLoc()); - OperatorDecl *op = nullptr; + NullablePtr op; if (FD->isUnaryOperator()) { if (FD->getAttrs().hasAttribute()) { - op = evaluateOrDefault(evaluator, - LookupPrefixOperatorRequest{desc}, nullptr); + op = FD->lookupPrefixOperator(operatorName); } else if (FD->getAttrs().hasAttribute()) { - op = evaluateOrDefault(evaluator, - LookupPostfixOperatorRequest{desc}, nullptr); + op = FD->lookupPostfixOperator(operatorName); } else { - auto prefixOp = evaluateOrDefault(evaluator, - LookupPrefixOperatorRequest{desc}, - nullptr); - auto postfixOp = evaluateOrDefault(evaluator, - LookupPostfixOperatorRequest{desc}, - nullptr); + auto *prefixOp = FD->lookupPrefixOperator(operatorName); + auto *postfixOp = FD->lookupPostfixOperator(operatorName); // If we found both prefix and postfix, or neither prefix nor postfix, // complain. We can't fix this situation. @@ -1822,9 +1791,11 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // If we found both, point at them. if (prefixOp) { - diags.diagnose(prefixOp, diag::unary_operator_declaration_here, false) + diags.diagnose(prefixOp, diag::unary_operator_declaration_here, + /*isPostfix*/ false) .fixItInsert(FD->getLoc(), "prefix "); - diags.diagnose(postfixOp, diag::unary_operator_declaration_here, true) + diags.diagnose(postfixOp, diag::unary_operator_declaration_here, + /*isPostfix*/ true) .fixItInsert(FD->getLoc(), "postfix "); } else { // FIXME: Introduce a Fix-It that adds the operator declaration? @@ -1841,7 +1812,8 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // Fix the AST and determine the insertion text. const char *insertionText; auto &C = FD->getASTContext(); - if (postfixOp) { + auto isPostfix = static_cast(postfixOp); + if (isPostfix) { insertionText = "postfix "; op = postfixOp; FD->getAttrs().add(new (C) PostfixAttr(/*implicit*/false)); @@ -1853,15 +1825,20 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { // Emit diagnostic with the Fix-It. diags.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute, - static_cast(postfixOp)) + isPostfix) .fixItInsert(FD->getFuncLoc(), insertionText); - diags.diagnose(op, diag::unary_operator_declaration_here, - static_cast(postfixOp)); + op.get()->diagnose(diag::unary_operator_declaration_here, isPostfix); } } else if (FD->isBinaryOperator()) { - op = evaluateOrDefault(evaluator, - LookupInfixOperatorRequest{desc}, - nullptr); + auto results = FD->lookupInfixOperator(operatorName); + + // If we have an ambiguity, diagnose and return. Otherwise fall through, as + // we have a custom diagnostic for missing operator decls. + if (results.isAmbiguous()) { + results.diagnoseAmbiguity(FD->getLoc()); + return nullptr; + } + op = results.getSingle(); } else { diags.diagnose(FD, diag::invalid_arg_count_for_operator); return nullptr; @@ -1909,8 +1886,7 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { opDiagnostic.fixItInsert(insertionLoc, insertion); return nullptr; } - - return op; + return op.get(); } bool swift::isMemberOperator(FuncDecl *decl, Type type) { diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 5b887ae22b43b..2240e7b762046 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -429,26 +429,29 @@ static void checkOperatorOrPrecedenceGroupRedeclaration( auto *module = currentFile->getParentModule(); auto &ctx = module->getASTContext(); - auto desc = OperatorLookupDescriptor::forModule(module, decl->getName(), - /*cascades*/ true, - /*diagLoc*/ SourceLoc()); + auto desc = OperatorLookupDescriptor::forModule(module, decl->getName()); auto otherDecls = lookupOthers(desc); for (auto *other : otherDecls) { if (other == decl || other->isInvalid()) continue; - // Emit a redeclaration error if the two declarations occur in the same - // source file. We currently allow redeclarations across source files to - // allow the user to shadow operator decls from imports, as we currently - // favor those decls over ones from other files. - // FIXME: Once we prefer operator decls from the same module, start - // diagnosing redeclarations across files. + bool shouldDiagnose = false; if (currentFile == other->getDeclContext()->getParentSourceFile()) { - // Make sure we get the diagnostic ordering to be sensible. + // For a same-file redeclaration, make sure we get the diagnostic ordering + // to be sensible. if (decl->getLoc().isValid() && other->getLoc().isValid() && ctx.SourceMgr.isBeforeInBuffer(decl->getLoc(), other->getLoc())) { std::swap(decl, other); } + shouldDiagnose = true; + } else { + // If the declarations are in different files, only diagnose if we've + // enabled the new operator lookup behaviour where decls in the current + // module are now favored over imports. + shouldDiagnose = ctx.LangOpts.EnableNewOperatorLookup; + } + + if (shouldDiagnose) { ctx.Diags.diagnose(decl, diagID); ctx.Diags.diagnose(other, noteID); decl->setInvalid(); diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index ae84ed824b78a..da8b782d0a483 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -18,6 +18,7 @@ #include "TypeChecker.h" #include "swift/AST/NameLookup.h" #include "swift/AST/NameLookupRequests.h" +#include "swift/AST/OperatorNameLookup.h" #include "swift/AST/Decl.h" #include "swift/AST/Initializer.h" #include "swift/AST/ParameterList.h" @@ -130,32 +131,18 @@ Expr *TypeChecker::substituteInputSugarTypeForResult(ApplyExpr *E) { static PrecedenceGroupDecl *lookupPrecedenceGroupForOperator(DeclContext *DC, Identifier name, SourceLoc loc) { - auto desc = OperatorLookupDescriptor::forFile( - DC->getParentSourceFile(), name, DC->isCascadingContextForLookup(true), - loc); - auto &Ctx = DC->getASTContext(); - if (auto op = evaluateOrDefault(Ctx.evaluator, - LookupInfixOperatorRequest{desc}, - nullptr)) { - return op->getPrecedenceGroup(); - } else { - Ctx.Diags.diagnose(loc, diag::unknown_binop); - } - return nullptr; + auto *op = DC->lookupInfixOperator(name).getSingleOrDiagnose(loc); + return op ? op->getPrecedenceGroup() : nullptr; } PrecedenceGroupDecl * TypeChecker::lookupPrecedenceGroupForInfixOperator(DeclContext *DC, Expr *E) { /// Look up the builtin precedence group with the given name. - auto getBuiltinPrecedenceGroup = [](DeclContext *DC, Identifier name, - SourceLoc loc) { - auto group = TypeChecker::lookupPrecedenceGroup(DC, name, loc); - if (!group) { - DC->getASTContext().Diags.diagnose( - loc, diag::missing_builtin_precedence_group, name); - } - return group; + auto getBuiltinPrecedenceGroup = [&](DeclContext *DC, Identifier name, + SourceLoc loc) -> PrecedenceGroupDecl * { + auto groups = TypeChecker::lookupPrecedenceGroup(DC, name, loc); + return groups.getSingleOrDiagnose(loc, /*forBuiltin*/ true); }; auto &Context = DC->getASTContext(); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 33961ce7894cd..588ac6d1254b2 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1012,8 +1012,8 @@ LookupResult lookupConstructors( PrecedenceGroupDecl *lookupPrecedenceGroupForInfixOperator(DeclContext *dc, Expr *op); -PrecedenceGroupDecl *lookupPrecedenceGroup(DeclContext *dc, Identifier name, - SourceLoc nameLoc); +PrecedenceGroupLookupResult +lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); /// Check whether the given declaration can be written as a /// member of the given base type. diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index f9992f5ff963b..61d78835833d1 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1364,19 +1364,35 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { Identifier opName = getIdentifier(IID); pathTrace.addOperator(opName); + auto &ctx = getContext(); + auto desc = OperatorLookupDescriptor::forModule(baseModule, opName); switch (rawOpKind) { case OperatorKind::Infix: - return baseModule->lookupInfixOperator(opName); case OperatorKind::Prefix: - return baseModule->lookupPrefixOperator(opName); - case OperatorKind::Postfix: - return baseModule->lookupPostfixOperator(opName); - case OperatorKind::PrecedenceGroup: - return baseModule->lookupPrecedenceGroup(opName); + case OperatorKind::Postfix: { + auto req = DirectOperatorLookupRequest{ + desc, getASTOperatorFixity(static_cast(rawOpKind))}; + auto results = evaluateOrDefault(ctx.evaluator, req, {}); + if (results.size() != 1) { + return llvm::make_error("operator not found", pathTrace, + opName); + } + return results[0]; + } + case OperatorKind::PrecedenceGroup: { + auto results = evaluateOrDefault( + ctx.evaluator, DirectPrecedenceGroupLookupRequest{desc}, {}); + if (results.size() != 1) { + return llvm::make_error("precedencegroup not found", + pathTrace, opName); + } + return results[0]; + } default: // Unknown operator kind. fatal(); } + llvm_unreachable("Unhandled case in switch!"); } case XREF_GENERIC_PARAM_PATH_PIECE: diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index c065390337623..d246ee346d22a 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -2247,9 +2247,6 @@ OperatorDecl *ModuleFile::lookupOperator(Identifier name, if (getStableFixity(fixity) == item.first) return cast(getDecl(item.second)); } - - // FIXME: operators re-exported from other modules? - return nullptr; } diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index f338cde1562f1..09f53e1658124 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -401,6 +401,21 @@ static inline OperatorKind getStableFixity(OperatorFixity fixity) { llvm_unreachable("Unhandled case in switch"); } +/// Translates a stable Serialization fixity back to an AST operator fixity. +static inline OperatorFixity getASTOperatorFixity(OperatorKind fixity) { + switch (fixity) { + case Prefix: + return OperatorFixity::Prefix; + case Postfix: + return OperatorFixity::Postfix; + case Infix: + return OperatorFixity::Infix; + case PrecedenceGroup: + llvm_unreachable("Not an operator kind"); + } + llvm_unreachable("Unhandled case in switch"); +} + // These IDs must \em not be renumbered or reordered without incrementing // the module version. enum GenericRequirementKind : uint8_t { diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 25457cc984af8..8a4432fb46a0a 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -879,10 +879,8 @@ function(_add_swift_target_library_single target name) if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS") swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} SWIFTLIB_INCLUDE) - target_include_directories("${target}" SYSTEM PRIVATE ${SWIFTLIB_INCLUDE}) - set_target_properties(${target} - PROPERTIES - CXX_STANDARD 14) + target_include_directories("${target}" SYSTEM PRIVATE + ${SWIFTLIB_INCLUDE}) endif() if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") diff --git a/stdlib/public/Darwin/Foundation/Publishers+Timer.swift b/stdlib/public/Darwin/Foundation/Publishers+Timer.swift index 76011cd73400d..f4f42d95b948b 100644 --- a/stdlib/public/Darwin/Foundation/Publishers+Timer.swift +++ b/stdlib/public/Darwin/Foundation/Publishers+Timer.swift @@ -126,7 +126,7 @@ extension Timer { lock.cleanupLock() } - func addSubsriber(_ sub: S) + func addSubscriber(_ sub: S) where S.Failure == Failure, S.Input == Output @@ -195,7 +195,7 @@ extension Timer { } public func receive(subscriber: S) where Failure == S.Failure, Output == S.Input { - routingSubscription.addSubsriber(subscriber) + routingSubscription.addSubscriber(subscriber) } public func connect() -> Cancellable { diff --git a/stdlib/public/core/SetAlgebra.swift b/stdlib/public/core/SetAlgebra.swift index 75ecabdfd28be..8ef4c914d4e7a 100644 --- a/stdlib/public/core/SetAlgebra.swift +++ b/stdlib/public/core/SetAlgebra.swift @@ -202,7 +202,7 @@ public protocol SetAlgebra: Equatable, ExpressibleByArrayLiteral { /// - Parameter member: The element of the set to remove. /// - Returns: For ordinary sets, an element equal to `member` if `member` is /// contained in the set; otherwise, `nil`. In some cases, a returned - /// element may be distinguishable from `newMember` by identity comparison + /// element may be distinguishable from `member` by identity comparison /// or some other means. /// /// For sets where the set type and element type are the same, like diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index aedddd46b33ef..a3a6ffcac2b3c 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -114,7 +114,9 @@ Metadata *TargetSingletonMetadataInitialization::allocate( // isn't Swift metadata but a plain old ObjC class instead. if (metadata->getKind() == MetadataKind::Class) { auto *classMetadata = static_cast(metadata); +#if SWIFT_OBJC_INTEROP classMetadata->setAsTypeMetadata(); +#endif auto *fullMetadata = asFullMetadata(metadata); // Begin by initializing the value witness table; everything else is @@ -537,8 +539,6 @@ initializeClassMetadataFromPattern(ClassMetadata *metadata, auto classRO = metadataExtraData + pattern->ClassRODataOffset; metadata->Data = reinterpret_cast(classRO) | SWIFT_CLASS_IS_SWIFT_MASK; -#else - metadata->Data = SWIFT_CLASS_IS_SWIFT_MASK; #endif // Class flags. @@ -2201,8 +2201,6 @@ _swift_relocateClassMetadata(const ClassDescriptor *description, auto classRO = pattern->Data.get(); metadata->Data = reinterpret_cast(classRO) | SWIFT_CLASS_IS_SWIFT_MASK; -#else - metadata->Data = SWIFT_CLASS_IS_SWIFT_MASK; #endif // Class flags. diff --git a/test/Constraints/argument_matching.swift b/test/Constraints/argument_matching.swift index f93366259302a..febabc64f094d 100644 --- a/test/Constraints/argument_matching.swift +++ b/test/Constraints/argument_matching.swift @@ -134,6 +134,16 @@ fun_31849281(a: { !$0 }, c: [nil, 42], b: { (num: Int) -> String in return Strin fun_31849281(a: { !$0 }, c: [nil, 42], b: { "\($0)" }) // expected-error @-1 {{argument 'b' must precede argument 'c'}} {{26-26=b: { "\\($0)" }, }} {{38-54=}} +struct ReorderAndAllLabels { + func f(aa: Int, bb: Int, cc: Int, dd: Int) {} + + func test() { + f(bb: 1, ccx: 2, ddx: 3, aa: 0) // expected-error {{argument 'aa' must precede argument 'bb'}} {{28-35=}} {{7-7=aa: 0, }} {{none}} + + f(bbx: 1, ccx: 2, ddx: 3, aa: 0) // expected-error {{incorrect argument labels in call (have 'bbx:ccx:ddx:aa:', expected 'aa:bb:cc:dd:')}} {{7-10=aa}} {{15-18=bb}} {{23-26=cc}} {{31-33=dd}} {{none}} + } +} + // ------------------------------------------- // Default arguments // ------------------------------------------- @@ -176,6 +186,16 @@ defargs2(first: 1, last: 4, x: 1) // expected-error{{argument 'x' must precede a func rdar43525641(_ a: Int, _ b: Int = 0, c: Int = 0, _ d: Int) {} rdar43525641(1, c: 2, 3) // Ok +func testLabelErrorDefault() { + func f(aa: Int, bb: Int, cc: Int = 0) {} + + f(aax: 0, bbx: 1, cc: 2) + // expected-error@-1 {{incorrect argument labels in call (have 'aax:bbx:cc:', expected 'aa:bb:cc:')}} + + f(aax: 0, bbx: 1) + // expected-error@-1 {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} +} + // ------------------------------------------- // Variadics // ------------------------------------------- @@ -386,6 +406,16 @@ 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=}} +func testLabelErrorVariadic() { + func f(aa: Int, bb: Int, cc: Int...) {} + + f(aax: 0, bbx: 1, cc: 2, 3, 4) + // expected-error@-1 {{incorrect argument labels in call (have 'aax:bbx:cc:_:_:', expected 'aa:bb:cc:_:_:')}} + + f(aax: 0, bbx: 1) + // expected-error@-1 {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} +} + // ------------------------------------------- // Positions around defaults and variadics // ------------------------------------------- @@ -652,6 +682,115 @@ struct PositionsAroundDefaultsAndVariadics { } } +// ------------------------------------------- +// Matching position of unlabeled parameters +// ------------------------------------------- + +func testUnlabeledParameterBindingPosition() { + do { + func f(_ aa: Int) {} + + f(0, 1) + // expected-error@-1:10 {{extra argument in call}} + } + + do { + // expected-note@+1 *{{'f(aa:_:)' declared here}} + func f(aa: Int, _ bb: Int) { } + + f(1) + // expected-error@-1 {{missing argument for parameter 'aa' in call}} + + f(0, 1) + // expected-error@-1:6 {{missing argument label 'aa:' in call}} + + f(0, xx: 1) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:14 {{extra argument 'xx' in call}} + + f(xx: 0, 1) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + // expected-error@-2:14 {{extra argument in call}} + + f(0, 1, 9) + // expected-error@-1:13 {{extra argument in call}} + + f(0, 1, xx: 9) + // expected-error@-1:17 {{extra argument 'xx' in call}} + + f(xx: 91, 1, 92) + // expected-error@-1 {{extra arguments at positions #2, #3 in call}} + // expected-error@-2 {{missing argument for parameter 'aa' in call}} + } + + do { + func f(_ aa: Int, bb: Int, _ cc: Int) { } + + f(bb: 1, 0, 2) + // expected-error@-1 {{unnamed argument #3 must precede argument 'bb'}} + } + + do { + func f(_ aa: Int = 80, bb: Int, _ cc: Int) {} + + f(bb: 1, 2) // ok + } + + do { + // expected-note@+1 *{{'f(_:bb:_:)' declared here}} + func f(_ aa: Int, bb: Int, _ cc: Int...) { } + + f(bb: 1, 2, 3, 4) + // expected-error@-1 {{missing argument for parameter #1 in call}} + } + + do { + func f(_ aa: Int, bb: Int = 81, _ cc: Int...) {} + + f(0, 2, 3) // ok + } + + do { + // expected-note@+1 *{{'f(aa:_:_:)' declared here}} + func f(aa: Int, _ bb: Int, _ cc: Int) {} + + f(0, 1) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + } + + do { + // expected-note@+1 *{{'f(aa:_:_:)' declared here}} + func f(aa: Int, _ bb: Int = 81, _ cc: Int) {} + + f(0, 1) + // expected-error@-1:7 {{missing argument for parameter 'aa' in call}} + } + + do { + // expected-note@+1 *{{'f(aa:bb:_:)' declared here}} + func f(aa: Int, bb: Int, _ cc: Int) {} + + f(0, 2) + // expected-error@-1:6 {{missing argument labels 'aa:bb:' in call}} + // expected-error@-2:8 {{missing argument for parameter 'bb' in call}} + + f(0, bb: 1, 2) + // expected-error@-1:6 {{missing argument label 'aa:' in call}} + } + + do { + func f(_ aa: Int, _ bb: Int = 81, cc: Int, _ dd: Int) {} + + f(0, cc: 2, 3) // ok + } + + do { + func f(_ aa: Int, _ bb: Int = 81, cc: Int = 82, _ dd: Int) {} + + f(0, cc: 2, 3) // ok + } +} + // ------------------------------------------- // Missing arguments // ------------------------------------------- @@ -894,6 +1033,19 @@ mismatchOverloaded1.method1(5, secondArg: nil) // Prefer available to unavailable declaration, if it comes up. mismatchOverloaded1.method2(5) { $0 } +struct RelabelAndTrailingClosure { + func f1(aa: Int, bb: Int, cc: () -> Void = {}) {} + func f2(aa: Int, bb: Int, _ cc: () -> Void = {}) {} + + func test() { + f1(aax: 1, bbx: 2) {} // expected-error {{incorrect argument labels in call (have 'aax:bbx:_:', expected 'aa:bb:cc:')}} {{8-11=aa}} {{16-19=bb}} {{none}} + f2(aax: 1, bbx: 2) {} // expected-error {{incorrect argument labels in call (have 'aax:bbx:_:', expected 'aa:bb:_:')}} {{8-11=aa}} {{16-19=bb}} {{none}} + + f1(aax: 1, bbx: 2) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{8-11=aa}} {{16-19=bb}} {{none}} + f2(aax: 1, bbx: 2) // expected-error {{incorrect argument labels in call (have 'aax:bbx:', expected 'aa:bb:')}} {{8-11=aa}} {{16-19=bb}} {{none}} + } +} + // ------------------------------------------- // Values of function type // ------------------------------------------- @@ -1035,3 +1187,65 @@ CurriedClass.m1(2, b: 42) // expected-error {{instance member 'm1' cannot be u // 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?}} + +// ------------------------------------------- +// Multiple label errors +// ------------------------------------------- + +func testLabelErrorsBasic() { + func f(_ aa: Int, _ bb: Int, cc: Int, dd: Int, ee: Int, ff: Int) {} + + // 1 wrong + f(0, 1, ccx: 2, dd: 3, ee: 4, ff: 5) + // expected-error@-1 {{incorrect argument label in call (have '_:_:ccx:dd:ee:ff:', expected '_:_:cc:dd:ee:ff:')}} {{11-14=cc}} {{none}} + + // 1 missing + f(0, 1, 2, dd: 3, ee: 4, ff: 5) + // expected-error@-1 {{missing argument label 'cc:' in call}} {{11-11=cc: }} {{none}} + + // 1 extra + f(aa: 0, 1, cc: 2, dd: 3, ee: 4, ff: 5) + // expected-error@-1 {{extraneous argument label 'aa:' in call}} {{5-9=}} {{none}} + + // 1 ooo + f(0, 1, dd: 3, cc: 2, ee: 4, ff: 5) + // expected-error@-1 {{argument 'cc' must precede argument 'dd'}} {{16-23=}} {{11-11=cc: 2, }} {{none}} + + // 2 wrong + f(0, 1, ccx: 2, ddx: 3, ee: 4, ff: 5) + // expected-error@-1 {{incorrect argument labels in call (have '_:_:ccx:ddx:ee:ff:', expected '_:_:cc:dd:ee:ff:')}} {{11-14=cc}} {{19-22=dd}} {{none}} + + // 2 missing + f(0, 1, 2, 3, ee: 4, ff: 5) + // expected-error@-1 {{missing argument labels 'cc:dd:' in call}} {{11-11=cc: }} {{14-14=dd: }} {{none}} + + // 2 extra + f(aa: 0, bb: 1, cc: 2, dd: 3, ee: 4, ff: 5) + // expected-error@-1 {{extraneous argument labels 'aa:bb:' in call}} {{5-9=}} {{12-16=}} {{none}} + + // 2 ooo + f(0, 1, dd: 3, cc: 2, ff: 5, ee: 4) + // expected-error@-1 {{argument 'cc' must precede argument 'dd'}} {{16-23=}} {{11-11=cc: 2, }} {{none}} + + // 1 wrong + 1 missing + f(0, 1, ccx: 2, 3, ee: 4, ff: 5) + // expected-error@-1 {{incorrect argument labels in call (have '_:_:ccx:_:ee:ff:', expected '_:_:cc:dd:ee:ff:')}} {{11-14=cc}} {{19-19=dd: }} {{none}} + + // 1 wrong + 1 extra + f(aa: 0, 1, ccx: 2, dd: 3, ee: 4, ff: 5) + // expected-error@-1 {{incorrect argument labels in call (have 'aa:_:ccx:dd:ee:ff:', expected '_:_:cc:dd:ee:ff:')}} {{5-9=}} {{15-18=cc}} {{none}} + + // 1 wrong + 1 ooo + f(0, 1, ccx: 2, dd: 3, ff: 5, ee: 4) + // expected-error@-1 {{incorrect argument labels in call (have '_:_:ccx:dd:ff:ee:', expected '_:_:cc:dd:ee:ff:')}} {{11-14=cc}} {{26-28=ee}} {{33-35=ff}} {{none}} +} + +struct DiagnoseAllLabels { + func f(aa: Int, bb: Int, cc: Int..., dd: Int, ee: Int = 0, ff: Int = 0) {} + + func test() { + f(aax: 0, bbx: 1, cc: 21, 22, 23, dd: 3, ff: 5) // expected-error {{incorrect argument labels in call (have 'aax:bbx:cc:_:_:dd:ff:', expected 'aa:bb:cc:_:_:dd:ff:')}} {{7-10=aa}} {{15-18=bb}} {{none}} + + f(aax: 0, bbx: 1, dd: 3, ff: 5) // expected-error {{incorrect argument labels in call (have 'aax:bbx:dd:ff:', expected 'aa:bb:dd:ff:')}} {{7-10=aa}} {{15-18=bb}} {{none}} + } +} diff --git a/test/IRGen/class_metadata.swift b/test/IRGen/class_metadata.swift index ef631cc6a7897..5a2f6c85f1d92 100644 --- a/test/IRGen/class_metadata.swift +++ b/test/IRGen/class_metadata.swift @@ -1,6 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/chex.py < %s > %t/class_metadata.swift -// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %t/class_metadata.swift -check-prefix=CHECK -check-prefix=CHECK-%target-ptrsize -check-prefix CHECK-%target-import-type -check-prefix=CHECK-%target-cpu +// RUN: %target-swift-frontend -enable-objc-interop -emit-ir %s | %FileCheck %t/class_metadata.swift -check-prefixes=CHECK,CHECK-%target-ptrsize,CHECK-%target-import-type,CHECK-%target-cpu -D#MDSIZE=7 +// RUN: %target-swift-frontend -disable-objc-interop -emit-ir %s | %FileCheck %t/class_metadata.swift -check-prefixes=CHECK,CHECK-%target-ptrsize,CHECK-%target-import-type,CHECK-%target-cpu -D#MDSIZE=4 class A {} @@ -20,16 +21,16 @@ class A {} // Negative size in words. // CHECK-SAME: i32 2, // Positive size in words. -// CHECK-32-SAME: i32 14, -// CHECK-64-SAME: i32 11, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 1]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 1]], // Field count. // CHECK-SAME: i32 0, // Field offset vector offset. -// CHECK-32-SAME: i32 13, -// CHECK-64-SAME: i32 10, +// CHECK-32-SAME: i32 [[#MDSIZE + 6]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3]], // V-table offset. -// CHECK-32-SAME: i32 13, -// CHECK-64-SAME: i32 10, +// CHECK-32-SAME: i32 [[#MDSIZE + 6]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3]], // V-table length. // CHECK-SAME: i32 1, // CHECK-SAME: %swift.method_descriptor { @@ -61,15 +62,15 @@ class B : A {} // Negative size in words. // CHECK-SAME: i32 2, // Positive size in words. -// CHECK-32-SAME: i32 14, -// CHECK-64-SAME: i32 11, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 1]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 1]], // Immediate member count. // CHECK-SAME: i32 0, // Field count. // CHECK-SAME: i32 0, // Field offset vector offset. -// CHECK-32-SAME: i32 14, -// CHECK-64-SAME: i32 11, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 1]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 1]], // Number of method overrides. // CHECK-SAME: i32 1, // CHECK-SAME: %swift.method_override_descriptor { @@ -100,15 +101,15 @@ class C : B {} // Negative size in words. // CHECK-SAME: i32 2, // Positive size in words. -// CHECK-32-SAME: i32 15, -// CHECK-64-SAME: i32 12, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 2]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 2]], // Num immediate members. // CHECK-32-SAME: i32 1, // Field count. // CHECK-SAME: i32 0, // Field offset vector offset. -// CHECK-32-SAME: i32 15, -// CHECK-64-SAME: i32 12, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 2]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 2]], // Instantiation cache. // CHECK-SAME: i32 {{.*}} @"$s14class_metadata1CCMI" // Instantiation pattern. @@ -163,15 +164,15 @@ class D : E {} // Negative size in words. // CHECK-SAME: i32 2, // Positive size in words. -// CHECK-32-SAME: i32 14, -// CHECK-64-SAME: i32 11, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 1]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 1]], // Immediate member count. // CHECK-SAME: i32 0, // Field count. // CHECK-SAME: i32 0, // Field offset vector offset. -// CHECK-32-SAME: i32 14, -// CHECK-64-SAME: i32 11, +// CHECK-32-SAME: i32 [[#MDSIZE + 6 + 1]], +// CHECK-64-SAME: i32 [[#MDSIZE + 3 + 1]], // Number of method overrides. // CHECK-SAME: i32 1, // CHECK-SAME: %swift.method_override_descriptor { diff --git a/test/IRGen/class_resilience.sil b/test/IRGen/class_resilience.sil index bdad174d78145..84fbd12eed59a 100644 --- a/test/IRGen/class_resilience.sil +++ b/test/IRGen/class_resilience.sil @@ -1,7 +1,8 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class %S/../Inputs/resilient_class.swift -I %t -// RUN: %target-swift-frontend -I %t -emit-ir -enable-library-evolution %s | %FileCheck %s +// RUN: %target-swift-frontend -enable-objc-interop -I %t -emit-ir -enable-library-evolution %s | %FileCheck %s --check-prefixes=CHECK,CHECK-objc +// RUN: %target-swift-frontend -disable-objc-interop -I %t -emit-ir -enable-library-evolution %s | %FileCheck %s --check-prefixes=CHECK,CHECK-native // RUN: %target-swift-frontend -I %t -emit-ir -enable-library-evolution -O %s // REQUIRES: CPU=x86_64 @@ -24,11 +25,13 @@ import resilient_class // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s15resilient_class22ResilientOutsideParentCMa"(i64 0) // CHECK-NEXT: [[META:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK-NEXT: [[META_ADDR:%.*]] = bitcast %swift.type* [[META]] to i8* -// CHECK-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 48 +// CHECK-objc-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 48 +// CHECK-native-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 24 // CHECK-NEXT: [[SIZE_PTR:%.*]] = bitcast i8* [[SIZE_ADDR]] to i32* // CHECK-NEXT: [[SIZE_2:%.*]] = load i32, i32* [[SIZE_PTR]], align 8 // CHECK-NEXT: [[SIZE:%.*]] = zext i32 [[SIZE_2]] to i64 -// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 52 +// CHECK-objc-NEXT: [[ALIGN_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 52 +// CHECK-native-NEXT: [[ALIGN_ADDR:%.*]] = getelementptr inbounds i8, i8* [[META_ADDR]], i32 28 // CHECK-NEXT: [[ALIGN_PTR:%.*]] = bitcast i8* [[ALIGN_ADDR]] to i16* // CHECK-NEXT: [[ALIGN_2:%.*]] = load i16, i16* [[ALIGN_PTR]], align 4 // CHECK-NEXT: [[ALIGN:%.*]] = zext i16 [[ALIGN_2]] to i64 diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift index 4d57a912dbad6..5f1e2212559fd 100644 --- a/test/IRGen/class_resilience.swift +++ b/test/IRGen/class_resilience.swift @@ -3,7 +3,8 @@ // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/../Inputs/resilient_class.swift -// RUN: %target-swift-frontend -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -check-prefix=CHECK-%target-cpu --check-prefix=CHECK-%target-runtime-STABLE-ABI-%target-mandates-stable-abi -DINT=i%target-ptrsize +// RUN: %target-swift-frontend -enable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-%target-import-type-objc-STABLE-ABI-%target-mandates-stable-abi -DINT=i%target-ptrsize -D#MDWORDS=7 -D#MDSIZE32=52 -D#MDSIZE64=80 -D#WORDSIZE=%target-alignment +// RUN: %target-swift-frontend -disable-objc-interop -I %t -emit-ir -enable-library-evolution %t/class_resilience.swift | %FileCheck %t/class_resilience.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-native-STABLE-ABI-%target-mandates-stable-abi -DINT=i%target-ptrsize -D#MDWORDS=4 -D#MDSIZE32=40 -D#MDSIZE64=56 -D#WORDSIZE=%target-alignment // RUN: %target-swift-frontend -I %t -emit-ir -enable-library-evolution -O %t/class_resilience.swift // CHECK: @"$s16class_resilience26ClassWithResilientPropertyC1s16resilient_struct4SizeVvpWvd" = hidden global [[INT]] 0 @@ -20,8 +21,8 @@ // CHECK: @"$s16class_resilience27ClassWithResilientThenEmptyC9resilient0H7_struct0E3IntVvpWvd" = hidden global [[INT]] 0, // CHECK: @"$s16class_resilience26ClassWithResilientPropertyCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]] -// CHECK-32-SAME: { [[INT]] 52, i32 2, i32 17 } -// CHECK-64-SAME: { [[INT]] 80, i32 2, i32 14 } +// CHECK-32-SAME: { [[INT]] [[#MDSIZE32]], i32 2, i32 [[#MDWORDS + 6 + 4]] } +// CHECK-64-SAME: { [[INT]] [[#MDSIZE64]], i32 2, i32 [[#MDWORDS + 3 + 4]] } // CHECK: @"$s16class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd" = hidden constant [[INT]] {{8|16}} // CHECK: @"$s16class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd" = hidden constant [[INT]] {{12|20}} @@ -101,20 +102,20 @@ // CHECK-native-SAME: i32 0 // CHECK: @"$s16class_resilience17MyResilientParentCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]] -// CHECK-32-SAME: { [[INT]] 52, i32 2, i32 15 } -// CHECK-64-SAME: { [[INT]] 80, i32 2, i32 12 } +// CHECK-32-SAME: { [[INT]] [[#MDSIZE32]], i32 2, i32 [[#MDWORDS + 6 + 2]] } +// CHECK-64-SAME: { [[INT]] [[#MDSIZE64]], i32 2, i32 [[#MDWORDS + 3 + 2]] } // CHECK: @"$s16class_resilience16MyResilientChildCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]] -// CHECK-32-SAME: { [[INT]] 60, i32 2, i32 16 } -// CHECK-64-SAME: { [[INT]] 96, i32 2, i32 13 } +// CHECK-32-SAME: { [[INT]] [[#MDSIZE32 + WORDSIZE + WORDSIZE]], i32 2, i32 [[#MDWORDS + 6 + 3]] } +// CHECK-64-SAME: { [[INT]] [[#MDSIZE64 + WORDSIZE + WORDSIZE]], i32 2, i32 [[#MDWORDS + 3 + 3]] } // CHECK: @"$s16class_resilience24MyResilientGenericParentCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]] -// CHECK-32-SAME: { [[INT]] 52, i32 2, i32 16 } -// CHECK-64-SAME: { [[INT]] 80, i32 2, i32 13 } +// CHECK-32-SAME: { [[INT]] [[#MDSIZE32]], i32 2, i32 [[#MDWORDS + 6 + 3]] } +// CHECK-64-SAME: { [[INT]] [[#MDSIZE64]], i32 2, i32 [[#MDWORDS + 3 + 3]] } // CHECK: @"$s16class_resilience24MyResilientConcreteChildCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]] -// CHECK-32-SAME: { [[INT]] 64, i32 2, i32 18 } -// CHECK-64-SAME: { [[INT]] 104, i32 2, i32 15 } +// CHECK-32-SAME: { [[INT]] [[#MDSIZE32 + WORDSIZE + WORDSIZE + WORDSIZE]], i32 2, i32 [[#MDWORDS + 6 + 5]] } +// CHECK-64-SAME: { [[INT]] [[#MDSIZE64 + WORDSIZE + WORDSIZE + WORDSIZE]], i32 2, i32 [[#MDWORDS + 3 + 5]] } // CHECK: @"$s16class_resilience27ClassWithEmptyThenResilientC5emptyAA0E0VvpWvd" = hidden constant [[INT]] 0, // CHECK: @"$s16class_resilience27ClassWithResilientThenEmptyC5emptyAA0G0VvpWvd" = hidden constant [[INT]] 0, @@ -400,7 +401,8 @@ public class ClassWithResilientThenEmpty { // CHECK: entry: // CHECK-NEXT: [[FIELDS:%.*]] = alloca [3 x i8**] // CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* %0 to [[INT]]* -// CHECK-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{10|13}} +// CHECK-objc-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{10|13}} +// CHECK-native-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{7|10}} // CHECK-NEXT: [[FIELDS_ADDR:%.*]] = bitcast [3 x i8**]* [[FIELDS]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 {{12|24}}, i8* [[FIELDS_ADDR]]) // CHECK-NEXT: [[FIELDS_PTR:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* [[FIELDS]], i32 0, i32 0 @@ -415,8 +417,9 @@ public class ClassWithResilientThenEmpty { // -- ClassLayoutFlags = 0x100 (HasStaticVTable) // CHECK-native: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) -// CHECK-objc-STABLE-ABI-TRUE: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) -// CHECK-objc-STABLE-ABI-FALSE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-DIRECT-objc-STABLE-ABI-TRUE: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-DIRECT-objc-STABLE-ABI-FALSE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-INDIRECT-objc-STABLE-ABI-TRUE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 3, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) // CHECK-NEXT: [[INITDEP_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK-NEXT: [[INITDEP_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1 // CHECK-NEXT: [[INITDEP_PRESENT:%.*]] = icmp eq %swift.type* [[INITDEP_METADATA]], null @@ -478,7 +481,8 @@ public class ClassWithResilientThenEmpty { // CHECK: entry: // CHECK-NEXT: [[FIELDS:%.*]] = alloca [2 x i8**] // CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* %0 to [[INT]]* -// CHECK-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{10|13}} +// CHECK-objc-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{10|13}} +// CHECK-native-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] {{7|10}} // CHECK-NEXT: [[FIELDS_ADDR:%.*]] = bitcast [2 x i8**]* [[FIELDS]] to i8* // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 {{8|16}}, i8* [[FIELDS_ADDR]]) // CHECK-NEXT: [[FIELDS_PTR:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* [[FIELDS]], i32 0, i32 0 @@ -493,8 +497,9 @@ public class ClassWithResilientThenEmpty { // -- ClassLayoutFlags = 0x100 (HasStaticVTable) // CHECK-native: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) -// CHECK-objc-STABLE-ABI-TRUE: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) -// CHECK-objc-STABLE-ABI-FALSE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-DIRECT-objc-STABLE-ABI-TRUE: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-DIRECT-objc-STABLE-ABI-FALSE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) +// CHECK-INDIRECT-objc-STABLE-ABI-TRUE:[[T0:%.*]] = call swiftcc %swift.metadata_response @swift_initClassMetadata2(%swift.type* %0, [[INT]] 256, [[INT]] 2, i8*** [[FIELDS_PTR]], [[INT]]* [[FIELDS_DEST]]) // CHECK-NEXT: [[INITDEP_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK-NEXT: [[INITDEP_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1 // CHECK-NEXT: [[INITDEP_PRESENT:%.*]] = icmp eq %swift.type* [[INITDEP_METADATA]], null diff --git a/test/IRGen/dynamic_init.sil b/test/IRGen/dynamic_init.sil index a5eb515fd89c9..1d063ff981d25 100644 --- a/test/IRGen/dynamic_init.sil +++ b/test/IRGen/dynamic_init.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s +// RUN: %target-swift-frontend -enable-objc-interop -emit-ir %s | %FileCheck %s --check-prefixes=CHECK,CHECK-objc +// RUN: %target-swift-frontend -disable-objc-interop -emit-ir %s | %FileCheck %s --check-prefixes=CHECK,CHECK-native // REQUIRES: CPU=x86_64 @@ -20,7 +21,8 @@ sil @$s12dynamic_init1CCfD : $@convention(method) (@owned C) -> () sil @$s12dynamic_init15testDynamicInityAA1CCm2cm_tF : $@convention(method) (@thick C.Type) -> () { bb0(%0 : $@thick C.Type): // CHECK: [[META:%[0-9]+]] = bitcast %swift.type* %0 to %T12dynamic_init1CC* (%swift.type*)** - // CHECK: [[VTABLE_OFFSET:%[0-9]+]] = getelementptr inbounds %T12dynamic_init1CC* (%swift.type*)*, %T12dynamic_init1CC* (%swift.type*)** [[META]], i64 10 + // CHECK-objc: [[VTABLE_OFFSET:%[0-9]+]] = getelementptr inbounds %T12dynamic_init1CC* (%swift.type*)*, %T12dynamic_init1CC* (%swift.type*)** [[META]], i64 10 + // CHECK-native: [[VTABLE_OFFSET:%[0-9]+]] = getelementptr inbounds %T12dynamic_init1CC* (%swift.type*)*, %T12dynamic_init1CC* (%swift.type*)** [[META]], i64 7 // CHECK: [[CTOR:%[0-9]+]] = load %T12dynamic_init1CC* (%swift.type*)*, %T12dynamic_init1CC* (%swift.type*)** [[VTABLE_OFFSET]], align 8 %2 = class_method %0 : $@thick C.Type, #C.init!allocator : (C.Type) -> () -> C, $@convention(method) (@thick C.Type) -> @owned C // CHECK: [[RESULT:%[0-9]+]] = call swiftcc %T12dynamic_init1CC* [[CTOR]](%swift.type* swiftself %0) diff --git a/test/IRGen/framepointer_arm64.sil b/test/IRGen/framepointer_arm64.sil index e82a1dabf4ef4..2ab1c7e888535 100644 --- a/test/IRGen/framepointer_arm64.sil +++ b/test/IRGen/framepointer_arm64.sil @@ -4,9 +4,7 @@ // 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 +// REQUIRES: OS=ios sil_stage canonical diff --git a/test/IRGen/fulfillment.sil b/test/IRGen/fulfillment.sil index 5cfea02b8ddda..cb8b0b830a12d 100644 --- a/test/IRGen/fulfillment.sil +++ b/test/IRGen/fulfillment.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-objc-interop | %FileCheck %s --check-prefixes=CHECK,CHECK-objc +// RUN: %target-swift-frontend -primary-file %s -emit-ir -disable-objc-interop | %FileCheck %s --check-prefixes=CHECK,CHECK-native // REQUIRES: CPU=x86_64 @@ -31,13 +32,16 @@ sil hidden_external @use_all : $@convention(thin) () - // CHECK: [[T0:%.*]] = bitcast %T11fulfillment1BC* %0 to %swift.type** // CHECK-NEXT: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[T0]], align 8 // CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type** -// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-objc-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-native-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 7 // CHECK-NEXT: %T = load %swift.type*, %swift.type** [[T1]], align 8 // CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type** -// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 11 +// CHECK-objc-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 11 +// CHECK-native-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 8 // CHECK-NEXT: %U = load %swift.type*, %swift.type** [[T1]], align 8 // CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i8*** -// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 12 +// CHECK-objc-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 12 +// CHECK-native-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 9 // CHECK-NEXT: %U.P = load i8**, i8*** [[T1]], align 8 sil hidden @class_pointer : $@convention(thin) (@guaranteed B) -> () { bb0(%0 : $B): @@ -73,7 +77,8 @@ sil @callee : $@convention(method) <τ_0_0 where τ_0_0 : A2, τ_0_0.AssocTy : C // CHECK-LABEL: define{{.*}} swiftcc void @caller(%T11fulfillment1KC** {{.*}}, %swift.type* %Self, i8** %SelfWitnessTable) // CHECK: entry: // CHECK: %1 = bitcast %swift.type* %Self to i8*** -// CHECK: %2 = getelementptr inbounds i8**, i8*** %1, i64 11 +// CHECK-objc: %2 = getelementptr inbounds i8**, i8*** %1, i64 11 +// CHECK-native: %2 = getelementptr inbounds i8**, i8*** %1, i64 8 // CHECK: %"\CF\84_1_0.C" = load i8**, i8*** %2 // CHECK: call swiftcc void @callee(%swift.type* %Self, i8** %SelfWitnessTable, i8** %"\CF\84_1_0.C" sil @caller : $@convention(witness_method: A2) <τ_0_0><τ_1_0 where τ_0_0 : K<τ_1_0>, τ_1_0 : C> (@in_guaranteed τ_0_0) -> () { diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil index 94b44d5d7710b..8781f38bd361a 100644 --- a/test/IRGen/generic_classes.sil +++ b/test/IRGen/generic_classes.sil @@ -23,13 +23,15 @@ import Swift // -- negative size in words // CHECK-SAME: i32 2, // -- positive size in words -// CHECK-SAME: i32 18, +// CHECK-objc-SAME: i32 18, +// CHECK-native-SAME: i32 15, // -- num immediate members // CHECK-SAME: i32 8, // -- num fields // CHECK-SAME: i32 3, // -- field offset vector offset -// CHECK-SAME: i32 11, +// CHECK-objc-SAME: i32 11, +// CHECK-native-SAME: i32 8, // -- template instantiation cache // CHECK-SAME: [16 x i8*]* @"$s15generic_classes11RootGenericCMI" // -- template instantiation pattern @@ -37,7 +39,8 @@ import Swift // -- generic parameters, requirements, key arguments, extra arguments // CHECK-SAME: i16 1, i16 0, i16 1, i16 0 // -- vtable offset -// CHECK-SAME: i32 14, +// CHECK-objc-SAME: i32 14, +// CHECK-native-SAME: i32 11, // -- vtable size // CHECK-SAME: i32 4 // CHECK-SAME: } @@ -91,22 +94,27 @@ import Swift // CHECK-SAME: }> // CHECK: @"$s15generic_classes14RootNonGenericCMf" = internal global <{ {{.*}} }> <{ +// -- destructor // CHECK-SAME: void (%T15generic_classes14RootNonGenericC*)* @"$s15generic_classes14RootNonGenericCfD", +// -- witness table pointer // CHECK-DIRECT-SAME: i8** @"$sBoWV", // CHECK-INDIRECT-SAME: i8** null, -// CHECK-native-SAME: i64 0, -// CHECK-native-SAME: %swift.type* null, -// CHECK-native-SAME: %swift.opaque* null, +// -- swift object type // CHECK-objc-SAME: i64 ptrtoint (%objc_class* @"$s15generic_classes14RootNonGenericCMm" to i64), +// CHECK-native-SAME: i64 0, +// -- superclass // CHECK-DIRECT-objc-SAME: %objc_class* @"OBJC_CLASS_$_{{(_TtCs12_)?}}SwiftObject", // CHECK-INDIRECT-objc-SAME: %swift.type* null, +// CHECK-native-SAME: %swift.type* null, +// -- objc only fields // CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache, -// CHECK-SAME: %swift.opaque* null, -// CHECK-native-SAME: i64 1, +// CHECK-objc-SAME: %swift.opaque* null, // CHECK-objc-SAME: @_DATA__TtC15generic_classes14RootNonGeneric +// -- flags, sizes, and offsets... // CHECK-SAME: i32 33, // CHECK-SAME: i16 7, // CHECK-SAME: i16 0, +// -- nominal type descriptor // CHECK-SAME: {{.*}}* @"$s15generic_classes14RootNonGenericCMn" // CHECK-SAME: }> @@ -250,11 +258,13 @@ sil @$s15generic_classes024RecursiveGenericInheritsD0CfD : $@convention(method) // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s15generic_classes11RootGenericCMa"(i64 0, %swift.type* %G) // CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8* -// CHECK: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 48 +// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 48 +// CHECK-native: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 24 // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK: [[SIZE32:%.*]] = load i32, i32* [[T1]], align 8 // CHECK: [[SIZE:%.*]] = zext i32 [[SIZE32]] to i64 -// CHECK: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 52 +// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 52 +// CHECK-native: [[T0:%.*]] = getelementptr inbounds i8, i8* [[METADATA_ARRAY]], i32 28 // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i16* // CHECK: [[ALIGN16:%.*]] = load i16, i16* [[T1]], align 4 // CHECK: [[ALIGN:%.*]] = zext i16 [[ALIGN16]] to i64 @@ -278,7 +288,8 @@ entry(%c : $RootGeneric): // RootGeneric.y has dependent layout; load the offset from the metadata // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @RootGeneric_concrete_fragile_dependent_member_access_y // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* -// CHECK: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 12 +// CHECK-objc: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 12 +// CHECK-native: [[Y_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 9 // CHECK: [[Y_OFFSET:%.*]] = load i64, i64* [[Y_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Y_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Y_OFFSET]] @@ -305,7 +316,8 @@ entry(%z : $*Int, %c : $RootGeneric): // RootGeneric.z has dependent layout; load the offset from the metadata // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @RootGeneric_concrete_fragile_dependent_member_access_z // CHECK: [[TYPE_METADATA_ARRAY:%.*]] = bitcast %swift.type* {{%.*}} to i64* -// CHECK: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 13 +// CHECK-objc: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 13 +// CHECK-native: [[Z_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[TYPE_METADATA_ARRAY]], i64 10 // CHECK: [[Z_OFFSET:%.*]] = load i64, i64* [[Z_OFFSET_ADDR]], align 8 // CHECK: [[CLASS_BYTE_ARRAY:%.*]] = bitcast [[ROOTGENERIC]]* {{%.*}} to i8* // CHECK: [[Z_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CLASS_BYTE_ARRAY]], i64 [[Z_OFFSET]] @@ -375,7 +387,8 @@ entry(%c : $RootGeneric): // Initialize our own dependent field offsets. // CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64* -// CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 20 +// CHECK-objc: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 20 +// CHECK-native: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 17 // CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 // CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %B) // CHECK: [[B_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 diff --git a/test/IRGen/generic_types.swift b/test/IRGen/generic_types.swift index d19a5ace298a2..1a5cc5be5e86d 100644 --- a/test/IRGen/generic_types.swift +++ b/test/IRGen/generic_types.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime +// RUN: %target-swift-frontend -enable-objc-interop %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-objc +// RUN: %target-swift-frontend -disable-objc-interop %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-native // REQUIRES: CPU=x86_64 @@ -20,13 +21,15 @@ // -- negative size in words // CHECK-SAME: i32 2, // -- positive size in words -// CHECK-SAME: i32 17, +// CHECK-objc-SAME: i32 17, +// CHECK-native-SAME: i32 14, // -- num immediate members // CHECK-SAME: i32 7, // -- num fields // CHECK-SAME: i32 1, // -- field offset vector offset -// CHECK-SAME: i32 11, +// CHECK-objc-SAME: i32 11, +// CHECK-native-SAME: i32 8, // -- instantiation cache // CHECK-SAME: @"$s13generic_types1ACMI" // -- instantiation pattern diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift index 1aaba1131ea8d..baaf17e92dbfb 100644 --- a/test/IRGen/generic_vtable.swift +++ b/test/IRGen/generic_vtable.swift @@ -1,6 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/chex.py < %s > %t/generic_vtable.swift -// RUN: %target-swift-frontend %t/generic_vtable.swift -emit-ir | %FileCheck %t/generic_vtable.swift --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize -check-prefix CHECK-%target-import-type -check-prefix CHECK-%target-abi +// RUN: %target-swift-frontend -enable-objc-interop %t/generic_vtable.swift -emit-ir | %FileCheck %t/generic_vtable.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-import-type,CHECK-%target-abi -DINT=i%target-ptrsize +// RUN: %target-swift-frontend -disable-objc-interop %t/generic_vtable.swift -emit-ir | %FileCheck %t/generic_vtable.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-import-type,CHECK-%target-abi -DINT=i%target-ptrsize public class Base { public func m1() {} @@ -25,8 +26,10 @@ public class Concrete : Derived { // CHECK-DIRECT-SAME: , // CHECK-INDIRECT-SAME: , // -- vtable offset -// CHECK-32-SAME: i32 16, -// CHECK-64-SAME: i32 10, +// CHECK-objc32-SAME: i32 16, +// CHECK-native32-SAME: i32 13, +// CHECK-objc64-SAME: i32 10, +// CHECK-native64-SAME: i32 7, // -- vtable size // CHECK-SAME: i32 3, // -- vtable entry for m1() @@ -59,8 +62,10 @@ public class Concrete : Derived { // -- flags: has vtable, has override table, is class, is unique, is generic // CHECK-SAME: , // -- vtable offset -// CHECK-32-SAME: i32 17, -// CHECK-64-SAME: i32 14, +// CHECK-objc32-SAME: i32 17, +// CHECK-native32-SAME: i32 14, +// CHECK-objc64-SAME: i32 14, +// CHECK-native64-SAME: i32 11, // -- vtable size // CHECK-SAME: i32 1, // -- vtable entry for m3() @@ -95,8 +100,10 @@ public class Concrete : Derived { // -- flags: has vtable, has override table, in-place initialization, is class, is unique // CHECK-SAME: , // -- vtable offset -// CHECK-32-SAME: i32 19, -// CHECK-64-SAME: i32 15, +// CHECK-objc32-SAME: i32 19, +// CHECK-native32-SAME: i32 16, +// CHECK-objc64-SAME: i32 15, +// CHECK-native64-SAME: i32 12, // -- vtable size // CHECK-SAME: i32 1, // -- vtable entry for m4() diff --git a/test/IRGen/partial_apply_forwarder.sil b/test/IRGen/partial_apply_forwarder.sil index 786fe2fcef7ea..50ead1c5882c4 100644 --- a/test/IRGen/partial_apply_forwarder.sil +++ b/test/IRGen/partial_apply_forwarder.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize +// RUN: %target-swift-frontend -enable-objc-interop -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize --check-prefixes=CHECK,CHECK-objc +// RUN: %target-swift-frontend -disable-objc-interop -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize --check-prefixes=CHECK,CHECK-native sil_stage canonical import Builtin @@ -96,7 +97,8 @@ sil hidden_external @takingEmptyAndQ : $@convention(thin) <τ_0_0 where τ_0_0 // CHECK: [[TYADDR:%.*]] = getelementptr inbounds %T23partial_apply_forwarder7WeakBoxC, %T23partial_apply_forwarder7WeakBoxC* %1, i32 0, i32 0, i32 0 // CHECK: [[TY:%.*]] = load %swift.type*, %swift.type** [[TYADDR]] // CHECK: [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type** -// CHECK: [[PARAMTYADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-objc: [[PARAMTYADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-native: [[PARAMTYADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 7|i32 10)}} // CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[PARAMTYADDR]] // CHECK: [[WITNESS:%.*]] = call i8** @swift_getWitnessTable( // CHECK: [[OBJ:%.*]] = bitcast %swift.refcounted* %0 to %T23partial_apply_forwarder7WeakBoxC.1* @@ -155,7 +157,8 @@ bb0(%0 : $*τ_0_1, %2: $EmptyType): // CHECK: [[TY:%.*]] = load %swift.type*, %swift.type** [[TYADDR]] // CHECK: [[CAST:%.*]] = bitcast %T23partial_apply_forwarder7WeakBoxC* %0 to %T23partial_apply_forwarder7WeakBoxC.1* // CHECK: [[TYPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type** -// CHECK: [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-objc: [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-native: [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 7|i32 10)}} // CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[TYPARAM]] // CHECK: [[WITNESS:%.*]] = call i8** @swift_getWitnessTable // CHECK: tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[CAST]], i8** [[WITNESS]]) @@ -209,7 +212,8 @@ sil hidden_external @takingQAndS : $@convention(thin) <τ_0_0 where τ_0_0 : Q> // CHECK: %.asUnsubstituted = bitcast %T23partial_apply_forwarder7WeakBoxC* [[WB]] to %T23partial_apply_forwarder7WeakBoxC.1* // CHECK: call void @swift_release(%swift.refcounted* %0) // CHECK: [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type** -// CHECK: [[GENPARAMADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-objc: [[GENPARAMADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}} +// CHECK-native: [[GENPARAMADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 7|i32 10)}} // CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[GENPARAMADDR]] // CHECK: [[WITNESS:%.*]] = call i8** @swift_getWitnessTable // CHECK: tail call swiftcc void @takingQAndS(i64 [[X]], %T23partial_apply_forwarder7WeakBoxC.1* %.asUnsubstituted, i8** [[WITNESS]]) diff --git a/test/IRGen/sil_witness_methods.sil b/test/IRGen/sil_witness_methods.sil index 62dbce92f8465..aa9112c8938a6 100644 --- a/test/IRGen/sil_witness_methods.sil +++ b/test/IRGen/sil_witness_methods.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend -enable-objc-interop %s -emit-ir | %FileCheck --check-prefixes=CHECK,CHECK-objc %s +// RUN: %target-swift-frontend -disable-objc-interop %s -emit-ir | %FileCheck --check-prefixes=CHECK,CHECK-native %s // REQUIRES: CPU=x86_64 @@ -36,13 +37,16 @@ entry(%x : $*Foo): // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_concrete_method_witness(%T19sil_witness_methods3BarC** noalias nocapture swiftself dereferenceable({{.*}}) %0, %swift.type* %Self, i8** %SelfWitnessTable) // CHECK: [[T0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-objc: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-native: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 7 // CHECK: %T = load %swift.type*, %swift.type** [[T1]], align 8 // CHECK: [[U0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11 +// CHECK-objc: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11 +// CHECK-native: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 8 // CHECK: %U = load %swift.type*, %swift.type** [[U1]], align 8 // CHECK: [[V0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12 +// CHECK-objc: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12 +// CHECK-native: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 9 // CHECK: %V = load %swift.type*, %swift.type** [[V1]], align 8 sil @generic_type_concrete_method_witness : $@convention(witness_method: P) (@in Bar) -> @thick Bar.Type { entry(%x : $*Bar): @@ -66,13 +70,16 @@ entry(%x : $@thick Foo.Type): // The use of %0 or %Self here is irrelevant. // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_concrete_static_method_witness(%swift.type* swiftself %0, %swift.type* %Self, i8** %SelfWitnessTable) // CHECK: [[T0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-objc: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10 +// CHECK-native: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 7 // CHECK: %T = load %swift.type*, %swift.type** [[T1]], align 8 // CHECK: [[U0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11 +// CHECK-objc: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11 +// CHECK-native: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 8 // CHECK: %U = load %swift.type*, %swift.type** [[U1]], align 8 // CHECK: [[V0:%.*]] = bitcast %swift.type* %Self to %swift.type** -// CHECK: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12 +// CHECK-objc: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12 +// CHECK-native: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 9 // CHECK: %V = load %swift.type*, %swift.type** [[V1]], align 8 sil @generic_type_concrete_static_method_witness : $@convention(witness_method: P) (@thick Bar.Type) -> @thick Bar.Type { entry(%x : $@thick Bar.Type): diff --git a/test/IRGen/tail_alloc.sil b/test/IRGen/tail_alloc.sil index 51fbd0a32f39c..6ad3dba2ebd88 100644 --- a/test/IRGen/tail_alloc.sil +++ b/test/IRGen/tail_alloc.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck %s -DINT=i%target-ptrsize +// RUN: %target-swift-frontend -enable-objc-interop -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck --check-prefixes=CHECK,CHECK-objc %s -DINT=i%target-ptrsize +// RUN: %target-swift-frontend -disable-objc-interop -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck --check-prefixes=CHECK,CHECK-native %s -DINT=i%target-ptrsize // // REQUIRES: CPU=x86_64 @@ -112,11 +113,13 @@ bb0(%0 : $Builtin.Word, %1 : $@thick T.Type): // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} {{.*}}* @alloc_dynamic // CHECK: [[BYTE_PTR:%[0-9]+]] = bitcast %swift.type* %0 to i8* -// CHECK-NEXT: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 48 +// CHECK-objc-NEXT: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 48 +// CHECK-native-NEXT: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 24 // CHECK-NEXT: [[INT_PTR:%[0-9]+]] = bitcast i8* [[SIZE_ADDR]] to i32* // CHECK-NEXT: [[SIZE:%[0-9]+]] = load i32, i32* [[INT_PTR]] // CHECK-NEXT: [[SIZE64:%[0-9]+]] = zext i32 [[SIZE]] to i64 -// CHECK-NEXT: [[ALIGN_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 52 +// CHECK-objc-NEXT: [[ALIGN_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 52 +// CHECK-native-NEXT: [[ALIGN_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 28 // CHECK-NEXT: [[SHORT_PTR:%[0-9]+]] = bitcast i8* [[ALIGN_ADDR]] to i16* // CHECK-NEXT: [[ALIGN:%[0-9]+]] = load i16, i16* [[SHORT_PTR]] // CHECK-NEXT: [[ALIGN64:%[0-9]+]] = zext i16 [[ALIGN]] to i64 diff --git a/test/IRGen/vtable.sil b/test/IRGen/vtable.sil index 3be6a614fa4b2..20cbcdaad3a25 100644 --- a/test/IRGen/vtable.sil +++ b/test/IRGen/vtable.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime +// RUN: %target-swift-frontend -enable-objc-interop -emit-ir %s | %FileCheck %s --check-prefixes=CHECK,CHECK-objc,CHECK-%target-import-type-objc +// RUN: %target-swift-frontend -disable-objc-interop -emit-ir %s | %FileCheck %s --check-prefixes=CHECK,CHECK-native // REQUIRES: executable_test // REQUIRES: CPU=x86_64 @@ -19,29 +20,27 @@ sil @$s6vtable1CCfd : $@convention(method) (@owned C) -> @owned Builtin.NativeOb sil @$s6vtable1CCfD : $@convention(method) (@owned C) -> () // CHECK-objc: @"$s6vtable1CCMf" = internal global [[C_METADATA_T:<{.*\* }>]] <{ -// CHECK-objc: void ([[C]]*)* @"$s6vtable1CCfD", -// CHECK-objc: i8** {{@"\$sBoWV"|null}}, -// CHECK-objc: i64 ptrtoint (%objc_class* @"$s6vtable1CCMm" to i64), -// CHECK-objc: %objc_class* @"OBJC_CLASS_$_{{(_TtCs12_)?}}SwiftObject", -// CHECK-objc: %swift.opaque* @_objc_empty_cache, -// CHECK-objc: %swift.opaque* null, -// CHECK-objc: i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_DATA__TtC6vtable1C to i64), i64 {{1|2}}), -// CHECK-objc: i32 {{3|2}}, i32 0, i32 16, i16 7, i16 0, -// CHECK-objc: i32 104, i32 16, -// CHECK-objc: @"$s6vtable1CCMn" -// CHECK-objc: [[C]]* (%swift.type*)* @"$s6vtable1CCACycACmcfC" -// CHECK-objc: }> +// CHECK-objc: void ([[C]]*)* @"$s6vtable1CCfD", +// CHECK-objc: i8** {{@"\$sBoWV"|null}}, +// CHECK-objc: i64 ptrtoint (%objc_class* @"$s6vtable1CCMm" to i64), +// CHECK-DIRECT-objc: %objc_class* @"OBJC_CLASS_$_{{(_TtCs12_)?}}SwiftObject", +// CHECK-INDIRECT-objc: %swift.type* null, +// CHECK-objc: %swift.opaque* @_objc_empty_cache, +// CHECK-objc: %swift.opaque* null, +// CHECK-objc: i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_DATA__TtC6vtable1C to i64), i64 {{1|2}}), +// CHECK-objc: i32 {{3|2}}, i32 0, i32 16, i16 7, i16 0, +// CHECK-objc: i32 104, i32 16, +// CHECK-objc: @"$s6vtable1CCMn" +// CHECK-objc: [[C]]* (%swift.type*)* @"$s6vtable1CCACycACmcfC" +// CHECK-objc: }> // CHECK-native: @"$s6vtable1CCMf" = internal global [[C_METADATA_T:<{.*\* }>]] <{ // CHECK-native: void ([[C]]*)* @"$s6vtable1CCfD", // CHECK-native: i8** {{@"\$sBoWV"|null}}, // CHECK-native: i64 0, // CHECK-native: %swift.type* null, -// CHECK-native: %swift.opaque* null, -// CHECK-native: %swift.opaque* null, -// CHECK-native: i64 1, // CHECK-native: i32 {{3|2}}, i32 0, i32 16, i16 7, i16 0, -// CHECK-native: i32 104, i32 16, +// CHECK-native: i32 80, i32 16, // CHECK-native: @"$s6vtable1CCMn" // CHECK-native: [[C]]* (%swift.type*)* @"$s6vtable1CCACycACmcfC" // CHECK-native: }> diff --git a/test/IRGen/vtable_multi_file.swift b/test/IRGen/vtable_multi_file.swift index 7bc50df82fd31..95503a0359c9f 100644 --- a/test/IRGen/vtable_multi_file.swift +++ b/test/IRGen/vtable_multi_file.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -primary-file %s %S/Inputs/vtable_multi_file_helper.swift -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend -enable-objc-interop -primary-file %s %S/Inputs/vtable_multi_file_helper.swift -emit-ir | %FileCheck --check-prefixes=CHECK,CHECK-OBJC %s +// RUN: %target-swift-frontend -disable-objc-interop -primary-file %s %S/Inputs/vtable_multi_file_helper.swift -emit-ir | %FileCheck --check-prefixes=CHECK,CHECK-NO-OBJC %s // REQUIRES: CPU=x86_64 @@ -15,7 +16,8 @@ func baseClassVtablesIncludeImplicitInits() { // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s17vtable_multi_file8SubclassCMa"(i64 0) // CHECK: [[T0:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK: [[T1:%.*]] = bitcast %swift.type* [[T0]] to { i64, %swift.bridge* } (%swift.type*)** - // CHECK: [[T2:%.*]] = getelementptr inbounds { i64, %swift.bridge* } (%swift.type*)*, { i64, %swift.bridge* } (%swift.type*)** [[T1]], i64 11 + // CHECK-OBJC: [[T2:%.*]] = getelementptr inbounds { i64, %swift.bridge* } (%swift.type*)*, { i64, %swift.bridge* } (%swift.type*)** [[T1]], i64 11 + // CHECK-NO-OBJC: [[T2:%.*]] = getelementptr inbounds { i64, %swift.bridge* } (%swift.type*)*, { i64, %swift.bridge* } (%swift.type*)** [[T1]], i64 8 // CHECK: load { i64, %swift.bridge* } (%swift.type*)*, { i64, %swift.bridge* } (%swift.type*)** [[T2]] markUsed(Subclass.classProp) } diff --git a/test/Sema/object_literals_ios.swift b/test/Sema/object_literals_ios.swift index facc3a9631d43..b4ef8d54b7983 100644 --- a/test/Sema/object_literals_ios.swift +++ b/test/Sema/object_literals_ios.swift @@ -6,20 +6,24 @@ struct S: _ExpressibleByColorLiteral { } let y: S = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) -let y2 = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) // expected-error{{could not infer type of color literal}} expected-note{{import UIKit to use 'UIColor' as the default color literal type}} +let y2 = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) // expected-error{{could not infer type of color literal}} +// expected-note@-1{{import UIKit to use 'UIColor' as the default color literal type}} let y3 = #colorLiteral(red: 1, bleen: 0, grue: 0, alpha: 1) // expected-error{{incorrect argument labels in call (have 'red:bleen:grue:alpha:', expected 'red:green:blue:alpha:')}} -// expected-error@-1 {{could not infer type of color literal}} expected-note@-1 {{import UIKit to use 'UIColor' as the default color literal type}} +// expected-error@-1 {{could not infer type of color literal}} +// expected-note@-2 {{import UIKit to use 'UIColor' as the default color literal type}} struct I: _ExpressibleByImageLiteral { init(imageLiteralResourceName: String) {} } let z: I = #imageLiteral(resourceName: "hello.png") -let z2 = #imageLiteral(resourceName: "hello.png") // expected-error{{could not infer type of image literal}} expected-note{{import UIKit to use 'UIImage' as the default image literal type}} +let z2 = #imageLiteral(resourceName: "hello.png") // expected-error{{could not infer type of image literal}} +// expected-note@-1{{import UIKit to use 'UIImage' as the default image literal type}} struct Path: _ExpressibleByFileReferenceLiteral { init(fileReferenceLiteralResourceName: String) {} } let p1: Path = #fileLiteral(resourceName: "what.txt") -let p2 = #fileLiteral(resourceName: "what.txt") // expected-error{{could not infer type of file reference literal}} expected-note{{import Foundation to use 'URL' as the default file reference literal type}} +let p2 = #fileLiteral(resourceName: "what.txt") // expected-error{{could not infer type of file reference literal}} +// expected-note@-1{{import Foundation to use 'URL' as the default file reference literal type}} diff --git a/test/Sema/object_literals_osx.swift b/test/Sema/object_literals_osx.swift index b49c28989f9bd..2fb5e2fc0b503 100644 --- a/test/Sema/object_literals_osx.swift +++ b/test/Sema/object_literals_osx.swift @@ -6,24 +6,32 @@ struct S: _ExpressibleByColorLiteral { } let y: S = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) -let y2 = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) // expected-error{{could not infer type of color literal}} expected-note{{import AppKit to use 'NSColor' as the default color literal type}} -let y3 = #colorLiteral(red: 1, bleen: 0, grue: 0, alpha: 1) // expected-error{{incorrect argument labels in call (have 'red:bleen:grue:alpha:', expected 'red:green:blue:alpha:')}} expected-error{{could not infer type of color literal}} expected-note{{import AppKit to use 'NSColor' as the default color literal type}} +let y2 = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) // expected-error{{could not infer type of color literal}} +// expected-note@-1{{import AppKit to use 'NSColor' as the default color literal type}} +let y3 = #colorLiteral(red: 1, bleen: 0, grue: 0, alpha: 1) // expected-error{{incorrect argument labels in call (have 'red:bleen:grue:alpha:', expected 'red:green:blue:alpha:')}} +// expected-error@-1{{could not infer type of color literal}} +// expected-note@-2{{import AppKit to use 'NSColor' as the default color literal type}} struct I: _ExpressibleByImageLiteral { init(imageLiteralResourceName: String) {} } let z: I = #imageLiteral(resourceName: "hello.png") -let z2 = #imageLiteral(resourceName: "hello.png") // expected-error{{could not infer type of image literal}} expected-note{{import AppKit to use 'NSImage' as the default image literal type}} +let z2 = #imageLiteral(resourceName: "hello.png") // expected-error{{could not infer type of image literal}} +// expected-note@-1{{import AppKit to use 'NSImage' as the default image literal type}} struct Path: _ExpressibleByFileReferenceLiteral { init(fileReferenceLiteralResourceName: String) {} } let p1: Path = #fileLiteral(resourceName: "what.txt") -let p2 = #fileLiteral(resourceName: "what.txt") // expected-error{{could not infer type of file reference literal}} expected-note{{import Foundation to use 'URL' as the default file reference literal type}} +let p2 = #fileLiteral(resourceName: "what.txt") // expected-error{{could not infer type of file reference literal}} +// expected-note@-1{{import Foundation to use 'URL' as the default file reference literal type}} -let text = #fileLiteral(resourceName: "TextFile.txt").relativeString! // expected-error{{could not infer type of file reference literal}} expected-note{{import Foundation to use 'URL' as the default file reference literal type}} +let text = #fileLiteral(resourceName: "TextFile.txt").relativeString! // expected-error{{could not infer type of file reference literal}} +// expected-note@-1{{import Foundation to use 'URL' as the default file reference literal type}} // rdar://problem/49861813 -#fileLiteral() // expected-error{{missing argument for parameter 'resourceName' in call}} expected-error{{could not infer type of file reference literal}} expected-note{{import Foundation to use 'URL' as the default file reference literal type}} +#fileLiteral() // expected-error{{missing argument for parameter 'resourceName' in call}} +// expected-error@-1{{could not infer type of file reference literal}} +// expected-note@-2{{import Foundation to use 'URL' as the default file reference literal type}} diff --git a/test/Serialization/Recovery/typedefs.swift b/test/Serialization/Recovery/typedefs.swift index ab82f8db91f49..8d98362f1858b 100644 --- a/test/Serialization/Recovery/typedefs.swift +++ b/test/Serialization/Recovery/typedefs.swift @@ -13,8 +13,8 @@ // RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -DVERIFY %s -verify // RUN: %target-swift-frontend -emit-silgen -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST %s | %FileCheck -check-prefix CHECK-SIL %s -// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/custom-modules -DTEST %s | %FileCheck -check-prefix CHECK-IR %s -// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST %s | %FileCheck -check-prefix CHECK-IR %s +// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/custom-modules -DTEST %s | %FileCheck --check-prefixes=CHECK-IR,CHECK-IR-%target-runtime %s +// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST %s | %FileCheck --check-prefixes=CHECK-IR,CHECK-IR-%target-runtime %s // RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -Xcc -DBAD %S/Inputs/typedefs-helper.swift -verify @@ -38,7 +38,8 @@ public func testVTableBuilding(user: User) { // for the vtable slot for 'lastMethod()'. If the layout here // changes, please check that offset is still correct. // CHECK-IR-NOT: ret - // CHECK-IR: getelementptr inbounds void (%T3Lib4UserC*)*, void (%T3Lib4UserC*)** %{{[0-9]+}}, {{i64 28|i32 31}} + // CHECK-IR-objc: getelementptr inbounds void (%T3Lib4UserC*)*, void (%T3Lib4UserC*)** %{{[0-9]+}}, {{i64 28|i32 31}} + // CHECK-IR-native: getelementptr inbounds void (%T3Lib4UserC*)*, void (%T3Lib4UserC*)** %{{[0-9]+}}, {{i64 25|i32 28}} user.lastMethod() } // CHECK-IR: ret void diff --git a/test/api-digester/Inputs/cake_baseline/cake.swift b/test/api-digester/Inputs/cake_baseline/cake.swift index 8ac2884bca90a..63604ca8c1553 100644 --- a/test/api-digester/Inputs/cake_baseline/cake.swift +++ b/test/api-digester/Inputs/cake_baseline/cake.swift @@ -40,6 +40,9 @@ public struct C6 {} @frozen public enum IceKind {} +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public enum FutureKind {} + public protocol P1 {} public protocol P2 {} diff --git a/test/api-digester/Inputs/cake_current/cake.swift b/test/api-digester/Inputs/cake_current/cake.swift index 353c8c632a748..f6c3d365a404b 100644 --- a/test/api-digester/Inputs/cake_current/cake.swift +++ b/test/api-digester/Inputs/cake_current/cake.swift @@ -40,6 +40,11 @@ public struct C6 {} public enum IceKind {} +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public enum FutureKind { + case FineToAdd +} + public protocol P1 {} public protocol P2 {} diff --git a/test/api-digester/Outputs/cake-abi.json b/test/api-digester/Outputs/cake-abi.json index a6f9baf090553..baf48c95925bf 100644 --- a/test/api-digester/Outputs/cake-abi.json +++ b/test/api-digester/Outputs/cake-abi.json @@ -615,6 +615,7 @@ "usr": "s:4cake6NumberO", "moduleName": "cake", "enumRawTypeName": "Int", + "isEnumExhaustive": true, "conformances": [ { "kind": "Conformance", diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json index 13fd939c1e866..8a487febb665b 100644 --- a/test/api-digester/Outputs/cake.json +++ b/test/api-digester/Outputs/cake.json @@ -635,6 +635,7 @@ "usr": "s:4cake6NumberO", "moduleName": "cake", "enumRawTypeName": "Int", + "isEnumExhaustive": true, "conformances": [ { "kind": "Conformance", diff --git a/test/api-digester/dump-module.swift b/test/api-digester/dump-module.swift index c0bdcb213a869..79955afcf567e 100644 --- a/test/api-digester/dump-module.swift +++ b/test/api-digester/dump-module.swift @@ -1,4 +1,4 @@ -// REQUIRES: macosx +// REQUIRES: OS=macosx // RUN: %empty-directory(%t.mod) // RUN: %empty-directory(%t.sdk) // RUN: %empty-directory(%t.module-cache) diff --git a/test/decl/operator/Inputs/lookup_other_noncompat.swift b/test/decl/operator/Inputs/lookup_other_noncompat.swift new file mode 100644 index 0000000000000..db4d2ab60ca0b --- /dev/null +++ b/test/decl/operator/Inputs/lookup_other_noncompat.swift @@ -0,0 +1,5 @@ + +// Also declared in the files being tested. +precedencegroup RedeclaredInModule {} +// expected-note@-1 {{previous precedence group declaration here}} +// expected-note@-2 {{found this matching precedence group}} diff --git a/test/decl/operator/Inputs/redeclaration_other.swift b/test/decl/operator/Inputs/redeclaration_other.swift new file mode 100644 index 0000000000000..f60b80c446209 --- /dev/null +++ b/test/decl/operator/Inputs/redeclaration_other.swift @@ -0,0 +1,10 @@ +precedencegroup RedeclaredAcrossFiles {} // expected-note {{previous precedence group declaration here}} + +infix operator ^^^ // expected-note {{previous operator declaration here}} +prefix operator >>> // expected-note {{previous operator declaration here}} +postfix operator <<< // expected-note {{previous operator declaration here}} + +precedencegroup P1 {} +infix operator ^^^^ : P1 // expected-note {{previous operator declaration here}} + +infix operator &&& diff --git a/test/decl/operator/lookup.swift b/test/decl/operator/lookup.swift new file mode 100644 index 0000000000000..1c40082d17000 --- /dev/null +++ b/test/decl/operator/lookup.swift @@ -0,0 +1,113 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleD.swift -module-name D -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleC.swift -module-name C -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleB.swift -module-name B -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleA.swift -module-name A -o %t -I %t +// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_module_exportsAC.swift -module-name ExportsAC -o %t -I %t +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/lookup_other.swift %S/Inputs/lookup_other2.swift %S/Inputs/lookup_other_noncompat.swift -I %t -enable-new-operator-lookup + +import ExportsAC +import B + +infix operator ^^^ : DeclaredAcrossFiles +func ^^^ (lhs: Int, rhs: Int) -> Int { 0 } +func &&& (lhs: Int, rhs: Int) -> Int { 0 } + +// The operator decl >>> is declared in module A, which we should be able to +// see through ExportsAC. +prefix func >>> (rhs: Double) {} + +// Make sure we can also see precedencegroups in module A through ExportsAC. +infix operator ^^^^ : DeclaredInModuleA + +// The operator decl for ??? is declared in both modules A and B, but has the +// same default precedence group in both, so there's no ambiguity. +func ??? (lhs: Int, rhs: Int) {} + +// Same for ???!, declared in modules ExportsAC and B, but has the same +// precedence group in both. +func ???! (lhs: Int, rhs: Int) {} + +// The operator decl for ???? is declared in both modules A and B, and has a +// different precedence group in each. Therefore ambiguous. +func ???? (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} + +// Same for ????!, declared in both modules ExportsAC and B, and has a different +// precedence group in each. Therefore ambiguous. +func ????! (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} + +// The precedencegroup is declared in both modules A and B, therefore ambiguous. +infix operator : DeclaredInModulesAB // expected-error {{multiple precedence groups found}} + +// The precedencegroup is declared in both modules ExportsAC and B, therefore +// ambiguous. +infix operator : DeclaredInModulesBExportsAC // expected-error {{multiple precedence groups found}} + +// While this precedencegroup is declared in both modules A and B, it's also +// declared in this module, which therefore shadows those decls. +infix operator : DeclaredInModulesABShadowed + +// The operator decl for : ShadowsModuleA + +// This precedencegroup is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former. +infix operator : ShadowsModulesAC + +// This operator decl is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former. +func ????? (lhs: Int, rhs: Int) {} + +// This operator decl is declared in modules A, C, and ExportsAC, but the +// latter shadows both of the former, despite them having different +// precedencegroups. +func ?????? (lhs: Int, rhs: Int) {} + +// Module D is imported through exports in both lookup_other and lookup_other2. +// Make sure we correctly handle visiting the same module twice. +infix operator <> : DeclaredInModuleD + +// Also declared in lookup_other. +precedencegroup RedeclaredInModule {} +// expected-error@-1 {{precedence group redeclared}} +// expected-note@-2 {{found this matching precedence group}} + +infix operator *** : RedeclaredInModule // expected-error {{multiple precedence groups found}} + +func testOperatorLookup() { + // In lookup_other, DeclaredAcrossFiles is left associative, whereas in + // module B it is non-associative. Make sure we use lookup_other's. + _ = 5 ^^^ 5 ^^^ 5 // Okay. + + // Same for &&&, in lookup_other it is declared as left associative. + _ = 5 &&& 5 &&& 5 + + // The operator >>> is declared in module A, which we should be able to see + // through ExportsAC. + >>>1 + + // We've been evil and overriden TernaryPrecedence in both modules A and B. + // Make sure we emit an ambiguity error without emitting a 'broken stdlib' + // error. + true ? () : () // expected-error {{multiple precedence groups found}} +} + +precedencegroup CastingPrecedence { + lowerThan: AssignmentPrecedence +} + +func testBuiltinPrecedenceGroupOverriding() { + // Evil, but allowed. + var x = 0 + x = 0 as Int // expected-error {{cannot convert value of type '()' to type 'Int' in coercion}} +} diff --git a/test/decl/operator/lookup_compatibility.swift b/test/decl/operator/lookup_compatibility.swift index 603ab9149fd3c..cf6db1e5c7b78 100644 --- a/test/decl/operator/lookup_compatibility.swift +++ b/test/decl/operator/lookup_compatibility.swift @@ -14,13 +14,15 @@ infix operator ^^^ : DeclaredAcrossFiles func ^^^ (lhs: Int, rhs: Int) -> Int { 0 } func &&& (lhs: Int, rhs: Int) -> Int { 0 } -// FIXME(SR-12132): The operator decl >>> is declared in module A, which we -// should be able to see through ExportsAC. -prefix func >>> (rhs: Double) {} // expected-error {{operator implementation without matching operator declaration}} +// The operator decl >>> is declared in module A, which we should be able to +// see through ExportsAC. Note that this is possible even with the compatibility +// behavior as we can use the new lookup logic when the result is unambiguous. +prefix func >>> (rhs: Double) {} -// FIXME(SR-12132): We should also see precedencegroups in module A through -// ExportsAC. -infix operator ^^^^ : DeclaredInModuleA // expected-error {{unknown precedence group 'DeclaredInModuleA'}} +// Make sure we can also see precedencegroups in module A through ExportsAC. +// Note that this is possible even with the compatibility behavior as we can use +// the new lookup logic when the result is unambiguous. +infix operator ^^^^ : DeclaredInModuleA // The operator decl for ??? is declared in both modules A and B, but has the // same default precedence group in both, so there's no ambiguity. @@ -38,9 +40,7 @@ func ???? (lhs: Int, rhs: Int) {} // The operator decl for ????! is declared in both modules ExportsAC and B, and // has a different precedence group in each. Therefore ambiguous. -// FIXME: We shouldn't emit the unknown operator decl error. func ????! (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}} -// expected-error@-1 {{operator implementation without matching operator declaration}} // Same as ????, the precedencegroup is declared in both modules A and B, but // we don't look into module A for compatibility. @@ -48,9 +48,7 @@ infix operator : DeclaredInModulesAB // The precedencegroup is declared in both modules ExportsAC and B, therefore // ambiguous. -// FIXME: We shouldn't emit the 'unknown precedence group' error. infix operator : DeclaredInModulesBExportsAC // expected-error {{multiple precedence groups found}} -// expected-error@-1 {{unknown precedence group 'DeclaredInModulesBExportsAC'}} // This precedencegroup is declared in this module as well as in both modules A // and B. The decl in this module should shadow the imported ones, but for @@ -82,10 +80,9 @@ func ????? (lhs: Int, rhs: Int) {} // precedencegroups. func ?????? (lhs: Int, rhs: Int) {} -// FIXME: Module D is imported through exports in both lookup_other and -// lookup_other2, but we fail to detect the fact that we're visiting the same -// thing twice. -infix operator <> : DeclaredInModuleD // expected-error {{unknown precedence group 'DeclaredInModuleD'}} +// Module D is imported through exports in both lookup_other and lookup_other2. +// Make sure we correctly handle visiting the same module twice. +infix operator <> : DeclaredInModuleD // Also declared in lookup_other. To preserve compatibility, we allow an // unambiguous lookup that will favor this declaration over lookup_other. @@ -109,9 +106,9 @@ func testOperatorLookup() { >>>1 // We've been evil and overriden TernaryPrecedence in both modules A and B. - // FIXME: We shouldn't emit the 'broken stdlib' error. + // Make sure we emit an ambiguity error without emitting a 'broken stdlib' + // error. true ? () : () // expected-error {{multiple precedence groups found}} - // expected-error@-1 {{broken standard library: missing builtin precedence group 'TernaryPrecedence'}} } precedencegroup CastingPrecedence { diff --git a/test/decl/operator/redeclaration.swift b/test/decl/operator/redeclaration.swift new file mode 100644 index 0000000000000..ce07817fe2eb4 --- /dev/null +++ b/test/decl/operator/redeclaration.swift @@ -0,0 +1,31 @@ +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/redeclaration_other.swift -enable-new-operator-lookup + +precedencegroup RedeclaredAcrossFiles {} // expected-error {{precedence group redeclared}} + +precedencegroup RedeclaredSameFile {} // expected-note {{previous precedence group declaration here}} +precedencegroup RedeclaredSameFile {} // expected-error {{precedence group redeclared}} + +precedencegroup RedeclaredSameFile2 { // expected-note {{previous precedence group declaration here}} + assignment: true +} +precedencegroup RedeclaredSameFile2 {} // expected-error {{precedence group redeclared}} + +// These are all declared in the other file. +infix operator ^^^ // expected-error {{operator redeclared}} +prefix operator >>> // expected-error {{operator redeclared}} +postfix operator <<< // expected-error {{operator redeclared}} +infix operator ^^^^ // expected-error {{operator redeclared}} + +// This is declared as an infix operator in the other file, so no problem. +prefix operator &&& +postfix operator &&& + +infix operator %%% // expected-note {{previous operator declaration here}} +infix operator %%% // expected-error {{operator redeclared}} + +prefix operator %%% // expected-note {{previous operator declaration here}} +prefix operator %%% // expected-error {{operator redeclared}} + +precedencegroup P2 {} +infix operator *** : P2 // expected-note {{previous operator declaration here}} +infix operator *** // expected-error {{operator redeclared}} diff --git a/test/multifile/require-layout-generic-arg-closure.swift b/test/multifile/require-layout-generic-arg-closure.swift index c579c448f726e..255a0e51e950f 100644 --- a/test/multifile/require-layout-generic-arg-closure.swift +++ b/test/multifile/require-layout-generic-arg-closure.swift @@ -1,5 +1,8 @@ -// RUN: %target-swift-frontend -module-name test -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE1 %s -// RUN: %target-swift-frontend -module-name test -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE2 %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-objc %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-objc %s + +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-native %s +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-native %s // REQUIRES: CPU=x86_64 @@ -10,7 +13,8 @@ // FILE1: [[T1:%.*]] = bitcast %T4test3SubC* %0 to %swift.type** // FILE1: [[TYPEMETADATA:%.*]] = load %swift.type*, %swift.type** [[T1]] // FILE1: [[T2:%.*]] = bitcast %swift.type* [[TYPEMETADATA]] to %swift.type** -// FILE1: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-objc: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-native: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 13 // FILE1: [[T:%.*]] = load %swift.type*, %swift.type** [[T_PTR]] // FILE1: call swiftcc %swift.metadata_response @"$s4test3SubCMa"(i64 255, %swift.type* [[T]]) diff --git a/test/multifile/require-layout-generic-arg-subscript.swift b/test/multifile/require-layout-generic-arg-subscript.swift index e2fb435394d9e..25018d3524ec2 100644 --- a/test/multifile/require-layout-generic-arg-subscript.swift +++ b/test/multifile/require-layout-generic-arg-subscript.swift @@ -1,5 +1,8 @@ -// RUN: %target-swift-frontend -module-name test -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE1 %s -// RUN: %target-swift-frontend -module-name test -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE2 %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-objc %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-objc %s + +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-native %s +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-native %s // REQUIRES: CPU=x86_64 @@ -9,7 +12,8 @@ // FILE1: [[T1:%.*]] = bitcast %T4test3SubC* %0 to %swift.type** // FILE1: [[TYPEMETADATA:%.*]] = load %swift.type*, %swift.type** [[T1]] // FILE1: [[T2:%.*]] = bitcast %swift.type* [[TYPEMETADATA]] to %swift.type** -// FILE1: [[T_IN_CLASSMETADATA:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-objc: [[T_IN_CLASSMETADATA:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-native: [[T_IN_CLASSMETADATA:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 13 // FILE1: [[T:%.*]] = load %swift.type*, %swift.type** [[T_IN_CLASSMETADATA]] // FILE1: call %swift.type* @swift_getMetatypeMetadata(%swift.type* [[T]]) public class AccessorTest { diff --git a/test/multifile/require-layout-generic-arg.swift b/test/multifile/require-layout-generic-arg.swift index d35c9ea688ea6..9c610f5d9dc48 100644 --- a/test/multifile/require-layout-generic-arg.swift +++ b/test/multifile/require-layout-generic-arg.swift @@ -1,5 +1,8 @@ -// RUN: %target-swift-frontend -module-name test -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE1 %s -// RUN: %target-swift-frontend -module-name test -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefix=FILE2 %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-objc %s +// RUN: %target-swift-frontend -module-name test -enable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-objc %s + +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify -primary-file %s %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE1,FILE1-native %s +// RUN: %target-swift-frontend -module-name test -disable-objc-interop -emit-ir -verify %s -primary-file %S/Inputs/require-layout-generic-class.swift | %FileCheck --check-prefixes=FILE2,FILE2-native %s // REQUIRES: CPU=x86_64 @@ -9,7 +12,8 @@ // FILE1: [[T1:%.*]] = bitcast %T4test3SubC* %0 to %swift.type** // FILE1: [[TYPEMETADATA:%.*]] = load %swift.type*, %swift.type** [[T1]] // FILE1: [[T2:%.*]] = bitcast %swift.type* [[TYPEMETADATA]] to %swift.type** -// FILE1: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-objc: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 16 +// FILE1-native: [[T_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i64 13 // FILE1: [[T:%.*]] = load %swift.type*, %swift.type** [[T_PTR]] public func requestType(_ c: Sub) { print(T.self) diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp index 84ecd79fb78ef..66d1112058750 100644 --- a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp +++ b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp @@ -126,7 +126,9 @@ SDKNodeTypeAlias::SDKNodeTypeAlias(SDKNodeInitInfo Info): SDKNodeDeclType::SDKNodeDeclType(SDKNodeInitInfo Info): SDKNodeDecl(Info, SDKNodeKind::DeclType), SuperclassUsr(Info.SuperclassUsr), SuperclassNames(Info.SuperclassNames), - EnumRawTypeName(Info.EnumRawTypeName), IsExternal(Info.IsExternal), + EnumRawTypeName(Info.EnumRawTypeName), + IsExternal(Info.IsExternal), + IsEnumExhaustive(Info.IsEnumExhaustive), HasMissingDesignatedInitializers(Info.HasMissingDesignatedInitializers), InheritsConvenienceInitializers(Info.InheritsConvenienceInitializers) {} @@ -1426,6 +1428,7 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD) // Get enum raw type name if this is an enum. if (auto *ED = dyn_cast(VD)) { + IsEnumExhaustive = ED->isFormallyExhaustive(nullptr); if (auto RT = ED->getRawType()) { if (auto *D = RT->getNominalOrBoundGenericNominal()) { EnumRawTypeName = D->getName().str(); @@ -1981,6 +1984,7 @@ void SDKNodeDeclType::jsonize(json::Output &out) { output(out, KeyKind::KK_superclassUsr, SuperclassUsr); output(out, KeyKind::KK_enumRawTypeName, EnumRawTypeName); output(out, KeyKind::KK_isExternal, IsExternal); + output(out, KeyKind::KK_isEnumExhaustive, IsEnumExhaustive); output(out, KeyKind::KK_hasMissingDesignatedInitializers, HasMissingDesignatedInitializers); output(out, KeyKind::KK_inheritsConvenienceInitializers, diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.h b/tools/swift-api-digester/ModuleAnalyzerNodes.h index db19837d46ebc..b1426059dce51 100644 --- a/tools/swift-api-digester/ModuleAnalyzerNodes.h +++ b/tools/swift-api-digester/ModuleAnalyzerNodes.h @@ -524,6 +524,7 @@ class SDKNodeDeclType: public SDKNodeDecl { // Check whether the type declaration is pulled from an external module so we // can incorporate extensions in the interested module. bool IsExternal; + bool IsEnumExhaustive; bool HasMissingDesignatedInitializers; bool InheritsConvenienceInitializers; public: @@ -550,6 +551,11 @@ class SDKNodeDeclType: public SDKNodeDecl { return EnumRawTypeName; } + bool isEnumExhaustive() const { + assert(isEnum()); + return IsEnumExhaustive; + } + bool hasMissingDesignatedInitializers() const { return HasMissingDesignatedInitializers; }; diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp index 72b216defaa15..b8ab15e72a9d2 100644 --- a/tools/swift-api-digester/swift-api-digester.cpp +++ b/tools/swift-api-digester/swift-api-digester.cpp @@ -1216,7 +1216,9 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { if (!Ctx.checkingABI()) { if (auto *Var = dyn_cast(Right)) { if (Var->getDeclKind() == DeclKind::EnumElement) { - Var->emitDiag(Var->getLoc(), diag::enum_case_added); + if (Var->getParent()->getAs()->isEnumExhaustive()) { + Var->emitDiag(Var->getLoc(), diag::enum_case_added); + } } } }