Merge pull request #7768 from kconner/fix-omitted-word-in-ownership-manifesto
Fix an omitted word in the Ownership Manifesto
diff --git a/.pep8 b/.pep8
index 8d2e668..8d7296d 100644
--- a/.pep8
+++ b/.pep8
@@ -1,2 +1,2 @@
[flake8]
-filename = *.py,80+-check,backtrace-check,Benchmark_Driver,Benchmark_DTrace.in,Benchmark_GuardMalloc.in,Benchmark_RuntimeLeaksRunner.in,build-script,check-incremental,clang++,coverage-build-db,coverage-generate-data,coverage-query-db,coverage-touch-tests,gyb,ld,line-directive,mock-distcc,ns-html2rst,PathSanitizingFileCheck,recursive-lipo,rth,run-test,scale-test,submit-benchmark-results,update-checkout,viewcfg,symbolicate-linux-fatal
+filename = *.py,80+-check,backtrace-check,Benchmark_Driver,Benchmark_DTrace.in,Benchmark_GuardMalloc.in,Benchmark_RuntimeLeaksRunner.in,build-script,check-incremental,clang++,coverage-build-db,coverage-generate-data,coverage-query-db,coverage-touch-tests,gyb,ld,line-directive,mock-distcc,ns-html2rst,PathSanitizingFileCheck,python-lint,recursive-lipo,round-trip-syntax-test,rth,run-test,scale-test,submit-benchmark-results,update-checkout,viewcfg,symbolicate-linux-fatal
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 196afd7..f91a13f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
| Contents |
| :--------------------- |
+| [Swift 4.0](#swift-40) |
| [Swift 3.1](#swift-31) |
| [Swift 3.0](#swift-30) |
| [Swift 2.2](#swift-22) |
@@ -17,6 +18,28 @@
</details>
+Swift 4.0
+---------
+
+* [SE-0148][]:
+
+ Subscript declarations can now be defined to have generic parameter lists.
+ Example:
+
+ ```
+ extension JSON {
+ subscript<T>(key: String) -> T?
+ where T : JSONConvertible {
+ // ...
+ }
+ }
+ ```
+
+* [SE-0110][]:
+
+ In Swift 4 mode, Swift's type system properly distinguishes between functions that
+ take one tuple argument, and functions that take multiple arguments.
+
* More types of C macros which define integer constants are supported by the
importer. Specifically the `+, -, *, /, ^, >>, ==, <, <=, >, >=` operators
are now recognized, and the previously-supported `<<, &&, ||, &, |`
@@ -6408,3 +6431,11 @@
[SE-0145]: <https://github.com/apple/swift-evolution/blob/master/proposals/0145-package-manager-version-pinning.md>
[SE-0146]: <https://github.com/apple/swift-evolution/blob/master/proposals/0146-package-manager-product-definitions.md>
[SE-0147]: <https://github.com/apple/swift-evolution/blob/master/proposals/0147-move-unsafe-initialize-from.md>
+[SE-0148]: <https://github.com/apple/swift-evolution/blob/master/proposals/0148-generic-subscripts.md>
+[SE-0149]: <https://github.com/apple/swift-evolution/blob/master/proposals/0149-package-manager-top-of-tree.md>
+[SE-0150]: <https://github.com/apple/swift-evolution/blob/master/proposals/0150-package-manager-branch-support.md>
+[SE-0151]: <https://github.com/apple/swift-evolution/blob/master/proposals/0151-package-manager-swift-language-compatibility-version.md>
+[SE-0152]: <https://github.com/apple/swift-evolution/blob/master/proposals/0152-package-manager-tools-version.md>
+[SE-0153]: <https://github.com/apple/swift-evolution/blob/master/proposals/0153-compensate-for-the-inconsistency-of-nscopyings-behaviour.md>
+[SE-0154]: <https://github.com/apple/swift-evolution/blob/master/proposals/0154-dictionary-key-and-value-collections.md>
+[SE-0155]: <https://github.com/apple/swift-evolution/blob/master/proposals/0155-normalize-enum-case-representation.md>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b47c464..cacf882 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -270,6 +270,10 @@
"Build the standard libraries and overlays with resilience enabled; see docs/LibraryEvolution.rst"
FALSE)
+option(SWIFT_STDLIB_USE_NONATOMIC_RC
+ "Build the standard libraries and overlays with nonatomic reference count operations enabled"
+ FALSE)
+
option(SWIFT_STDLIB_ENABLE_SIL_OWNERSHIP
"Build the standard libraries and overlays with sil ownership enabled."
FALSE)
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 82b7755..6d87720 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -48,6 +48,7 @@
single-source/GlobalClass
single-source/Hanoi
single-source/Hash
+ single-source/HashQuadratic
single-source/Histogram
single-source/Integrate
single-source/IterateData
diff --git a/benchmark/scripts/generate_harness/CMakeLists.txt_template b/benchmark/scripts/generate_harness/CMakeLists.txt_template
index 79eba3b..d4f0abb 100644
--- a/benchmark/scripts/generate_harness/CMakeLists.txt_template
+++ b/benchmark/scripts/generate_harness/CMakeLists.txt_template
@@ -67,9 +67,18 @@
set(SWIFT_LIBRARY_PATH "${tmp_dir}/lib/swift")
endif()
-runcmd(COMMAND "xcrun" "-toolchain" "${SWIFT_DARWIN_XCRUN_TOOLCHAIN}" "-f" "clang"
- VARIABLE CLANG_EXEC
- ERROR "Unable to find Clang driver")
+# If the CMAKE_C_COMPILER is already clang, don't find it again,
+# thus allowing the --host-cc build-script argument to work here.
+get_filename_component(c_compiler ${CMAKE_C_COMPILER} NAME)
+
+if(${c_compiler} STREQUAL "clang")
+ set(CLANG_EXEC ${CMAKE_C_COMPILER})
+else()
+ runcmd(COMMAND "xcrun" "-toolchain" "${SWIFT_DARWIN_XCRUN_TOOLCHAIN}" "-f" "clang"
+ VARIABLE CLANG_EXEC
+ ERROR "Unable to find Clang driver")
+endif()
+
# You have to delete CMakeCache.txt in the swift build to force a
# reconfiguration.
diff --git a/benchmark/single-source/HashQuadratic.swift b/benchmark/single-source/HashQuadratic.swift
new file mode 100644
index 0000000..0895aad
--- /dev/null
+++ b/benchmark/single-source/HashQuadratic.swift
@@ -0,0 +1,33 @@
+//===--- HashQuadratic.swift ----------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import TestsUtils
+
+let size = 3_000_000
+
+@inline(never)
+public func run_HashQuadratic(_ N: Int) {
+ for _ in 1...N {
+ var dict1: [Int: Int] = [:]
+ for i in 0..<size {
+ dict1[i] = i * 2
+ }
+
+ var dict2: [Int: Int] = [:]
+ for (k, v) in dict1 {
+ dict2[k] = v
+ }
+
+ CheckResults(dict1[size/2] == dict2[size/2],
+ "Incorrect results in HashQuadratic")
+ }
+}
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index a716acd..d21cb0c 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -53,6 +53,7 @@
import GlobalClass
import Hanoi
import Hash
+import HashQuadratic
import Histogram
import Integrate
import IterateData
@@ -113,21 +114,19 @@
"Array2D": run_Array2D,
"ArrayAppend": run_ArrayAppend,
"ArrayAppendArrayOfInt": run_ArrayAppendArrayOfInt,
+ "ArrayAppendAscii": run_ArrayAppendAscii,
"ArrayAppendFromGeneric": run_ArrayAppendFromGeneric,
"ArrayAppendGenericStructs": run_ArrayAppendGenericStructs,
+ "ArrayAppendLatin1": run_ArrayAppendLatin1,
"ArrayAppendLazyMap": run_ArrayAppendLazyMap,
"ArrayAppendOptionals": run_ArrayAppendOptionals,
"ArrayAppendRepeatCol": run_ArrayAppendRepeatCol,
"ArrayAppendReserved": run_ArrayAppendReserved,
"ArrayAppendSequence": run_ArrayAppendSequence,
"ArrayAppendStrings": run_ArrayAppendStrings,
- "ArrayAppendASCII": run_ArrayAppendAscii,
- "ArrayAppendLatin1": run_ArrayAppendLatin1,
- "ArrayAppendUTF16": run_ArrayAppendUTF16,
"ArrayAppendToFromGeneric": run_ArrayAppendToFromGeneric,
"ArrayAppendToGeneric": run_ArrayAppendToGeneric,
- "ArrayPlusEqualSingleElementCollection": run_ArrayPlusEqualSingleElementCollection,
- "ArrayPlusEqualFiveElementCollection": run_ArrayPlusEqualFiveElementCollection,
+ "ArrayAppendUTF16": run_ArrayAppendUTF16,
"ArrayInClass": run_ArrayInClass,
"ArrayLiteral": run_ArrayLiteral,
"ArrayOfGenericPOD": run_ArrayOfGenericPOD,
@@ -135,6 +134,8 @@
"ArrayOfPOD": run_ArrayOfPOD,
"ArrayOfRef": run_ArrayOfRef,
"ArrayPlusEqualArrayOfInt": run_ArrayPlusEqualArrayOfInt,
+ "ArrayPlusEqualFiveElementCollection": run_ArrayPlusEqualFiveElementCollection,
+ "ArrayPlusEqualSingleElementCollection": run_ArrayPlusEqualSingleElementCollection,
"ArraySubscript": run_ArraySubscript,
"ArrayValueProp": run_ArrayValueProp,
"ArrayValueProp2": run_ArrayValueProp2,
@@ -164,6 +165,7 @@
"ErrorHandling": run_ErrorHandling,
"GlobalClass": run_GlobalClass,
"Hanoi": run_Hanoi,
+ "HashQuadratic": run_HashQuadratic,
"HashTest": run_HashTest,
"Histogram": run_Histogram,
"Integrate": run_Integrate,
@@ -172,15 +174,16 @@
"LinkedList": run_LinkedList,
"MapReduce": run_MapReduce,
"MapReduceAnyCollection": run_MapReduceAnyCollection,
- "MapReduceShort": run_MapReduceShort,
- "MapReduceSequence": run_MapReduceSequence,
- "MapReduceLazySequence": run_MapReduceLazySequence,
- "MapReduceLazyCollection": run_MapReduceLazyCollection,
- "MapReduceLazyCollectionShort": run_MapReduceLazyCollectionShort,
- "MapReduceString": run_MapReduceString,
- "MapReduceShortString": run_MapReduceShortString,
+ "MapReduceAnyCollectionShort": run_MapReduceAnyCollectionShort,
"MapReduceClass": run_MapReduceClass,
"MapReduceClassShort": run_MapReduceClassShort,
+ "MapReduceLazyCollection": run_MapReduceLazyCollection,
+ "MapReduceLazyCollectionShort": run_MapReduceLazyCollectionShort,
+ "MapReduceLazySequence": run_MapReduceLazySequence,
+ "MapReduceSequence": run_MapReduceSequence,
+ "MapReduceShort": run_MapReduceShort,
+ "MapReduceShortString": run_MapReduceShortString,
+ "MapReduceString": run_MapReduceString,
"Memset": run_Memset,
"MonteCarloE": run_MonteCarloE,
"MonteCarloPi": run_MonteCarloPi,
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 993c156..0acbd41 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -241,6 +241,8 @@
list(APPEND result "-D_CRT_USE_WINAPI_FAMILY_DESKTOP_APP")
# TODO(compnerd) handle /MT
list(APPEND result "-D_DLL")
+ # NOTE: We assume that we are using VS 2015 U2+
+ list(APPEND result "-D_ENABLE_ATOMIC_ALIGNMENT_FIX")
endif()
if(CFLAGS_ENABLE_ASSERTIONS)
diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake
index a4b4ff1..39b0d2b 100644
--- a/cmake/modules/SwiftConfigureSDK.cmake
+++ b/cmake/modules/SwiftConfigureSDK.cmake
@@ -22,6 +22,13 @@
message(STATUS " Triple name: ${SWIFT_SDK_${prefix}_TRIPLE_NAME}")
message(STATUS " Architectures: ${SWIFT_SDK_${prefix}_ARCHITECTURES}")
message(STATUS " Object Format: ${SWIFT_SDK_${prefix}_OBJECT_FORMAT}")
+ foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
+ if(${SWIFT_SDK_${prefix}_ARCH_${arch}_LINKER})
+ message(STATUS " Linker (${arch}): ${SWIFT_SDK_${prefix}_ARCH_${arch}_LINKER}")
+ else()
+ message(STATUS " Linker (${arch}): ${CMAKE_LINKER}")
+ endif()
+ endforeach()
foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
message(STATUS
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index a9bb87e..bb20246 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -239,6 +239,10 @@
list(APPEND swift_flags "-Xfrontend" "-enable-resilience")
endif()
+ if(SWIFT_STDLIB_USE_NONATOMIC_RC)
+ list(APPEND swift_flags "-Xfrontend" "-assume-single-threaded")
+ endif()
+
if(SWIFT_STDLIB_ENABLE_SIL_OWNERSHIP AND SWIFTFILE_IS_STDLIB)
list(APPEND swift_flags "-Xfrontend" "-enable-sil-ownership")
endif()
diff --git a/docs/HighLevelSILOptimizations.rst b/docs/HighLevelSILOptimizations.rst
index 7cb9e45..3178b4c 100644
--- a/docs/HighLevelSILOptimizations.rst
+++ b/docs/HighLevelSILOptimizations.rst
@@ -349,6 +349,11 @@
@_semantics("optimize.sil.never")
func miscompile() { ... }
+sil.specialize.generic.never
+
+ The sil optimizer should never create generic specializations of this function.
+
+
Availability checks
~~~~~~~~~~~~~~~~~~~
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 0ee207f..6e45602 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -3743,6 +3743,7 @@
* `init_existential_opaque`_
* `open_existential_opaque`_
+ * `deinit_existential_opaque`_
- **Class existential containers**: If a protocol type is constrained by one or
more class protocols, then the existential container for that type is
@@ -3847,6 +3848,22 @@
``init_existential_addr`` but haven't had their contained value initialized.
A fully initialized existential must be destroyed with ``destroy_addr``.
+deinit_existential_opaque
+`````````````````````````
+::
+
+ sil-instruction ::= 'deinit_existential_opaque' sil-operand
+
+ deinit_existential_opaque %0 : $P
+ // %0 must be of a $P opaque type for non-class protocol or protocol
+ // composition type P
+
+Undoes the partial initialization performed by
+``init_existential_opaque``. ``deinit_existential_opaque`` is only valid for
+existential containers that have been partially initialized by
+``init_existential_opaque`` but haven't had their contained value initialized.
+A fully initialized existential must be destroyed with ``destroy_value``.
+
open_existential_addr
`````````````````````
::
diff --git a/docs/Testing.rst b/docs/Testing.rst
index ffc1183..b7fd2a5 100644
--- a/docs/Testing.rst
+++ b/docs/Testing.rst
@@ -431,7 +431,7 @@
* ``swift_ast_verifier``: present if the AST verifier is enabled in this build.
* When writing a test specific to x86, if possible, prefer ``REQUIRES:
- CPU=i386 || CPU=x86_64`` over ``REQUIRES: CPU=x86_64``.
+ CPU=i386_or_x86_64`` to ``REQUIRES: CPU=x86_64``.
* ``swift_test_mode_optimize[_unchecked|none]`` and
``swift_test_mode_optimize[_unchecked|none]_<CPUNAME>``: specify a test mode
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 1fddf63..fc285c4 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -24,9 +24,11 @@
#include "swift/AST/DefaultArgumentKind.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/GenericParamKey.h"
+#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/TypeAlignments.h"
+#include "swift/AST/TypeWalker.h"
#include "swift/AST/Witness.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/OptionalEnum.h"
@@ -238,11 +240,15 @@
/// \brief Whether this declaration is currently being validated.
unsigned BeingValidated : 1;
+ /// \brief Whether we have started validating the declaration; this *isn't*
+ /// reset after finishing it.
+ unsigned ValidationStarted : 1;
+
/// \brief Whether this declaration was added to the surrounding
/// DeclContext of an active #if config clause.
unsigned EscapedFromIfConfig : 1;
};
- enum { NumDeclBits = 12 };
+ enum { NumDeclBits = 13 };
static_assert(NumDeclBits <= 32, "fits in an unsigned");
class PatternBindingDeclBitfields {
@@ -423,13 +429,8 @@
class TypeAliasDeclBitfields {
friend class TypeAliasDecl;
unsigned : NumGenericTypeDeclBits;
-
- /// Whether we have completed validation of the typealias.
- /// This is necessary because unlike other declarations, a
- /// typealias will not get an interface type right away.
- unsigned HasCompletedValidation : 1;
};
- enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits + 1 };
+ enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits };
static_assert(NumTypeAliasDeclBits <= 32, "fits in an unsigned");
class NominalTypeDeclBitFields {
@@ -577,9 +578,6 @@
/// FIXME: Is this too fine-grained?
unsigned CheckedInheritanceClause : 1;
- /// Whether this extension has already been validated.
- unsigned Validated : 1;
-
/// An encoding of the default and maximum access level for this extension.
///
/// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
@@ -590,7 +588,7 @@
/// Whether there is are lazily-loaded conformances for this extension.
unsigned HasLazyConformances : 1;
};
- enum { NumExtensionDeclBits = NumDeclBits + 6 };
+ enum { NumExtensionDeclBits = NumDeclBits + 5 };
static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned");
class IfConfigDeclBitfields {
@@ -659,6 +657,7 @@
DeclBits.FromClang = false;
DeclBits.EarlyAttrValidation = false;
DeclBits.BeingValidated = false;
+ DeclBits.ValidationStarted = false;
DeclBits.EscapedFromIfConfig = false;
}
@@ -815,8 +814,19 @@
void setIsBeingValidated(bool ibv = true) {
assert(DeclBits.BeingValidated != ibv);
DeclBits.BeingValidated = ibv;
+ if (ibv) {
+ DeclBits.ValidationStarted = true;
+ }
}
+ bool hasValidationStarted() const { return DeclBits.ValidationStarted; }
+
+ /// Manually indicate that validation has started for the declaration.
+ ///
+ /// This is implied by setIsBeingValidated(true) (i.e. starting validation)
+ /// and so rarely needs to be called directly.
+ void setValidationStarted() { DeclBits.ValidationStarted = true; }
+
bool escapedFromIfConfig() const {
return DeclBits.EscapedFromIfConfig;
}
@@ -1644,19 +1654,9 @@
void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }
- /// Whether we started validating this extension.
- bool validated() const {
- return ExtensionDeclBits.Validated;
- }
-
- /// Set whether we have validated this extension.
- void setValidated(bool validated = true) {
- ExtensionDeclBits.Validated = validated;
- }
-
/// Whether we have fully checked the extension.
bool hasValidSignature() const {
- return validated() && !isBeingValidated();
+ return hasValidationStarted() && !isBeingValidated();
}
/// Whether we already type-checked the inheritance clause.
@@ -2017,28 +2017,6 @@
}
};
-/// This represents one part of a #if block. If the condition field is
-/// non-null, then this represents a #if or a #elseif, otherwise it represents
-/// an #else block.
-struct IfConfigDeclClause {
- /// The location of the #if, #elseif, or #else keyword.
- SourceLoc Loc;
-
- /// The condition guarding this #if or #elseif block. If this is null, this
- /// is a #else clause.
- Expr *Cond;
-
- ArrayRef<Decl*> Members;
-
- /// True if this is the active clause of the #if block.
- bool isActive;
-
- IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef<Decl*> Members,
- bool isActive)
- : Loc(Loc), Cond(Cond), Members(Members), isActive(isActive) {}
-};
-
-
/// IfConfigDecl - This class represents the declaration-side representation of
/// #if/#else/#endif blocks. Active and inactive block members are stored
/// separately, with the intention being that active members will be handed
@@ -2046,21 +2024,21 @@
class IfConfigDecl : public Decl {
/// An array of clauses controlling each of the #if/#elseif/#else conditions.
/// The array is ASTContext allocated.
- ArrayRef<IfConfigDeclClause> Clauses;
+ ArrayRef<IfConfigClause<Decl *>> Clauses;
SourceLoc EndLoc;
public:
- IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigDeclClause> Clauses,
+ IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause<Decl *>> Clauses,
SourceLoc EndLoc, bool HadMissingEnd)
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
{
IfConfigDeclBits.HadMissingEnd = HadMissingEnd;
}
- ArrayRef<IfConfigDeclClause> getClauses() const { return Clauses; }
+ ArrayRef<IfConfigClause<Decl *>> getClauses() const { return Clauses; }
/// Return the active clause, or null if there is no active one.
- const IfConfigDeclClause *getActiveClause() const {
+ const IfConfigClause<Decl *> *getActiveClause() const {
for (auto &Clause : Clauses)
if (Clause.isActive) return &Clause;
return nullptr;
@@ -2068,7 +2046,7 @@
const ArrayRef<Decl*> getActiveMembers() const {
if (auto *Clause = getActiveClause())
- return Clause->Members;
+ return Clause->Elements;
return {};
}
@@ -2442,14 +2420,6 @@
/// aliases.
void setUnderlyingType(Type type);
- bool hasCompletedValidation() const {
- return TypeAliasDeclBits.HasCompletedValidation;
- }
-
- void setHasCompletedValidation() {
- TypeAliasDeclBits.HasCompletedValidation = 1;
- }
-
/// For generic typealiases, return the unbound generic type.
UnboundGenericType *getUnboundGenericType() const;
@@ -2583,14 +2553,19 @@
/// The default definition.
TypeLoc DefaultDefinition;
+ /// The where clause attached to the associated type.
+ TrailingWhereClause *TrailingWhere;
+
LazyMemberLoader *Resolver = nullptr;
uint64_t ResolverContextData;
public:
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
- SourceLoc nameLoc, TypeLoc defaultDefinition);
+ SourceLoc nameLoc, TypeLoc defaultDefinition,
+ TrailingWhereClause *trailingWhere);
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
- SourceLoc nameLoc, LazyMemberLoader *definitionResolver,
+ SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
+ LazyMemberLoader *definitionResolver,
uint64_t resolverData);
/// Get the protocol in which this associated type is declared.
@@ -2608,6 +2583,14 @@
return const_cast<AssociatedTypeDecl *>(this)->getDefaultDefinitionLoc();
}
+ /// Retrieve the trailing where clause for this associated type, if any.
+ TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; }
+
+ /// Set the trailing where clause for this associated type.
+ void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
+ TrailingWhere = trailingWhereClause;
+ }
+
/// computeType - Compute the type (and declared type) of this associated
/// type; can only be called after the alias type has been resolved.
void computeType();
@@ -3413,6 +3396,19 @@
/// Retrieve the set of protocols inherited from this protocol.
llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
+ /// Walk all of the protocols inherited by this protocol, transitively,
+ /// invoking the callback function for each protocol.
+ ///
+ /// \param fn The callback function that will be invoked for each inherited
+ /// protocol. It can return \c Continue to continue the traversal,
+ /// \c SkipChildren to avoid visiting the children of the given protocol
+ /// but continue the search, and \c Stop to halt the search.
+ ///
+ /// \returns \c true if \c fn returned \c Stop for any protocol, \c false
+ /// otherwise.
+ bool walkInheritedProtocols(
+ llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const;
+
/// \brief Determine whether this protocol inherits from the given ("super")
/// protocol.
bool inheritsFrom(const ProtocolDecl *Super) const;
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index a1dd113..c5e2979 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -208,6 +208,9 @@
ERROR(enum_case_dot_prefix,none,
"extraneous '.' in enum 'case' declaration", ())
+ERROR(associatedtype_where_swift_3,none,
+ "where clauses on associated types are fragile; use '-swift-version 4' to experiment.", ())
+
// Variable getters/setters
ERROR(static_var_decl_global_scope,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 377c8b6..42e442f 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -164,6 +164,9 @@
ERROR(cannot_match_expr_pattern_with_value,none,
"expression pattern of type %0 cannot match values of type %1",
(Type, Type))
+ERROR(cannot_match_unresolved_expr_pattern_with_value,none,
+ "pattern cannot match values of type %0",
+ (Type))
ERROR(cannot_reference_compare_types,none,
"cannot check reference equality of functions; operands here have types "
@@ -1562,9 +1565,6 @@
ERROR(requires_generic_param_made_equal_to_concrete,none,
"same-type requirement makes generic parameter %0 non-generic",
(Type))
-ERROR(requires_superclass_conflict,none,
- "%select{generic parameter |protocol |}0%1 cannot be a subclass of both "
- "%2 and %3", (unsigned, Type, Type, Type))
ERROR(recursive_type_reference,none,
"%0 %1 references itself", (DescriptiveDeclKind, Identifier))
ERROR(recursive_requirement_reference,none,
@@ -1586,9 +1586,17 @@
(Identifier, Type, Type))
WARNING(redundant_same_type_to_concrete,none,
"redundant same-type constraint %0 == %1", (Type, Type))
-NOTE(redundancy_here,none,
+NOTE(same_type_redundancy_here,none,
"same-type constraint %1 == %2 %select{written here|implied here}0",
(bool, Type, Type))
+ERROR(requires_superclass_conflict,none,
+ "%select{generic parameter |protocol |}0%1 cannot be a subclass of both "
+ "%2 and %3", (unsigned, Type, Type, Type))
+WARNING(redundant_superclass_constraint,none,
+ "redundant superclass constraint %0 : %1", (Type, Type))
+NOTE(superclass_redundancy_here,none,
+ "superclass constraint %1 : %2 %select{written here|implied here}0",
+ (bool, Type, Type))
ERROR(mutiple_layout_constraints,none,
"multiple layout constraints cannot be used at the same time: %0 and %1",
diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h
index 8c7721d..a859f92 100644
--- a/include/swift/AST/GenericSignature.h
+++ b/include/swift/AST/GenericSignature.h
@@ -114,8 +114,9 @@
/// \param substitutions The generic parameter -> generic argument
/// substitutions that will have been applied to these types.
/// These are used to produce the "parameter = argument" bindings in the test.
- std::string gatherGenericParamBindingsText(
- ArrayRef<Type> types, const TypeSubstitutionMap &substitutions) const;
+ std::string
+ gatherGenericParamBindingsText(ArrayRef<Type> types,
+ TypeSubstitutionFn substitutions) const;
/// Retrieve the requirements.
ArrayRef<Requirement> getRequirements() const {
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index d6aef4f..ed575c4 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -21,6 +21,7 @@
#define SWIFT_GENERICSIGNATUREBUILDER_H
#include "swift/AST/Decl.h"
+#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeLoc.h"
@@ -31,6 +32,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/TrailingObjects.h"
#include <functional>
#include <memory>
@@ -50,17 +52,428 @@
class RequirementRepr;
class SILModule;
class SourceLoc;
+class SubstitutionMap;
class Type;
class TypeRepr;
class ASTContext;
class DiagnosticEngine;
+/// \brief Collects a set of requirements of generic parameters, both explicitly
+/// stated and inferred, and determines the set of archetypes for each of
+/// the generic parameters.
+class GenericSignatureBuilder {
+public:
+ /// Describes a potential archetype, which stands in for a generic parameter
+ /// type or some type derived from it.
+ class PotentialArchetype;
+
+ using UnresolvedType = llvm::PointerUnion<PotentialArchetype *, Type>;
+ struct ResolvedType;
+
+ using RequirementRHS =
+ llvm::PointerUnion3<Type, PotentialArchetype *, LayoutConstraint>;
+
+ class RequirementSource;
+
+ class FloatingRequirementSource;
+
+ /// Describes a constraint that is bounded on one side by a concrete type.
+ struct ConcreteConstraint {
+ PotentialArchetype *archetype;
+ Type concreteType;
+ const RequirementSource *source;
+ };
+
+ /// Describes an equivalence class of potential archetypes.
+ struct EquivalenceClass {
+ /// Concrete type to which this equivalence class is equal.
+ ///
+ /// This is the semantic concrete type; the constraints as written
+ /// (or implied) are stored in \c concreteTypeConstraints;
+ Type concreteType;
+
+ /// The same-type-to-concrete constraints written within this
+ /// equivalence class.
+ std::vector<ConcreteConstraint> concreteTypeConstraints;
+
+ /// Superclass constraint, which requires that the type fulfilling the
+ /// requirements of this equivalence class to be the same as or a subtype
+ /// of this superclass.
+ Type superclass;
+
+ /// Superclass constraints written within this equivalence class.
+ std::vector<ConcreteConstraint> superclassConstraints;
+
+ /// The members of the equivalence class.
+ TinyPtrVector<PotentialArchetype *> members;
+
+ /// Construct a new equivalence class containing only the given
+ /// potential archetype (which represents itself).
+ EquivalenceClass(PotentialArchetype *representative);
+
+ /// Find a source of the same-type constraint that maps a potential
+ /// archetype in this equivalence class to a concrete type along with
+ /// that concrete type as written.
+ Optional<ConcreteConstraint>
+ findAnyConcreteConstraintAsWritten(
+ PotentialArchetype *preferredPA = nullptr) const;
+
+ /// Find a source of the superclass constraint in this equivalence class
+ /// that has a type equivalence to \c superclass, along with that
+ /// superclass type as written.
+ Optional<ConcreteConstraint>
+ findAnySuperclassConstraintAsWritten(
+ PotentialArchetype *preferredPA = nullptr) const;
+};
+
+ friend class RequirementSource;
+
+private:
+ class InferRequirementsWalker;
+ friend class InferRequirementsWalker;
+ friend class GenericSignature;
+
+ ASTContext &Context;
+ DiagnosticEngine &Diags;
+ struct Implementation;
+ std::unique_ptr<Implementation> Impl;
+
+ GenericSignatureBuilder(const GenericSignatureBuilder &) = delete;
+ GenericSignatureBuilder &operator=(const GenericSignatureBuilder &) = delete;
+
+ /// Update an existing constraint source reference when another constraint
+ /// source was found to produce the same constraint. Only the better
+ /// constraint source will be kept.
+ ///
+ /// \returns true if the new constraint source was better, false otherwise.
+ bool updateRequirementSource(const RequirementSource *&existingSource,
+ const RequirementSource *newSource);
+
+ /// Retrieve the constraint source conformance for the superclass constraint
+ /// of the given potential archetype (if present) to the given protocol.
+ ///
+ /// \param pa The potential archetype whose superclass constraint is being
+ /// queried.
+ ///
+ /// \param proto The protocol to which we are establishing conformance.
+ ///
+ /// \param protoSource The requirement source for the conformance to the
+ /// given protocol.
+ const RequirementSource *resolveSuperConformance(
+ GenericSignatureBuilder::PotentialArchetype *pa,
+ ProtocolDecl *proto,
+ const RequirementSource *&protoSource);
+
+ /// \brief Add a new conformance requirement specifying that the given
+ /// potential archetype conforms to the given protocol.
+ bool addConformanceRequirement(PotentialArchetype *T,
+ ProtocolDecl *Proto,
+ const RequirementSource *Source);
+
+ bool addConformanceRequirement(PotentialArchetype *T,
+ ProtocolDecl *Proto,
+ const RequirementSource *Source,
+ llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);
+
+public:
+ /// \brief Add a new same-type requirement between two fully resolved types
+ /// (output of \c GenericSignatureBuilder::resolve).
+ ///
+ /// If the types refer to two concrete types that are fundamentally
+ /// incompatible (e.g. \c Foo<Bar<T>> and \c Foo<Baz>), \c diagnoseMismatch is
+ /// called with the two types that don't match (\c Bar<T> and \c Baz for the
+ /// previous example).
+ bool
+ addSameTypeRequirement(ResolvedType paOrT1, ResolvedType paOrT2,
+ FloatingRequirementSource Source,
+ llvm::function_ref<void(Type, Type)> diagnoseMismatch);
+
+ /// \brief Add a new same-type requirement between two fully resolved types
+ /// (output of GenericSignatureBuilder::resolve).
+ ///
+ /// The two types must not be incompatible concrete types.
+ bool addSameTypeRequirement(ResolvedType paOrT1, ResolvedType paOrT2,
+ FloatingRequirementSource Source);
+
+ /// \brief Add a new same-type requirement between two unresolved types.
+ ///
+ /// The types are resolved with \c GenericSignatureBuilder::resolve, and must
+ /// not be incompatible concrete types.
+ bool addSameTypeRequirement(UnresolvedType paOrT1, UnresolvedType paOrT2,
+ FloatingRequirementSource Source);
+
+ /// \brief Add a new same-type requirement between two unresolved types.
+ ///
+ /// The types are resolved with \c GenericSignatureBuilder::resolve. \c
+ /// diagnoseMismatch is called if the two types refer to incompatible concrete
+ /// types.
+ bool
+ addSameTypeRequirement(UnresolvedType paOrT1, UnresolvedType paOrT2,
+ FloatingRequirementSource Source,
+ llvm::function_ref<void(Type, Type)> diagnoseMismatch);
+
+ /// Update the superclass for the equivalence class of \c T.
+ ///
+ /// This assumes that the constraint has already been recorded
+ bool updateSuperclass(PotentialArchetype *T,
+ Type superclass,
+ const RequirementSource *source);
+
+private:
+ /// \brief Add a new superclass requirement specifying that the given
+ /// potential archetype has the given type as an ancestor.
+ bool addSuperclassRequirement(PotentialArchetype *T,
+ Type Superclass,
+ const RequirementSource *Source);
+
+ /// \brief Add a new conformance requirement specifying that the given
+ /// potential archetypes are equivalent.
+ bool addSameTypeRequirementBetweenArchetypes(PotentialArchetype *T1,
+ PotentialArchetype *T2,
+ const RequirementSource *Source);
+
+ /// \brief Add a new conformance requirement specifying that the given
+ /// potential archetype is bound to a concrete type.
+ bool addSameTypeRequirementToConcrete(PotentialArchetype *T,
+ Type Concrete,
+ const RequirementSource *Source);
+
+ /// \brief Add a new same-type requirement specifying that the given two
+ /// types should be the same.
+ ///
+ /// \param diagnoseMismatch Callback invoked when the types in the same-type
+ /// requirement mismatch.
+ bool addSameTypeRequirementBetweenConcrete(
+ Type T1, Type T2, FloatingRequirementSource Source,
+ llvm::function_ref<void(Type, Type)> diagnoseMismatch);
+
+ /// Add the requirements placed on the given type parameter
+ /// to the given potential archetype.
+ bool addInheritedRequirements(TypeDecl *decl, PotentialArchetype *pa,
+ const RequirementSource *parentSource,
+ llvm::SmallPtrSetImpl<ProtocolDecl *> &visited);
+
+ /// Visit all of the potential archetypes.
+ template<typename F>
+ void visitPotentialArchetypes(F f);
+
+ void markPotentialArchetypeRecursive(PotentialArchetype *pa,
+ ProtocolDecl *proto,
+ const RequirementSource *source);
+
+public:
+ /// Construct a new generic signature builder.
+ ///
+ /// \param lookupConformance Conformance-lookup routine that will be used
+ /// to satisfy conformance requirements for concrete types.
+ explicit GenericSignatureBuilder(ASTContext &ctx,
+ std::function<GenericFunction> lookupConformance);
+
+ GenericSignatureBuilder(GenericSignatureBuilder &&);
+ ~GenericSignatureBuilder();
+
+ /// Retrieve the AST context.
+ ASTContext &getASTContext() const { return Context; }
+
+ /// Retrieve the conformance-lookup function used by this generic signature builder.
+ std::function<GenericFunction> getLookupConformanceFn() const;
+
+ /// Retrieve the lazy resolver, if there is one.
+ LazyResolver *getLazyResolver() const;
+
+ /// Enumerate the requirements that describe the signature of this
+ /// generic signature builder.
+ ///
+ /// \param f A function object that will be passed each requirement
+ /// and requirement source.
+ void enumerateRequirements(llvm::function_ref<
+ void (RequirementKind kind,
+ PotentialArchetype *archetype,
+ RequirementRHS constraint,
+ const RequirementSource *source)> f);
+
+public:
+ /// \brief Add a new generic parameter for which there may be requirements.
+ void addGenericParameter(GenericTypeParamDecl *GenericParam);
+
+ /// Add the requirements placed on the given abstract type parameter
+ /// to the given potential archetype.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool addGenericParameterRequirements(GenericTypeParamDecl *GenericParam);
+
+ /// \brief Add a new generic parameter for which there may be requirements.
+ void addGenericParameter(GenericTypeParamType *GenericParam);
+
+ /// \brief Add a new requirement.
+ ///
+ /// \returns true if this requirement makes the set of requirements
+ /// inconsistent, in which case a diagnostic will have been issued.
+ bool addRequirement(const RequirementRepr *Req,
+ const RequirementSource *source = nullptr,
+ const SubstitutionMap *subMap = nullptr);
+
+ /// \brief Add an already-checked requirement.
+ ///
+ /// Adding an already-checked requirement cannot fail. This is used to
+ /// re-inject requirements from outer contexts.
+ ///
+ /// \returns true if this requirement makes the set of requirements
+ /// inconsistent, in which case a diagnostic will have been issued.
+ bool addRequirement(const Requirement &req, FloatingRequirementSource source);
+
+ bool addRequirement(const Requirement &req, FloatingRequirementSource source,
+ llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);
+
+ /// \brief Add a new requirement.
+ ///
+ /// \returns true if this requirement makes the set of requirements
+ /// inconsistent, in which case a diagnostic will have been issued.
+
+ bool addLayoutRequirement(PotentialArchetype *PAT,
+ LayoutConstraint Layout,
+ const RequirementSource *Source);
+
+ /// \brief Add all of a generic signature's parameters and requirements.
+ void addGenericSignature(GenericSignature *sig);
+
+ /// \brief Build the generic signature.
+ GenericSignature *getGenericSignature();
+
+ /// Infer requirements from the given type, recursively.
+ ///
+ /// This routine infers requirements from a type that occurs within the
+ /// signature of a generic function. For example, given:
+ ///
+ /// \code
+ /// func f<K, V>(dict : Dictionary<K, V>) { ... }
+ /// \endcode
+ ///
+ /// where \c Dictionary requires that its key type be \c Hashable,
+ /// the requirement \c K : Hashable is inferred from the parameter type,
+ /// because the type \c Dictionary<K,V> cannot be formed without it.
+ void inferRequirements(TypeLoc type);
+
+ /// Infer requirements from the given pattern, recursively.
+ ///
+ /// This routine infers requirements from a type that occurs within the
+ /// signature of a generic function. For example, given:
+ ///
+ /// \code
+ /// func f<K, V>(dict : Dictionary<K, V>) { ... }
+ /// \endcode
+ ///
+ /// where \c Dictionary requires that its key type be \c Hashable,
+ /// the requirement \c K : Hashable is inferred from the parameter type,
+ /// because the type \c Dictionary<K,V> cannot be formed without it.
+ void inferRequirements(ParameterList *params,GenericParamList *genericParams);
+
+ /// Finalize the set of requirements, performing any remaining checking
+ /// required before generating archetypes.
+ ///
+ /// \param allowConcreteGenericParams If true, allow generic parameters to
+ /// be made concrete.
+ void finalize(SourceLoc loc,
+ ArrayRef<GenericTypeParamType *> genericParams,
+ bool allowConcreteGenericParams=false);
+
+ /// Diagnose any remaining renames.
+ ///
+ /// \returns \c true if there were any remaining renames to diagnose.
+ bool diagnoseRemainingRenames(SourceLoc loc,
+ ArrayRef<GenericTypeParamType *> genericParams);
+
+private:
+ /// Describes the relationship between a given constraint and
+ /// the canonical constraint of the equivalence class.
+ enum class ConstraintRelation {
+ /// The constraint is unrelated.
+ ///
+ /// This is a conservative result that can be used when, for example,
+ /// we have incomplete information to make a determination.
+ Unrelated,
+ /// The constraint is redundant and can be removed without affecting the
+ /// semantics.
+ Redundant,
+ /// The constraint conflicts, meaning that the signature is erroneous.
+ Conflicting,
+ };
+
+ /// Check a list of concrete constraints, removing self-derived constraints
+ /// and diagnosing redundant constraints.
+ ///
+ /// \param isSuitableRepresentative Determines whether the given constraint
+ /// is a suitable representative.
+ ///
+ /// \param checkConstraint Checks the given constraint against the
+ /// canonical constraint to determine which diagnostics (if any) should be
+ /// emitted.
+ ///
+ /// \returns the representative constraint.
+ ConcreteConstraint checkConstraintList(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ std::vector<ConcreteConstraint> &constraints,
+ llvm::function_ref<bool(const ConcreteConstraint &)>
+ isSuitableRepresentative,
+ llvm::function_ref<ConstraintRelation(Type)>
+ checkConstraint,
+ Optional<Diag<unsigned, Type, Type, Type>>
+ conflictingDiag,
+ Diag<Type, Type> redundancyDiag,
+ Diag<bool, Type, Type> otherNoteDiag);
+
+ /// Check for redundant concrete type constraints within the equivalence
+ /// class of the given potential archetype.
+ void checkRedundantConcreteTypeConstraints(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ PotentialArchetype *pa);
+
+ /// Check for redundant superclass constraints within the equivalence
+ /// class of the given potential archetype.
+ void checkRedundantSuperclassConstraints(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ PotentialArchetype *pa);
+
+public:
+ /// \brief Resolve the given type to the potential archetype it names.
+ ///
+ /// This routine will synthesize nested types as required to refer to a
+ /// potential archetype, even in cases where no requirement specifies the
+ /// requirement for such an archetype. FIXME: The failure to include such a
+ /// requirement will be diagnosed at some point later (when the types in the
+ /// signature are fully resolved).
+ ///
+ /// For any type that cannot refer to an archetype, this routine returns null.
+ PotentialArchetype *resolveArchetype(Type type);
+
+ /// \brief Resolve the given type as far as this Builder knows how.
+ ///
+ /// This returns either a non-typealias potential archetype or a Type, if \c
+ /// type is concrete.
+ // FIXME: the hackTypeFromGenericTypeAlias is just temporarily patching over
+ // problems with generic typealiases (see the comment on the ResolvedType
+ // function)
+ ResolvedType resolve(UnresolvedType type,
+ bool hackTypeFromGenericTypeAlias = false);
+
+ /// \brief Dump all of the requirements, both specified and inferred.
+ LLVM_ATTRIBUTE_DEPRECATED(
+ void dump(),
+ "only for use within the debugger");
+
+ /// Dump all of the requirements to the given output stream.
+ void dump(llvm::raw_ostream &out);
+};
+
/// Describes how a generic signature determines a requirement, from its origin
/// in some requirement written in the source, inferred through a path of
/// other implications (e.g., introduced by a particular protocol).
///
/// Requirement sources are uniqued within a generic signature builder.
-class RequirementSource : public llvm::FoldingSetNode {
+class GenericSignatureBuilder::RequirementSource final
+ : public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<RequirementSource, PotentialArchetype *> {
+
public:
enum Kind : uint8_t {
/// A requirement stated explicitly, e.g., in a where clause or type
@@ -126,11 +539,12 @@
private:
/// The kind of storage we have.
enum class StorageKind : uint8_t {
- None,
+ RootArchetype,
TypeRepr,
RequirementRepr,
ProtocolDecl,
ProtocolConformance,
+ AssociatedTypeDecl,
};
/// The kind of storage we have.
@@ -138,6 +552,9 @@
/// The actual storage, described by \c storageKind.
union {
+ /// The root archetype.
+ PotentialArchetype *rootArchetype;
+
/// The type representation describing where the requirement came from.
const TypeRepr *typeRepr;
@@ -149,8 +566,32 @@
/// A protocol conformance used to satisfy the requirement.
ProtocolConformance *conformance;
+
+ /// An associated type to which a requirement is being applied.
+ AssociatedTypeDecl *assocType;
} storage;
+ friend TrailingObjects;
+
+ /// The trailing potential archetype, for
+ size_t numTrailingObjects(OverloadToken<PotentialArchetype *>) const {
+ switch (kind) {
+ case RequirementSignatureSelf:
+ return 1;
+
+ case Explicit:
+ case Inferred:
+ return storageKind == StorageKind::RootArchetype ? 0 : 1;
+
+ case NestedTypeNameMatch:
+ case ProtocolRequirement:
+ case Superclass:
+ case Parent:
+ case Concrete:
+ return 0;
+ }
+ }
+
/// Determines whether we have been provided with an acceptable storage kind
/// for the given requirement source kind.
static bool isAcceptableStorageKind(Kind kind, StorageKind storageKind);
@@ -158,6 +599,10 @@
/// Retrieve the opaque storage as a single pointer, for use in uniquing.
const void *getOpaqueStorage() const;
+ /// Retrieve the extra opaque storage as a single pointer, for use in
+ /// uniquing.
+ const void *getExtraOpaqueStorage() const;
+
/// Whether this kind of requirement source is a root.
static bool isRootKind(Kind kind) {
switch (kind) {
@@ -182,15 +627,15 @@
/// requirement source with one of the "root" kinds.
const RequirementSource * const parent;
- RequirementSource(Kind kind, const RequirementSource *parent)
- : kind(kind), storageKind(StorageKind::None), parent(parent) {
+ RequirementSource(Kind kind, const RequirementSource *parent,
+ PotentialArchetype *rootArchetype)
+ : kind(kind), storageKind(StorageKind::RootArchetype), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
"RequirementSource kind/storageKind mismatch");
- // Prevent uninitialized memory.
- storage.typeRepr = nullptr;
+ storage.rootArchetype = rootArchetype;
}
RequirementSource(Kind kind, const RequirementSource *parent,
@@ -216,7 +661,7 @@
}
RequirementSource(Kind kind, const RequirementSource *parent,
- ProtocolDecl *protocol)
+ ProtocolDecl *protocol)
: kind(kind), storageKind(StorageKind::ProtocolDecl), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
@@ -227,7 +672,7 @@
}
RequirementSource(Kind kind, const RequirementSource *parent,
- ProtocolConformance *conformance)
+ ProtocolConformance *conformance)
: kind(kind), storageKind(StorageKind::ProtocolConformance),
parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
@@ -238,35 +683,48 @@
storage.conformance = conformance;
}
+ RequirementSource(Kind kind, const RequirementSource *parent,
+ AssociatedTypeDecl *assocType)
+ : kind(kind), storageKind(StorageKind::AssociatedTypeDecl),
+ parent(parent) {
+ assert((static_cast<bool>(parent) != isRootKind(kind)) &&
+ "Root RequirementSource should not have parent (or vice versa)");
+ assert(isAcceptableStorageKind(kind, storageKind) &&
+ "RequirementSource kind/storageKind mismatch");
+
+ storage.assocType = assocType;
+ }
+
public:
/// Retrieve an abstract requirement source.
- static const RequirementSource *forAbstract(GenericSignatureBuilder &builder);
+ static const RequirementSource *forAbstract(PotentialArchetype *root);
/// Retrieve a requirement source representing an explicit requirement
/// stated in an 'inheritance' clause.
- static const RequirementSource *forExplicit(GenericSignatureBuilder &builder,
+ static const RequirementSource *forExplicit(PotentialArchetype *root,
const TypeRepr *typeRepr);
/// Retrieve a requirement source representing an explicit requirement
/// stated in an 'where' clause.
- static const RequirementSource *forExplicit(GenericSignatureBuilder &builder,
+ static const RequirementSource *forExplicit(
+ PotentialArchetype *root,
const RequirementRepr *requirementRepr);
/// Retrieve a requirement source representing a requirement that is
/// inferred from some part of a generic declaration's signature, e.g., the
/// parameter or result type of a generic function.
- static const RequirementSource *forInferred(GenericSignatureBuilder &builder,
+ static const RequirementSource *forInferred(PotentialArchetype *root,
const TypeRepr *typeRepr);
/// Retrieve a requirement source representing the requirement signature
/// computation for a protocol.
static const RequirementSource *forRequirementSignature(
- GenericSignatureBuilder &builder,
- ProtocolDecl *protocol);
+ PotentialArchetype *root,
+ ProtocolDecl *protocol);
- /// Retrieve an requirement source for nested type name matches.
+ /// Retrieve a requirement source for nested type name matches.
static const RequirementSource *forNestedTypeNameMatch(
- GenericSignatureBuilder &builder);
+ PotentialArchetype *root);
/// A requirement source that describes that a requirement comes from a
/// requirement of the given protocol described by the parent.
@@ -287,7 +745,13 @@
/// A constraint source that describes that a constraint that is resolved
/// for a nested type via a constraint on its parent.
- const RequirementSource *viaParent(GenericSignatureBuilder &builder) const;
+ ///
+ /// \param assocType the associated type that
+ const RequirementSource *viaParent(GenericSignatureBuilder &builder,
+ AssociatedTypeDecl *assocType) const;
+
+ /// Retrieve the potential archetype at the root.
+ PotentialArchetype *getRootPotentialArchetype() const;
/// Whether the requirement can be derived from something in its path.
///
@@ -301,6 +765,13 @@
/// to a protocol.
bool isDerivedViaConcreteConformance() const;
+ /// Determine whether the given derived requirement \c source, when rooted at
+ /// the potential archetype \c pa, is actually derived from the same
+ /// requirement. Such "self-derived" requirements do not make the original
+ /// requirement redundant, because without said original requirement, the
+ /// derived requirement ceases to hold.
+ bool isSelfDerivedSource(PotentialArchetype *pa) const;
+
/// Retrieve a source location that corresponds to the requirement.
SourceLoc getLoc() const;
@@ -333,17 +804,26 @@
return storage.conformance;
}
+ /// Retrieve the associated type declaration for this requirement, if there
+ /// is one.
+ AssociatedTypeDecl *getAssociatedType() const {
+ if (storageKind != StorageKind::AssociatedTypeDecl) return nullptr;
+ return storage.assocType;
+ }
+
/// Profiling support for \c FoldingSet.
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, kind, parent, getOpaqueStorage());
+ Profile(ID, kind, parent, getOpaqueStorage(), getExtraOpaqueStorage());
}
/// Profiling support for \c FoldingSet.
static void Profile(llvm::FoldingSetNodeID &ID, Kind kind,
- const RequirementSource *parent, const void *storage) {
+ const RequirementSource *parent, const void *storage,
+ const void *extraStorage) {
ID.AddInteger(kind);
ID.AddPointer(parent);
ID.AddPointer(storage);
+ ID.AddPointer(extraStorage);
}
LLVM_ATTRIBUTE_DEPRECATED(
@@ -362,313 +842,56 @@
void print(llvm::raw_ostream &out, SourceManager *SrcMgr) const;
};
-/// \brief Collects a set of requirements of generic parameters, both explicitly
-/// stated and inferred, and determines the set of archetypes for each of
-/// the generic parameters.
-class GenericSignatureBuilder {
-public:
- /// Describes a potential archetype, which stands in for a generic parameter
- /// type or some type derived from it.
- class PotentialArchetype;
+/// A requirement source that potentially lacks a root \c PotentialArchetype.
+/// The root will be supplied as soon as the appropriate dependent type is
+/// resolved.
+class GenericSignatureBuilder::FloatingRequirementSource {
+ enum Kind {
+ /// A fully-resolved requirement source, which does not need a root.
+ Resolved,
+ /// An explicit requirement source lacking a root.
+ Explicit,
+ /// An inferred requirement source lacking a root.
+ Inferred
+ } kind;
- using UnresolvedType = llvm::PointerUnion<PotentialArchetype *, Type>;
- struct ResolvedType;
+ using Storage =
+ llvm::PointerUnion3<const RequirementSource *, const TypeRepr *,
+ const RequirementRepr *>;
- using RequirementRHS =
- llvm::PointerUnion3<Type, PotentialArchetype *, LayoutConstraint>;
+ Storage storage;
- /// Describes an equivalence class of potential archetypes.
- struct EquivalenceClass {
- /// Concrete type to which this equivalence class is equal.
- Type concreteType;
-
- /// The members of the equivalence class.
- TinyPtrVector<PotentialArchetype *> members;
-
- /// Construct a new equivalence class containing only the given
- /// potential archetype (which represents itself).
- EquivalenceClass(PotentialArchetype *representative);
- };
-
- friend class RequirementSource;
-
-private:
- class InferRequirementsWalker;
- friend class InferRequirementsWalker;
- friend class GenericSignature;
-
- ASTContext &Context;
- DiagnosticEngine &Diags;
- struct Implementation;
- std::unique_ptr<Implementation> Impl;
-
- GenericSignatureBuilder(const GenericSignatureBuilder &) = delete;
- GenericSignatureBuilder &operator=(const GenericSignatureBuilder &) = delete;
-
- /// Update an existing constraint source reference when another constraint
- /// source was found to produce the same constraint. Only the better
- /// constraint source will be kept.
- ///
- /// \returns true if the new constraint source was better, false otherwise.
- bool updateRequirementSource(const RequirementSource *&existingSource,
- const RequirementSource *newSource);
-
- /// Retrieve the constraint source conformance for the superclass constraint
- /// of the given potential archetype (if present) to the given protocol.
- ///
- /// \param pa The potential archetype whose superclass constraint is being
- /// queried.
- ///
- /// \param proto The protocol to which we are establishing conformance.
- ///
- /// \param protoSource The requirement source for the conformance to the
- /// given protocol.
- const RequirementSource *resolveSuperConformance(
- GenericSignatureBuilder::PotentialArchetype *pa,
- ProtocolDecl *proto,
- const RequirementSource *&protoSource);
-
- /// \brief Add a new conformance requirement specifying that the given
- /// potential archetype conforms to the given protocol.
- bool addConformanceRequirement(PotentialArchetype *T,
- ProtocolDecl *Proto,
- const RequirementSource *Source);
-
- bool addConformanceRequirement(PotentialArchetype *T,
- ProtocolDecl *Proto,
- const RequirementSource *Source,
- llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);
+ FloatingRequirementSource(Kind kind, Storage storage)
+ : kind(kind), storage(storage) { }
public:
- /// \brief Add a new same-type requirement between two fully resolved types
- /// (output of \c GenericSignatureBuilder::resolve).
- ///
- /// If the types refer to two concrete types that are fundamentally
- /// incompatible (e.g. \c Foo<Bar<T>> and \c Foo<Baz>), \c diagnoseMismatch is
- /// called with the two types that don't match (\c Bar<T> and \c Baz for the
- /// previous example).
- bool
- addSameTypeRequirement(ResolvedType paOrT1, ResolvedType paOrT2,
- const RequirementSource *Source,
- llvm::function_ref<void(Type, Type)> diagnoseMismatch);
+ /// Implicit conversion from a resolved requirement source.
+ FloatingRequirementSource(const RequirementSource *source)
+ : FloatingRequirementSource(Resolved, source) { }
- /// \brief Add a new same-type requirement between two fully resolved types
- /// (output of GenericSignatureBuilder::resolve).
- ///
- /// The two types must not be incompatible concrete types.
- bool addSameTypeRequirement(ResolvedType paOrT1, ResolvedType paOrT2,
- const RequirementSource *Source);
+ static FloatingRequirementSource forAbstract() {
+ return { Explicit, Storage() };
+ }
- /// \brief Add a new same-type requirement between two unresolved types.
- ///
- /// The types are resolved with \c GenericSignatureBuilder::resolve, and must
- /// not be incompatible concrete types.
- bool addSameTypeRequirement(UnresolvedType paOrT1, UnresolvedType paOrT2,
- const RequirementSource *Source);
+ static FloatingRequirementSource forExplicit(const TypeRepr *typeRepr) {
+ return { Explicit, typeRepr };
+ }
- /// \brief Add a new same-type requirement between two unresolved types.
- ///
- /// The types are resolved with \c GenericSignatureBuilder::resolve. \c
- /// diagnoseMismatch is called if the two types refer to incompatible concrete
- /// types.
- bool
- addSameTypeRequirement(UnresolvedType paOrT1, UnresolvedType paOrT2,
- const RequirementSource *Source,
- llvm::function_ref<void(Type, Type)> diagnoseMismatch);
+ static FloatingRequirementSource forExplicit(
+ const RequirementRepr *requirementRepr) {
+ return { Explicit, requirementRepr };
+ }
-private:
- /// \brief Add a new superclass requirement specifying that the given
- /// potential archetype has the given type as an ancestor.
- bool addSuperclassRequirement(PotentialArchetype *T,
- Type Superclass,
- const RequirementSource *Source);
+ static FloatingRequirementSource forInferred(const TypeRepr *typeRepr) {
+ return { Inferred, typeRepr };
+ }
- /// \brief Add a new conformance requirement specifying that the given
- /// potential archetypes are equivalent.
- bool addSameTypeRequirementBetweenArchetypes(PotentialArchetype *T1,
- PotentialArchetype *T2,
- const RequirementSource *Source);
-
- /// \brief Add a new conformance requirement specifying that the given
- /// potential archetype is bound to a concrete type.
- bool addSameTypeRequirementToConcrete(PotentialArchetype *T,
- Type Concrete,
- const RequirementSource *Source);
+ /// Retrieve the complete requirement source rooted at the given potential
+ /// archetype.
+ const RequirementSource *getSource(PotentialArchetype *pa) const;
- /// \brief Add a new same-type requirement specifying that the given two
- /// types should be the same.
- ///
- /// \param diagnoseMismatch Callback invoked when the types in the same-type
- /// requirement mismatch.
- bool addSameTypeRequirementBetweenConcrete(
- Type T1, Type T2, const RequirementSource *Source,
- llvm::function_ref<void(Type, Type)> diagnoseMismatch);
-
- /// Add the requirements placed on the given type parameter
- /// to the given potential archetype.
- bool addInheritedRequirements(TypeDecl *decl, PotentialArchetype *pa,
- const RequirementSource *parentSource,
- llvm::SmallPtrSetImpl<ProtocolDecl *> &visited);
-
- /// Visit all of the potential archetypes.
- template<typename F>
- void visitPotentialArchetypes(F f);
-
- void markPotentialArchetypeRecursive(PotentialArchetype *pa,
- ProtocolDecl *proto,
- const RequirementSource *source);
-
-public:
- /// Construct a new generic signature builder.
- ///
- /// \param lookupConformance Conformance-lookup routine that will be used
- /// to satisfy conformance requirements for concrete types.
- explicit GenericSignatureBuilder(ASTContext &ctx,
- std::function<GenericFunction> lookupConformance);
-
- GenericSignatureBuilder(GenericSignatureBuilder &&);
- ~GenericSignatureBuilder();
-
- /// Retrieve the AST context.
- ASTContext &getASTContext() const { return Context; }
-
- /// Retrieve the conformance-lookup function used by this generic signature builder.
- std::function<GenericFunction> getLookupConformanceFn() const;
-
- /// Retrieve the lazy resolver, if there is one.
- LazyResolver *getLazyResolver() const;
-
- /// Enumerate the requirements that describe the signature of this
- /// generic signature builder.
- ///
- /// \param f A function object that will be passed each requirement
- /// and requirement source.
- void enumerateRequirements(llvm::function_ref<
- void (RequirementKind kind,
- PotentialArchetype *archetype,
- RequirementRHS constraint,
- const RequirementSource *source)> f);
-
-public:
- /// \brief Add a new generic parameter for which there may be requirements.
- void addGenericParameter(GenericTypeParamDecl *GenericParam);
-
- /// Add the requirements placed on the given abstract type parameter
- /// to the given potential archetype.
- ///
- /// \returns true if an error occurred, false otherwise.
- bool addGenericParameterRequirements(GenericTypeParamDecl *GenericParam);
-
- /// \brief Add a new generic parameter for which there may be requirements.
- void addGenericParameter(GenericTypeParamType *GenericParam);
-
- /// \brief Add a new requirement.
- ///
- /// \returns true if this requirement makes the set of requirements
- /// inconsistent, in which case a diagnostic will have been issued.
- bool addRequirement(const RequirementRepr *Req);
-
- /// \brief Add an already-checked requirement.
- ///
- /// Adding an already-checked requirement cannot fail. This is used to
- /// re-inject requirements from outer contexts.
- ///
- /// \returns true if this requirement makes the set of requirements
- /// inconsistent, in which case a diagnostic will have been issued.
- bool addRequirement(const Requirement &req, const RequirementSource *source);
-
- bool addRequirement(const Requirement &req, const RequirementSource *source,
- llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);
-
- bool addLayoutRequirement(PotentialArchetype *PAT,
- LayoutConstraint Layout,
- const RequirementSource *Source);
-
- /// \brief Add all of a generic signature's parameters and requirements.
- void addGenericSignature(GenericSignature *sig);
-
- /// \brief Build the generic signature.
- GenericSignature *getGenericSignature();
-
- /// Infer requirements from the given type, recursively.
- ///
- /// This routine infers requirements from a type that occurs within the
- /// signature of a generic function. For example, given:
- ///
- /// \code
- /// func f<K, V>(dict : Dictionary<K, V>) { ... }
- /// \endcode
- ///
- /// where \c Dictionary requires that its key type be \c Hashable,
- /// the requirement \c K : Hashable is inferred from the parameter type,
- /// because the type \c Dictionary<K,V> cannot be formed without it.
- void inferRequirements(TypeLoc type, unsigned minDepth, unsigned maxDepth);
-
- /// Infer requirements from the given pattern, recursively.
- ///
- /// This routine infers requirements from a type that occurs within the
- /// signature of a generic function. For example, given:
- ///
- /// \code
- /// func f<K, V>(dict : Dictionary<K, V>) { ... }
- /// \endcode
- ///
- /// where \c Dictionary requires that its key type be \c Hashable,
- /// the requirement \c K : Hashable is inferred from the parameter type,
- /// because the type \c Dictionary<K,V> cannot be formed without it.
- void inferRequirements(ParameterList *params,GenericParamList *genericParams);
-
- /// Finalize the set of requirements, performing any remaining checking
- /// required before generating archetypes.
- ///
- /// \param allowConcreteGenericParams If true, allow generic parameters to
- /// be made concrete.
- void finalize(SourceLoc loc,
- ArrayRef<GenericTypeParamType *> genericParams,
- bool allowConcreteGenericParams=false);
-
- /// Diagnose any remaining renames.
- ///
- /// \returns \c true if there were any remaining renames to diagnose.
- bool diagnoseRemainingRenames(SourceLoc loc,
- ArrayRef<GenericTypeParamType *> genericParams);
-
-private:
- /// Check for redundant concrete type constraints within the equivalence
- /// class of the given potential archetype.
- void checkRedundantConcreteTypeConstraints(
- ArrayRef<GenericTypeParamType *> genericParams,
- PotentialArchetype *pa);
-
-public:
- /// \brief Resolve the given type to the potential archetype it names.
- ///
- /// This routine will synthesize nested types as required to refer to a
- /// potential archetype, even in cases where no requirement specifies the
- /// requirement for such an archetype. FIXME: The failure to include such a
- /// requirement will be diagnosed at some point later (when the types in the
- /// signature are fully resolved).
- ///
- /// For any type that cannot refer to an archetype, this routine returns null.
- PotentialArchetype *resolveArchetype(Type type);
-
- /// \brief Resolve the given type as far as this Builder knows how.
- ///
- /// This returns either a non-typealias potential archetype or a Type, if \c
- /// type is concrete.
- // FIXME: the hackTypeFromGenericTypeAlias is just temporarily patching over
- // problems with generic typealiases (see the comment on the ResolvedType
- // function)
- ResolvedType resolve(UnresolvedType type,
- bool hackTypeFromGenericTypeAlias = false);
-
- /// \brief Dump all of the requirements, both specified and inferred.
- LLVM_ATTRIBUTE_DEPRECATED(
- void dump(),
- "only for use within the debugger");
-
- /// Dump all of the requirements to the given output stream.
- void dump(llvm::raw_ostream &out);
+ /// Retrieve the source location for this requirement.
+ SourceLoc getLoc() const;
};
class GenericSignatureBuilder::PotentialArchetype {
@@ -713,12 +936,6 @@
llvm::MapVector<PotentialArchetype *, const RequirementSource *>
SameTypeConstraints;
- /// \brief The superclass of this archetype, if specified.
- Type Superclass;
-
- /// The source of the superclass requirement.
- const RequirementSource *SuperclassSource = nullptr;
-
/// \brief The list of protocols to which this archetype will conform.
llvm::MapVector<ProtocolDecl *, const RequirementSource *> ConformsTo;
@@ -736,16 +953,6 @@
llvm::MapVector<Identifier, llvm::TinyPtrVector<PotentialArchetype *>>
NestedTypes;
- /// The concrete types to which this potential archetype has been
- /// constrained.
- ///
- /// This vector runs parallel to ConcreteTypeSources.
- llvm::TinyPtrVector<Type> concreteTypes;
-
- /// The source of the concrete type requirements that were written on
- /// this potential archetype.
- llvm::TinyPtrVector<const RequirementSource *> concreteTypeSources;
-
/// Whether this is an unresolved nested type.
unsigned isUnresolvedNestedType : 1;
@@ -910,12 +1117,12 @@
GenericSignatureBuilder &builder);
/// Retrieve the superclass of this archetype.
- Type getSuperclass() const { return Superclass; }
-
- /// Retrieve the requirement source for the superclass requirement.
- const RequirementSource *getSuperclassSource() const {
- return SuperclassSource;
- }
+ Type getSuperclass() const {
+ if (auto equiv = getEquivalenceClassIfPresent())
+ return equiv->superclass;
+
+ return nullptr;
+ }
/// Retrieve the layout constraint of this archetype.
LayoutConstraint getLayout() const { return Layout; }
@@ -973,22 +1180,6 @@
SameTypeConstraints.end());
}
- /// Retrieve the concrete types as written on this potential archetype.
- const llvm::TinyPtrVector<Type>& getConcreteTypesAsWritten() const {
- return concreteTypes;
- }
-
- /// Retrieve the concrete type sources as written on this potential archetype.
- ArrayRef<const RequirementSource *> getConcreteTypeSourcesAsWritten() const {
- return concreteTypeSources;
- }
-
- /// Find a source of the same-type constraint that maps this potential
- /// archetype to a concrete type somewhere in the equivalence class of this
- /// type along with the concrete type that was written there.
- Optional<std::pair<Type, const RequirementSource *>>
- findAnyConcreteTypeSourceAsWritten() const;
-
/// \brief Retrieve (or create) a nested type with the given name.
PotentialArchetype *getNestedType(Identifier Name,
GenericSignatureBuilder &builder);
diff --git a/include/swift/AST/IfConfigClause.h b/include/swift/AST/IfConfigClause.h
new file mode 100644
index 0000000..7c8c1cf
--- /dev/null
+++ b/include/swift/AST/IfConfigClause.h
@@ -0,0 +1,52 @@
+//===--- IfConfigClause.h ---------------------------------------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IfConfigClause.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_AST_IFCONFIGCLAUSE_H
+#define SWIFT_AST_IFCONFIGCLAUSE_H
+
+#include "llvm/ADT/ArrayRef.h"
+
+namespace swift {
+ class Expr;
+ class SourceLoc;
+
+/// This represents one part of a #if block. If the condition field is
+/// non-null, then this represents a #if or a #elseif, otherwise it represents
+/// an #else block.
+template <typename ElemTy>
+struct IfConfigClause {
+ /// The location of the #if, #elseif, or #else keyword.
+ SourceLoc Loc;
+
+ /// The condition guarding this #if or #elseif block. If this is null, this
+ /// is a #else clause.
+ Expr *Cond;
+
+ /// Elements inside the clause
+ ArrayRef<ElemTy> Elements;
+
+ /// True if this is the active clause of the #if block.
+ bool isActive;
+
+ IfConfigClause<ElemTy>(SourceLoc Loc, Expr *Cond,
+ ArrayRef<ElemTy> Elements, bool isActive)
+ : Loc(Loc), Cond(Cond), Elements(Elements), isActive(isActive) {
+ }
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h
index 3c561ce..5100365 100644
--- a/include/swift/AST/Pattern.h
+++ b/include/swift/AST/Pattern.h
@@ -492,7 +492,7 @@
SourceLoc DotLoc;
SourceLoc NameLoc;
Identifier Name;
- EnumElementDecl *ElementDecl;
+ PointerUnion<EnumElementDecl *, Expr*> ElementDeclOrUnresolvedOriginalExpr;
Pattern /*nullable*/ *SubPattern;
public:
@@ -501,10 +501,25 @@
Pattern *SubPattern, Optional<bool> Implicit = None)
: Pattern(PatternKind::EnumElement),
ParentType(ParentType), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
- ElementDecl(Element), SubPattern(SubPattern) {
+ ElementDeclOrUnresolvedOriginalExpr(Element),
+ SubPattern(SubPattern) {
if (Implicit.hasValue() && *Implicit)
setImplicit();
}
+
+ /// Create an unresolved EnumElementPattern for a `.foo` pattern relying on
+ /// contextual type.
+ EnumElementPattern(SourceLoc DotLoc,
+ SourceLoc NameLoc,
+ Identifier Name,
+ Pattern *SubPattern,
+ Expr *UnresolvedOriginalExpr)
+ : Pattern(PatternKind::EnumElement),
+ ParentType(), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
+ ElementDeclOrUnresolvedOriginalExpr(UnresolvedOriginalExpr),
+ SubPattern(SubPattern) {
+
+ }
bool hasSubPattern() const { return SubPattern; }
@@ -524,8 +539,19 @@
Identifier getName() const { return Name; }
- EnumElementDecl *getElementDecl() const { return ElementDecl; }
- void setElementDecl(EnumElementDecl *d) { ElementDecl = d; }
+ EnumElementDecl *getElementDecl() const {
+ return ElementDeclOrUnresolvedOriginalExpr.dyn_cast<EnumElementDecl*>();
+ }
+ void setElementDecl(EnumElementDecl *d) {
+ ElementDeclOrUnresolvedOriginalExpr = d;
+ }
+
+ Expr *getUnresolvedOriginalExpr() const {
+ return ElementDeclOrUnresolvedOriginalExpr.get<Expr*>();
+ }
+ bool hasUnresolvedOriginalExpr() const {
+ return ElementDeclOrUnresolvedOriginalExpr.is<Expr*>();
+ }
SourceLoc getNameLoc() const { return NameLoc; }
SourceLoc getLoc() const { return NameLoc; }
diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h
index 928da0f..9a6adf5 100644
--- a/include/swift/AST/Stmt.h
+++ b/include/swift/AST/Stmt.h
@@ -20,6 +20,7 @@
#include "swift/AST/Availability.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/ASTNode.h"
+#include "swift/AST/IfConfigClause.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/NullablePtr.h"
#include "llvm/Support/TrailingObjects.h"
@@ -653,41 +654,17 @@
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Guard; }
};
-
-/// This represents one part of a #if block. If the condition field is
-/// non-null, then this represents a #if or a #elseif, otherwise it represents
-/// an #else block.
-struct IfConfigStmtClause {
- /// The location of the #if, #elseif, or #else keyword.
- SourceLoc Loc;
-
- /// The condition guarding this #if or #elseif block. If this is null, this
- /// is a #else clause.
- Expr *Cond;
-
- /// Elements inside the clause
- ArrayRef<ASTNode> Elements;
-
- /// True if this is the active clause of the #if block.
- bool isActive;
-
- IfConfigStmtClause(SourceLoc Loc, Expr *Cond,
- ArrayRef<ASTNode> Elements, bool isActive)
- : Loc(Loc), Cond(Cond), Elements(Elements), isActive(isActive) {
- }
-};
-
/// IfConfigStmt - This class models the statement-side representation of
/// #if/#else/#endif blocks.
class IfConfigStmt : public Stmt {
/// An array of clauses controlling each of the #if/#elseif/#else conditions.
/// The array is ASTContext allocated.
- ArrayRef<IfConfigStmtClause> Clauses;
+ ArrayRef<IfConfigClause<ASTNode>> Clauses;
SourceLoc EndLoc;
bool HadMissingEnd;
public:
- IfConfigStmt(ArrayRef<IfConfigStmtClause> Clauses, SourceLoc EndLoc,
+ IfConfigStmt(ArrayRef<IfConfigClause<ASTNode>> Clauses, SourceLoc EndLoc,
bool HadMissingEnd)
: Stmt(StmtKind::IfConfig, /*implicit=*/false),
Clauses(Clauses), EndLoc(EndLoc), HadMissingEnd(HadMissingEnd) {}
@@ -699,7 +676,9 @@
bool hadMissingEnd() const { return HadMissingEnd; }
- const ArrayRef<IfConfigStmtClause> &getClauses() const { return Clauses; }
+ const ArrayRef<IfConfigClause<ASTNode>> &getClauses() const {
+ return Clauses;
+ }
ArrayRef<ASTNode> getActiveClauseElements() const {
for (auto &Clause : Clauses)
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index 26fdde0..5d3fb2a 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -361,7 +361,6 @@
OptionalTypeKind &kind);
static CanType getReferenceStorageReferentImpl(CanType type);
static CanType getLValueOrInOutObjectTypeImpl(CanType type);
- static ClassDecl *getClassBoundImpl(CanType type);
public:
explicit CanType(TypeBase *P = 0) : Type(P) {
@@ -438,15 +437,6 @@
/// it returns an empty LayoutConstraint.
LayoutConstraint getLayoutConstraint() const;
- /// \brief Retrieve the most-specific class bound of this type,
- /// which is either a class, a bound-generic class, or a class-bounded
- /// archetype.
- ///
- /// Returns nil if this is an archetype with a non-specific class bound.
- ClassDecl *getClassBound() const {
- return getClassBoundImpl(*this);
- }
-
CanType getAnyOptionalObjectType() const {
OptionalTypeKind kind;
return getAnyOptionalObjectTypeImpl(*this, kind);
diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h
index 5bdebfd..166bc0e 100644
--- a/include/swift/AST/TypeRepr.h
+++ b/include/swift/AST/TypeRepr.h
@@ -283,6 +283,9 @@
SimpleIdentTypeRepr(SourceLoc Loc, Identifier Id)
: ComponentIdentTypeRepr(TypeReprKind::SimpleIdent, Loc, Id) {}
+ SimpleIdentTypeRepr(const SimpleIdentTypeRepr &repr)
+ : SimpleIdentTypeRepr(repr.getLoc(), repr.getIdentifier()) {}
+
static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::SimpleIdent;
}
@@ -846,6 +849,9 @@
FixedTypeRepr(Type Ty, SourceLoc Loc)
: TypeRepr(TypeReprKind::Fixed), Ty(Ty), Loc(Loc) {}
+ FixedTypeRepr(const FixedTypeRepr& repr)
+ : FixedTypeRepr(repr.Ty, repr.Loc) {}
+
/// Retrieve the location.
SourceLoc getLoc() const { return Loc; }
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 77f492e..743761b 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -606,13 +606,6 @@
LazyResolver *resolver,
DeclContext *gpContext = nullptr);
- /// \brief Determine whether the given type is "generic", meaning that
- /// it involves generic types for which generic arguments have not been
- /// provided.
- /// For example, the type Vector and Vector<Int>.InnerGeneric are both
- /// unspecialized generic, but the type Vector<Int> is not.
- bool isUnspecializedGeneric();
-
/// \brief Determine whether this type is a legal, lowered SIL type.
///
/// A type is SIL-illegal if it is:
@@ -882,13 +875,15 @@
/// Get the substitutions to apply to the type of the given member as seen
/// from this base type.
///
- /// If the member has its own generic parameters, they will remain unchanged
- /// by the substitution.
+ /// \param genericEnv If non-null, generic parameters of the member are
+ /// mapped to context archetypes of this generic environment.
SubstitutionMap getMemberSubstitutionMap(ModuleDecl *module,
- const ValueDecl *member);
+ const ValueDecl *member,
+ GenericEnvironment *genericEnv=nullptr);
/// Deprecated version of the above.
- TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member);
+ TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member,
+ GenericEnvironment *genericEnv=nullptr);
/// Retrieve the type of the given member as seen through the given base
/// type, substituting generic arguments where necessary.
@@ -4471,6 +4466,8 @@
inline Type TypeBase::getNominalParent() {
if (auto classType = getAs<NominalType>()) {
return classType->getParent();
+ } else if (auto unboundType = getAs<UnboundGenericType>()) {
+ return unboundType->getParent();
} else {
return castTo<BoundGenericType>()->getParent();
}
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index cd5f872..82a1cee 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -29,6 +29,20 @@
#include <vector>
namespace swift {
+
+ /// Kind of implicit platform conditions.
+ enum class PlatformConditionKind {
+ /// The active os target (OSX, iOS, Linux, etc.)
+ OS,
+ /// The active arch target (x86_64, i386, arm, arm64, etc.)
+ Arch,
+ /// The active endianness target (big or little)
+ Endianness,
+ /// Runtime support (_ObjC or _Native)
+ Runtime,
+ };
+ enum { NumPlatformConditionKind = 4 };
+
/// \brief A collection of options that affect the language dialect and
/// provide compiler debugging facilities.
class LangOptions {
@@ -114,6 +128,10 @@
/// solver should be debugged.
unsigned DebugConstraintSolverAttempt = 0;
+ /// \brief Enable the experimental constraint propagation in the
+ /// type checker.
+ bool EnableConstraintPropagation = false;
+
/// \brief Enable the iterative type checker.
bool IterativeTypeChecker = false;
@@ -198,14 +216,9 @@
}
/// Sets an implicit platform condition.
- ///
- /// There are currently three supported platform conditions:
- /// - os: The active os target (OSX or iOS)
- /// - arch: The active arch target (x86_64, i386, arm, arm64)
- /// - _runtime: Runtime support (_ObjC or _Native)
- void addPlatformConditionValue(StringRef Name, StringRef Value) {
- assert(!Name.empty() && !Value.empty());
- PlatformConditionValues.emplace_back(Name, Value);
+ void addPlatformConditionValue(PlatformConditionKind Kind, StringRef Value) {
+ assert(!Value.empty());
+ PlatformConditionValues.emplace_back(Kind, Value);
}
/// Removes all values added with addPlatformConditionValue.
@@ -214,7 +227,7 @@
}
/// Returns the value for the given platform condition or an empty string.
- StringRef getPlatformConditionValue(StringRef Name) const;
+ StringRef getPlatformConditionValue(PlatformConditionKind Kind) const;
/// Explicit conditional compilation flags, initialized via the '-D'
/// compiler flag.
@@ -226,7 +239,7 @@
/// Determines if a given conditional compilation flag has been set.
bool isCustomConditionalCompilationFlagSet(StringRef Name) const;
- ArrayRef<std::pair<std::string, std::string>>
+ ArrayRef<std::pair<PlatformConditionKind, std::string>>
getPlatformConditionValues() const {
return PlatformConditionValues;
}
@@ -240,35 +253,18 @@
return EffectiveLanguageVersion.isVersion3();
}
- /// Returns true if the 'os' platform condition argument represents
+ /// Returns true if the given platform condition argument represents
/// a supported target operating system.
///
- /// Note that this also canonicalizes the OS name if the check returns
- /// true.
- ///
/// \param suggestions Populated with suggested replacements
/// if a match is not found.
- static bool checkPlatformConditionOS(
- StringRef &OSName, std::vector<StringRef> &suggestions);
-
- /// Returns true if the 'arch' platform condition argument represents
- /// a supported target architecture.
- ///
- /// \param suggestions Populated with suggested replacements
- /// if a match is not found.
- static bool isPlatformConditionArchSupported(
- StringRef ArchName, std::vector<StringRef> &suggestions);
-
- /// Returns true if the 'endian' platform condition argument represents
- /// a supported target endianness.
- ///
- /// \param suggestions Populated with suggested replacements
- /// if a match is not found.
- static bool isPlatformConditionEndiannessSupported(
- StringRef endianness, std::vector<StringRef> &suggestions);
+ static bool checkPlatformConditionSupported(
+ PlatformConditionKind Kind, StringRef Value,
+ std::vector<StringRef> &suggestions);
private:
- llvm::SmallVector<std::pair<std::string, std::string>, 3>
+ llvm::SmallVector<std::pair<PlatformConditionKind, std::string>,
+ NumPlatformConditionKind>
PlatformConditionValues;
llvm::SmallVector<std::string, 2> CustomConditionalCompilationFlags;
};
diff --git a/include/swift/Basic/OwnedString.h b/include/swift/Basic/OwnedString.h
index f4240b2..8745de6 100644
--- a/include/swift/Basic/OwnedString.h
+++ b/include/swift/Basic/OwnedString.h
@@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
diff --git a/include/swift/Basic/Timer.h b/include/swift/Basic/Timer.h
index 8558cd2..20f199c 100644
--- a/include/swift/Basic/Timer.h
+++ b/include/swift/Basic/Timer.h
@@ -33,8 +33,7 @@
public:
explicit SharedTimer(StringRef name) {
if (CompilationTimersEnabled == State::Enabled)
- Timer.emplace(name, StringRef("Swift compilation"), StringRef("swift"),
- StringRef("swift related timers"));
+ Timer.emplace(name, name, "swift", "Swift compilation");
else
CompilationTimersEnabled = State::Skipped;
}
diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h
index 242f075..c0881c9 100644
--- a/include/swift/ClangImporter/ClangImporter.h
+++ b/include/swift/ClangImporter/ClangImporter.h
@@ -260,8 +260,7 @@
/// The return value may be an empty identifier, in which case the enum would
/// not be imported.
///
- /// This is mostly an implementation detail of the importer, but is also
- /// used by the debugger.
+ /// This is not used by the importer itself, but is used by the debugger.
Identifier getEnumConstantName(const clang::EnumConstantDecl *enumConstant);
/// Writes the mangled name of \p clangDecl to \p os.
diff --git a/include/swift/ClangImporter/ClangModule.h b/include/swift/ClangImporter/ClangModule.h
index a3ed69b..11d3a38 100644
--- a/include/swift/ClangImporter/ClangModule.h
+++ b/include/swift/ClangImporter/ClangModule.h
@@ -17,6 +17,7 @@
#define SWIFT_CLANGIMPORTER_CLANGMODULE_H
#include "swift/AST/Module.h"
+#include "swift/ClangImporter/ClangImporter.h"
namespace clang {
class ASTContext;
@@ -26,12 +27,11 @@
namespace swift {
class ASTContext;
-class ClangImporter;
class ModuleLoader;
/// \brief Represents a Clang module that has been imported into Swift.
class ClangModuleUnit final : public LoadedFile {
- ClangImporter &owner;
+ ClangImporter::Implementation &owner;
const clang::Module *clangModule;
llvm::PointerIntPair<ModuleDecl *, 1, bool> adapterModule;
mutable ArrayRef<ModuleDecl::ImportedModule> importedModulesForLookup;
@@ -42,7 +42,7 @@
/// True if the given Module contains an imported Clang module unit.
static bool hasClangModule(ModuleDecl *M);
- ClangModuleUnit(ModuleDecl &M, ClangImporter &owner,
+ ClangModuleUnit(ModuleDecl &M, ClangImporter::Implementation &owner,
const clang::Module *clangModule);
/// \brief Retrieve the underlying Clang module.
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index c472f12..633e77f 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -307,7 +307,7 @@
unsigned commonPartsCount(DeclNameViewer &Other) const;
};
-/// This provide a utility for writing to a underlying string buffer multiple
+/// This provide a utility for writing to an underlying string buffer mulitiple
/// string pieces and retrieve them later when the underlying buffer is stable.
class DelayedStringRetriever : public raw_ostream {
SmallVectorImpl<char> &OS;
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index cd1111b..260b898 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -139,6 +139,9 @@
def debug_constraints_attempt : Separate<["-"], "debug-constraints-attempt">,
HelpText<"Debug the constraint solver at a given attempt">;
+def propagate_constraints : Flag<["-"], "propagate-constraints">,
+ HelpText<"Enable constraint propagation in the type checker">;
+
def iterative_type_checker : Flag<["-"], "iterative-type-checker">,
HelpText<"Enable the iterative type checker">;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 5496801..ea69199 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -750,6 +750,9 @@
DeclAttributes &Attributes);
ParserStatus parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
SourceLoc *classRequirementLoc);
+ ParserStatus parseDeclItem(bool &PreviousHadSemi,
+ Parser::ParseDeclOptions Options,
+ llvm::function_ref<void(Decl*)> handler);
bool parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
Diag<> ErrorDiag, ParseDeclOptions Options,
llvm::function_ref<void(Decl*)> handler);
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 8097ab5..a2fcbcd 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -869,6 +869,8 @@
return {true, metadataPointer};
}
}
+
+ swift_runtime_unreachable("Unhandled IsaEncodingKind in switch.");
}
/// Read the parent type metadata from a nested nominal type metadata.
diff --git a/include/swift/Runtime/HeapObject.h b/include/swift/Runtime/HeapObject.h
index e21d417..cfb6fba 100644
--- a/include/swift/Runtime/HeapObject.h
+++ b/include/swift/Runtime/HeapObject.h
@@ -510,6 +510,16 @@
void swift_unownedRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
+/// Increment the unowned retain count.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRetain(HeapObject *value)
+ SWIFT_CC(RegisterPreservingCC);
+
+/// Decrement the unowned retain count.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRelease(HeapObject *value)
+ SWIFT_CC(RegisterPreservingCC);
+
/// Increment the unowned retain count by n.
SWIFT_RT_ENTRY_VISIBILITY
void swift_unownedRetain_n(HeapObject *value, int n)
@@ -520,12 +530,28 @@
void swift_unownedRelease_n(HeapObject *value, int n)
SWIFT_CC(RegisterPreservingCC);
+/// Increment the unowned retain count by n.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRetain_n(HeapObject *value, int n)
+ SWIFT_CC(RegisterPreservingCC);
+
+/// Decrement the unowned retain count by n.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRelease_n(HeapObject *value, int n)
+ SWIFT_CC(RegisterPreservingCC);
+
/// Increment the strong retain count of an object, aborting if it has
/// been deallocated.
SWIFT_RT_ENTRY_VISIBILITY
void swift_unownedRetainStrong(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
+/// Increment the strong retain count of an object, aborting if it has
+/// been deallocated.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRetainStrong(HeapObject *value)
+ SWIFT_CC(RegisterPreservingCC);
+
/// Increment the strong retain count of an object which may have been
/// deallocated, aborting if it has been deallocated, and decrement its
/// unowned reference count.
@@ -533,6 +559,13 @@
void swift_unownedRetainStrongAndRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
+/// Increment the strong retain count of an object which may have been
+/// deallocated, aborting if it has been deallocated, and decrement its
+/// unowned reference count.
+SWIFT_RT_ENTRY_VISIBILITY
+void swift_nonatomic_unownedRetainStrongAndRelease(HeapObject *value)
+ SWIFT_CC(RegisterPreservingCC);
+
/// Aborts if the object has been deallocated.
SWIFT_RUNTIME_EXPORT
void swift_unownedCheck(HeapObject *value);
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 555a2b0..4a8ceb0 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -769,6 +769,8 @@
value_witness_types::storeExtraInhabitant *storeExtraInhabitant;
value_witness_types::getExtraInhabitantIndex *getExtraInhabitantIndex;
+#define SET_WITNESS(NAME) base.NAME,
+
constexpr ExtraInhabitantsValueWitnessTable()
: ValueWitnessTable{}, extraInhabitantFlags(),
storeExtraInhabitant(nullptr),
@@ -778,9 +780,15 @@
value_witness_types::extraInhabitantFlags eif,
value_witness_types::storeExtraInhabitant *sei,
value_witness_types::getExtraInhabitantIndex *geii)
- : ValueWitnessTable(base), extraInhabitantFlags(eif),
+ : ValueWitnessTable{
+ FOR_ALL_FUNCTION_VALUE_WITNESSES(SET_WITNESS)
+ base.size,
+ base.flags,
+ base.stride
+ }, extraInhabitantFlags(eif),
storeExtraInhabitant(sei),
getExtraInhabitantIndex(geii) {}
+#undef SET_WITNESS
static bool classof(const ValueWitnessTable *table) {
return table->flags.hasExtraInhabitants();
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 9c82868..2be2880 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -369,6 +369,20 @@
ARGS(RefCountedPtrTy),
ATTRS(NoUnwind))
+// void swift_nonatomic_unownedRetain(void *ptr);
+FUNCTION(NonAtomicNativeUnownedRetain, swift_nonatomic_unownedRetain,
+ RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy),
+ ATTRS(NoUnwind))
+
+// void swift_nonatomic_unownedRelease(void *ptr);
+FUNCTION(NonAtomicNativeUnownedRelease, swift_nonatomic_unownedRelease,
+ RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy),
+ ATTRS(NoUnwind))
+
// void swift_unownedRetain_n(void *ptr, int32_t n);
FUNCTION(UnownedRetainN, swift_unownedRetain_n,
RegisterPreservingCC,
@@ -383,12 +397,33 @@
ARGS(RefCountedPtrTy, Int32Ty),
ATTRS(NoUnwind))
+// void swift_nonatomic_unownedRetain_n(void *ptr, int32_t n);
+FUNCTION(NonAtomicUnownedRetainN, swift_nonatomic_unownedRetain_n,
+ RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy, Int32Ty),
+ ATTRS(NoUnwind))
+
+// void swift_nonatomic_unownedRelease_n(void *ptr, int32_t n);
+FUNCTION(NonAtomicUnownedReleaseN, swift_nonatomic_unownedRelease_n,
+ RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy, Int32Ty),
+ ATTRS(NoUnwind))
+
// void swift_unownedRetainStrong(void *ptr);
FUNCTION(NativeStrongRetainUnowned, swift_unownedRetainStrong, RegisterPreservingCC,
RETURNS(VoidTy),
ARGS(RefCountedPtrTy),
ATTRS(NoUnwind))
+// void swift_nonatomic_unownedRetainStrong(void *ptr);
+FUNCTION(NonAtomicNativeStrongRetainUnowned, swift_nonatomic_unownedRetainStrong,
+ RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy),
+ ATTRS(NoUnwind))
+
// void swift_unownedRetainStrongAndRelease(void *ptr);
FUNCTION(NativeStrongRetainAndUnownedRelease,
swift_unownedRetainStrongAndRelease, RegisterPreservingCC,
@@ -396,6 +431,13 @@
ARGS(RefCountedPtrTy),
ATTRS(NoUnwind))
+// void swift_nonatomic_unownedRetainStrongAndRelease(void *ptr);
+FUNCTION(NonAtomicNativeStrongRetainAndUnownedRelease,
+ swift_nonatomic_unownedRetainStrongAndRelease, RegisterPreservingCC,
+ RETURNS(VoidTy),
+ ARGS(RefCountedPtrTy),
+ ATTRS(NoUnwind))
+
// void swift_weakDestroy(WeakReference *object);
FUNCTION(NativeWeakDestroy, swift_weakDestroy, DefaultCC,
RETURNS(VoidTy),
diff --git a/include/swift/SIL/PatternMatch.h b/include/swift/SIL/PatternMatch.h
index 831abb1..b50ac0f 100644
--- a/include/swift/SIL/PatternMatch.h
+++ b/include/swift/SIL/PatternMatch.h
@@ -369,6 +369,7 @@
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialOpaqueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialRefInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(DeinitExistentialAddrInst)
+UNARY_OP_MATCH_WITH_ARG_MATCHER(DeinitExistentialOpaqueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(ProjectBlockStorageInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(StrongRetainInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(StrongReleaseInst)
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 79821fb..1088268 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -479,7 +479,8 @@
/// non-address values.
SILValue emitLoadValueOperation(SILLocation Loc, SILValue LV,
LoadOwnershipQualifier Qualifier) {
- assert(LV->getType().isLoadable(F.getModule()));
+ assert(!SILModuleConventions(F.getModule()).useLoweredAddresses()
+ || LV->getType().isLoadable(F.getModule()));
const auto &lowering = getTypeLowering(LV->getType());
return lowering.emitLoad(*this, Loc, LV, Qualifier);
}
@@ -819,17 +820,19 @@
}
UnmanagedRetainValueInst *createUnmanagedRetainValue(SILLocation Loc,
- SILValue operand) {
+ SILValue operand,
+ Atomicity atomicity) {
assert(F.hasQualifiedOwnership());
return insert(new (F.getModule()) UnmanagedRetainValueInst(
- getSILDebugLocation(Loc), operand));
+ getSILDebugLocation(Loc), operand, atomicity));
}
UnmanagedReleaseValueInst *createUnmanagedReleaseValue(SILLocation Loc,
- SILValue operand) {
+ SILValue operand,
+ Atomicity atomicity) {
assert(F.hasQualifiedOwnership());
return insert(new (F.getModule()) UnmanagedReleaseValueInst(
- getSILDebugLocation(Loc), operand));
+ getSILDebugLocation(Loc), operand, atomicity));
}
CopyValueInst *createCopyValue(SILLocation Loc, SILValue operand) {
@@ -856,9 +859,10 @@
}
UnmanagedAutoreleaseValueInst *
- createUnmanagedAutoreleaseValue(SILLocation Loc, SILValue operand) {
+ createUnmanagedAutoreleaseValue(SILLocation Loc, SILValue operand,
+ Atomicity atomicity) {
return insert(new (F.getModule()) UnmanagedAutoreleaseValueInst(
- getSILDebugLocation(Loc), operand));
+ getSILDebugLocation(Loc), operand, atomicity));
}
SetDeallocatingInst *createSetDeallocating(SILLocation Loc,
@@ -1175,6 +1179,12 @@
getSILDebugLocation(Loc), Existential));
}
+ DeinitExistentialOpaqueInst *
+ createDeinitExistentialOpaque(SILLocation Loc, SILValue Existential) {
+ return insert(new (F.getModule()) DeinitExistentialOpaqueInst(
+ getSILDebugLocation(Loc), Existential));
+ }
+
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
SILValue Storage) {
auto CaptureTy = Storage->getType()
@@ -1529,6 +1539,11 @@
// Memory management helpers
//===--------------------------------------------------------------------===//
+ /// Returns the default atomicity of the module.
+ Atomicity getDefaultAtomicity() {
+ return getModule().isDefaultAtomic() ? Atomicity::Atomic : Atomicity::NonAtomic;
+ }
+
/// Try to fold a destroy_addr operation into the previous instructions, or
/// generate an explicit one if that fails. If this inserts a new
/// instruction, it returns it, otherwise it returns null.
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 1308eba..9184783 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -143,28 +143,43 @@
SILType getTypeInClonedContext(SILType Ty) {
// Substitute opened existential types, if we have any.
- if (!OpenedExistentialSubs.empty()) {
- auto &F = getBuilder().getFunction();
- Ty = Ty.subst(F.getModule(),
- QueryTypeSubstitutionMap{OpenedExistentialSubs},
- MakeAbstractConformanceForGenericType());
- }
-
- return Ty;
+ return SILType::getPrimitiveObjectType(
+ getASTTypeInClonedContext(Ty.getSwiftRValueType()))
+ .copyCategory(Ty);
}
SILType getOpType(SILType Ty) {
Ty = getTypeInClonedContext(Ty);
return asImpl().remapType(Ty);
}
-
+
CanType getASTTypeInClonedContext(CanType ty) {
- // Substitute opened existential types, if we have any.
- if (!OpenedExistentialSubs.empty()) {
- ty = ty.subst(QueryTypeSubstitutionMap{OpenedExistentialSubs},
- MakeAbstractConformanceForGenericType())
- ->getCanonicalType();
- }
- return ty;
+ // Do not substitute opened existential types, if we do not have any.
+ if (!ty->hasOpenedExistential())
+ return ty;
+ // Do not substitute opened existential types, if it is not required.
+ // This is often the case when cloning basic blocks inside the same
+ // function.
+ if (OpenedExistentialSubs.empty())
+ return ty;
+
+ return ty.transform(
+ [&](Type t) -> Type {
+ if (t->isOpenedExistential()) {
+ auto found = OpenedExistentialSubs.find(
+ t->castTo<ArchetypeType>());
+ // If an opened existential is supposed to be
+ // remapped, it is guaranteed by construction
+ // to be in the OpenedExistentialSubs, because
+ // a cloner always processes definitions of
+ // opened existentials before their uses and
+ // adds found opened existentials definitions
+ // to the map.
+ if (found != OpenedExistentialSubs.end())
+ return found->second;
+ return t;
+ }
+ return t;
+ })->getCanonicalType();
}
CanType getOpASTType(CanType ty) {
ty = getASTTypeInClonedContext(ty);
@@ -1176,7 +1191,8 @@
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createUnmanagedRetainValue(
- getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
+ getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
+ Inst->getAtomicity()));
}
template <typename ImplClass>
@@ -1211,7 +1227,8 @@
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createUnmanagedReleaseValue(
- getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
+ getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
+ Inst->getAtomicity()));
}
template <typename ImplClass>
@@ -1238,7 +1255,8 @@
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createUnmanagedAutoreleaseValue(
- getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
+ getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
+ Inst->getAtomicity()));
}
template<typename ImplClass>
@@ -1645,6 +1663,15 @@
getOpValue(Inst->getOperand())));
}
+template <typename ImplClass>
+void SILCloner<ImplClass>::visitDeinitExistentialOpaqueInst(
+ DeinitExistentialOpaqueInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(
+ Inst, getBuilder().createDeinitExistentialOpaque(
+ getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
+}
+
template<typename ImplClass>
void
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {
diff --git a/include/swift/SIL/SILFunctionConventions.h b/include/swift/SIL/SILFunctionConventions.h
index 182db02..615fc12 100644
--- a/include/swift/SIL/SILFunctionConventions.h
+++ b/include/swift/SIL/SILFunctionConventions.h
@@ -148,6 +148,12 @@
/// Get the error result type.
SILType getSILErrorType() { return getSILType(funcTy->getErrorResult()); }
+ /// Returns an array of result info.
+ /// Provides convenient access to the underlying SILFunctionType.
+ ArrayRef<SILResultInfo> getResults() const {
+ return funcTy->getResults();
+ }
+
/// Get the number of SIL results passed as address-typed arguments.
unsigned getNumIndirectSILResults() const {
return silConv.loweredAddresses ? funcTy->getNumIndirectFormalResults() : 0;
@@ -243,7 +249,7 @@
/// SILFunctionType.
unsigned getNumParameters() const { return funcTy->getNumParameters(); }
- /// Returns an array if parameter info, not including indirect
+ /// Returns an array of parameter info, not including indirect
/// results. Provides convenient access to the underlying SILFunctionType.
ArrayRef<SILParameterInfo> getParameters() const {
return funcTy->getParameters();
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d8c47ec..77766a7 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -3021,8 +3021,11 @@
/*HasValue*/ false> {
friend SILBuilder;
- UnmanagedRetainValueInst(SILDebugLocation DebugLoc, SILValue operand)
- : UnaryInstructionBase(DebugLoc, operand) {}
+ UnmanagedRetainValueInst(SILDebugLocation DebugLoc, SILValue operand,
+ Atomicity atomicity)
+ : UnaryInstructionBase(DebugLoc, operand) {
+ setAtomicity(atomicity);
+ }
};
/// Destroys a loadable value in an unmanaged, unbalanced way. Only meant for
@@ -3034,8 +3037,11 @@
/*HasValue*/ false> {
friend SILBuilder;
- UnmanagedReleaseValueInst(SILDebugLocation DebugLoc, SILValue operand)
- : UnaryInstructionBase(DebugLoc, operand) {}
+ UnmanagedReleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
+ Atomicity atomicity)
+ : UnaryInstructionBase(DebugLoc, operand) {
+ setAtomicity(atomicity);
+ }
};
/// Transfers ownership of a loadable value to the current autorelease
@@ -3046,8 +3052,11 @@
/*HasValue*/ false> {
friend SILBuilder;
- UnmanagedAutoreleaseValueInst(SILDebugLocation DebugLoc, SILValue operand)
- : UnaryInstructionBase(DebugLoc, operand) {}
+ UnmanagedAutoreleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
+ Atomicity atomicity)
+ : UnaryInstructionBase(DebugLoc, operand) {
+ setAtomicity(atomicity);
+ }
};
/// Transfers ownership of a loadable value to the current autorelease pool.
@@ -4167,6 +4176,15 @@
: UnaryInstructionBase(DebugLoc, Existential) {}
};
+class DeinitExistentialOpaqueInst
+ : public UnaryInstructionBase<ValueKind::DeinitExistentialOpaqueInst,
+ SILInstruction, /*HAS_RESULT*/ false> {
+ friend SILBuilder;
+
+ DeinitExistentialOpaqueInst(SILDebugLocation DebugLoc, SILValue Existential)
+ : UnaryInstructionBase(DebugLoc, Existential) {}
+};
+
/// Projects the capture storage address from a @block_storage address.
class ProjectBlockStorageInst
: public UnaryInstructionBase<ValueKind::ProjectBlockStorageInst,
diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h
index f4ed80f..f184c9b 100644
--- a/include/swift/SIL/SILModule.h
+++ b/include/swift/SIL/SILModule.h
@@ -642,6 +642,11 @@
/// Returns true if the builtin or intrinsic is no-return.
bool isNoReturnBuiltinOrIntrinsic(Identifier Name);
+
+ /// Returns true if the default atomicity of the module is Atomic.
+ bool isDefaultAtomic() const {
+ return ! getOptions().AssumeSingleThreaded;
+ }
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 63e796d..770fec1 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -227,6 +227,8 @@
INST(InitExistentialOpaqueInst, SILInstruction, init_existential_opaque, MayWrite, DoesNotRelease)
INST(DeinitExistentialAddrInst, SILInstruction, deinit_existential_addr, MayHaveSideEffects,
DoesNotRelease)
+ INST(DeinitExistentialOpaqueInst, SILInstruction, deinit_existential_opaque, MayHaveSideEffects,
+ DoesNotRelease)
INST(OpenExistentialAddrInst, SILInstruction, open_existential_addr, MayRead, DoesNotRelease)
INST(InitExistentialRefInst, SILInstruction, init_existential_ref, None, DoesNotRelease)
INST(OpenExistentialRefInst, SILInstruction, open_existential_ref, None, DoesNotRelease)
diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h
index 1bdd049..cb46848 100644
--- a/include/swift/SIL/SILType.h
+++ b/include/swift/SIL/SILType.h
@@ -127,12 +127,6 @@
return SILType(T, SILValueCategory::Address);
}
- /// Apply a substitution to the function type.
- static CanSILFunctionType substFuncType(SILModule &silModule,
- const SubstitutionMap &subs,
- CanSILFunctionType SrcTy,
- bool dropGenerics);
-
bool isNull() const { return value.getPointer() == nullptr; }
explicit operator bool() const { return bool(value.getPointer()); }
@@ -166,15 +160,6 @@
CanType getSwiftRValueType() const {
return CanType(value.getPointer());
}
-
- /// Returns the Swift type equivalent to this SIL type. If the SIL type is
- /// an address type, returns an InOutType.
- CanType getSwiftType() const {
- CanType rvalueTy = getSwiftRValueType();
- if (isAddress())
- return CanInOutType::get(rvalueTy);
- return rvalueTy;
- }
/// Returns the AbstractCC of a function type.
/// The SILType must refer to a function type.
@@ -436,9 +421,14 @@
SILType substGenericArgs(SILModule &M,
SubstitutionList Subs) const;
+ /// If the original type is generic, pass the signature as genericSig.
+ ///
+ /// If the replacement types are generic, you must push a generic context
+ /// first.
SILType subst(SILModule &silModule,
TypeSubstitutionFn subs,
- LookupConformanceFn conformances) const;
+ LookupConformanceFn conformances,
+ CanGenericSignature genericSig=CanGenericSignature()) const;
SILType subst(SILModule &silModule, const SubstitutionMap &subs) const;
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 6c2f784..dd42035 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -622,7 +622,8 @@
CanSILFunctionType
getMaterializeForSetCallbackType(AbstractStorageDecl *storage,
CanGenericSignature genericSig,
- Type selfType);
+ Type selfType,
+ SILFunctionTypeRepresentation rep);
/// Return the SILFunctionType for a native function value of the
/// given type.
@@ -675,13 +676,6 @@
SILConstantInfo getConstantOverrideInfo(SILDeclRef constant,
SILDeclRef base);
- /// Substitute the given function type so that it implements the
- /// given substituted type.
- CanSILFunctionType substFunctionType(CanSILFunctionType origFnType,
- CanAnyFunctionType origLoweredType,
- CanAnyFunctionType substLoweredInterfaceType,
- const Optional<ForeignErrorConvention> &foreignError);
-
/// Get the empty tuple type as a SILType.
SILType getEmptyTupleType() {
return getLoweredType(TupleType::getEmpty(Context));
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index e8ff184..234016d 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -97,12 +97,12 @@
}
Substitution remapSubstitution(Substitution sub) {
- sub = sub.subst(SwiftMod, SubsMap);
-
// Remap opened archetypes into the cloned context.
- return Substitution(getASTTypeInClonedContext(sub.getReplacement()
- ->getCanonicalType()),
- sub.getConformances());
+ sub = Substitution(
+ getASTTypeInClonedContext(sub.getReplacement()->getCanonicalType()),
+ sub.getConformances());
+ // Now remap the substitution.
+ return sub.subst(SwiftMod, SubsMap);
}
ProtocolConformanceRef remapConformance(CanType type,
diff --git a/include/swift/SILOptimizer/Utils/Devirtualize.h b/include/swift/SILOptimizer/Utils/Devirtualize.h
index dfcfe5e..44bede7 100644
--- a/include/swift/SILOptimizer/Utils/Devirtualize.h
+++ b/include/swift/SILOptimizer/Utils/Devirtualize.h
@@ -54,9 +54,7 @@
SILValue ClassInstance);
DevirtualizationResult tryDevirtualizeClassMethod(FullApplySite AI,
SILValue ClassInstance);
-DevirtualizationResult tryDevirtualizeWitnessMethod(ApplySite AI);
-/// Check if an upcast is legal.
-bool isLegalUpcast(SILType FromTy, SILType ToTy);
+DevirtualizationResult tryDevirtualizeWitnessMethod(ApplySite AI);
}
#endif
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
index caf0480..6ca651c 100644
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ b/include/swift/SILOptimizer/Utils/Local.h
@@ -110,22 +110,10 @@
/// - a type of the return value is a subclass of the expected return type.
/// - actual return type and expected return type differ in optionality.
/// - both types are tuple-types and some of the elements need to be casted.
-///
-/// If CheckOnly flag is set, then this function only checks if the
-/// required casting is possible. If it is not possible, then None
-/// is returned.
-/// If CheckOnly is not set, then a casting code is generated and the final
-/// casted value is returned.
-Optional<SILValue> castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
- SILValue Value,
- SILType SrcTy,
- SILType DestTy,
- bool CheckOnly = false);
-
-/// Check if the optimizer can cast a value into the expected,
-/// ABI compatible type if necessary.
-bool canCastValueToABICompatibleType(SILModule &M,
- SILType SrcTy, SILType DestTy);
+SILValue castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
+ SILValue Value,
+ SILType SrcTy,
+ SILType DestTy);
/// Returns a project_box if it is the next instruction after \p ABI and
/// and has \p ABI as operand. Otherwise it creates a new project_box right
diff --git a/include/swift/Sema/Semantics.h b/include/swift/Sema/Semantics.h
index c399df2..524a2b5 100644
--- a/include/swift/Sema/Semantics.h
+++ b/include/swift/Sema/Semantics.h
@@ -1,4 +1,4 @@
-//===--- Semantics.h - Swift Container for Semantic Info ----*- C++ -*-===//
+//===--- Semantics.h - Swift Container for Semantic Info --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index fd084f9..e790e71 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 320; // Last change: inherited protocols
+const uint16_t VERSION_MINOR = 321; // Last change: restrict to extension
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -1181,7 +1181,7 @@
using XRefTypePathPieceLayout = BCRecordLayout<
XREF_TYPE_PATH_PIECE,
IdentifierIDField, // name
- BCFixed<1> // only in nominal
+ BCFixed<1> // restrict to protocol extension
>;
using XRefValuePathPieceLayout = BCRecordLayout<
diff --git a/include/swift/Syntax/DeclSyntax.h b/include/swift/Syntax/DeclSyntax.h
index f826ed4..eb936fa 100644
--- a/include/swift/Syntax/DeclSyntax.h
+++ b/include/swift/Syntax/DeclSyntax.h
@@ -1,4 +1,4 @@
-//===--- DeclSyntax.cpp - Declaration Syntax Interface ----------*- C++ -*-===//
+//===--- DeclSyntax.h - Declaration Syntax Interface ------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -25,6 +25,7 @@
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/TokenSyntax.h"
#include "swift/Syntax/TypeSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
#include "llvm/ADT/BitVector.h"
@@ -56,7 +57,7 @@
#pragma mark - unknown-declaration Data
-class UnknownDeclSyntaxData : public DeclSyntaxData {
+class UnknownDeclSyntaxData : public UnknownSyntaxData {
UnknownDeclSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
public:
@@ -71,7 +72,7 @@
#pragma mark - unknown-declaration API
-class UnknownDeclSyntax : public DeclSyntax {
+class UnknownDeclSyntax : public UnknownSyntax {
friend class SyntaxData;
friend class UnknownStmtSyntaxData;
friend class LegacyASTTransformer;
diff --git a/include/swift/Syntax/ExprSyntax.h b/include/swift/Syntax/ExprSyntax.h
index 2873c65..5dbebda 100644
--- a/include/swift/Syntax/ExprSyntax.h
+++ b/include/swift/Syntax/ExprSyntax.h
@@ -1,4 +1,4 @@
-//===--- ExprSyntax.h - Swift Expression Syntax Interface --------*- C++ -*-===//
+//===--- ExprSyntax.h - Swift Expression Syntax Interface -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -23,12 +23,16 @@
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
using llvm::Optional;
namespace swift {
namespace syntax {
+class GenericArgumentClauseSyntax;
+class GenericArgumentClauseSyntaxData;
+
class ExprSyntaxData : public SyntaxData {
protected:
ExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
@@ -58,7 +62,7 @@
#pragma mark - unknown-expression Data
-class UnknownExprSyntaxData : public ExprSyntaxData {
+class UnknownExprSyntaxData : public UnknownSyntaxData {
UnknownExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
public:
@@ -73,17 +77,17 @@
#pragma mark - unknown-expression API
-class UnknownExprSyntax : public ExprSyntax {
+class UnknownExprSyntax : public UnknownSyntax {
friend class SyntaxData;
friend class UnknownExprSyntaxData;
friend class LegacyASTTransformer;
using DataType = UnknownExprSyntaxData;
+public:
UnknownExprSyntax(const RC<SyntaxData> Root,
const UnknownExprSyntaxData *Data);
-public:
static bool classof(const Syntax *S) {
return S->getKind() == SyntaxKind::UnknownExpr;
}
@@ -144,6 +148,329 @@
}
};
+#pragma mark - symbolic-reference Data
+
+class SymbolicReferenceExprSyntaxData : public ExprSyntaxData {
+ friend class SymbolicReferenceExprSyntax;
+ friend class SyntaxData;
+ friend struct SyntaxFactory;
+
+ RC<GenericArgumentClauseSyntaxData> CachedGenericArgClause;
+
+ SymbolicReferenceExprSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<SymbolicReferenceExprSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<SymbolicReferenceExprSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *S) {
+ return S->getKind() == SyntaxKind::SymbolicReferenceExpr;
+ }
+};
+
+#pragma mark - symbolic-reference API
+
+/// symbolic-reference-expression -> identifier generic-argument-clause?
+///
+/// This is shown as primary-expression -> identifier generic-argument-clause?
+/// in the grammar. It can be just an identifier referring to some
+/// declaration, or it could perhaps be a constructor call to `Array<Int>`.
+class SymbolicReferenceExprSyntax : public ExprSyntax {
+
+ using DataType = SymbolicReferenceExprSyntaxData;
+
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class Syntax;
+ friend class SymbolicReferenceExprSyntaxData;
+
+ enum class Cursor : CursorIndex {
+ Identifier,
+ GenericArgumentClause
+ };
+
+ SymbolicReferenceExprSyntax(const RC<SyntaxData> Root,
+ const DataType *Data);
+
+public:
+
+ /// Get the identifier for the symbol to which this expression refers.
+ RC<TokenSyntax> getIdentifier() const;
+
+ /// Return a new `SymbolicReferenceExprSyntax` with the given identifier.
+ SymbolicReferenceExprSyntax
+ withIdentifier(RC<TokenSyntax> NewIdentifier) const;
+
+ /// Return the generic arguments this symbolic reference has, if it has one.
+ llvm::Optional<GenericArgumentClauseSyntax> getGenericArgumentClause() const;
+
+ /// Return a new `SymbolicReferenceExprSyntax` with the given generic
+ /// arguments.
+ SymbolicReferenceExprSyntax
+ withGenericArgumentClause(GenericArgumentClauseSyntax NewGenericArgs) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::SymbolicReferenceExpr;
+ }
+};
+
+#pragma mark - function-call-argument Data
+
+class FunctionCallArgumentSyntaxData : public SyntaxData {
+ friend struct SyntaxFactory;
+ friend class FunctionCallArgumentSyntax;
+ friend class SyntaxData;
+
+ RC<ExprSyntaxData> CachedExpression;
+
+ FunctionCallArgumentSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallArgumentSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallArgumentSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *S) {
+ return S->getKind() == SyntaxKind::FunctionCallArgument;
+ }
+};
+
+#pragma mark - function-call-argument API
+
+/// function-call-argument -> label? ':'? (expression | operator) ','?
+class FunctionCallArgumentSyntax : public Syntax {
+
+ using DataType = FunctionCallArgumentSyntaxData;
+
+ friend struct SyntaxFactory;
+ friend class SyntaxData;
+ friend class Syntax;
+ friend class FunctionCallArgumentSyntaxData;
+ friend class FunctionCallArgumentListSyntax;
+
+ enum class Cursor {
+ Label,
+ Colon,
+ Expression,
+ Comma,
+ };
+
+ FunctionCallArgumentSyntax(const RC<SyntaxData> Root,
+ const DataType *Data);
+
+public:
+
+ /// Return the label identifier for this argument, if it has one.
+ RC<TokenSyntax> getLabel() const;
+
+ /// Return a new `FunctionCallArgumentSyntax` with the given label.
+ FunctionCallArgumentSyntax withLabel(RC<TokenSyntax> NewLabel) const;
+
+ /// Get the colon ':' token in between the label and argument,
+ /// if there is one.
+ RC<TokenSyntax> getColonToken() const;
+
+ /// Return a new `FunctionCallArgumentSyntax` with the given colon ':' token.
+ FunctionCallArgumentSyntax withColonToken(RC<TokenSyntax> NewColon) const;
+
+ /// Returns the expression of the argument.
+ llvm::Optional<ExprSyntax> getExpression() const;
+
+ /// Return a new `FunctionCallArgumentSyntax` with the given expression
+ /// argument.
+ FunctionCallArgumentSyntax withExpression(ExprSyntax NewExpression) const;
+
+ /// Get the comma ',' token immediately following this argument, if there
+ /// is one.
+ RC<TokenSyntax> getTrailingComma() const;
+
+ /// Return a new `FunctionCallArgumentSyntax` with the given comma attached
+ /// to the end of the argument.
+ FunctionCallArgumentSyntax
+ withTrailingComma(RC<TokenSyntax> NewTrailingComma) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionCallArgument;
+ }
+};
+
+#pragma mark - function-call-argument-list Data
+
+class FunctionCallArgumentListSyntaxData : public SyntaxData {
+ friend struct SyntaxFactory;
+ friend class FunctionCallArgumentListSyntax;
+ friend class FunctionCallExprSyntaxBuilder;
+ friend class SyntaxData;
+
+ std::vector<RC<FunctionCallArgumentSyntaxData>> CachedArguments;
+
+ FunctionCallArgumentListSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallArgumentListSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallArgumentListSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *S) {
+ return S->getKind() == SyntaxKind::FunctionCallArgumentList;
+ }
+};
+
+#pragma mark - function-call-argument-list API
+
+/// function-call-argument-list -> function-call-argument
+/// function-call-argument-list?
+class FunctionCallArgumentListSyntax : public Syntax {
+ friend struct SyntaxFactory;
+ friend class FunctionCallArgumentListSyntaxData;
+ friend class FunctionCallExprSyntax;
+ friend class Syntax;
+ friend class SyntaxData;
+
+ using DataType = FunctionCallArgumentListSyntaxData;
+
+ FunctionCallArgumentListSyntax(const RC<SyntaxData> Root,
+ const DataType *Data);
+
+public:
+ /// Return the number of arguments in this list.
+ size_t getNumArguments() const;
+
+ /// Get the argument at the given Index.
+ FunctionCallArgumentSyntax getArgument(size_t n) const;
+
+ /// Returns a new `FunctionCallArgumentListSyntax` with the given
+ /// argument added to the end.
+ FunctionCallArgumentListSyntax
+ withAdditionalArgument(FunctionCallArgumentSyntax AdditionalArgument) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionCallArgumentList;
+ }
+};
+
+#pragma mark - function-call-expression Data
+
+class FunctionCallExprSyntaxData : public ExprSyntaxData {
+ friend struct SyntaxFactory;
+ friend class FunctionCallExprSyntax;
+ friend class FunctionCallExprSyntaxBuilder;
+ friend class SyntaxData;
+
+ RC<ExprSyntaxData> CachedCalledExpression;
+ RC<FunctionCallArgumentListSyntaxData> CachedArgumentList;
+
+ FunctionCallExprSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallExprSyntaxData>
+ make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ static RC<FunctionCallExprSyntaxData> makeBlank();
+
+public:
+ static bool classof(const SyntaxData *S) {
+ return S->getKind() == SyntaxKind::FunctionCallExpr;
+ }
+};
+
+#pragma mark - function-call-expression API
+
+class FunctionCallExprSyntax : public ExprSyntax {
+ using DataType = FunctionCallExprSyntaxData;
+ friend struct SyntaxFactory;
+ friend class FunctionCallExprSyntaxData;
+ friend class FunctionCallExprSyntaxBuilder;
+ friend class Syntax;
+ friend class SyntaxData;
+
+ enum class Cursor: CursorIndex {
+ CalledExpression,
+ LeftParen,
+ ArgumentList,
+ RightParen,
+ };
+
+ FunctionCallExprSyntax(const RC<SyntaxData> Root, const DataType *Data);
+
+public:
+
+ /// Get the base expression getting called.
+ ExprSyntax getCalledExpression() const;
+
+ /// Return a new `FunctionCallExprSyntax` with the given base expression
+ /// to be called.
+ FunctionCallExprSyntax
+ withCalledExpression(ExprSyntax NewBaseExpression) const;
+
+ /// Return the left parenthesis '(' token in this call.
+ RC<TokenSyntax> getLeftParen() const;
+
+ /// Return a new `FunctionCallExprSyntax` with the given left parenthesis '('
+ /// token.
+ FunctionCallExprSyntax withLeftParen(RC<TokenSyntax> NewLeftParen) const;
+
+ /// Get the list of arguments in this call expression.
+ FunctionCallArgumentListSyntax getArgumentList() const;
+
+ /// Return a new `FunctionCallExprSyntax` with the given argument list.
+ FunctionCallExprSyntax
+ withArgumentList(FunctionCallArgumentListSyntax NewArgumentList) const;
+
+ /// Return the right parenthesis ')' token in this call.
+ RC<TokenSyntax> getRightParen() const;
+
+ /// Return a new `FunctionCallExprSyntax` with the given right parenthesis ')'
+ /// token.
+ FunctionCallExprSyntax withRightParen(RC<TokenSyntax> NewLeftParen) const;
+
+ static bool classof(const Syntax *S) {
+ return S->getKind() == SyntaxKind::FunctionCallExpr;
+ }
+};
+
+#pragma mark - function-call-argument-list-builder
+class FunctionCallExprSyntaxBuilder {
+ RawSyntax::LayoutList CallLayout;
+ RawSyntax::LayoutList ListLayout;
+public:
+
+ /// Start the builder with all elements marked as missing or empty.
+ FunctionCallExprSyntaxBuilder();
+
+ /// Use the given expression as the call target.
+ FunctionCallExprSyntaxBuilder &
+ useCalledExpression(ExprSyntax CalledExpression);
+
+ /// Use the given left parenthesis '(' token in the function call.
+ FunctionCallExprSyntaxBuilder &useLeftParen(RC<TokenSyntax> LeftParen);
+
+ /// Add an additional argument to the layout.
+ FunctionCallExprSyntaxBuilder &
+ appendArgument(FunctionCallArgumentSyntax AdditionalArgument);
+
+ /// Use the given right parenthesis ')' token in the function call.
+ FunctionCallExprSyntaxBuilder &useRightParen(RC<TokenSyntax> RightParen);
+
+ /// Return a `FunctionCallExprSyntax` with the arguments added so far.
+ FunctionCallExprSyntax build() const;
+};
+
} // end namespace syntax
} // end namespace swift
diff --git a/include/swift/Syntax/Format.h b/include/swift/Syntax/Format.h
index ca89034..b6cd188 100644
--- a/include/swift/Syntax/Format.h
+++ b/include/swift/Syntax/Format.h
@@ -1,4 +1,4 @@
-//===--- Format.cpp - Declaration Syntax Formatting Interface ---*- C++ -*-===//
+//===--- Format.h - Declaration Syntax Formatting Interface -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/include/swift/Syntax/GenericSyntax.h b/include/swift/Syntax/GenericSyntax.h
index e31eec9..753018e 100644
--- a/include/swift/Syntax/GenericSyntax.h
+++ b/include/swift/Syntax/GenericSyntax.h
@@ -1,4 +1,4 @@
-//===--- GenericSyntax.cpp - Swift Generic Syntax Interface -----*- C++ -*-===//
+//===--- GenericSyntax.h - Swift Generic Syntax Interface -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -433,7 +433,9 @@
class GenericArgumentClauseSyntax : public Syntax {
friend struct SyntaxFactory;
friend class GenericArgumentClauseBuilder;
+ friend class SymbolicReferenceExprSyntax;
friend class SyntaxData;
+ friend class Syntax;
using DataType = GenericArgumentClauseSyntaxData;
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index 1b58de0..40a53c3 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -235,6 +235,18 @@
return Kind >= SyntaxKind::First_Expr && Kind <= SyntaxKind::Last_Expr;
}
+ /// Return true if this raw syntax node is a token.
+ bool isToken() const {
+ return Kind == SyntaxKind::Token;
+ }
+
+ bool isUnknown() const {
+ return Kind == SyntaxKind::Unknown ||
+ Kind == SyntaxKind::UnknownDecl ||
+ Kind == SyntaxKind::UnknownExpr ||
+ Kind == SyntaxKind::UnknownStmt;
+ }
+
/// Get the absolute position of this raw syntax: its offset, line,
/// and column.
AbsolutePosition getAbsolutePosition(RC<RawSyntax> Root) const;
diff --git a/include/swift/Syntax/Rewriter.h b/include/swift/Syntax/Rewriter.h
index bdebab2..224373d 100644
--- a/include/swift/Syntax/Rewriter.h
+++ b/include/swift/Syntax/Rewriter.h
@@ -27,6 +27,7 @@
#include "swift/Syntax/ExprSyntax.h"
#include "swift/Syntax/StmtSyntax.h"
#include "swift/Syntax/Syntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
namespace swift {
namespace syntax {
diff --git a/include/swift/Syntax/StmtSyntax.h b/include/swift/Syntax/StmtSyntax.h
index 523133f..d4c93a5 100644
--- a/include/swift/Syntax/StmtSyntax.h
+++ b/include/swift/Syntax/StmtSyntax.h
@@ -22,6 +22,7 @@
#include "swift/Syntax/References.h"
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxData.h"
+#include "swift/Syntax/UnknownSyntax.h"
using llvm::Optional;
@@ -66,7 +67,7 @@
#pragma mark - unknown-statement Data
-class UnknownStmtSyntaxData : public StmtSyntaxData {
+class UnknownStmtSyntaxData : public UnknownSyntaxData {
UnknownStmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
public:
@@ -81,12 +82,12 @@
#pragma mark - unknown-statement API
-class UnknownStmtSyntax : public StmtSyntax {
+class UnknownStmtSyntax : public UnknownSyntax {
friend class SyntaxData;
friend class UnknownStmtSyntaxData;
friend class LegacyASTTransformer;
- using DataType = UnknownExprSyntaxData;
+ using DataType = UnknownStmtSyntaxData;
UnknownStmtSyntax(const RC<SyntaxData> Root,
const UnknownStmtSyntaxData *Data);
diff --git a/include/swift/Syntax/Syntax.h b/include/swift/Syntax/Syntax.h
index 3528fb2..7be6fd9 100644
--- a/include/swift/Syntax/Syntax.h
+++ b/include/swift/Syntax/Syntax.h
@@ -39,7 +39,6 @@
const auto NoParent = llvm::None;
class SyntaxData;
-class UnknownSyntaxData;
/// The main handle for syntax nodes - subclasses contain all public
/// structured editing APIs.
@@ -138,6 +137,9 @@
/// Returns true if this syntax node represents a type.
bool isType() const;
+ /// Returns true if this syntax is of some "unknown" kind.
+ bool isUnknown() const;
+
/// Print the syntax node with full fidelity to the given output stream.
void print(llvm::raw_ostream &OS) const;
@@ -155,19 +157,6 @@
// TODO: hasSameStructureAs ?
};
-/// A chunk of "unknown" syntax - effectively a sequence of tokens.
-class UnknownSyntax final : public Syntax {
- friend struct SyntaxFactory;
-
- UnknownSyntax(const RC<SyntaxData> Root, UnknownSyntaxData *Data);
- static UnknownSyntax make(RC<RawSyntax> Raw);
-
-public:
- static bool classof(const Syntax *S) {
- return S->getKind() == SyntaxKind::Unknown;
- }
-};
-
} // end namespace syntax
} // end namespace swift
diff --git a/include/swift/Syntax/SyntaxData.h b/include/swift/Syntax/SyntaxData.h
index c048dcc..f27e59e 100644
--- a/include/swift/Syntax/SyntaxData.h
+++ b/include/swift/Syntax/SyntaxData.h
@@ -242,28 +242,14 @@
/// Returns true if the data node represents expression syntax.
bool isExpr() const;
+ /// Returns true if this syntax is of some "unknown" kind.
+ bool isUnknown() const;
+
/// Dump a debug description of the syntax data for debugging to
/// standard error.
void dump(llvm::raw_ostream &OS) const;
};
-class UnknownSyntaxData final : public SyntaxData {
- friend class SyntaxData;
- friend class UnknownSyntax;
- friend struct SyntaxFactory;
- friend class LegacyASTTransformer;
-
- UnknownSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0)
- : SyntaxData(Raw, Parent, IndexInParent) {}
-
- static RC<UnknownSyntaxData> make(RC<RawSyntax> Raw,
- const SyntaxData *Parent = nullptr,
- CursorIndex IndexInParent = 0);
-public:
- static bool classof(const SyntaxData *SD);
-};
-
} // end namespace syntax
} // end namespace swift
diff --git a/include/swift/Syntax/SyntaxFactory.h b/include/swift/Syntax/SyntaxFactory.h
index 4f09467..d1d74c8 100644
--- a/include/swift/Syntax/SyntaxFactory.h
+++ b/include/swift/Syntax/SyntaxFactory.h
@@ -129,6 +129,43 @@
/// as missing.
static IntegerLiteralExprSyntax makeBlankIntegerLiteralExpr();
+ /// Make a symbolic reference with the given identifier and optionally a
+ /// generic argument clause.
+ static SymbolicReferenceExprSyntax
+ makeSymbolicReferenceExpr(RC<TokenSyntax> Identifier,
+ llvm::Optional<GenericArgumentClauseSyntax> GenericArgs);
+
+ /// Make a symbolic reference expression with the identifier and
+ /// generic argument clause marked as missing.
+ static SymbolicReferenceExprSyntax makeBlankSymbolicReferenceExpr();
+
+ /// Make a function call argument with all elements marked as missing.
+ static FunctionCallArgumentSyntax makeBlankFunctionCallArgument();
+
+ /// Make a function call argument based on an expression with the
+ /// given elements.
+ static FunctionCallArgumentSyntax
+ makeFunctionCallArgument(RC<TokenSyntax> Label, RC<TokenSyntax> Colon,
+ ExprSyntax ExpressionArgument,
+ RC<TokenSyntax> TrailingComma);
+
+ /// Make a function call argument list with the given arguments.
+ static FunctionCallArgumentListSyntax
+ makeFunctionCallArgumentList(
+ std::vector<FunctionCallArgumentSyntax> Arguments);
+
+ /// Make a function call argument list with no arguments.
+ static FunctionCallArgumentListSyntax makeBlankFunctionCallArgumentList();
+
+ /// Make a function call expression with the given elements.
+ static FunctionCallExprSyntax
+ makeFunctionCallExpr(ExprSyntax CalledExpr, RC<TokenSyntax> LeftParen,
+ FunctionCallArgumentListSyntax Arguments,
+ RC<TokenSyntax> RightParen);
+
+ /// Make a function call expression with all elements marked as missing.
+ static FunctionCallExprSyntax makeBlankFunctionCallExpr();
+
#pragma mark - Tokens
/// Make a 'fallthrough' keyword with the specified leading and
@@ -353,7 +390,7 @@
/// Make a metatype type with all elements marked as missing.
static MetatypeTypeSyntax makeBlankMetatypeType();
- /// Make an sugared Array type, as in `[MyType]`.
+ /// Make a sugared Array type, as in `[MyType]`.
static ArrayTypeSyntax makeArrayType(RC<TokenSyntax> LeftSquareBracket,
TypeSyntax ElementType,
RC<TokenSyntax> RightSquareBracket);
diff --git a/include/swift/Syntax/SyntaxKinds.def b/include/swift/Syntax/SyntaxKinds.def
index e5b0c70..941d50d 100644
--- a/include/swift/Syntax/SyntaxKinds.def
+++ b/include/swift/Syntax/SyntaxKinds.def
@@ -1,4 +1,4 @@
-//===--- SyntaxKinds.def - Swift Syntax Node Metaprogramming -------------===//
+//===--- SyntaxKinds.def - Swift Syntax Node Metaprogramming --------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -86,13 +86,18 @@
MISSING_SYNTAX(MissingExpr, ExprSyntax)
SYNTAX(UnknownExpr, ExprSyntax)
SYNTAX(IntegerLiteralExpr, ExprSyntax)
-SYNTAX_RANGE(Expr, MissingExpr, IntegerLiteralExpr)
+ SYNTAX(FunctionCallExpr, ExprSyntax)
+ SYNTAX(SymbolicReferenceExpr, ExprSyntax)
+SYNTAX_RANGE(Expr, MissingExpr, SymbolicReferenceExpr)
+// Other stuff
SYNTAX(BalancedTokens, Syntax)
SYNTAX(TypeAttribute, Syntax)
SYNTAX(TypeAttributes, Syntax)
SYNTAX(TupleTypeElement, Syntax)
SYNTAX(FunctionTypeArgument, Syntax)
+SYNTAX(FunctionCallArgumentList, Syntax)
+SYNTAX(FunctionCallArgument, Syntax)
#undef ABSTRACT_SYNTAX
#undef DECL
diff --git a/include/swift/Syntax/TypeSyntax.h b/include/swift/Syntax/TypeSyntax.h
index 5afb0ed..07bf362 100644
--- a/include/swift/Syntax/TypeSyntax.h
+++ b/include/swift/Syntax/TypeSyntax.h
@@ -32,8 +32,7 @@
class GenericParameterClauseSyntax;
class GenericParameterClauseSyntaxData;
-#pragma mark -
-#pragma mark balanced-tokens Data
+#pragma mark - balanced-tokens Data
class BalancedTokensSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -52,8 +51,7 @@
}
};
-#pragma mark -
-#pragma mark balanced-tokens API
+#pragma mark - balanced-tokens API
/// balanced-tokens -> Any identifier, keyword, literal, or operator
/// | Any punctuation except (, ), [, ], {, or }
@@ -77,8 +75,7 @@
}
};
-#pragma mark -
-#pragma mark type-attribute Data
+#pragma mark - type-attribute Data
class TypeAttributeSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -99,8 +96,7 @@
}
};
-#pragma mark -
-#pragma mark type-attribute API
+#pragma mark - type-attribute API
/// type-attribute -> '@' identifier attribute-argument-clause?
/// attribute-argument-clause -> '(' balanced-tokens ')'
@@ -162,8 +158,7 @@
}
};
-#pragma mark -
-#pragma mark type-attributes Data
+#pragma mark - type-attributes Data
class TypeAttributesSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -183,8 +178,7 @@
}
};
-#pragma mark -
-#pragma mark type-attributes API
+#pragma mark - type-attributes API
/// type-attributes -> type-attribute
/// | type-attribute type-attributes
@@ -208,8 +202,7 @@
}
};
-#pragma mark -
-#pragma mark type-syntax Data
+#pragma mark - type-syntax Data
class TypeSyntaxData : public SyntaxData {
friend class SyntaxData;
@@ -226,8 +219,7 @@
}
};
-#pragma mark -
-#pragma mark type-syntax API
+#pragma mark - type-syntax API
/// type -> array-type
/// | dictionary-type
@@ -251,8 +243,7 @@
}
};
-#pragma mark -
-#pragma mark type-identifier Data
+#pragma mark - type-identifier Data
class TypeIdentifierSyntaxData final : public TypeSyntaxData {
friend struct SyntaxFactory;
@@ -276,8 +267,7 @@
}
};
-#pragma mark -
-#pragma mark type-identifier API
+#pragma mark - type-identifier API
/// type-identifier -> type-name generic-argument-clause?
/// | type-name generic-argument-clause '.' type-identifier
@@ -320,8 +310,7 @@
}
};
-#pragma mark -
-#pragma mark type-argument-list Data
+#pragma mark - type-argument-list Data
class TypeArgumentListSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -342,8 +331,7 @@
}
};
-#pragma mark -
-#pragma mark tuple-type-element Data
+#pragma mark - tuple-type-element Data
class TupleTypeElementSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -362,8 +350,7 @@
}
};
-#pragma mark -
-#pragma mark tuple-type-element API
+#pragma mark - tuple-type-element API
/// tuple-type-element -> (identifier ':')? type-attributes? 'inout'? type
///
@@ -425,8 +412,7 @@
};
-#pragma mark -
-#pragma mark type-argument-list API
+#pragma mark - type-argument-list API
/// type-argument-list
/// -> function-type-argument
@@ -451,8 +437,8 @@
}
};
-#pragma mark -
-#pragma mark tuple-type Data
+#pragma mark - tuple-type Data
+
class TupleTypeSyntaxData final : public TypeSyntaxData {
friend class SyntaxData;
friend struct SyntaxFactory;
@@ -472,8 +458,7 @@
}
};
-#pragma mark -
-#pragma mark tuple-type API
+#pragma mark - tuple-type API
/// tuple-type -> '(' tuple-type-element-list ')'
class TupleTypeSyntax final : public TypeSyntax {
@@ -513,8 +498,7 @@
}
};
-#pragma mark -
-#pragma mark tuple-type Builder
+#pragma mark - tuple-type Builder
/// Incrementally builds tuple type syntax.
class TupleTypeSyntaxBuilder final {
@@ -543,8 +527,7 @@
TupleTypeSyntax build() const;
};
-#pragma mark -
-#pragma mark metatype-type Data
+#pragma mark - metatype-type Data
class MetatypeTypeSyntaxData final : public TypeSyntaxData {
friend struct SyntaxFactory;
@@ -562,8 +545,7 @@
}
};
-#pragma mark -
-#pragma mark metatype-type API
+#pragma mark - metatype-type API
/// metatype-type -> type '.' 'Type'
/// | type '.' 'Protocol'
@@ -605,8 +587,7 @@
}
};
-#pragma mark -
-#pragma mark optional-type Data
+#pragma mark - optional-type Data
class OptionalTypeSyntaxData final : public TypeSyntaxData {
friend class SyntaxData;
@@ -624,8 +605,7 @@
}
};
-#pragma mark -
-#pragma mark optional-type API
+#pragma mark - optional-type API
/// optional-type -> type '?'
class OptionalTypeSyntax final : public TypeSyntax {
@@ -661,8 +641,7 @@
}
};
-#pragma mark -
-#pragma mark implicitly-unwrapped-optional-type Data
+#pragma mark - implicitly-unwrapped-optional-type Data
class ImplicitlyUnwrappedOptionalTypeSyntaxData final : public TypeSyntaxData {
friend struct SyntaxFactory;
@@ -682,8 +661,7 @@
}
};
-#pragma mark -
-#pragma mark implicitly-unwrapped-optional-type API
+#pragma mark - implicitly-unwrapped-optional-type API
/// implicitly-unwrapped-optional-type -> type '!'
class ImplicitlyUnwrappedOptionalTypeSyntax final : public TypeSyntax {
@@ -722,8 +700,7 @@
}
};
-#pragma mark -
-#pragma mark array-type Data
+#pragma mark - array-type Data
class ArrayTypeSyntaxData final : public TypeSyntaxData {
friend class SyntaxData;
@@ -744,8 +721,7 @@
}
};
-#pragma mark -
-#pragma mark array-type API
+#pragma mark - array-type API
// array-type -> '[' type ']'
class ArrayTypeSyntax final : public TypeSyntax {
@@ -788,8 +764,7 @@
}
};
-#pragma mark -
-#pragma mark dictionary-type Data
+#pragma mark - dictionary-type Data
class DictionaryTypeSyntaxData final : public TypeSyntaxData {
friend class SyntaxData;
@@ -813,8 +788,7 @@
}
};
-#pragma mark -
-#pragma mark dictionary-type API
+#pragma mark - dictionary-type API
// dictionary-type -> '[' type ':' type ']'
class DictionaryTypeSyntax final : public TypeSyntax {
@@ -875,8 +849,7 @@
}
};
-#pragma mark -
-#pragma mark function-type-argument Data
+#pragma mark - function-type-argument Data
class FunctionTypeArgumentSyntaxData final : public SyntaxData {
friend class SyntaxData;
@@ -897,8 +870,7 @@
}
};
-#pragma mark -
-#pragma mark function-type-argument API
+#pragma mark - function-type-argument API
class FunctionTypeArgumentSyntax final : public Syntax {
friend struct SyntaxFactory;
@@ -925,8 +897,7 @@
};
-#pragma mark -
-#pragma mark function-type Data
+#pragma mark - function-type Data
class FunctionTypeSyntaxData final : public TypeSyntaxData {
friend class SyntaxData;
@@ -947,8 +918,7 @@
}
};
-#pragma mark -
-#pragma mark function-type API
+#pragma mark - function-type API
/// function-type ->
/// type-attributes? function-type-argument-clause 'throws'? '->' type
@@ -1045,8 +1015,7 @@
}
};
-#pragma mark -
-#pragma mark function-type Builder
+#pragma mark - function-type Builder
/// Incrementally builds function type syntax.
class FunctionTypeSyntaxBuilder final {
diff --git a/include/swift/Syntax/UnknownSyntax.h b/include/swift/Syntax/UnknownSyntax.h
new file mode 100644
index 0000000..7158e03
--- /dev/null
+++ b/include/swift/Syntax/UnknownSyntax.h
@@ -0,0 +1,89 @@
+//===--- UnknownSyntax.h - Swift Unknown Syntax Interface -----------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SYNTAX_UNKNOWNSYNTAX_H
+#define SWIFT_SYNTAX_UNKNOWNSYNTAX_H
+
+#include "swift/Syntax/SyntaxData.h"
+#include "swift/Syntax/Syntax.h"
+
+#include <vector>
+
+namespace swift {
+namespace syntax {
+
+#pragma mark unknown-syntax Data
+
+class UnknownSyntaxData : public SyntaxData {
+ friend class SyntaxData;
+ friend class UnknownSyntax;
+ friend struct SyntaxFactory;
+ friend class LegacyASTTransformer;
+
+protected:
+ std::vector<RC<SyntaxData>> CachedChildren;
+
+ UnknownSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ const CursorIndex IndexInParent = 0);
+public:
+
+ static RC<UnknownSyntaxData> make(RC<RawSyntax> Raw,
+ const SyntaxData *Parent = nullptr,
+ CursorIndex IndexInParent = 0);
+
+ size_t getNumChildren() const {
+ return CachedChildren.size();
+ }
+
+ /// Get the child at the given Index.
+ ///
+ /// Precondition: Index <= getNumChildren();
+ Syntax getChild(size_t Index) const;
+
+ static bool classof(const SyntaxData *SD) {
+ return SD->isUnknown();
+ }
+};
+
+#pragma mark unknown-syntax API
+
+/// A chunk of "unknown" syntax.
+///
+/// Effectively wraps a tree of RawSyntax.
+///
+/// This should not be vended by SyntaxFactory.
+class UnknownSyntax : public Syntax {
+ friend struct SyntaxFactory;
+ friend class Syntax;
+
+ using DataType = UnknownSyntaxData;
+
+public:
+ UnknownSyntax(const RC<SyntaxData> Root, const UnknownSyntaxData *Data);
+
+ /// Get the number of child nodes in this piece of syntax, not including
+ /// tokens.
+ size_t getNumChildren() const;
+
+ /// Get the Nth child of this piece of syntax.
+ Syntax getChild(const size_t N) const;
+
+ static bool classof(const Syntax *S) {
+ return S->isUnknown();
+ }
+};
+
+} // end namespace syntax
+} // end namespace swift
+
+#endif // SWIFT_SYNTAX_UNKNOWNSYNTAX_H
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 0f7e463..7be8ea7 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -365,11 +365,11 @@
//===----------------------------------------------------------------------===//
// Print a name.
-static void printName(raw_ostream &os, Identifier name) {
- if (name.empty())
+static void printName(raw_ostream &os, DeclName name) {
+ if (!name)
os << "<anonymous>";
else
- os << name.str();
+ os << name;
}
namespace {
@@ -1004,7 +1004,7 @@
OS << "#else:\n";
}
- for (auto D : Clause.Members) {
+ for (auto D : Clause.Elements) {
OS << '\n';
printRec(D);
}
@@ -1148,7 +1148,7 @@
break;
}
}
- os << "extension";
+ os << " extension";
break;
case DeclContextKind::Initializer:
@@ -1166,18 +1166,12 @@
os << "top-level code";
break;
- case DeclContextKind::AbstractFunctionDecl: {
- auto *AFD = cast<AbstractFunctionDecl>(dc);
- if (isa<FuncDecl>(AFD))
- os << "func decl";
- if (isa<ConstructorDecl>(AFD))
- os << "init";
- if (isa<DestructorDecl>(AFD))
- os << "deinit";
+ case DeclContextKind::AbstractFunctionDecl:
+ printName(os, cast<AbstractFunctionDecl>(dc)->getFullName());
break;
- }
+
case DeclContextKind::SubscriptDecl:
- os << "subscript decl";
+ printName(os, cast<SubscriptDecl>(dc)->getFullName());
break;
}
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b6eeb2b..c57b4cf 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -622,6 +622,20 @@
if (auto genericSig = GenericSigOrEnv.dyn_cast<GenericSignature *>())
return genericSig;
+ // The signature of a Protocol is trivial (Self: TheProtocol) so let's compute
+ // it.
+ if (auto PD = dyn_cast<ProtocolDecl>(this)) {
+ auto self = PD->getSelfInterfaceType()->castTo<GenericTypeParamType>();
+ auto req =
+ Requirement(RequirementKind::Conformance, self, PD->getDeclaredType());
+ GenericTypeParamType *params[] = {self};
+ Requirement reqs[] = {req};
+
+ auto &ctx = getASTContext();
+ return GenericSignature::get(ctx.AllocateCopy(params),
+ ctx.AllocateCopy(reqs));
+ }
+
return nullptr;
}
@@ -808,7 +822,6 @@
ExtendedType(extendedType),
Inherited(inherited)
{
- ExtensionDeclBits.Validated = false;
ExtensionDeclBits.CheckedInheritanceClause = false;
ExtensionDeclBits.DefaultAndMaxAccessLevel = 0;
ExtensionDeclBits.HasLazyConformances = false;
@@ -2006,7 +2019,7 @@
selfTy, const_cast<AssociatedTypeDecl *>(ATD));
}
- Type interfaceType = getInterfaceType();
+ Type interfaceType = hasInterfaceType() ? getInterfaceType() : nullptr;
if (interfaceType.isNull() || interfaceType->is<ErrorType>())
return interfaceType;
@@ -2261,10 +2274,7 @@
Identifier Name, SourceLoc NameLoc,
GenericParamList *GenericParams, DeclContext *DC)
: GenericTypeDecl(DeclKind::TypeAlias, DC, Name, NameLoc, {}, GenericParams),
- TypeAliasLoc(TypeAliasLoc),
- EqualLoc(EqualLoc) {
- TypeAliasDeclBits.HasCompletedValidation = false;
-}
+ TypeAliasLoc(TypeAliasLoc), EqualLoc(EqualLoc) {}
SourceRange TypeAliasDecl::getSourceRange() const {
if (UnderlyingTy.hasLocation())
@@ -2273,7 +2283,7 @@
}
void TypeAliasDecl::setUnderlyingType(Type underlying) {
- setHasCompletedValidation();
+ setValidationStarted();
// lldb creates global typealiases containing archetypes
// sometimes...
@@ -2342,19 +2352,20 @@
AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
Identifier name, SourceLoc nameLoc,
- TypeLoc defaultDefinition)
- : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
- KeywordLoc(keywordLoc), DefaultDefinition(defaultDefinition)
-{ }
+ TypeLoc defaultDefinition,
+ TrailingWhereClause *trailingWhere)
+ : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
+ KeywordLoc(keywordLoc), DefaultDefinition(defaultDefinition),
+ TrailingWhere(trailingWhere) {}
AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
Identifier name, SourceLoc nameLoc,
+ TrailingWhereClause *trailingWhere,
LazyMemberLoader *definitionResolver,
uint64_t resolverData)
- : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
- KeywordLoc(keywordLoc), Resolver(definitionResolver),
- ResolverContextData(resolverData)
-{
+ : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
+ KeywordLoc(keywordLoc), TrailingWhere(trailingWhere),
+ Resolver(definitionResolver), ResolverContextData(resolverData) {
assert(Resolver && "missing resolver");
}
@@ -2725,6 +2736,41 @@
return result;
}
+bool ProtocolDecl::walkInheritedProtocols(
+ llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const {
+ auto self = const_cast<ProtocolDecl *>(this);
+
+ // Visit all of the inherited protocols.
+ SmallPtrSet<ProtocolDecl *, 8> visited;
+ SmallVector<ProtocolDecl *, 4> stack;
+ stack.push_back(self);
+ visited.insert(self);
+ while (!stack.empty()) {
+ // Pull the next protocol off the stack.
+ auto proto = stack.back();
+ stack.pop_back();
+
+ switch (fn(proto)) {
+ case TypeWalker::Action::Stop:
+ return true;
+
+ case TypeWalker::Action::Continue:
+ // Add inherited protocols to the stack.
+ for (auto inherited : proto->getInheritedProtocols()) {
+ if (visited.insert(inherited).second)
+ stack.push_back(inherited);
+ }
+ break;
+
+ case TypeWalker::Action::SkipChildren:
+ break;
+ }
+ }
+
+ return false;
+
+}
+
bool ProtocolDecl::inheritsFrom(const ProtocolDecl *super) const {
if (this == super)
return false;
@@ -2735,26 +2781,27 @@
}
bool ProtocolDecl::requiresClassSlow() {
- if (!isRequirementSignatureComputed()) return false;
+ ProtocolDeclBits.RequiresClass =
+ walkInheritedProtocols([&](ProtocolDecl *proto) {
+ // If the 'requires class' bit is valid, we don't need to search any
+ // further.
+ if (proto->ProtocolDeclBits.RequiresClassValid) {
+ // If this protocol has a class requirement, we're done.
+ if (proto->ProtocolDeclBits.RequiresClass)
+ return TypeWalker::Action::Stop;
- ProtocolDeclBits.RequiresClass = false;
+ return TypeWalker::Action::SkipChildren;
+ }
- // Ensure that the result cannot change in future.
+ // Quick check: @objc indicates that it requires a class.
+ if (proto->getAttrs().hasAttribute<ObjCAttr>() || proto->isObjC())
+ return TypeWalker::Action::Stop;
- if (getAttrs().hasAttribute<ObjCAttr>() || isObjC()) {
- ProtocolDeclBits.RequiresClass = true;
- return true;
- }
+ // Keep looking.
+ return TypeWalker::Action::Continue;
+ });
- // Check inherited protocols for class-ness.
- for (auto *proto : getInheritedProtocols()) {
- if (proto->requiresClass()) {
- ProtocolDeclBits.RequiresClass = true;
- return true;
- }
- }
-
- return false;
+ return ProtocolDeclBits.RequiresClass;
}
bool ProtocolDecl::existentialConformsToSelfSlow() {
@@ -2787,7 +2834,6 @@
// Check whether any of the inherited protocols fail to conform to
// themselves.
- // FIXME: does this need a resolver?
for (auto proto : getInheritedProtocols()) {
if (!proto->existentialConformsToSelf()) {
ProtocolDeclBits.ExistentialConformsToSelf = false;
@@ -3058,9 +3104,10 @@
GenericSignatureBuilder builder(getASTContext(),
LookUpConformanceInModule(module));
builder.addGenericParameter(selfType);
- builder.addRequirement(requirement,
- RequirementSource::forRequirementSignature(builder,
- this));
+ builder.addRequirement(
+ requirement,
+ GenericSignatureBuilder::RequirementSource
+ ::forRequirementSignature(builder.resolveArchetype(selfType), this));
builder.finalize(SourceLoc(), { selfType });
RequirementSignature = builder.getGenericSignature();
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 0a3bebe..56747a6 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -79,7 +79,7 @@
}
std::string GenericSignature::gatherGenericParamBindingsText(
- ArrayRef<Type> types, const TypeSubstitutionMap &substitutions) const {
+ ArrayRef<Type> types, TypeSubstitutionFn substitutions) const {
llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams;
for (auto type : types) {
type.visit([&](Type type) {
@@ -106,11 +106,11 @@
result += gp->getName().str();
result += " = ";
- auto found = substitutions.find(canonGP);
- if (found == substitutions.end())
+ auto type = substitutions(canonGP);
+ if (!type)
return "";
- result += found->second.getString();
+ result += type.getString();
}
result += "]";
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index c039407..b3f69c4 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -39,7 +39,11 @@
using llvm::DenseMap;
namespace {
+ typedef GenericSignatureBuilder::RequirementSource RequirementSource;
+ typedef GenericSignatureBuilder::FloatingRequirementSource
+ FloatingRequirementSource;
typedef GenericSignatureBuilder::PotentialArchetype PotentialArchetype;
+ typedef GenericSignatureBuilder::ConcreteConstraint ConcreteConstraint;
typedef GenericSignatureBuilder::EquivalenceClass EquivalenceClass;
} // end anonymous namespace
@@ -78,38 +82,53 @@
switch (kind) {
case Explicit:
switch (storageKind) {
- case StorageKind::None:
+ case StorageKind::RootArchetype:
case StorageKind::TypeRepr:
case StorageKind::RequirementRepr:
return true;
case StorageKind::ProtocolDecl:
case StorageKind::ProtocolConformance:
+ case StorageKind::AssociatedTypeDecl:
return false;
}
case Inferred:
switch (storageKind) {
- case StorageKind::None:
+ case StorageKind::RootArchetype:
case StorageKind::TypeRepr:
return true;
case StorageKind::ProtocolDecl:
case StorageKind::ProtocolConformance:
case StorageKind::RequirementRepr:
+ case StorageKind::AssociatedTypeDecl:
return false;
}
case NestedTypeNameMatch:
- case Parent:
switch (storageKind) {
- case StorageKind::None:
+ case StorageKind::RootArchetype:
return true;
case StorageKind::TypeRepr:
case StorageKind::ProtocolDecl:
case StorageKind::ProtocolConformance:
case StorageKind::RequirementRepr:
+ case StorageKind::AssociatedTypeDecl:
+ return false;
+ }
+
+ case Parent:
+ switch (storageKind) {
+ case StorageKind::AssociatedTypeDecl:
+ return true;
+
+ case StorageKind::RootArchetype:
+ case StorageKind::TypeRepr:
+ case StorageKind::ProtocolDecl:
+ case StorageKind::ProtocolConformance:
+ case StorageKind::RequirementRepr:
return false;
}
@@ -119,10 +138,11 @@
case StorageKind::ProtocolDecl:
return true;
- case StorageKind::None:
+ case StorageKind::RootArchetype:
case StorageKind::TypeRepr:
case StorageKind::ProtocolConformance:
case StorageKind::RequirementRepr:
+ case StorageKind::AssociatedTypeDecl:
return false;
}
@@ -132,10 +152,11 @@
case StorageKind::ProtocolConformance:
return true;
- case StorageKind::None:
+ case StorageKind::RootArchetype:
case StorageKind::ProtocolDecl:
case StorageKind::TypeRepr:
case StorageKind::RequirementRepr:
+ case StorageKind::AssociatedTypeDecl:
return false;
}
}
@@ -143,9 +164,8 @@
const void *RequirementSource::getOpaqueStorage() const {
switch (storageKind) {
- case StorageKind::None:
- // Note: always null.
- return storage.typeRepr;
+ case StorageKind::RootArchetype:
+ return storage.rootArchetype;
case StorageKind::TypeRepr:
return storage.typeRepr;
@@ -158,9 +178,19 @@
case StorageKind::ProtocolDecl:
return storage.protocol;
+
+ case StorageKind::AssociatedTypeDecl:
+ return storage.assocType;
}
}
+const void *RequirementSource::getExtraOpaqueStorage() const {
+ if (numTrailingObjects(OverloadToken<PotentialArchetype *>()) == 1)
+ return getTrailingObjects<PotentialArchetype *>()[0];
+
+ return nullptr;
+}
+
bool RequirementSource::isDerivedRequirement() const {
switch (kind) {
case Explicit:
@@ -204,23 +234,60 @@
return false;
}
-#define REQUIREMENT_SOURCE_FACTORY_BODY(SourceKind, Parent, Storage) \
- llvm::FoldingSetNodeID nodeID; \
- Profile(nodeID, Kind::SourceKind, Parent, Storage); \
- \
- void *insertPos = nullptr; \
- if (auto known = \
- builder.Impl->RequirementSources.FindNodeOrInsertPos(nodeID, \
- insertPos)) \
- return known; \
- \
- auto result = new RequirementSource(Kind::SourceKind, Parent, Storage); \
- builder.Impl->RequirementSources.InsertNode(result, insertPos); \
- return result
+bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
+ // If it's not a derived requirement, it's not self-derived.
+ if (!isDerivedRequirement()) return false;
-#define REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(SourceKind, Parent) \
+ // Collect the path of associated types from the root pa.
+ SmallVector<AssociatedTypeDecl *, 4> assocTypes;
+ PotentialArchetype *currentPA = nullptr;
+ for (auto source = this; source; source = source->parent) {
+ switch (source->kind) {
+ case RequirementSource::Parent:
+ assocTypes.push_back(source->getAssociatedType());
+ break;
+
+ case RequirementSource::NestedTypeNameMatch:
+ return false;
+
+ case RequirementSource::Explicit:
+ case RequirementSource::Inferred:
+ case RequirementSource::RequirementSignatureSelf:
+ currentPA = source->getRootPotentialArchetype();
+ break;
+
+ case RequirementSource::Concrete:
+ case RequirementSource::ProtocolRequirement:
+ case RequirementSource::Superclass:
+ break;
+ }
+ }
+
+ assert(currentPA && "Missing root potential archetype");
+
+ // Check whether anything of the potential archetypes in the path are
+ // equivalent to the end of the path.
+ auto rep = pa->getRepresentative();
+ for (auto assocType : reversed(assocTypes)) {
+ // Check whether this potential archetype is in the same equivalence class.
+ if (currentPA->getRepresentative() == rep) return true;
+
+ // Get the next nested type, but only if we've seen it before.
+ // FIXME: Feels hacky.
+ auto knownNested = currentPA->NestedTypes.find(assocType->getName());
+ if (knownNested == currentPA->NestedTypes.end()) return false;
+ currentPA = knownNested->second.front();
+ }
+
+ // FIXME: currentPA == pa?
+ return false;
+}
+
+#define REQUIREMENT_SOURCE_FACTORY_BODY( \
+ SourceKind, Parent, Storage, ExtraStorage, \
+ NumPotentialArchetypes) \
llvm::FoldingSetNodeID nodeID; \
- Profile(nodeID, Kind::SourceKind, Parent, nullptr); \
+ Profile(nodeID, Kind::SourceKind, Parent, Storage, ExtraStorage); \
\
void *insertPos = nullptr; \
if (auto known = \
@@ -228,73 +295,113 @@
insertPos)) \
return known; \
\
- auto result = new RequirementSource(Kind::SourceKind, Parent); \
+ unsigned size = \
+ totalSizeToAlloc<PotentialArchetype *>(NumPotentialArchetypes); \
+ void *mem = malloc(size); \
+ auto result = new (mem) RequirementSource(Kind::SourceKind, Parent, \
+ Storage); \
+ if (NumPotentialArchetypes > 0) \
+ result->getTrailingObjects<PotentialArchetype *>()[0] = ExtraStorage; \
builder.Impl->RequirementSources.InsertNode(result, insertPos); \
return result
const RequirementSource *RequirementSource::forAbstract(
- GenericSignatureBuilder &builder) {
- REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(Explicit, nullptr);
+ PotentialArchetype *root) {
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, root, nullptr, 0);
}
const RequirementSource *RequirementSource::forExplicit(
- GenericSignatureBuilder &builder,
+ PotentialArchetype *root,
const TypeRepr *typeRepr) {
- REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, typeRepr);
+ // If the type representation is NULL, we have an abstract requirement
+ // source.
+ if (!typeRepr)
+ return forAbstract(root);
+
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, typeRepr, root, 1);
}
const RequirementSource *RequirementSource::forExplicit(
- GenericSignatureBuilder &builder,
+ PotentialArchetype *root,
const RequirementRepr *requirementRepr) {
- REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, requirementRepr);
+ // If the requirement representation is NULL, we have an abstract requirement
+ // source.
+ if (!requirementRepr)
+ return forAbstract(root);
+
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, requirementRepr, root, 1);
}
const RequirementSource *RequirementSource::forInferred(
- GenericSignatureBuilder &builder,
+ PotentialArchetype *root,
const TypeRepr *typeRepr) {
- REQUIREMENT_SOURCE_FACTORY_BODY(Inferred, nullptr, typeRepr);
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(Inferred, nullptr, typeRepr, root, 1);
}
const RequirementSource *RequirementSource::forRequirementSignature(
- GenericSignatureBuilder &builder,
+ PotentialArchetype *root,
ProtocolDecl *protocol) {
- REQUIREMENT_SOURCE_FACTORY_BODY(RequirementSignatureSelf, nullptr, protocol);
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(RequirementSignatureSelf, nullptr, protocol,
+ root, 1);
}
const RequirementSource *RequirementSource::forNestedTypeNameMatch(
- GenericSignatureBuilder &builder) {
- REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(NestedTypeNameMatch, nullptr);
+ PotentialArchetype *root) {
+ auto &builder = *root->getBuilder();
+ REQUIREMENT_SOURCE_FACTORY_BODY(NestedTypeNameMatch, nullptr, root, nullptr,
+ 0);
}
const RequirementSource *RequirementSource::viaAbstractProtocolRequirement(
GenericSignatureBuilder &builder,
ProtocolDecl *protocol) const {
- REQUIREMENT_SOURCE_FACTORY_BODY(ProtocolRequirement, this, protocol);
+ REQUIREMENT_SOURCE_FACTORY_BODY(ProtocolRequirement, this, protocol,
+ nullptr, 0);
}
const RequirementSource *RequirementSource::viaSuperclass(
GenericSignatureBuilder &builder,
ProtocolConformance *conformance) const {
- REQUIREMENT_SOURCE_FACTORY_BODY(Superclass, this, conformance);
+ REQUIREMENT_SOURCE_FACTORY_BODY(Superclass, this, conformance, nullptr, 0);
}
const RequirementSource *RequirementSource::viaConcrete(
GenericSignatureBuilder &builder,
ProtocolConformance *conformance) const {
- REQUIREMENT_SOURCE_FACTORY_BODY(Concrete, this, conformance);
+ REQUIREMENT_SOURCE_FACTORY_BODY(Concrete, this, conformance, nullptr, 0);
}
const RequirementSource *RequirementSource::viaParent(
- GenericSignatureBuilder &builder) const {
- REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(Parent, this);
+ GenericSignatureBuilder &builder,
+ AssociatedTypeDecl *assocType) const {
+ REQUIREMENT_SOURCE_FACTORY_BODY(Parent, this, assocType, nullptr, 0);
}
-#undef REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE
#undef REQUIREMENT_SOURCE_FACTORY_BODY
+PotentialArchetype *RequirementSource::getRootPotentialArchetype() const {
+ /// Find the root.
+ auto root = this;
+ while (auto parent = root->parent)
+ root = parent;
+
+ // If the root archetype is in extra storage, grab it from there.
+ if (root->numTrailingObjects(OverloadToken<PotentialArchetype *>()) == 1)
+ return root->getTrailingObjects<PotentialArchetype *>()[0];
+
+ // Otherwise, it's in inline storage.
+ assert(storageKind == StorageKind::RootArchetype);
+ return storage.rootArchetype;
+}
+
ProtocolDecl *RequirementSource::getProtocolDecl() const {
switch (storageKind) {
- case StorageKind::None:
+ case StorageKind::RootArchetype:
case StorageKind::TypeRepr:
case StorageKind::RequirementRepr:
return nullptr;
@@ -307,6 +414,9 @@
return storage.conformance->getProtocol();
return nullptr;
+
+ case StorageKind::AssociatedTypeDecl:
+ return storage.assocType->getProtocol();
}
}
@@ -365,6 +475,9 @@
if (parent) {
parent->print(out, srcMgr);
out << " -> ";
+ } else {
+ auto pa = getRootPotentialArchetype();
+ out << pa->getDebugName() << ": ";
}
switch (kind) {
@@ -413,7 +526,7 @@
};
switch (storageKind) {
- case StorageKind::None:
+ case StorageKind::RootArchetype:
break;
case StorageKind::TypeRepr:
@@ -432,9 +545,53 @@
<< storage.conformance->getProtocol()->getName() << ")";
}
break;
+
+ case StorageKind::AssociatedTypeDecl:
+ out << " (" << storage.assocType->getProtocol()->getName()
+ << "::" << storage.assocType->getName() << ")";
+ break;
}
}
+const RequirementSource *FloatingRequirementSource::getSource(
+ PotentialArchetype *pa) const {
+ switch (kind) {
+ case Resolved:
+ return storage.get<const RequirementSource *>();
+
+ case Explicit:
+ if (auto requirementRepr = storage.dyn_cast<const RequirementRepr *>())
+ return RequirementSource::forExplicit(pa, requirementRepr);
+ if (auto typeRepr = storage.dyn_cast<const TypeRepr *>())
+ return RequirementSource::forExplicit(pa, typeRepr);
+ return RequirementSource::forAbstract(pa);
+
+ case Inferred:
+ return RequirementSource::forInferred(pa, storage.get<const TypeRepr *>());
+ }
+}
+
+SourceLoc FloatingRequirementSource::getLoc() const {
+ if (auto source = storage.dyn_cast<const RequirementSource *>())
+ return source->getLoc();
+
+ if (auto typeRepr = storage.dyn_cast<const TypeRepr *>())
+ return typeRepr->getLoc();
+
+ if (auto requirementRepr = storage.dyn_cast<const RequirementRepr *>()) {
+ switch (requirementRepr->getKind()) {
+ case RequirementReprKind::LayoutConstraint:
+ case RequirementReprKind::TypeConstraint:
+ return requirementRepr->getColonLoc();
+
+ case RequirementReprKind::SameType:
+ return requirementRepr->getEqualLoc();
+ }
+ }
+
+ return SourceLoc();
+}
+
GenericSignatureBuilder::PotentialArchetype::~PotentialArchetype() {
for (const auto &nested : NestedTypes) {
for (auto pa : nested.second) {
@@ -501,38 +658,44 @@
--builder.Impl->NumUnresolvedNestedTypes;
}
-Optional<std::pair<Type, const RequirementSource *>>
-PotentialArchetype::findAnyConcreteTypeSourceAsWritten() const {
- using Result = std::pair<Type, const RequirementSource *>;
-
- // Local function to look for a source in the given potential archetype.
- auto lookInPA = [](const PotentialArchetype *pa) -> Optional<Result> {
- for (unsigned i : indices(pa->concreteTypeSources)) {
- auto source = pa->concreteTypeSources[i];
- if (source->getLoc().isValid())
- return Result(pa->concreteTypes[i], source);
- }
-
- return None;
- };
-
- // If we have a concrete type source with location information, use that.
- if (auto result = lookInPA(this))
- return result;
-
+Optional<ConcreteConstraint>
+EquivalenceClass::findAnyConcreteConstraintAsWritten(
+ PotentialArchetype *preferredPA) const {
// If we don't have a concrete type, there's no source.
- auto rep = getRepresentative();
- if (!rep->isConcreteType()) return None;
+ if (!concreteType) return None;
- // Otherwise, go look for the source.
- for (auto pa : rep->getEquivalenceClassMembers()) {
- if (pa != this) {
- if (auto result = lookInPA(pa))
+ // Go look for a source with source-location information.
+ Optional<ConcreteConstraint> result;
+ for (const auto &constraint : concreteTypeConstraints) {
+ if (constraint.source->getLoc().isValid()) {
+ result = constraint;
+ if (!preferredPA || constraint.archetype == preferredPA)
return result;
}
}
- return None;
+ return result;
+}
+
+Optional<ConcreteConstraint>
+EquivalenceClass::findAnySuperclassConstraintAsWritten(
+ PotentialArchetype *preferredPA) const {
+ // If we don't have a superclass, there's no source.
+ if (!superclass) return None;
+
+ // Go look for a source with source-location information.
+ Optional<ConcreteConstraint> result;
+ for (const auto &constraint : superclassConstraints) {
+ if (constraint.source->getLoc().isValid() &&
+ constraint.concreteType->isEqual(superclass)) {
+ result = constraint;
+
+ if (!preferredPA || constraint.archetype == preferredPA)
+ return result;
+ }
+ }
+
+ return result;
}
bool GenericSignatureBuilder::updateRequirementSource(
@@ -570,8 +733,16 @@
// Conformance to this protocol is redundant; update the requirement source
// appropriately.
- auto superclassSource =
- pa->getSuperclassSource()->viaSuperclass(*this, conformance->getConcrete());
+ auto paEquivClass = pa->getOrCreateEquivalenceClass();
+ const RequirementSource *superclassSource;
+ if (auto writtenSource =
+ paEquivClass->findAnySuperclassConstraintAsWritten(pa))
+ superclassSource = writtenSource->source;
+ else
+ superclassSource = paEquivClass->superclassConstraints.front().source;
+
+ superclassSource =
+ superclassSource->viaSuperclass(*this, conformance->getConcrete());
updateRequirementSource(protoSource, superclassSource);
return superclassSource;
}
@@ -603,7 +774,6 @@
static ResolvedType forNewTypeAlias(PotentialArchetype *pa) {
assert(pa->getParent() && pa->getTypeAliasDecl() &&
- pa->concreteTypes.empty() &&
pa->getEquivalenceClassMembers().size() == 1 &&
"not a new typealias");
return ResolvedType(pa);
@@ -635,7 +805,7 @@
if (!concreteType) return;
// Add the same-type constraint.
- auto nestedSource = superSource->viaParent(builder);
+ auto nestedSource = superSource->viaParent(builder, assocType);
concreteType = superConformance->getDeclContext()
->mapTypeOutOfContext(concreteType);
@@ -709,7 +879,8 @@
// and make it equivalent to the first potential archetype we encountered.
auto otherPA = new PotentialArchetype(this, assocType);
known->second.push_back(otherPA);
- auto sameNamedSource = RequirementSource::forNestedTypeNameMatch(builder);
+ auto sameNamedSource = RequirementSource::forNestedTypeNameMatch(
+ known->second.front());
builder.addSameTypeRequirement(known->second.front(), otherPA,
sameNamedSource);
@@ -921,11 +1092,12 @@
// These requirements are all implied based on the parent's concrete
// conformance.
- auto source = parentConcreteSource->viaConcrete(builder, /*FIXME: */nullptr)
- ->viaParent(builder);
auto assocType = nestedPA->getResolvedAssociatedType();
if (!assocType) return;
+ auto source = parentConcreteSource->viaConcrete(builder, /*FIXME: */nullptr)
+ ->viaParent(builder, assocType);
+
// FIXME: Get the conformance from the parent.
auto conformance = lookupConformance(assocType->getProtocol());
@@ -964,9 +1136,6 @@
if (rep != this)
repNested = rep->getNestedType(nestedName, builder);
- auto sameNestedTypeSource =
- RequirementSource::forNestedTypeNameMatch(builder);
-
// Attempt to resolve this nested type to an associated type
// of one of the protocols to which the parent potential
// archetype conforms.
@@ -1032,9 +1201,11 @@
ProtocolConformanceRef(proto));
type = type.subst(subMap, SubstFlags::UseErrorType);
- builder.addSameTypeRequirement(ResolvedType::forNewTypeAlias(pa),
- builder.resolve(type),
- sameNestedTypeSource, diagnoseMismatch);
+ builder.addSameTypeRequirement(
+ ResolvedType::forNewTypeAlias(pa),
+ builder.resolve(type),
+ RequirementSource::forNestedTypeNameMatch(pa),
+ diagnoseMismatch);
} else
continue;
@@ -1047,14 +1218,18 @@
// Produce a same-type constraint between the two same-named
// potential archetypes.
- builder.addSameTypeRequirement(pa, nested.front(), sameNestedTypeSource,
- diagnoseMismatch);
+ builder.addSameTypeRequirement(
+ pa, nested.front(),
+ RequirementSource::forNestedTypeNameMatch(pa),
+ diagnoseMismatch);
} else {
nested.push_back(pa);
if (repNested) {
- builder.addSameTypeRequirement(pa, repNested, sameNestedTypeSource,
- diagnoseMismatch);
+ builder.addSameTypeRequirement(
+ pa, repNested,
+ RequirementSource::forNestedTypeNameMatch(pa),
+ diagnoseMismatch);
}
}
@@ -1081,7 +1256,8 @@
if (isConcreteType()) {
for (auto equivT : rep->getEquivalenceClassMembers()) {
concretizeNestedTypeFromConcreteParent(
- equivT, sameNestedTypeSource, nestedPA, builder,
+ equivT, RequirementSource::forNestedTypeNameMatch(nestedPA),
+ nestedPA, builder,
[&](ProtocolDecl *proto) -> ProtocolConformanceRef {
auto depTy = nestedPA->getDependentType({},
/*allowUnresolved=*/true)
@@ -1109,7 +1285,7 @@
// somewhere else.
bool failed = builder.addConformanceRequirement(
this, assocType->getProtocol(),
- RequirementSource::forInferred(builder, nullptr));
+ RequirementSource::forInferred(this, nullptr));
(void)failed;
// Trigger the construction of nested types with this name.
@@ -1341,31 +1517,40 @@
else
Out.indent(Indent) << getNestedName();
+ auto equivClass = getEquivalenceClassIfPresent();
+
// Print superclass.
- if (Superclass) {
- Out << " : ";
- Superclass.print(Out);
- Out << " ";
- if (!SuperclassSource->isDerivedRequirement())
- Out << "*";
- Out << "[";
- SuperclassSource->print(Out, SrcMgr);
- Out << "]";
+ if (equivClass && equivClass->superclass) {
+ for (const auto &constraint : equivClass->superclassConstraints) {
+ if (constraint.archetype != this) continue;
+
+ Out << " : ";
+ constraint.concreteType.print(Out);
+
+ Out << " ";
+ if (!constraint.source->isDerivedRequirement())
+ Out << "*";
+ Out << "[";
+ constraint.source->print(Out, SrcMgr);
+ Out << "]";
+ }
}
// Print concrete type.
- for (unsigned i : indices(concreteTypes)) {
- auto concreteType = concreteTypes[i];
- Out << " == ";
- concreteType.print(Out);
+ if (equivClass && equivClass->concreteType) {
+ for (const auto &constraint : equivClass->concreteTypeConstraints) {
+ if (constraint.archetype != this) continue;
- auto concreteTypeSource = concreteTypeSources[i];
- Out << " ";
- if (!concreteTypeSource->isDerivedRequirement())
- Out << "*";
- Out << "[";
- concreteTypeSource->print(Out, SrcMgr);
- Out << "]";
+ Out << " == ";
+ constraint.concreteType.print(Out);
+
+ Out << " ";
+ if (!constraint.source->isDerivedRequirement())
+ Out << "*";
+ Out << "[";
+ constraint.source->print(Out, SrcMgr);
+ Out << "]";
+ }
}
// Print requirements.
@@ -1595,19 +1780,19 @@
Visited.erase(Proto);
};
+ auto concreteSelf = T->getDependentType({}, /*allowUnresolved=*/true);
+ auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions(
+ Proto, concreteSelf, ProtocolConformanceRef(Proto));
+
// Use the requirement signature to avoid rewalking the entire protocol. This
// cannot compute the requirement signature directly, because that may be
// infinitely recursive: this code is also used to construct it.
if (Proto->isRequirementSignatureComputed()) {
auto reqSig = Proto->getRequirementSignature();
- auto concreteSelf = T->getDependentType({}, /*allowUnresolved=*/true);
- auto subMap = SubstitutionMap::getProtocolSubstitutions(
- Proto, concreteSelf, ProtocolConformanceRef(Proto));
-
auto innerSource = Source->viaAbstractProtocolRequirement(*this, Proto);
for (auto rawReq : reqSig->getRequirements()) {
- auto req = rawReq.subst(subMap);
+ auto req = rawReq.subst(protocolSubMap);
assert(req && "substituting Self in requirement shouldn't fail");
if (addRequirement(*req, innerSource, Visited))
return true;
@@ -1633,6 +1818,12 @@
if (addInheritedRequirements(AssocType, AssocPA, Source, Visited))
return true;
}
+ if (auto WhereClause = AssocType->getTrailingWhereClause()) {
+ auto innerSource = Source->viaAbstractProtocolRequirement(*this, Proto);
+ for (auto &req : WhereClause->getRequirements()) {
+ addRequirement(&req, innerSource, &protocolSubMap);
+ }
+ }
} else if (auto TypeAlias = dyn_cast<TypeAliasDecl>(Member)) {
// FIXME: this should check that the typealias is makes sense (e.g. has
// the same/compatible type as typealiases in parent protocols) and
@@ -1642,8 +1833,6 @@
// unresolved PA that prints an error later.
(void)TypeAlias;
}
-
- // FIXME: Requirement declarations.
}
return false;
@@ -1677,28 +1866,11 @@
return false;
}
-bool GenericSignatureBuilder::addSuperclassRequirement(PotentialArchetype *T,
- Type Superclass,
- const RequirementSource *Source) {
- T = T->getRepresentative();
-
- // Make sure the concrete type fulfills the superclass requirement
- // of the archetype.
- if (T->isConcreteType()) {
- Type concrete = T->getConcreteType();
- if (!Superclass->isExactSuperclassOf(concrete, getLazyResolver())) {
- if (auto source = T->findAnyConcreteTypeSourceAsWritten()) {
- Diags.diagnose(source->second->getLoc(), diag::type_does_not_inherit,
- T->getDependentType(/*FIXME:*/{ },
- /*allowUnresolved=*/true),
- source->first, Superclass)
- .highlight(Source->getLoc());
- }
- return true;
- }
-
- return false;
- }
+bool GenericSignatureBuilder::updateSuperclass(
+ PotentialArchetype *T,
+ Type superclass,
+ const RequirementSource *source) {
+ auto equivClass = T->getOrCreateEquivalenceClass();
// Local function to handle the update of superclass conformances
// when the superclass constraint changes.
@@ -1724,73 +1896,49 @@
}
};
- // If T already has a superclass, make sure it's related.
- if (T->Superclass) {
- // TODO: In principle, this could be isBindableToSuperclassOf instead of
- // isExactSubclassOf. If you had:
- //
- // class Foo<T>
- // class Bar: Foo<Int>
- //
- // func foo<T, U where U: Foo<T>, U: Bar>(...) { ... }
- //
- // then the second constraint should be allowed, constraining U to Bar
- // and secondarily imposing a T == Int constraint.
- if (T->Superclass->isExactSuperclassOf(Superclass, nullptr)) {
- T->Superclass = Superclass;
-
- // We've strengthened the bound, so update superclass conformances.
- updateSuperclassConformances();
- // TODO: Similar to the above, a more general isBindableToSuperclassOf
- // base class constraint could potentially introduce secondary constraints.
- // If you had:
- //
- // class Foo<T>
- // class Bar: Foo<Int>
- //
- // func foo<T, U where U: Bar, U: Foo<T>>(...) { ... }
- //
- // then the second `U: Foo<T>` constraint introduces a `T == Int`
- // constraint.
- } else if (!Superclass->isExactSuperclassOf(T->Superclass, nullptr)) {
- if (Source->getLoc().isValid()) {
- // Figure out what kind of subject we have; it will affect the
- // diagnostic.
- auto subjectType = T->getDependentType(/*FIXME: */{ }, true);
- unsigned kind;
- if (auto gp = subjectType->getAs<GenericTypeParamType>()) {
- if (gp->getDecl() &&
- isa<ProtocolDecl>(gp->getDecl()->getDeclContext())) {
- kind = 1;
- subjectType = cast<ProtocolDecl>(gp->getDecl()->getDeclContext())
- ->getDeclaredInterfaceType();
- } else {
- kind = 0;
- }
- } else {
- kind = 2;
- }
-
- Diags.diagnose(Source->getLoc(), diag::requires_superclass_conflict,
- kind, subjectType, T->Superclass, Superclass)
- .highlight(T->SuperclassSource->getLoc());
- }
- return true;
- }
-
- updateRequirementSource(T->SuperclassSource, Source);
+ // If we haven't yet recorded a superclass constraint for this equivalence
+ // class, do so now.
+ if (!equivClass->superclass) {
+ equivClass->superclass = superclass;
+ updateSuperclassConformances();
return false;
}
- // Set the superclass.
- T->Superclass = Superclass;
- T->SuperclassSource = Source;
+ // T already has a superclass; make sure it's related.
+ auto existingSuperclass = equivClass->superclass;
+ // TODO: In principle, this could be isBindableToSuperclassOf instead of
+ // isExactSubclassOf. If you had:
+ //
+ // class Foo<T>
+ // class Bar: Foo<Int>
+ //
+ // func foo<T, U where U: Foo<T>, U: Bar>(...) { ... }
+ //
+ // then the second constraint should be allowed, constraining U to Bar
+ // and secondarily imposing a T == Int constraint.
+ if (existingSuperclass->isExactSuperclassOf(superclass, nullptr)) {
+ equivClass->superclass = superclass;
- // Update based on these conformances.
- updateSuperclassConformances();
+ // We've strengthened the bound, so update superclass conformances.
+ updateSuperclassConformances();
+ return false;
+ }
+
return false;
}
+bool GenericSignatureBuilder::addSuperclassRequirement(
+ PotentialArchetype *T,
+ Type superclass,
+ const RequirementSource *source) {
+ // Record the constraint.
+ T->getOrCreateEquivalenceClass()->superclassConstraints
+ .push_back(ConcreteConstraint{T, superclass, source});
+
+ // Update the equivalence class with the constraint.
+ return updateSuperclass(T, superclass, source);
+}
+
void GenericSignatureBuilder::PotentialArchetype::addSameTypeConstraint(
PotentialArchetype *otherPA,
const RequirementSource *source) {
@@ -1831,8 +1979,10 @@
// Decide which potential archetype is to be considered the representative.
// It doesn't specifically matter which we use, but it's a minor optimization
// to prefer the canonical type.
- if (compareDependentTypes(&T2, &T1) < 0)
+ if (compareDependentTypes(&T2, &T1) < 0) {
std::swap(T1, T2);
+ std::swap(OrigT1, OrigT2);
+ }
// Merge any concrete constraints.
Type concrete1 = T1->getConcreteType();
@@ -1882,17 +2032,35 @@
delete equivClass2;
};
+ // Same-type-to-concrete requirements.
+ if (equivClass2 && equivClass2->concreteType) {
+ if (!equivClass->concreteType)
+ equivClass->concreteType = equivClass2->concreteType;
+
+ equivClass->concreteTypeConstraints.insert(
+ equivClass->concreteTypeConstraints.end(),
+ equivClass2->concreteTypeConstraints.begin(),
+ equivClass2->concreteTypeConstraints.end());
+ }
+
// Make T1 the representative of T2, merging the equivalence classes.
T2->representativeOrEquivClass = T1;
- // Same-type-to-concrete requirement.
- if (equivClass2 && equivClass2->concreteType && !equivClass->concreteType)
- equivClass->concreteType = equivClass2->concreteType;
-
// Superclass requirements.
- if (T2->Superclass) {
- addSuperclassRequirement(T1, T2->getSuperclass(),
- T2->getSuperclassSource());
+ if (equivClass2 && equivClass2->superclass) {
+ const RequirementSource *source2;
+ if (auto existingSource2 =
+ equivClass2->findAnySuperclassConstraintAsWritten(OrigT2))
+ source2 = existingSource2->source;
+ else
+ source2 = equivClass2->superclassConstraints.front().source;
+
+ (void)updateSuperclass(T1, equivClass2->superclass, source2);
+
+ equivClass->superclassConstraints.insert(
+ equivClass->concreteTypeConstraints.end(),
+ equivClass2->superclassConstraints.begin(),
+ equivClass2->superclassConstraints.end());
}
// Add all of the protocol conformance requirements of T2 to T1.
@@ -1902,13 +2070,13 @@
}
// Recursively merge the associated types of T2 into T1.
- auto sameNestedTypeSource = RequirementSource::forNestedTypeNameMatch(*this);
for (auto equivT2 : equivClass2Members) {
for (auto T2Nested : equivT2->NestedTypes) {
auto T1Nested = T1->getNestedType(T2Nested.first, *this);
- if (addSameTypeRequirement(T1Nested, T2Nested.second.front(),
- sameNestedTypeSource,
- [&](Type type1, Type type2) {
+ if (addSameTypeRequirement(
+ T1Nested, T2Nested.second.front(),
+ RequirementSource::forNestedTypeNameMatch(T1Nested),
+ [&](Type type1, Type type2) {
Diags.diagnose(Source->getLoc(),
diag::requires_same_type_conflict,
T1Nested->isGenericParam(),
@@ -1926,21 +2094,25 @@
PotentialArchetype *T,
Type Concrete,
const RequirementSource *Source) {
+ auto rep = T->getRepresentative();
+ auto equivClass = rep->getOrCreateEquivalenceClass();
+
// Record the concrete type and its source.
- T->concreteTypes.push_back(Concrete);
- T->concreteTypeSources.push_back(Source);
+ equivClass->concreteTypeConstraints.push_back(
+ ConcreteConstraint{T, Concrete, Source});
// If we've already been bound to a type, match that type.
- if (auto oldConcrete = T->getConcreteType()) {
+ if (equivClass->concreteType) {
bool mismatch = addSameTypeRequirement(
- oldConcrete, Concrete, Source, [&](Type type1, Type type2) {
- Diags.diagnose(Source->getLoc(),
- diag::requires_same_type_conflict,
- T->isGenericParam(),
- T->getDependentType(/*FIXME: */{ }, true), type1,
- type2);
+ equivClass->concreteType, Concrete, Source,
+ [&](Type type1, Type type2) {
+ Diags.diagnose(Source->getLoc(),
+ diag::requires_same_type_conflict,
+ T->isGenericParam(),
+ T->getDependentType(/*FIXME: */{ }, true), type1,
+ type2);
- });
+ });
if (mismatch) return true;
@@ -1949,10 +2121,7 @@
}
// Record the requirement.
- auto rep = T->getRepresentative();
- auto equivClass = rep->getOrCreateEquivalenceClass();
- if (!equivClass->concreteType)
- equivClass->concreteType = Concrete;
+ equivClass->concreteType = Concrete;
// Make sure the concrete type fulfills the requirements on the archetype.
// FIXME: Move later...
@@ -1986,24 +2155,6 @@
updateRequirementSource(conforms.second, concreteSource);
}
- // Make sure the concrete type fulfills the superclass requirement
- // of the archetype.
- if (rep->Superclass) {
- if (!rep->Superclass->isExactSuperclassOf(Concrete, getLazyResolver())) {
- Diags.diagnose(Source->getLoc(), diag::type_does_not_inherit,
- rep->getDependentType(/*FIXME: */{ },
- /*allowUnresolved=*/true),
- Concrete, rep->Superclass)
- .highlight(rep->SuperclassSource->getLoc());
- return true;
- }
-
- // The superclass requirement is made redundant by the concrete type
- // assignment.
- auto concreteSource = Source->viaConcrete(*this, nullptr);
- updateRequirementSource(rep->SuperclassSource, concreteSource);
- }
-
// Eagerly resolve any existing nested types to their concrete forms (others
// will be "concretized" as they are constructed, in getNestedType).
for (auto equivT : rep->getEquivalenceClassMembers()) {
@@ -2020,17 +2171,18 @@
}
bool GenericSignatureBuilder::addSameTypeRequirementBetweenConcrete(
- Type type1, Type type2, const RequirementSource *source,
+ Type type1, Type type2, FloatingRequirementSource source,
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
// Local class to handle matching the two sides of the same-type constraint.
class ReqTypeMatcher : public TypeMatcher<ReqTypeMatcher> {
GenericSignatureBuilder &builder;
- const RequirementSource *source;
+ FloatingRequirementSource source;
Type outerType1, outerType2;
llvm::function_ref<void(Type, Type)> diagnoseMismatch;
public:
- ReqTypeMatcher(GenericSignatureBuilder &builder, const RequirementSource *source,
+ ReqTypeMatcher(GenericSignatureBuilder &builder,
+ FloatingRequirementSource source,
Type outerType1, Type outerType2,
llvm::function_ref<void(Type, Type)> diagnoseMismatch)
: builder(builder), source(source), outerType1(outerType1),
@@ -2056,29 +2208,31 @@
return !matcher.match(type1, type2);
}
-bool GenericSignatureBuilder::addSameTypeRequirement(UnresolvedType paOrT1,
- UnresolvedType paOrT2,
- const RequirementSource *source) {
+bool GenericSignatureBuilder::addSameTypeRequirement(
+ UnresolvedType paOrT1,
+ UnresolvedType paOrT2,
+ FloatingRequirementSource source) {
return addSameTypeRequirement(resolve(paOrT1), resolve(paOrT2), source);
}
bool GenericSignatureBuilder::addSameTypeRequirement(
- UnresolvedType paOrT1, UnresolvedType paOrT2, const RequirementSource *source,
+ UnresolvedType paOrT1, UnresolvedType paOrT2,
+ FloatingRequirementSource source,
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
return addSameTypeRequirement(resolve(paOrT1), resolve(paOrT2), source,
diagnoseMismatch);
}
bool GenericSignatureBuilder::addSameTypeRequirement(ResolvedType paOrT1,
ResolvedType paOrT2,
- const RequirementSource *source) {
+ FloatingRequirementSource source) {
return addSameTypeRequirement(paOrT1, paOrT2, source,
[&](Type type1, Type type2) {
- Diags.diagnose(source->getLoc(), diag::requires_same_concrete_type,
+ Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
type1, type2);
});
}
bool GenericSignatureBuilder::addSameTypeRequirement(
- ResolvedType paOrT1, ResolvedType paOrT2, const RequirementSource *source,
+ ResolvedType paOrT1, ResolvedType paOrT2, FloatingRequirementSource source,
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
auto pa1 = paOrT1.getPotentialArchetype();
auto pa2 = paOrT2.getPotentialArchetype();
@@ -2087,12 +2241,13 @@
// If both sides of the requirement are type parameters, equate them.
if (pa1 && pa2) {
- return addSameTypeRequirementBetweenArchetypes(pa1, pa2, source);
+ return addSameTypeRequirementBetweenArchetypes(pa1, pa2,
+ source.getSource(pa1));
// If just one side is a type parameter, map it to a concrete type.
} else if (pa1) {
- return addSameTypeRequirementToConcrete(pa1, t2, source);
+ return addSameTypeRequirementToConcrete(pa1, t2, source.getSource(pa1));
} else if (pa2) {
- return addSameTypeRequirementToConcrete(pa2, t1, source);
+ return addSameTypeRequirementToConcrete(pa2, t1, source.getSource(pa2));
} else {
return addSameTypeRequirementBetweenConcrete(t1, t2, source,
diagnoseMismatch);
@@ -2155,10 +2310,10 @@
// Explicit requirement.
if (typeRepr)
- return RequirementSource::forExplicit(*this, typeRepr);
+ return RequirementSource::forExplicit(pa, typeRepr);
// An abstract explicit requirement.
- return RequirementSource::forAbstract(*this);
+ return RequirementSource::forAbstract(pa);
};
// Protocol requirement.
@@ -2184,13 +2339,23 @@
});
}
-bool GenericSignatureBuilder::addRequirement(const RequirementRepr *Req) {
- auto source = RequirementSource::forExplicit(*this, Req);
+bool GenericSignatureBuilder::addRequirement(const RequirementRepr *Req,
+ const RequirementSource *source,
+ const SubstitutionMap *subMap) {
+ auto localSource = source ? FloatingRequirementSource(source)
+ : FloatingRequirementSource::forExplicit(Req);
+
+ auto subst = [&](Type t) {
+ if (subMap)
+ return t.subst(*subMap);
+
+ return t;
+ };
switch (Req->getKind()) {
case RequirementReprKind::LayoutConstraint: {
// FIXME: Need to do something here.
- PotentialArchetype *PA = resolveArchetype(Req->getSubject());
+ PotentialArchetype *PA = resolveArchetype(subst(Req->getSubject()));
if (!PA) {
// FIXME: Poor location information.
// FIXME: Delay diagnostic until after type validation?
@@ -2199,14 +2364,15 @@
return true;
}
- if (addLayoutRequirement(PA, Req->getLayoutConstraint(), source))
+ if (addLayoutRequirement(PA, Req->getLayoutConstraint(),
+ localSource.getSource(PA)))
return true;
return false;
}
case RequirementReprKind::TypeConstraint: {
- PotentialArchetype *PA = resolveArchetype(Req->getSubject());
+ PotentialArchetype *PA = resolveArchetype(subst(Req->getSubject()));
if (!PA) {
// FIXME: Poor location information.
// FIXME: Delay diagnostic until after type validation?
@@ -2217,7 +2383,8 @@
// Check whether this is a supertype requirement.
if (Req->getConstraint()->getClassOrBoundGenericClass()) {
- return addSuperclassRequirement(PA, Req->getConstraint(), source);
+ return addSuperclassRequirement(PA, Req->getConstraint(),
+ localSource.getSource(PA));
}
SmallVector<ProtocolDecl *, 4> ConformsTo;
@@ -2228,7 +2395,7 @@
// Add each of the protocols.
for (auto Proto : ConformsTo)
- if (addConformanceRequirement(PA, Proto, source))
+ if (addConformanceRequirement(PA, Proto, localSource.getSource(PA)))
return true;
return false;
@@ -2246,22 +2413,22 @@
}
return addRequirement(Requirement(RequirementKind::SameType,
- Req->getFirstType(),
- Req->getSecondType()),
- source);
+ subst(Req->getFirstType()),
+ subst(Req->getSecondType())),
+ localSource);
}
llvm_unreachable("Unhandled requirement?");
}
bool GenericSignatureBuilder::addRequirement(const Requirement &req,
- const RequirementSource *source) {
+ FloatingRequirementSource source) {
llvm::SmallPtrSet<ProtocolDecl *, 8> Visited;
return addRequirement(req, source, Visited);
}
bool GenericSignatureBuilder::addRequirement(
- const Requirement &req, const RequirementSource *source,
+ const Requirement &req, FloatingRequirementSource source,
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) {
switch (req.getKind()) {
case RequirementKind::Superclass: {
@@ -2270,7 +2437,8 @@
if (!pa) return false;
assert(req.getSecondType()->getClassOrBoundGenericClass());
- return addSuperclassRequirement(pa, req.getSecondType(), source);
+ return addSuperclassRequirement(pa, req.getSecondType(),
+ source.getSource(pa));
}
case RequirementKind::Layout: {
@@ -2278,7 +2446,8 @@
PotentialArchetype *pa = resolveArchetype(req.getFirstType());
if (!pa) return false;
- return addLayoutRequirement(pa, req.getLayoutConstraint(), source);
+ return addLayoutRequirement(pa, req.getLayoutConstraint(),
+ source.getSource(pa));
}
case RequirementKind::Conformance: {
@@ -2292,10 +2461,11 @@
// Add each of the protocols.
for (auto proto : conformsTo) {
if (Visited.count(proto)) {
- markPotentialArchetypeRecursive(pa, proto, source);
+ markPotentialArchetypeRecursive(pa, proto, source.getSource(pa));
continue;
}
- if (addConformanceRequirement(pa, proto, source, Visited)) return true;
+ if (addConformanceRequirement(pa, proto, source.getSource(pa), Visited))
+ return true;
}
return false;
@@ -2305,8 +2475,8 @@
return addSameTypeRequirement(
req.getFirstType(), req.getSecondType(), source,
[&](Type type1, Type type2) {
- if (source->getLoc().isValid())
- Diags.diagnose(source->getLoc(), diag::requires_same_concrete_type,
+ if (source.getLoc().isValid())
+ Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
type1, type2);
});
}
@@ -2318,25 +2488,11 @@
class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
GenericSignatureBuilder &Builder;
TypeRepr *typeRepr;
- unsigned MinDepth;
- unsigned MaxDepth;
-
- /// We cannot add requirements to archetypes from outer generic parameter
- /// lists.
- bool isOuterArchetype(PotentialArchetype *PA) {
- unsigned ParamDepth = PA->getRootGenericParamKey().Depth;
- assert(ParamDepth <= MaxDepth);
- (void) MaxDepth;
- return ParamDepth < MinDepth;
- }
public:
InferRequirementsWalker(GenericSignatureBuilder &builder,
- TypeRepr *typeRepr,
- unsigned MinDepth,
- unsigned MaxDepth)
- : Builder(builder), typeRepr(typeRepr), MinDepth(MinDepth),
- MaxDepth(MaxDepth) { }
+ TypeRepr *typeRepr)
+ : Builder(builder), typeRepr(typeRepr) { }
Action walkToTypePost(Type ty) override {
auto boundGeneric = ty->getAs<BoundGenericType>();
@@ -2364,7 +2520,7 @@
// Handle the requirements.
// FIXME: Inaccurate TypeReprs.
- auto source = RequirementSource::forInferred(Builder, typeRepr);
+ auto source = FloatingRequirementSource::forInferred(typeRepr);
for (const auto &rawReq : genericSig->getRequirements()) {
if (auto req = rawReq.subst(getTypeSubstitution,
Builder.getLookupConformanceFn()))
@@ -2375,14 +2531,11 @@
}
};
-void GenericSignatureBuilder::inferRequirements(TypeLoc type,
- unsigned minDepth,
- unsigned maxDepth) {
+void GenericSignatureBuilder::inferRequirements(TypeLoc type) {
if (!type.getType())
return;
// FIXME: Crummy source-location information.
- InferRequirementsWalker walker(*this, type.getTypeRepr(),
- minDepth, maxDepth);
+ InferRequirementsWalker walker(*this, type.getTypeRepr());
type.getType().walk(walker);
}
@@ -2391,11 +2544,8 @@
if (genericParams == nullptr)
return;
- unsigned depth = genericParams->getDepth();
for (auto P : *params)
- inferRequirements(P->getTypeLoc(),
- /*minDepth=*/depth,
- /*maxDepth=*/depth);
+ inferRequirements(P->getTypeLoc());
}
/// Perform typo correction on the given nested type, producing the
@@ -2548,15 +2698,17 @@
visitPotentialArchetypes([&](PotentialArchetype *archetype) {
if (archetype != archetype->getRepresentative()) return;
- if (archetype->isConcreteType()) {
+ auto equivClass = archetype->getOrCreateEquivalenceClass();
+ if (equivClass->concreteType) {
// Check for recursive same-type bindings.
if (isRecursiveConcreteType(archetype, /*isSuperclass=*/false)) {
- if (auto source = archetype->findAnyConcreteTypeSourceAsWritten()) {
- Diags.diagnose(source->second->getLoc(),
+ if (auto constraint =
+ equivClass->findAnyConcreteConstraintAsWritten()) {
+ Diags.diagnose(constraint->source->getLoc(),
diag::recursive_same_type_constraint,
archetype->getDependentType(genericParams,
/*allowUnresolved=*/true),
- source->first);
+ constraint->concreteType);
}
archetype->RecursiveConcreteType = true;
@@ -2566,25 +2718,29 @@
}
// Check for recursive superclass bindings.
- if (archetype->getSuperclass()) {
+ if (equivClass->superclass) {
if (isRecursiveConcreteType(archetype, /*isSuperclass=*/true)) {
- if (archetype->SuperclassSource->getLoc().isValid())
- Diags.diagnose(archetype->SuperclassSource->getLoc(),
+ if (auto source = equivClass->findAnySuperclassConstraintAsWritten()) {
+ Diags.diagnose(source->source->getLoc(),
diag::recursive_superclass_constraint,
- archetype->getDependentType(genericParams,
+ source->archetype->getDependentType(
+ genericParams,
/*allowUnresolved=*/true),
- archetype->getSuperclass());
+ equivClass->superclass);
+ }
archetype->RecursiveSuperclassType = true;
+ } else {
+ checkRedundantSuperclassConstraints(genericParams, archetype);
}
}
});
- SmallPtrSet<PotentialArchetype *, 4> visited;
-
// Check for generic parameters which have been made concrete or equated
// with each other.
if (!allowConcreteGenericParams) {
+ SmallPtrSet<PotentialArchetype *, 4> visited;
+
unsigned depth = 0;
for (const auto &gp : Impl->GenericParams)
depth = std::max(depth, gp->getDepth());
@@ -2600,9 +2756,10 @@
// Don't allow a generic parameter to be equivalent to a concrete type,
// because then we don't actually have a parameter.
- if (rep->getConcreteType()) {
- if (auto source = rep->findAnyConcreteTypeSourceAsWritten())
- Diags.diagnose(source->second->getLoc(),
+ auto equivClass = rep->getOrCreateEquivalenceClass();
+ if (equivClass->concreteType) {
+ if (auto constraint = equivClass->findAnyConcreteConstraintAsWritten())
+ Diags.diagnose(constraint->source->getLoc(),
diag::requires_generic_param_made_equal_to_concrete,
rep->getDependentType(genericParams,
/*allowUnresolved=*/true));
@@ -2667,7 +2824,7 @@
*this);
addSameTypeRequirement(
pa, replacement,
- RequirementSource::forNestedTypeNameMatch(*this));
+ RequirementSource::forNestedTypeNameMatch(pa));
});
}
}
@@ -2690,101 +2847,97 @@
return invalid;
}
-namespace {
- /// Describes a concrete constraint on a potential archetype.
- struct ConcreteConstraint {
- PotentialArchetype *archetype;
- Type concreteType;
- const RequirementSource *source;
+namespace swift {
+ bool operator<(const ConcreteConstraint &lhs, const ConcreteConstraint &rhs) {
+ auto lhsPA = lhs.archetype;
+ auto rhsPA = rhs.archetype;
+ if (int result = compareDependentTypes(&lhsPA, &rhsPA))
+ return result < 0;
- friend bool operator<(const ConcreteConstraint &lhs,
- const ConcreteConstraint &rhs) {
- auto lhsPA = lhs.archetype;
- auto rhsPA = rhs.archetype;
- if (int result = compareDependentTypes(&lhsPA, &rhsPA))
- return result < 0;
+ if (int result = lhs.source->compare(rhs.source))
+ return result < 0;
- if (int result = lhs.source->compare(rhs.source))
- return result < 0;
-
- return false;
- }
-
- friend bool operator==(const ConcreteConstraint &lhs,
- const ConcreteConstraint &rhs) {
- return lhs.archetype == rhs.archetype &&
- lhs.concreteType->isEqual(rhs.concreteType) &&
- lhs.source == rhs.source;
- }
- };
-}
-
-void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints(
- ArrayRef<GenericTypeParamType *> genericParams,
- PotentialArchetype *representative) {
- Type concreteType = representative->getConcreteType();
- assert(concreteType && "No concrete type to check");
-
- Optional<ConcreteConstraint> representativeConstraint;
-
- // Gather the concrete constraints within this equivalence class.
- SmallVector<ConcreteConstraint, 4> concreteConstraints;
- for (auto pa : representative->getEquivalenceClassMembers()) {
- auto types = pa->getConcreteTypesAsWritten();
- auto sources = pa->getConcreteTypeSourcesAsWritten();
- for (unsigned i : indices(types)) {
- auto source = sources[i];
-
- // Save this constraint.
- auto constraint = ConcreteConstraint{pa, types[i], source};
- concreteConstraints.push_back(constraint);
-
- // Check whether this constraint is better than the best we've seen so far
- // at being the representative constraint against which others will be
- // compared.
- if (!representativeConstraint) {
- representativeConstraint = constraint;
- continue;
- }
-
- // We prefer derived constraints to non-derived constraints.
- bool thisIsDerived = source->isDerivedRequirement();
- bool representativeIsDerived =
- representativeConstraint->source->isDerivedRequirement();
- if (thisIsDerived != representativeIsDerived) {
- if (thisIsDerived)
- representativeConstraint = constraint;
-
- continue;
- }
-
- // We prefer constraints with locations to constraints without locations.
- bool thisHasValidSourceLoc = source->getLoc().isValid();
- bool representativeHasValidSourceLoc =
- representativeConstraint->source->getLoc().isValid();
- if (thisHasValidSourceLoc != representativeHasValidSourceLoc) {
- if (thisHasValidSourceLoc)
- representativeConstraint = constraint;
-
- continue;
- }
-
- // Otherwise, order via the constraint itself.
- if (constraint < *representativeConstraint)
- representativeConstraint = constraint;
- }
+ return false;
}
- // Sort the concrete constraints, so we get deterministic ordering of
- // diagnostics.
- llvm::array_pod_sort(concreteConstraints.begin(), concreteConstraints.end());
+ bool operator==(const ConcreteConstraint &lhs, const ConcreteConstraint &rhs){
+ return lhs.archetype == rhs.archetype &&
+ lhs.concreteType->isEqual(rhs.concreteType) &&
+ lhs.source == rhs.source;
+ }
+}
- // Local function to provide a note desribing the representative constraint.
+ConcreteConstraint GenericSignatureBuilder::checkConstraintList(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ std::vector<ConcreteConstraint> &constraints,
+ llvm::function_ref<bool(const ConcreteConstraint &)>
+ isSuitableRepresentative,
+ llvm::function_ref<ConstraintRelation(Type)>
+ checkConstraint,
+ Optional<Diag<unsigned, Type, Type, Type>>
+ conflictingDiag,
+ Diag<Type, Type> redundancyDiag,
+ Diag<bool, Type, Type> otherNoteDiag) {
+ // Remove self-derived constraints.
+ constraints.erase(
+ std::remove_if(constraints.begin(), constraints.end(),
+ [&](const ConcreteConstraint &constraint) {
+ return constraint.source->isSelfDerivedSource(
+ constraint.archetype);
+ }),
+ constraints.end());
+
+ // Sort the constraints, so we get a deterministic ordering of diagnostics.
+ llvm::array_pod_sort(constraints.begin(), constraints.end());
+
+ // Find a representative constraint.
+ Optional<ConcreteConstraint> representativeConstraint;
+ for (const auto &constraint : constraints) {
+ // If this isn't a suitable representative constraint, ignore it.
+ if (!isSuitableRepresentative(constraint))
+ continue;
+
+ // Check whether this constraint is better than the best we've seen so far
+ // at being the representative constraint against which others will be
+ // compared.
+ if (!representativeConstraint) {
+ representativeConstraint = constraint;
+ continue;
+ }
+
+ // We prefer derived constraints to non-derived constraints.
+ bool thisIsDerived = constraint.source->isDerivedRequirement();
+ bool representativeIsDerived =
+ representativeConstraint->source->isDerivedRequirement();
+ if (thisIsDerived != representativeIsDerived) {
+ if (thisIsDerived)
+ representativeConstraint = constraint;
+
+ continue;
+ }
+
+ // We prefer constraints with locations to constraints without locations.
+ bool thisHasValidSourceLoc = constraint.source->getLoc().isValid();
+ bool representativeHasValidSourceLoc =
+ representativeConstraint->source->getLoc().isValid();
+ if (thisHasValidSourceLoc != representativeHasValidSourceLoc) {
+ if (thisHasValidSourceLoc)
+ representativeConstraint = constraint;
+
+ continue;
+ }
+
+ // Otherwise, order via the constraint itself.
+ if (constraint < *representativeConstraint)
+ representativeConstraint = constraint;
+ }
+
+ // Local function to provide a note describing the representative constraint.
auto noteRepresentativeConstraint = [&] {
if (representativeConstraint->source->getLoc().isInvalid()) return;
Diags.diagnose(representativeConstraint->source->getLoc(),
- diag::redundancy_here,
+ otherNoteDiag,
representativeConstraint->source->isDerivedRequirement(),
representativeConstraint->archetype->
getDependentType(genericParams, /*allowUnresolved=*/true),
@@ -2792,26 +2945,193 @@
};
// Go through the concrete constraints looking for redundancies.
- for (const auto &constraint : concreteConstraints) {
+ bool diagnosedConflictingRepresentative = false;
+ for (const auto &constraint : constraints) {
// Leave the representative alone.
if (constraint == *representativeConstraint) continue;
- // Note: this is conservative. There might be redundant constraints that
- // don't get diagnosed here.
- if (!concreteType->isEqual(constraint.concreteType)) continue;
+ switch (checkConstraint(constraint.concreteType)) {
+ case ConstraintRelation::Unrelated:
+ continue;
- // If this requirement is not derived (but has a useful location),
- // complain that it is redundant.
- if (!constraint.source->isDerivedRequirement() &&
- constraint.source->getLoc().isValid()) {
- Diags.diagnose(constraint.source->getLoc(),
- diag::redundant_same_type_to_concrete,
- constraint.archetype->getDependentType(
- /*FIXME:*/{ },
+ case ConstraintRelation::Conflicting: {
+ // Figure out what kind of subject we have; it will affect the
+ // diagnostic.
+ auto getSubjectType =
+ [&](PotentialArchetype *T) -> std::pair<unsigned, Type> {
+ auto subjectType = T->getDependentType(genericParams, true);
+ unsigned kind;
+ if (auto gp = subjectType->getAs<GenericTypeParamType>()) {
+ if (gp->getDecl() &&
+ isa<ProtocolDecl>(gp->getDecl()->getDeclContext())) {
+ kind = 1;
+ subjectType = cast<ProtocolDecl>(gp->getDecl()->getDeclContext())
+ ->getDeclaredInterfaceType();
+ } else {
+ kind = 0;
+ }
+ } else {
+ kind = 2;
+ }
+
+ return std::make_pair(kind, subjectType);
+ };
+
+
+ // The requirement conflicts. If this constraint has a location, complain
+ // about it.
+ if (constraint.source->getLoc().isValid()) {
+ auto subject = getSubjectType(constraint.archetype);
+ Diags.diagnose(constraint.source->getLoc(), *conflictingDiag,
+ subject.first, subject.second,
+ constraint.concreteType,
+ representativeConstraint->concreteType);
+
+ noteRepresentativeConstraint();
+ break;
+ }
+
+ // If the representative itself conflicts and we haven't diagnosed it yet,
+ // do so now.
+ if (!diagnosedConflictingRepresentative &&
+ representativeConstraint->source->getLoc().isValid()) {
+ auto subject = getSubjectType(representativeConstraint->archetype);
+ Diags.diagnose(representativeConstraint->source->getLoc(),
+ *conflictingDiag,
+ subject.first, subject.second,
+ representativeConstraint->concreteType,
+ constraint.concreteType);
+
+ diagnosedConflictingRepresentative = true;
+ break;
+ }
+ break;
+ }
+
+ case ConstraintRelation::Redundant:
+ // If this requirement is not derived (but has a useful location),
+ // complain that it is redundant.
+ if (!constraint.source->isDerivedRequirement() &&
+ constraint.source->getLoc().isValid()) {
+ Diags.diagnose(constraint.source->getLoc(),
+ redundancyDiag,
+ constraint.archetype->getDependentType(
+ genericParams, /*allowUnresolved=*/true),
+ constraint.concreteType);
+
+ noteRepresentativeConstraint();
+ }
+ break;
+ }
+ }
+
+ return *representativeConstraint;
+}
+
+void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ PotentialArchetype *representative) {
+ auto equivClass = representative->getOrCreateEquivalenceClass();
+ assert(equivClass->concreteType && "No concrete type to check");
+
+ checkConstraintList(
+ genericParams, equivClass->concreteTypeConstraints,
+ [](const ConcreteConstraint &constraint) {
+ return true;
+ },
+ [&](Type concreteType) {
+ // If the concrete type is equivalent, the constraint is redundant.
+ // FIXME: Should check this constraint after substituting in the
+ // archetype anchors for each dependent type.
+ if (concreteType->isEqual(equivClass->concreteType))
+ return ConstraintRelation::Redundant;
+
+ // Call this unrelated.
+ return ConstraintRelation::Unrelated;
+ },
+ None,
+ diag::redundant_same_type_to_concrete,
+ diag::same_type_redundancy_here);
+}
+
+void GenericSignatureBuilder::checkRedundantSuperclassConstraints(
+ ArrayRef<GenericTypeParamType *> genericParams,
+ PotentialArchetype *representative) {
+ auto equivClass = representative->getOrCreateEquivalenceClass();
+ assert(equivClass->superclass && "No superclass constraint?");
+
+ // FIXME: We should be substituting in the canonical type in context so
+ // we can resolve superclass requirements, e.g., if you had:
+ //
+ // class Foo<T>
+ // class Bar: Foo<Int>
+ //
+ // func foo<T, U where U: Bar, U: Foo<T>>(...) { ... }
+ //
+ // then the second `U: Foo<T>` constraint introduces a `T == Int`
+ // constraint, and we will need to perform that substitution for this final
+ // check.
+
+ auto representativeConstraint =
+ checkConstraintList(
+ genericParams, equivClass->superclassConstraints,
+ [&](const ConcreteConstraint &constraint) {
+ return constraint.concreteType->isEqual(equivClass->superclass);
+ },
+ [&](Type superclass) {
+ // If this class is a superclass of the "best"
+ if (superclass->isExactSuperclassOf(equivClass->superclass, nullptr))
+ return ConstraintRelation::Redundant;
+
+ // Otherwise, it conflicts.
+ return ConstraintRelation::Conflicting;
+ },
+ diag::requires_superclass_conflict,
+ diag::redundant_superclass_constraint,
+ diag::superclass_redundancy_here);
+
+ // If we have a concrete type, check it.
+ // FIXME: Substitute into the concrete type.
+ if (equivClass->concreteType) {
+ // Make sure the concrete type fulfills the superclass requirement.
+ if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType,
+ nullptr)) {
+ if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
+ representativeConstraint.archetype)) {
+ Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
+ existing->archetype->getDependentType(
+ genericParams,
+ /*allowUnresolved=*/true),
+ existing->concreteType, equivClass->superclass);
+
+ // FIXME: Note the representative constraint.
+ } else if (representativeConstraint.source->getLoc().isValid()) {
+ Diags.diagnose(representativeConstraint.source->getLoc(),
+ diag::type_does_not_inherit,
+ representativeConstraint.archetype->getDependentType(
+ genericParams,
+ /*allowUnresolved=*/true),
+ equivClass->concreteType, equivClass->superclass);
+ }
+ } else if (representativeConstraint.source->getLoc().isValid()) {
+ // It does fulfill the requirement; diagnose the redundancy.
+ Diags.diagnose(representativeConstraint.source->getLoc(),
+ diag::redundant_superclass_constraint,
+ representativeConstraint.archetype->getDependentType(
+ genericParams,
/*allowUnresolved=*/true),
- constraint.concreteType);
+ representativeConstraint.concreteType);
- noteRepresentativeConstraint();
+ if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
+ representativeConstraint.archetype)) {
+ Diags.diagnose(existing->source->getLoc(),
+ diag::same_type_redundancy_here,
+ existing->source->isDerivedRequirement(),
+ existing->archetype->getDependentType(
+ genericParams,
+ /*allowUnresolved=*/true),
+ existing->concreteType);
+ }
}
}
}
@@ -2849,17 +3169,19 @@
/// the *implicit* same-type constraints.
///
/// \param pa The potential archetype to visit.
-/// \param visited The set of potential archetypes that have already been
-/// seen.
-/// \param found Used to record each potential archetype visited
-static void sameTypeDFS(PotentialArchetype *pa,
- SmallPtrSetImpl<PotentialArchetype *> &visited,
- SmallVectorImpl<PotentialArchetype *> &found) {
- // If we've already visited this potential archetype, we're done.
- if (!visited.insert(pa).second) return;
+/// \param paToComponent A mapping from each potential archetype to its
+/// component number.
+/// \param component The component number we're currently visiting.
+///
+/// \returns the best archetype anchor seen so far.
+static PotentialArchetype *sameTypeDFS(PotentialArchetype *pa,
+ unsigned component,
+ llvm::SmallDenseMap<PotentialArchetype *, unsigned>
+ &paToComponent) {
+ PotentialArchetype *anchor = pa;
- // Note that we've found this potential archetype.
- found.push_back(pa);
+ // If we've already visited this potential archetype, we're done.
+ if (!paToComponent.insert({pa, component}).second) return anchor;
// Visit its adjacent potential archetypes.
for (const auto &sameType : pa->getSameTypeConstraints()) {
@@ -2878,19 +3200,29 @@
break;
}
- sameTypeDFS(sameType.first, visited, found);
+ sameTypeDFS(sameType.first, component, paToComponent);
+
+ // If this type is better than the anchor, use it for the anchor.
+ if (compareDependentTypes(&sameType.first, &anchor) < 0)
+ anchor = sameType.first;
}
+
+ return anchor;
}
namespace {
/// Describes a component in the (implied) same-type constraint graph.
struct SameTypeComponent {
/// The potential archetype that acts as the anchor for this component.
- PotentialArchetype * anchor;
+ PotentialArchetype *anchor;
/// The (best) requirement source within the component that makes the
/// potential archetypes in this component equivalent to the concrete type.
- const RequirementSource * concreteTypeSource;
+ const RequirementSource *concreteTypeSource;
+
+ /// The (best) requirement source within the component that introduces
+ /// the superclass constraint.
+ const RequirementSource *superclassSource;
friend bool operator<(const SameTypeComponent &lhs,
const SameTypeComponent &rhs) {
@@ -2937,44 +3269,54 @@
/// canonical edges connects vertex i to vertex i+1 for i in 0..<size-1.
static SmallVector<SameTypeComponent, 2> getSameTypeComponents(
PotentialArchetype *rep) {
- SmallPtrSet<PotentialArchetype *, 8> visited;
+ llvm::SmallDenseMap<PotentialArchetype *, unsigned> paToComponent;
SmallVector<SameTypeComponent, 2> components;
for (auto pa : rep->getEquivalenceClassMembers()) {
// If we've already seen this potential archetype, there's nothing else to
// do.
- if (visited.count(pa) != 0) continue;
+ if (paToComponent.count(pa) != 0) continue;
// Find all of the potential archetypes within this connected component.
- SmallVector<PotentialArchetype *, 2> component;
- sameTypeDFS(pa, visited, component);
-
- // Find the best anchor and concrete type source for this component.
- PotentialArchetype *anchor = component[0];
- const RequirementSource *bestConcreteTypeSource = nullptr;
- auto considerNewSource = [&](const RequirementSource *source) {
- if (!bestConcreteTypeSource ||
- source->compare(bestConcreteTypeSource) < 0)
- bestConcreteTypeSource = source;
- };
-
- if (!anchor->getConcreteTypeSourcesAsWritten().empty())
- bestConcreteTypeSource = anchor->getConcreteTypeSourcesAsWritten()[0];
-
- for (auto componentPA : ArrayRef<PotentialArchetype *>(component)) {
- // Update the anchor.
- if (compareDependentTypes(&componentPA, &anchor) < 0)
- anchor = componentPA;
-
- // If this potential archetype has a better concrete type source than
- // the best we've seen, take it.
- for (auto source: componentPA->getConcreteTypeSourcesAsWritten())
- considerNewSource(source);
- }
+ auto anchor = sameTypeDFS(pa, components.size(), paToComponent);
// Record the anchor.
- components.push_back({anchor, bestConcreteTypeSource});
+ components.push_back({anchor, nullptr, nullptr});
}
+ // If there is a concrete type, figure out the best concrete type anchor
+ // per component.
+ auto equivClass = rep->getOrCreateEquivalenceClass();
+ for (const auto &concrete : equivClass->concreteTypeConstraints) {
+ // Dig out the component associated with constraint.
+ assert(paToComponent.count(concrete.archetype) > 0);
+ auto &component = components[paToComponent[concrete.archetype]];
+
+ // If it has a better source than we'd seen before for this component,
+ // keep it.
+ auto &bestConcreteTypeSource = component.concreteTypeSource;
+ if (!bestConcreteTypeSource ||
+ concrete.source->compare(bestConcreteTypeSource) < 0)
+ bestConcreteTypeSource = concrete.source;
+ }
+
+ // If there is a superclass and no concrete type, figure out the best
+ // superclass source per component.
+ if (equivClass->superclass && !equivClass->concreteType) {
+ for (const auto &superclass : equivClass->superclassConstraints) {
+ // Dig out the component associated with constraint.
+ assert(paToComponent.count(superclass.archetype) > 0);
+ auto &component = components[paToComponent[superclass.archetype]];
+
+ // If it has a better source than we'd seen before for this component,
+ // keep it.
+ auto &bestSuperclassSource = component.superclassSource;
+ if (!bestSuperclassSource ||
+ superclass.source->compare(bestSuperclassSource) < 0)
+ bestSuperclassSource = superclass.source;
+ }
+ }
+
+ // Sort the components.
llvm::array_pod_sort(components.begin(), components.end());
return components;
@@ -3047,12 +3389,20 @@
auto source =
knownAnchor->concreteTypeSource
? knownAnchor->concreteTypeSource
- : RequirementSource::forAbstract(*this);
+ : RequirementSource::forAbstract(archetype);
f(RequirementKind::SameType, archetype, concreteType, source);
continue;
}
+ // If we have a superclass, produce a superclass requirement
+ if (Type superclass = rep->getSuperclass()) {
+ f(RequirementKind::Superclass, archetype, superclass,
+ knownAnchor->superclassSource
+ ? knownAnchor->superclassSource
+ : RequirementSource::forAbstract(archetype));
+ }
+
// If we're at the last anchor in the component, do nothing;
auto nextAnchor = knownAnchor;
++nextAnchor;
@@ -3063,7 +3413,7 @@
auto otherPA = nextAnchor->anchor;
deferredSameTypeRequirement = [&f, archetype, otherPA, this] {
f(RequirementKind::SameType, archetype, otherPA,
- RequirementSource::forAbstract(*this));
+ RequirementSource::forAbstract(archetype));
};
}
}
@@ -3075,12 +3425,6 @@
if (archetype != archetype->getArchetypeAnchor(*this))
continue;
- // If we have a superclass, produce a superclass requirement
- if (Type superclass = rep->getSuperclass()) {
- f(RequirementKind::Superclass, archetype, superclass,
- rep->getSuperclassSource());
- }
-
// If we have a layout constraint, produce a layout requirement.
if (LayoutConstraint Layout = archetype->getLayout()) {
f(RequirementKind::Layout, archetype, Layout,
@@ -3166,9 +3510,8 @@
for (auto param : sig->getGenericParams())
addGenericParameter(param);
- auto source = RequirementSource::forAbstract(*this);
for (auto &reqt : sig->getRequirements()) {
- addRequirement(reqt, source);
+ addRequirement(reqt, FloatingRequirementSource::forAbstract());
}
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 521fcb2..659ad44 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/AST.h"
+#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/SubstitutionMap.h"
@@ -52,7 +53,7 @@
bool TypeLoc::isError() const {
assert(wasValidated() && "Type not yet validated");
- return getType()->hasError() || getType()->getCanonicalType()->hasError();
+ return getType()->hasError();
}
SourceRange TypeLoc::getSourceRange() const {
@@ -282,111 +283,17 @@
}
bool TypeBase::isSpecialized() {
- CanType CT = getCanonicalType();
- if (CT.getPointer() != this)
- return CT->isSpecialized();
+ Type t = getCanonicalType();
- return CT.findIf([](Type type) -> bool {
- return isa<BoundGenericType>(type.getPointer());
- });
-}
-
-bool TypeBase::isUnspecializedGeneric() {
- CanType CT = getCanonicalType();
- if (CT.getPointer() != this)
- return CT->isUnspecializedGeneric();
-
- switch (getKind()) {
-#define SUGARED_TYPE(id, parent) case TypeKind::id:
-#define TYPE(id, parent)
-#include "swift/AST/TypeNodes.def"
- llvm_unreachable("we're only working with CanType's here");
-
- case TypeKind::Error:
- case TypeKind::Unresolved:
- case TypeKind::TypeVariable:
- llvm_unreachable("querying invalid type");
-
- case TypeKind::UnboundGeneric:
- return true;
-
- case TypeKind::BoundGenericClass:
- case TypeKind::BoundGenericEnum:
- case TypeKind::BoundGenericStruct:
- return true;
-
- case TypeKind::Function: {
- auto funcTy = cast<AnyFunctionType>(this);
- return funcTy->getInput()->isUnspecializedGeneric() ||
- funcTy->getResult()->isUnspecializedGeneric();
+ for (;;) {
+ if (!t || !t->getAnyNominal())
+ return false;
+ if (t->is<BoundGenericType>())
+ return true;
+ t = t->getNominalParent();
}
- case TypeKind::GenericFunction:
- return true;
-
- case TypeKind::Class:
- case TypeKind::Struct:
- case TypeKind::Enum:
- if (auto parentTy = cast<NominalType>(this)->getParent())
- return parentTy->isUnspecializedGeneric();
- return false;
-
- case TypeKind::ExistentialMetatype:
- case TypeKind::Metatype:
- return cast<AnyMetatypeType>(this)->getInstanceType()
- ->isUnspecializedGeneric();
-
- case TypeKind::UnownedStorage:
- case TypeKind::UnmanagedStorage:
- case TypeKind::WeakStorage:
- return cast<ReferenceStorageType>(this)->getReferentType()
- ->isUnspecializedGeneric();
-
- case TypeKind::LValue:
- return cast<LValueType>(this)->getObjectType()->isUnspecializedGeneric();
- case TypeKind::InOut:
- return cast<InOutType>(this)->getObjectType()->isUnspecializedGeneric();
-
- case TypeKind::Tuple: {
- auto tupleTy = cast<TupleType>(this);
- for (auto &Elt : tupleTy->getElements())
- if (Elt.getType()->isUnspecializedGeneric())
- return true;
-
- return false;
- }
-
- case TypeKind::Archetype:
- case TypeKind::BuiltinFloat:
- case TypeKind::BuiltinInteger:
- case TypeKind::BuiltinUnknownObject:
- case TypeKind::BuiltinNativeObject:
- case TypeKind::BuiltinBridgeObject:
- case TypeKind::BuiltinRawPointer:
- case TypeKind::BuiltinUnsafeValueBuffer:
- case TypeKind::BuiltinVector:
- case TypeKind::Module:
- case TypeKind::DynamicSelf:
- case TypeKind::Protocol:
- case TypeKind::ProtocolComposition:
- case TypeKind::SILFunction:
- return false;
-
- case TypeKind::GenericTypeParam:
- case TypeKind::DependentMember:
- return false;
-
- case TypeKind::SILBlockStorage:
- return cast<SILBlockStorageType>(this)->getCaptureType()
- ->isUnspecializedGeneric();
- case TypeKind::SILBox:
- for (auto &arg : cast<SILBoxType>(this)->getGenericArgs()) {
- if (arg.getReplacement()->isUnspecializedGeneric())
- return true;
- }
- return false;
- }
- llvm_unreachable("bad TypeKind");
+ return false;
}
bool TypeBase::hasOpenedExistential(ArchetypeType *opened) {
@@ -543,44 +450,16 @@
return false;
}
-namespace {
-class GetRValueTypeVisitor : public TypeVisitor<GetRValueTypeVisitor, Type> {
-public:
- Type visitLValueType(LValueType *lvt) {
- // Look through lvalue types.
- assert(!lvt->getObjectType()->isLValueType()
- && "unexpected nested lvalue");
- return lvt->getObjectType();
- }
-
- Type visitTupleType(TupleType *tt) {
- // Look through lvalues in tuples.
- SmallVector<TupleTypeElt, 4> elts;
- for (auto &elt : tt->getElements()) {
- elts.push_back(elt.getWithType(visit(elt.getType())));
- }
- return TupleType::get(elts, tt->getASTContext());
- }
-
- Type visitParenType(ParenType *pt) {
- return ParenType::get(pt->getASTContext(), visit(pt->getUnderlyingType()));
- }
-
- Type visitType(TypeBase *t) {
- // Other types should not structurally contain lvalues.
- assert(!t->isLValueType()
- && "unexpected structural lvalue");
- return t;
- }
-};
-} // end anonymous namespace
-
Type TypeBase::getRValueType() {
// If the type is not an lvalue, this is a no-op.
if (!isLValueType())
return this;
-
- return GetRValueTypeVisitor().visit(this);
+
+ return Type(this).transform([](Type t) -> Type {
+ if (auto *lvalueTy = dyn_cast<LValueType>(t.getPointer()))
+ return lvalueTy->getObjectType();
+ return t;
+ });
}
Type TypeBase::getOptionalObjectType() {
@@ -661,24 +540,6 @@
return type;
}
-ClassDecl *CanType::getClassBoundImpl(CanType type) {
- if (auto classTy = dyn_cast<ClassType>(type))
- return classTy->getDecl();
-
- if (auto boundTy = dyn_cast<BoundGenericClassType>(type))
- return boundTy->getDecl();
-
- if (auto archetypeTy = dyn_cast<ArchetypeType>(type)) {
- assert(archetypeTy->requiresClass());
- if (Type supertype = archetypeTy->getSuperclass()) {
- return supertype->getClassOrBoundGenericClass();
- }
- return nullptr;
- }
-
- llvm_unreachable("class has no class bound!");
-}
-
LayoutConstraint CanType::getLayoutConstraint() const {
if (auto archetypeTy = dyn_cast<ArchetypeType>(*this)) {
return archetypeTy->getLayoutConstraint();
@@ -3240,7 +3101,7 @@
}
SubstitutionMap TypeBase::getContextSubstitutionMap(
- ModuleDecl *module, const DeclContext *dc) {
+ ModuleDecl *module, const DeclContext *dc) {
auto *genericSig = dc->getGenericSignatureOfContext();
if (genericSig == nullptr)
return SubstitutionMap();
@@ -3249,7 +3110,9 @@
LookUpConformanceInModule(module));
}
-TypeSubstitutionMap TypeBase::getMemberSubstitutions(const ValueDecl *member) {
+TypeSubstitutionMap TypeBase::getMemberSubstitutions(
+ const ValueDecl *member,
+ GenericEnvironment *genericEnv) {
auto *memberDC = member->getDeclContext();
TypeSubstitutionMap substitutions;
@@ -3262,14 +3125,18 @@
// We need this since code completion and diagnostics want to be able
// to call getTypeOfMember() with functions and nested types.
if (isa<AbstractFunctionDecl>(member) ||
- isa<GenericTypeDecl>(member)) {
+ isa<GenericTypeDecl>(member) ||
+ isa<SubscriptDecl>(member)) {
auto *innerDC = member->getInnermostDeclContext();
if (innerDC->isInnermostContextGeneric()) {
auto *sig = innerDC->getGenericSignatureOfContext();
for (auto param : sig->getInnermostGenericParams()) {
auto *genericParam = param->getCanonicalType()
->castTo<GenericTypeParamType>();
- substitutions[genericParam] = param;
+ substitutions[genericParam] =
+ (genericEnv
+ ? genericEnv->mapTypeIntoContext(param)
+ : param);
}
}
}
@@ -3278,13 +3145,15 @@
}
SubstitutionMap TypeBase::getMemberSubstitutionMap(
- ModuleDecl *module, const ValueDecl *member) {
+ ModuleDecl *module, const ValueDecl *member,
+ GenericEnvironment *genericEnv) {
auto *genericSig = member->getInnermostDeclContext()
->getGenericSignatureOfContext();
if (genericSig == nullptr)
return SubstitutionMap();
+ auto subs = getMemberSubstitutions(member, genericEnv);
return genericSig->getSubstitutionMap(
- QueryTypeSubstitutionMap{getMemberSubstitutions(member)},
+ QueryTypeSubstitutionMap{subs},
LookUpConformanceInModule(module));
}
diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp
index d568648..70cb225 100644
--- a/lib/AST/USRGeneration.cpp
+++ b/lib/AST/USRGeneration.cpp
@@ -57,6 +57,10 @@
clang::index::generateUSRForObjCProtocol(ObjCName, OS);
} else if (isa<VarDecl>(D)) {
clang::index::generateUSRForObjCProperty(ObjCName, D->isStatic(), OS);
+ } else if (isa<ConstructorDecl>(D)) {
+ // init() is a class member in Swift, but an instance method in ObjC.
+ clang::index::generateUSRForObjCMethod(ObjCName, /*isInstanceMember=*/true,
+ OS);
} else if (isa<AbstractFunctionDecl>(D)) {
clang::index::generateUSRForObjCMethod(ObjCName, D->isInstanceMember(), OS);
} else if (isa<EnumDecl>(D)) {
diff --git a/lib/Basic/Demangle.cpp b/lib/Basic/Demangle.cpp
index a4c71a9..281883f 100644
--- a/lib/Basic/Demangle.cpp
+++ b/lib/Basic/Demangle.cpp
@@ -628,11 +628,13 @@
/// TODO: This is an atrocity. Come up with a shorter name.
#define FUNCSIGSPEC_CREATE_PARAM_KIND(kind) \
- Factory.createNode(Node::Kind::FunctionSignatureSpecializationParamKind, \
- unsigned(FunctionSigSpecializationParamKind::kind))
+ Factory.createNode( \
+ Node::Kind::FunctionSignatureSpecializationParamKind, \
+ Node::IndexType(FunctionSigSpecializationParamKind::kind))
+
#define FUNCSIGSPEC_CREATE_PARAM_PAYLOAD(payload) \
- Factory.createNode(Node::Kind::FunctionSignatureSpecializationParamPayload, \
- payload)
+ Factory.createNode(Node::Kind::FunctionSignatureSpecializationParamPayload, \
+ payload)
bool demangleFuncSigSpecializationConstantProp(NodePointer parent) {
// Then figure out what was actually constant propagated. First check if
@@ -3413,7 +3415,8 @@
case Node::Kind::ReabstractionThunk:
case Node::Kind::ReabstractionThunkHelper: {
if (Options.ShortenThunk) {
- Printer << "thunk";
+ Printer << "thunk for ";
+ print(pointer->getChild(pointer->getNumChildren() - 2));
return;
}
Printer << "reabstraction thunk ";
diff --git a/lib/Basic/Demangler.cpp b/lib/Basic/Demangler.cpp
index 734af69..70ded11 100644
--- a/lib/Basic/Demangler.cpp
+++ b/lib/Basic/Demangler.cpp
@@ -1412,19 +1412,24 @@
// The parameters will be added later.
return addChild(Param, createNode(
Node::Kind::FunctionSignatureSpecializationParamKind,
- unsigned(FunctionSigSpecializationParamKind::ClosureProp)));
+ uint64_t(FunctionSigSpecializationParamKind::ClosureProp)));
case 'p': {
switch (nextChar()) {
case 'f':
// Consumes an identifier parameter, which will be added later.
- return addChild(Param, createNode(
- Node::Kind::FunctionSignatureSpecializationParamKind,
- unsigned(FunctionSigSpecializationParamKind::ConstantPropFunction)));
+ return addChild(
+ Param,
+ createNode(Node::Kind::FunctionSignatureSpecializationParamKind,
+ Node::IndexType(FunctionSigSpecializationParamKind::
+ ConstantPropFunction)));
case 'g':
// Consumes an identifier parameter, which will be added later.
- return addChild(Param, createNode(
- Node::Kind::FunctionSignatureSpecializationParamKind,
- unsigned(FunctionSigSpecializationParamKind::ConstantPropGlobal)));
+ return addChild(
+ Param,
+ createNode(
+ Node::Kind::FunctionSignatureSpecializationParamKind,
+ Node::IndexType(
+ FunctionSigSpecializationParamKind::ConstantPropGlobal)));
case 'i':
return addFuncSpecParamNumber(Param,
FunctionSigSpecializationParamKind::ConstantPropInteger);
@@ -1441,10 +1446,12 @@
case 'c': Encoding = "objc"; break;
default: return nullptr;
}
- addChild(Param, createNode(
- Node::Kind::FunctionSignatureSpecializationParamKind,
- unsigned(swift::Demangle::FunctionSigSpecializationParamKind::
- ConstantPropString)));
+ addChild(Param,
+ createNode(
+ Node::Kind::FunctionSignatureSpecializationParamKind,
+ Node::IndexType(
+ swift::Demangle::FunctionSigSpecializationParamKind::
+ ConstantPropString)));
return addChild(Param, createNode(
Node::Kind::FunctionSignatureSpecializationParamPayload,
Encoding));
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 19efc63..93ec8a9 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -52,6 +52,11 @@
"big"
};
+static const StringRef SupportedConditionalCompilationRuntimes[] = {
+ "_ObjC",
+ "_Native",
+};
+
template <size_t N>
bool contains(const StringRef (&Array)[N], const StringRef &V,
std::vector<StringRef> &suggestions) {
@@ -75,36 +80,31 @@
return false;
}
-bool LangOptions::checkPlatformConditionOS(
- StringRef &OSName, std::vector<StringRef> &suggestions) {
- if (OSName == "macOS")
- OSName = "OSX";
- return contains(SupportedConditionalCompilationOSs,
- OSName,
- suggestions);
-}
-
-bool
-LangOptions::isPlatformConditionArchSupported(
- StringRef ArchName, std::vector<StringRef> &suggestions) {
- return contains(SupportedConditionalCompilationArches,
- ArchName,
- suggestions);
-}
-
-bool
-LangOptions::isPlatformConditionEndiannessSupported(
- StringRef Endianness, std::vector<StringRef> &suggestions) {
- return contains(SupportedConditionalCompilationEndianness,
- Endianness,
- suggestions);
+bool LangOptions::
+checkPlatformConditionSupported(PlatformConditionKind Kind, StringRef Value,
+ std::vector<StringRef> &suggestions) {
+ switch (Kind) {
+ case PlatformConditionKind::OS:
+ return contains(SupportedConditionalCompilationOSs, Value,
+ suggestions);
+ case PlatformConditionKind::Arch:
+ return contains(SupportedConditionalCompilationArches, Value,
+ suggestions);
+ case PlatformConditionKind::Endianness:
+ return contains(SupportedConditionalCompilationEndianness, Value,
+ suggestions);
+ case PlatformConditionKind::Runtime:
+ return contains(SupportedConditionalCompilationRuntimes, Value,
+ suggestions);
+ }
+ llvm_unreachable("Unhandled enum value");
}
StringRef
-LangOptions::getPlatformConditionValue(StringRef Name) const {
+LangOptions::getPlatformConditionValue(PlatformConditionKind Kind) const {
// Last one wins.
for (auto &Opt : reversed(PlatformConditionValues)) {
- if (Opt.first == Name)
+ if (Opt.first == Kind)
return Opt.second;
}
return StringRef();
@@ -141,23 +141,23 @@
// Set the "os" platform condition.
if (Target.isMacOSX())
- addPlatformConditionValue("os", "OSX");
+ addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
else if (triple.isTvOS())
- addPlatformConditionValue("os", "tvOS");
+ addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
else if (triple.isWatchOS())
- addPlatformConditionValue("os", "watchOS");
+ addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
else if (triple.isiOS())
- addPlatformConditionValue("os", "iOS");
+ addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
else if (triple.isAndroid())
- addPlatformConditionValue("os", "Android");
+ addPlatformConditionValue(PlatformConditionKind::OS, "Android");
else if (triple.isOSLinux())
- addPlatformConditionValue("os", "Linux");
+ addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
else if (triple.isOSFreeBSD())
- addPlatformConditionValue("os", "FreeBSD");
+ addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
else if (triple.isOSWindows())
- addPlatformConditionValue("os", "Windows");
+ addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
else if (triple.isPS4())
- addPlatformConditionValue("os", "PS4");
+ addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
else
UnsupportedOS = true;
@@ -167,25 +167,25 @@
switch (Target.getArch()) {
case llvm::Triple::ArchType::arm:
case llvm::Triple::ArchType::thumb:
- addPlatformConditionValue("arch", "arm");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
break;
case llvm::Triple::ArchType::aarch64:
- addPlatformConditionValue("arch", "arm64");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
break;
case llvm::Triple::ArchType::ppc64:
- addPlatformConditionValue("arch", "powerpc64");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
break;
case llvm::Triple::ArchType::ppc64le:
- addPlatformConditionValue("arch", "powerpc64le");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
break;
case llvm::Triple::ArchType::x86:
- addPlatformConditionValue("arch", "i386");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
break;
case llvm::Triple::ArchType::x86_64:
- addPlatformConditionValue("arch", "x86_64");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
break;
case llvm::Triple::ArchType::systemz:
- addPlatformConditionValue("arch", "s390x");
+ addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
break;
default:
UnsupportedArch = true;
@@ -198,25 +198,25 @@
switch (Target.getArch()) {
case llvm::Triple::ArchType::arm:
case llvm::Triple::ArchType::thumb:
- addPlatformConditionValue("_endian", "little");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
break;
case llvm::Triple::ArchType::aarch64:
- addPlatformConditionValue("_endian", "little");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
break;
case llvm::Triple::ArchType::ppc64:
- addPlatformConditionValue("_endian", "big");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
break;
case llvm::Triple::ArchType::ppc64le:
- addPlatformConditionValue("_endian", "little");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
break;
case llvm::Triple::ArchType::x86:
- addPlatformConditionValue("_endian", "little");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
break;
case llvm::Triple::ArchType::x86_64:
- addPlatformConditionValue("_endian", "little");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
break;
case llvm::Triple::ArchType::systemz:
- addPlatformConditionValue("_endian", "big");
+ addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
break;
default:
llvm_unreachable("undefined architecture endianness");
@@ -224,9 +224,9 @@
// Set the "runtime" platform condition.
if (EnableObjCInterop)
- addPlatformConditionValue("_runtime", "_ObjC");
+ addPlatformConditionValue(PlatformConditionKind::Runtime, "_ObjC");
else
- addPlatformConditionValue("_runtime", "_Native");
+ addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native");
// If you add anything to this list, change the default size of
// PlatformConditionValues to not require an extra allocation
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 09b43dc..29b7d10 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -83,9 +83,7 @@
void handleImport(const clang::Module *imported) {
if (!imported)
return;
- ModuleDecl *nativeImported = Impl.finishLoadingClangModule(Importer, imported,
- /*preferAdapter=*/true);
- Impl.ImportedHeaderExports.push_back({ /*filter=*/{}, nativeImported });
+ Impl.DeferredHeaderImports.push_back(imported);
}
void InclusionDirective(clang::SourceLocation HashLoc,
@@ -835,7 +833,7 @@
// Set up the imported header module.
auto *importedHeaderModule = ModuleDecl::create(ctx.getIdentifier("__ObjC"), ctx);
importer->Impl.ImportedHeaderUnit =
- new (ctx) ClangModuleUnit(*importedHeaderModule, *importer, nullptr);
+ new (ctx) ClangModuleUnit(*importedHeaderModule, importer->Impl, nullptr);
importedHeaderModule->addFile(*importer->Impl.ImportedHeaderUnit);
importer->Impl.IsReadingBridgingPCH = false;
@@ -963,6 +961,9 @@
// Add any defined macros to the bridging header lookup table.
addMacrosToLookupTable(*BridgingHeaderLookupTable, getNameImporter());
+ // Finish loading any extra modules that were (transitively) imported.
+ handleDeferredImports();
+
// Wrap all Clang imports under a Swift import decl.
for (auto &Import : BridgeHeaderTopLevelImports) {
if (auto *ClangImport = Import.dyn_cast<clang::ImportDecl*>()) {
@@ -1008,16 +1009,11 @@
bool trackParsedSymbols,
bool implicitImport) {
if (llvm::sys::path::extension(header).endswith(PCH_EXTENSION)) {
- // We already imported this with -include-pch above, so we should have
- // collected a bunch of PCH-encoded module imports that we need to
- // replay to the HeaderImportCallbacks for processing.
Impl.ImportedHeaderOwners.push_back(adapter);
- clang::ASTReader &R = *Impl.Instance->getModuleManager();
- HeaderImportCallbacks CB(*this, Impl);
- for (auto ID : Impl.PCHImportedSubmodules) {
- CB.handleImport(R.getSubmodule(ID));
- }
- Impl.PCHImportedSubmodules.clear();
+ // We already imported this with -include-pch above, so we should have
+ // collected a bunch of PCH-encoded module imports that we just need to
+ // replay in handleDeferredImports.
+ Impl.handleDeferredImports();
return false;
}
clang::FileManager &fileManager = Impl.Instance->getFileManager();
@@ -1037,7 +1033,6 @@
llvm::MemoryBuffer::getMemBufferCopy(
importLine, Implementation::bridgingHeaderBufferName)
};
-
return Impl.importHeader(adapter, header, diagLoc, trackParsedSymbols,
std::move(sourceBuffer), implicitImport);
}
@@ -1234,12 +1229,11 @@
if (!clangModule)
return nullptr;
- return Impl.finishLoadingClangModule(*this, clangModule,
+ return Impl.finishLoadingClangModule(clangModule,
/*preferAdapter=*/false);
}
ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule(
- ClangImporter &owner,
const clang::Module *clangModule,
bool findAdapter) {
assert(clangModule);
@@ -1269,7 +1263,7 @@
result->setTestingEnabled();
wrapperUnit =
- new (SwiftContext) ClangModuleUnit(*result, owner, clangModule);
+ new (SwiftContext) ClangModuleUnit(*result, *this, clangModule);
result->addFile(*wrapperUnit);
cacheEntry.setPointerAndInt(wrapperUnit, true);
@@ -1280,7 +1274,7 @@
}
if (clangModule->isSubModule()) {
- finishLoadingClangModule(owner, clangModule->getTopLevelModule(), true);
+ finishLoadingClangModule(clangModule->getTopLevelModule(), true);
} else {
ModuleDecl *&loaded = SwiftContext.LoadedModules[result->getName()];
if (!loaded)
@@ -1294,6 +1288,25 @@
return result;
}
+// Run through the set of deferred imports -- either those referenced by
+// submodule ID from a bridging PCH, or those already loaded as clang::Modules
+// in response to an import directive in a bridging header -- and call
+// finishLoadingClangModule on each.
+void ClangImporter::Implementation::handleDeferredImports()
+{
+ clang::ASTReader &R = *Instance->getModuleManager();
+ for (clang::serialization::SubmoduleID ID : PCHImportedSubmodules) {
+ DeferredHeaderImports.push_back(R.getSubmodule(ID));
+ }
+ PCHImportedSubmodules.clear();
+ for (const clang::Module *M : DeferredHeaderImports) {
+ ModuleDecl *nativeImported =
+ finishLoadingClangModule(M, /*preferAdapter=*/true);
+ ImportedHeaderExports.push_back({ /*filter=*/{}, nativeImported });
+ }
+ DeferredHeaderImports.clear();
+}
+
ModuleDecl *ClangImporter::getImportedHeaderModule() const {
return Impl.ImportedHeaderUnit->getParentModule();
}
@@ -1381,7 +1394,6 @@
}
ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule(
- ClangImporter &importer,
const clang::Module *underlying) {
auto &cacheEntry = ModuleWrappers[underlying];
if (ClangModuleUnit *cached = cacheEntry.getPointer())
@@ -1393,7 +1405,7 @@
// Silence error messages about testably importing a Clang module.
wrapper->setTestingEnabled();
- auto file = new (SwiftContext) ClangModuleUnit(*wrapper, importer,
+ auto file = new (SwiftContext) ClangModuleUnit(*wrapper, *this,
underlying);
wrapper->addFile(*file);
cacheEntry.setPointer(file);
@@ -1414,9 +1426,7 @@
// ClangModuleUnit.
auto *M = maybeModule.getValue()->getTopLevelModule();
- auto &importer =
- static_cast<ClangImporter &>(*SwiftContext.getClangModuleLoader());
- return getWrapperForModule(importer, M);
+ return getWrapperForModule(M);
}
#pragma mark Source locations
@@ -1988,9 +1998,9 @@
}
// Find the corresponding lookup table.
- if (auto lookupTable = owner.Impl.findLookupTable(clangModule)) {
+ if (auto lookupTable = owner.findLookupTable(clangModule)) {
// Search it.
- owner.Impl.lookupVisibleDecls(*lookupTable, *actualConsumer);
+ owner.lookupVisibleDecls(*lookupTable, *actualConsumer);
}
}
@@ -2021,14 +2031,14 @@
actualConsumer = &blacklistConsumer;
// Find the corresponding lookup table.
- if (auto lookupTable = owner.Impl.findLookupTable(topLevelModule)) {
+ if (auto lookupTable = owner.findLookupTable(topLevelModule)) {
// Search it.
- owner.Impl.lookupVisibleDecls(*lookupTable, *actualConsumer);
+ owner.lookupVisibleDecls(*lookupTable, *actualConsumer);
// Add the extensions produced by importing categories.
for (auto category : lookupTable->categories()) {
if (auto extension = cast_or_null<ExtensionDecl>(
- owner.Impl.importDecl(category, owner.Impl.CurrentVersion)))
+ owner.importDecl(category, owner.CurrentVersion)))
results.push_back(extension);
}
@@ -2040,7 +2050,7 @@
for (auto entry : lookupTable->allGlobalsAsMembers()) {
auto decl = entry.get<clang::NamedDecl *>();
auto importedDecl =
- owner.Impl.importDecl(decl, owner.Impl.CurrentVersion);
+ owner.importDecl(decl, owner.CurrentVersion);
if (!importedDecl) continue;
auto ext = dyn_cast<ExtensionDecl>(importedDecl->getDeclContext());
@@ -2125,9 +2135,9 @@
}
// Find the corresponding lookup table.
- if (auto lookupTable = owner.Impl.findLookupTable(clangModule)) {
+ if (auto lookupTable = owner.findLookupTable(clangModule)) {
// Search it.
- owner.Impl.lookupValue(*lookupTable, name, *consumer);
+ owner.lookupValue(*lookupTable, name, *consumer);
}
}
@@ -2265,9 +2275,9 @@
VectorDeclConsumer consumer(results);
// Find the corresponding lookup table.
- if (auto lookupTable = owner.Impl.findLookupTable(clangModule)) {
+ if (auto lookupTable = owner.findLookupTable(clangModule)) {
// Search it.
- owner.Impl.lookupObjCMembers(*lookupTable, name, consumer);
+ owner.lookupObjCMembers(*lookupTable, name, consumer);
}
}
@@ -2278,9 +2288,9 @@
return;
// Find the corresponding lookup table.
- if (auto lookupTable = owner.Impl.findLookupTable(clangModule)) {
+ if (auto lookupTable = owner.findLookupTable(clangModule)) {
// Search it.
- owner.Impl.lookupAllObjCMembers(*lookupTable, consumer);
+ owner.lookupAllObjCMembers(*lookupTable, consumer);
}
}
@@ -2292,12 +2302,12 @@
return;
// Map the selector into a Clang selector.
- auto clangSelector = owner.Impl.exportSelector(selector);
+ auto clangSelector = owner.exportSelector(selector);
if (clangSelector.isNull()) return;
// Collect all of the Objective-C methods with this selector.
SmallVector<clang::ObjCMethodDecl *, 8> objcMethods;
- auto &clangSema = owner.Impl.getClangSema();
+ auto &clangSema = owner.getClangSema();
clangSema.CollectMultipleMethodsInGlobalPool(clangSelector,
objcMethods,
/*InstanceFirst=*/true,
@@ -2319,23 +2329,23 @@
// If we found a property accessor, import the property.
if (objcMethod->isPropertyAccessor())
- (void)owner.Impl.importDecl(objcMethod->findPropertyDecl(true),
- owner.Impl.CurrentVersion);
+ (void)owner.importDecl(objcMethod->findPropertyDecl(true),
+ owner.CurrentVersion);
// Import it.
// FIXME: Retrying a failed import works around recursion bugs in the Clang
// importer.
auto imported =
- owner.Impl.importDecl(objcMethod, owner.Impl.CurrentVersion);
+ owner.importDecl(objcMethod, owner.CurrentVersion);
if (!imported)
- imported = owner.Impl.importDecl(objcMethod, owner.Impl.CurrentVersion);
+ imported = owner.importDecl(objcMethod, owner.CurrentVersion);
if (!imported) continue;
if (auto func = dyn_cast<AbstractFunctionDecl>(imported))
results.push_back(func);
// If there is an alternate declaration, also look at it.
- for (auto alternate : owner.Impl.getAlternateDecls(imported)) {
+ for (auto alternate : owner.getAlternateDecls(imported)) {
if (auto func = dyn_cast<AbstractFunctionDecl>(alternate))
results.push_back(func);
}
@@ -2435,7 +2445,8 @@
// ClangModule Implementation
//===----------------------------------------------------------------------===//
-ClangModuleUnit::ClangModuleUnit(ModuleDecl &M, ClangImporter &owner,
+ClangModuleUnit::ClangModuleUnit(ModuleDecl &M,
+ ClangImporter::Implementation &owner,
const clang::Module *clangModule)
: LoadedFile(FileUnitKind::ClangModule, M), owner(owner),
clangModule(clangModule) {
@@ -2468,7 +2479,7 @@
if (!isTopLevel()) {
// FIXME: Is this correct for submodules?
auto topLevel = clangModule->getTopLevelModule();
- auto wrapper = owner.Impl.getWrapperForModule(owner, topLevel);
+ auto wrapper = owner.getWrapperForModule(topLevel);
return wrapper->getAdapterModule();
}
@@ -2504,8 +2515,8 @@
if (!clangModule) {
// This is the special "imported headers" module.
if (filter != ModuleDecl::ImportFilter::Private) {
- imports.append(owner.Impl.ImportedHeaderExports.begin(),
- owner.Impl.ImportedHeaderExports.end());
+ imports.append(owner.ImportedHeaderExports.begin(),
+ owner.ImportedHeaderExports.end());
}
return;
}
@@ -2541,7 +2552,7 @@
}
for (auto importMod : imported) {
- auto wrapper = owner.Impl.getWrapperForModule(owner, importMod);
+ auto wrapper = owner.getWrapperForModule(importMod);
auto actualMod = wrapper->getAdapterModule();
if (!actualMod) {
@@ -2550,8 +2561,7 @@
auto importTopLevel = importMod->getTopLevelModule();
if (importTopLevel != importMod &&
importTopLevel != clangModule->getTopLevelModule()) {
- auto topLevelWrapper = owner.Impl.getWrapperForModule(owner,
- importTopLevel);
+ auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
imports.push_back({ ModuleDecl::AccessPathTy(),
topLevelWrapper->getParentModule() });
}
@@ -2570,8 +2580,8 @@
if (!clangModule) {
// This is the special "imported headers" module.
- imports.append(owner.Impl.ImportedHeaderExports.begin(),
- owner.Impl.ImportedHeaderExports.end());
+ imports.append(owner.ImportedHeaderExports.begin(),
+ owner.ImportedHeaderExports.end());
return;
}
@@ -2608,7 +2618,7 @@
// Don't continue looking through submodules of modules that have
// overlays. The overlay might shadow things.
- auto wrapper = owner.Impl.getWrapperForModule(owner, nextTopLevel);
+ auto wrapper = owner.getWrapperForModule(nextTopLevel);
if (wrapper->getAdapterModule())
continue;
}
@@ -2626,7 +2636,7 @@
}
for (auto importMod : topLevelImported) {
- auto wrapper = owner.Impl.getWrapperForModule(owner, importMod);
+ auto wrapper = owner.getWrapperForModule(importMod);
auto actualMod = wrapper->getAdapterModule();
if (!actualMod || actualMod == topLevelAdapter)
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index bcacb55..6fcdebc 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2041,10 +2041,11 @@
decl->setImplicit();
}
- /// Create a typealias for the Swift 2 name of a Clang type declaration.
- Decl *importSwift2TypeAlias(const clang::NamedDecl *decl,
- ImportedName swift2Name,
- ImportedName correctSwiftName);
+ /// Create a typealias for the name of a Clang type declaration in an
+ /// alternate version of Swift.
+ Decl *importCompatibilityTypeAlias(const clang::NamedDecl *decl,
+ ImportedName compatibilityName,
+ ImportedName correctSwiftName);
/// Create a swift_newtype struct corresponding to a typedef. Returns
/// nullptr if unable.
@@ -2062,7 +2063,8 @@
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
- return importSwift2TypeAlias(Decl, importedName, *correctSwiftName);
+ return importCompatibilityTypeAlias(Decl, importedName,
+ *correctSwiftName);
Type SwiftType;
if (Decl->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
@@ -2277,7 +2279,8 @@
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
- return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
+ return importCompatibilityTypeAlias(decl, importedName,
+ *correctSwiftName);
auto dc =
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
@@ -2693,7 +2696,8 @@
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
- return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
+ return importCompatibilityTypeAlias(decl, importedName,
+ *correctSwiftName);
auto dc =
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
@@ -3873,7 +3877,7 @@
SmallVector<TypeLoc, 4> inheritedTypes;
importObjCProtocols(result, decl->getReferencedProtocols(),
inheritedTypes);
- result->setValidated();
+ result->setValidationStarted();
result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
result->setCheckedInheritanceClause();
result->setMemberLoader(&Impl, 0);
@@ -3957,7 +3961,8 @@
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
- return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
+ return importCompatibilityTypeAlias(decl, importedName,
+ *correctSwiftName);
Identifier name = importedName.getDeclName().getBaseName();
@@ -4092,7 +4097,8 @@
// If we've been asked to produce a Swift 2 stub, handle it via a
// typealias.
if (correctSwiftName)
- return importSwift2TypeAlias(decl, importedName, *correctSwiftName);
+ return importCompatibilityTypeAlias(decl, importedName,
+ *correctSwiftName);
auto name = importedName.getDeclName().getBaseName();
@@ -4630,9 +4636,10 @@
return theClass;
}
-Decl *SwiftDeclConverter::importSwift2TypeAlias(const clang::NamedDecl *decl,
- ImportedName swift2Name,
- ImportedName correctSwiftName) {
+Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
+ const clang::NamedDecl *decl,
+ ImportedName compatibilityName,
+ ImportedName correctSwiftName) {
// Import the referenced declaration. If it doesn't come in as a type,
// we don't care.
auto importedDecl = Impl.importDecl(decl, getActiveSwiftVersion());
@@ -4665,19 +4672,14 @@
// Create the type alias.
auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
- decl,
- Accessibility::Public, Impl.importSourceLoc(decl->getLocStart()),
- SourceLoc(), swift2Name.getDeclName().getBaseName(),
- Impl.importSourceLoc(decl->getLocation()),
- genericParams, dc);
+ decl, Accessibility::Public, Impl.importSourceLoc(decl->getLocStart()),
+ SourceLoc(), compatibilityName.getDeclName().getBaseName(),
+ Impl.importSourceLoc(decl->getLocation()), genericParams, dc);
alias->setUnderlyingType(underlyingType);
alias->setGenericEnvironment(genericEnv);
- // Record that this is the Swift 2 version of this declaration.
- Impl.ImportedDecls[{decl->getCanonicalDecl(), ImportNameVersion::Swift2}] =
- alias;
-
- // Mark it as the Swift 2 variant.
+ // Record that this is the official version of this declaration.
+ Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = alias;
markAsVariant(alias, correctSwiftName);
return alias;
}
@@ -6516,7 +6518,7 @@
if (!clangDecl)
return "";
- auto importedName = importFullName(clangDecl, ImportNameVersion::Swift3);
+ auto importedName = importFullName(clangDecl, CurrentVersion);
if (!importedName)
return "";
@@ -6758,7 +6760,7 @@
Result = converter.Visit(ClangDecl);
HadForwardDeclaration = converter.hadForwardDeclaration();
}
- if (!Result && version > ImportNameVersion::Swift2) {
+ if (!Result && version == CurrentVersion) {
// If we couldn't import this Objective-C entity, determine
// whether it was a required member of a protocol.
bool hasMissingRequiredMember = false;
@@ -7202,7 +7204,7 @@
auto swiftTyLoc = TypeLoc::withoutLoc(nominal->getDeclaredType());
auto ext = ExtensionDecl::create(SwiftContext, SourceLoc(), swiftTyLoc, {},
getClangModuleForDecl(decl), nullptr);
- ext->setValidated();
+ ext->setValidationStarted();
ext->setCheckedInheritanceClause();
ext->setMemberLoader(this, reinterpret_cast<uintptr_t>(declSubmodule));
@@ -7568,7 +7570,7 @@
Identifier
ClangImporter::getEnumConstantName(const clang::EnumConstantDecl *enumConstant){
- return Impl.importFullName(enumConstant, ImportNameVersion::Swift3)
+ return Impl.importFullName(enumConstant, Impl.CurrentVersion)
.getDeclName()
.getBaseName();
}
diff --git a/lib/ClangImporter/ImportMacro.cpp b/lib/ClangImporter/ImportMacro.cpp
index 60812f1..25966a1 100644
--- a/lib/ClangImporter/ImportMacro.cpp
+++ b/lib/ClangImporter/ImportMacro.cpp
@@ -51,9 +51,7 @@
// ClangModule.
auto *M = maybeModule.getValue()->getTopLevelModule();
- auto &importer =
- static_cast<ClangImporter &>(*SwiftContext.getClangModuleLoader());
- return getWrapperForModule(importer, M);
+ return getWrapperForModule(M);
}
template <typename T = clang::Expr>
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index 841c171..36e4dfa 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1626,7 +1626,7 @@
}
// Figure out the name for this parameter.
- Identifier bodyName = importFullName(param, ImportNameVersion::Swift3)
+ Identifier bodyName = importFullName(param, CurrentVersion)
.getDeclName()
.getBaseName();
@@ -2037,7 +2037,7 @@
}
// Figure out the name for this parameter.
- Identifier bodyName = importFullName(param, ImportNameVersion::Swift3)
+ Identifier bodyName = importFullName(param, CurrentVersion)
.getDeclName()
.getBaseName();
@@ -2194,7 +2194,7 @@
} else {
const clang::ParmVarDecl *param = clangDecl->parameters().front();
- ImportedName fullBodyName = importFullName(param,ImportNameVersion::Swift3);
+ ImportedName fullBodyName = importFullName(param, CurrentVersion);
Identifier bodyName = fullBodyName.getDeclName().getBaseName();
SourceLoc nameLoc = importSourceLoc(param->getLocation());
Identifier argLabel = functionName.getDeclName().getArgumentNames().front();
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 5447bd4..72b3fc6 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -275,6 +275,7 @@
bool IsReadingBridgingPCH;
llvm::SmallVector<clang::serialization::SubmoduleID, 2> PCHImportedSubmodules;
+ llvm::SmallVector<const clang::Module*, 2> DeferredHeaderImports;
const Version CurrentVersion;
@@ -815,13 +816,15 @@
/// \brief Retrieves the Swift wrapper for the given Clang module, creating
/// it if necessary.
- ClangModuleUnit *getWrapperForModule(ClangImporter &importer,
- const clang::Module *underlying);
+ ClangModuleUnit *getWrapperForModule(const clang::Module *underlying);
/// \brief Constructs a Swift module for the given Clang module.
- ModuleDecl *finishLoadingClangModule(ClangImporter &importer,
- const clang::Module *clangModule,
- bool preferAdapter);
+ ModuleDecl *finishLoadingClangModule(const clang::Module *clangModule,
+ bool preferAdapter);
+
+ /// \brief Call finishLoadingClangModule on each deferred import collected
+ /// while scanning a bridging header or PCH.
+ void handleDeferredImports();
/// \brief Retrieve the named Swift type, e.g., Int32.
///
@@ -1105,6 +1108,8 @@
D->setAccessibility(access);
if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
ASD->setSetterAccessibility(access);
+ // All imported decls are constructed fully validated.
+ D->setValidationStarted();
return D;
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 98af405..6fbb2a2 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -864,6 +864,7 @@
Opts.EnableASTScopeLookup |= Args.hasArg(OPT_enable_astscope_lookup);
Opts.DebugConstraintSolver |= Args.hasArg(OPT_debug_constraints);
+ Opts.EnableConstraintPropagation |= Args.hasArg(OPT_propagate_constraints);
Opts.IterativeTypeChecker |= Args.hasArg(OPT_iterative_type_checker);
Opts.DebugGenericSignatures |= Args.hasArg(OPT_debug_generic_signatures);
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index e19700c..05936b5 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -916,7 +916,7 @@
if (Clause.Cond && !annotateIfConfigConditionIdentifiers(Clause.Cond))
return false;
- for (auto *D : Clause.Members)
+ for (auto *D : Clause.Elements)
if (D->walk(*this))
return false;
}
diff --git a/lib/IRGen/DebugTypeInfo.cpp b/lib/IRGen/DebugTypeInfo.cpp
index 47d4de1..551ea82 100644
--- a/lib/IRGen/DebugTypeInfo.cpp
+++ b/lib/IRGen/DebugTypeInfo.cpp
@@ -90,7 +90,7 @@
Alignment align) {
// Prefer the original, potentially sugared version of the type if
// the type hasn't been mucked with by an optimization pass.
- auto LowTy = GV->getLoweredType().getSwiftType();
+ auto LowTy = GV->getLoweredType().getSwiftRValueType();
auto *Type = LowTy.getPointer();
if (auto *Decl = GV->getDecl()) {
auto DeclType =
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index b48f544..472f258 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -145,8 +145,14 @@
llvm::Constant *castFn;
// Get the best known type information about the destination type.
- auto destClass = toType.getSwiftRValueType().getClassBound();
- assert(destClass || toType.is<ArchetypeType>());
+ ClassDecl *destClass = nullptr;
+ if (auto archetypeTy = toType.getAs<ArchetypeType>()) {
+ if (auto superclassTy = archetypeTy->getSuperclass())
+ destClass = superclassTy->getClassOrBoundGenericClass();
+ } else {
+ destClass = toType.getClassOrBoundGenericClass();
+ assert(destClass != nullptr);
+ }
// If the destination type is known to have a Swift-compatible
// implementation, use the most specific entrypoint.
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 2d5d794..64cacf3 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -795,7 +795,7 @@
// Retain 'self' if necessary.
if (fnType->getParameters()[0].isConsumed()) {
- IGF.emitNativeStrongRetain(selfValue);
+ IGF.emitNativeStrongRetain(selfValue, IGF.getDefaultAtomicity());
}
// Adjust down to the defining subclass type if necessary.
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index 14732d8..f925bcc 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -1281,7 +1281,7 @@
assert(TIK >= Loadable);
Explosion tmp;
loadAsTake(IGF, addr, tmp);
- copy(IGF, tmp, e, Atomicity::Atomic);
+ copy(IGF, tmp, e, IGF.getDefaultAtomicity());
}
void assign(IRGenFunction &IGF, Explosion &e, Address addr) const override {
@@ -1291,7 +1291,7 @@
loadAsTake(IGF, addr, old);
initialize(IGF, e, addr);
if (!isPOD(ResilienceExpansion::Maximal))
- consume(IGF, old, Atomicity::Atomic);
+ consume(IGF, old, IGF.getDefaultAtomicity());
}
void initialize(IRGenFunction &IGF, Explosion &e, Address addr)
@@ -1503,7 +1503,7 @@
Explosion payloadCopy;
auto &loadableTI = getLoadablePayloadTypeInfo();
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
- loadableTI.copy(IGF, payloadValue, payloadCopy, Atomicity::Atomic);
+ loadableTI.copy(IGF, payloadValue, payloadCopy, IGF.getDefaultAtomicity());
(void)payloadCopy.claimAll(); // FIXME: repack if not bit-identical
}
@@ -1536,7 +1536,7 @@
Explosion payloadValue;
auto &loadableTI = getLoadablePayloadTypeInfo();
loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
- loadableTI.consume(IGF, payloadValue, Atomicity::Atomic);
+ loadableTI.consume(IGF, payloadValue, IGF.getDefaultAtomicity());
}
IGF.Builder.CreateBr(endBB);
@@ -2208,7 +2208,7 @@
llvm::Value *ptr) const {
switch (CopyDestroyKind) {
case NullableRefcounted:
- IGF.emitStrongRetain(ptr, Refcounting, Atomicity::Atomic);
+ IGF.emitStrongRetain(ptr, Refcounting, IGF.getDefaultAtomicity());
return;
case POD:
case Normal:
@@ -2232,7 +2232,7 @@
llvm::Value *ptr) const {
switch (CopyDestroyKind) {
case NullableRefcounted:
- IGF.emitStrongRelease(ptr, Refcounting, Atomicity::Atomic);
+ IGF.emitStrongRelease(ptr, Refcounting, IGF.getDefaultAtomicity());
return;
case POD:
case Normal:
@@ -2917,7 +2917,7 @@
projectPayloadValue(IGF, parts.payload, tagIndex, lti, value);
Explosion tmp;
- lti.copy(IGF, value, tmp, Atomicity::Atomic);
+ lti.copy(IGF, value, tmp, IGF.getDefaultAtomicity());
(void)tmp.claimAll(); // FIXME: repack if not bit-identical
});
@@ -2942,7 +2942,7 @@
Explosion value;
projectPayloadValue(IGF, parts.payload, tagIndex, lti, value);
- lti.consume(IGF, value, Atomicity::Atomic);
+ lti.consume(IGF, value, IGF.getDefaultAtomicity());
});
IGF.Builder.CreateRetVoid();
@@ -3119,7 +3119,7 @@
llvm::Value *ptr) const {
switch (CopyDestroyKind) {
case TaggedRefcounted:
- IGF.emitStrongRetain(ptr, Refcounting, Atomicity::Atomic);
+ IGF.emitStrongRetain(ptr, Refcounting, IGF.getDefaultAtomicity());
return;
case POD:
case BitwiseTakable:
@@ -3145,7 +3145,7 @@
llvm::Value *ptr) const {
switch (CopyDestroyKind) {
case TaggedRefcounted:
- IGF.emitStrongRelease(ptr, Refcounting, Atomicity::Atomic);
+ IGF.emitStrongRelease(ptr, Refcounting, IGF.getDefaultAtomicity());
return;
case POD:
case BitwiseTakable:
@@ -4060,7 +4060,7 @@
loadAsTake(IGF, dest, tmpOld);
initialize(IGF, tmpSrc, dest);
- consume(IGF, tmpOld, Atomicity::Atomic);
+ consume(IGF, tmpOld, IGF.getDefaultAtomicity());
return;
}
@@ -4254,7 +4254,7 @@
if (TI->isLoadable()) {
Explosion tmp;
loadAsTake(IGF, addr, tmp);
- consume(IGF, tmp, Atomicity::Atomic);
+ consume(IGF, tmp, IGF.getDefaultAtomicity());
return;
}
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index cc16f51..b51b45e 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -750,7 +750,7 @@
Explosion &out) const override {
// Load the instance pointer, which is unknown-refcounted.
llvm::Value *instance = asDerived().loadValue(IGF, address);
- asDerived().emitValueRetain(IGF, instance, Atomicity::Atomic);
+ asDerived().emitValueRetain(IGF, instance, IGF.getDefaultAtomicity());
out.add(instance);
// Load the witness table pointers.
@@ -772,7 +772,7 @@
Address instanceAddr = asDerived().projectValue(IGF, address);
llvm::Value *old = IGF.Builder.CreateLoad(instanceAddr);
IGF.Builder.CreateStore(e.claimNext(), instanceAddr);
- asDerived().emitValueRelease(IGF, old, Atomicity::Atomic);
+ asDerived().emitValueRelease(IGF, old, IGF.getDefaultAtomicity());
// Store the witness table pointers.
asDerived().emitStoreOfTables(IGF, e, address);
@@ -821,7 +821,7 @@
void destroy(IRGenFunction &IGF, Address addr, SILType T) const override {
llvm::Value *value = asDerived().loadValue(IGF, addr);
- asDerived().emitValueRelease(IGF, value, Atomicity::Atomic);
+ asDerived().emitValueRelease(IGF, value, IGF.getDefaultAtomicity());
}
void packIntoEnumPayload(IRGenFunction &IGF,
@@ -937,12 +937,12 @@
void emitValueRetain(IRGenFunction &IGF, llvm::Value *value,
Atomicity atomicity) const {
- IGF.emitUnownedRetain(value, Refcounting);
+ IGF.emitUnownedRetain(value, Refcounting, atomicity);
}
void emitValueRelease(IRGenFunction &IGF, llvm::Value *value,
Atomicity atomicity) const {
- IGF.emitUnownedRelease(value, Refcounting);
+ IGF.emitUnownedRelease(value, Refcounting, atomicity);
}
void emitValueFixLifetime(IRGenFunction &IGF, llvm::Value *value) const {
@@ -1077,24 +1077,29 @@
(void)e.claim(getNumStoredProtocols());
}
- void strongRetainUnowned(IRGenFunction &IGF, Explosion &e) const override {
- IGF.emitStrongRetainUnowned(e.claimNext(), Refcounting);
+ void strongRetainUnowned(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
+ IGF.emitStrongRetainUnowned(e.claimNext(), Refcounting, atomicity);
(void)e.claim(getNumStoredProtocols());
}
void strongRetainUnownedRelease(IRGenFunction &IGF,
- Explosion &e) const override {
- IGF.emitStrongRetainAndUnownedRelease(e.claimNext(), Refcounting);
+ Explosion &e,
+ Atomicity atomicity) const override {
+ IGF.emitStrongRetainAndUnownedRelease(e.claimNext(), Refcounting,
+ atomicity);
(void)e.claim(getNumStoredProtocols());
}
- void unownedRetain(IRGenFunction &IGF, Explosion &e) const override {
- IGF.emitUnownedRetain(e.claimNext(), Refcounting);
+ void unownedRetain(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
+ IGF.emitUnownedRetain(e.claimNext(), Refcounting, atomicity);
(void)e.claim(getNumStoredProtocols());
}
- void unownedRelease(IRGenFunction &IGF, Explosion &e) const override {
- IGF.emitUnownedRelease(e.claimNext(), Refcounting);
+ void unownedRelease(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
+ IGF.emitUnownedRelease(e.claimNext(), Refcounting, atomicity);
(void)e.claim(getNumStoredProtocols());
}
diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp
index ae977bc..e3b66ff 100644
--- a/lib/IRGen/GenFunc.cpp
+++ b/lib/IRGen/GenFunc.cpp
@@ -252,7 +252,7 @@
Address dataAddr = projectData(IGF, address);
auto data = IGF.Builder.CreateLoad(dataAddr);
if (!isPOD(ResilienceExpansion::Maximal))
- IGF.emitNativeStrongRetain(data);
+ IGF.emitNativeStrongRetain(data, IGF.getDefaultAtomicity());
e.add(data);
}
@@ -333,20 +333,24 @@
IGF.emitNativeStrongRelease(context, atomicity);
}
- void strongRetainUnowned(IRGenFunction &IGF, Explosion &e) const override {
+ void strongRetainUnowned(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
llvm_unreachable("unowned references to functions are not supported");
}
void strongRetainUnownedRelease(IRGenFunction &IGF,
- Explosion &e) const override {
- llvm_unreachable("unowned references to functions are not supported");
- }
-
- void unownedRetain(IRGenFunction &IGF, Explosion &e) const override {
+ Explosion &e,
+ Atomicity atomicity) const override {
llvm_unreachable("unowned references to functions are not supported");
}
- void unownedRelease(IRGenFunction &IGF, Explosion &e) const override {
+ void unownedRetain(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
+ llvm_unreachable("unowned references to functions are not supported");
+ }
+
+ void unownedRelease(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
llvm_unreachable("unowned references to functions are not supported");
}
@@ -373,7 +377,7 @@
void destroy(IRGenFunction &IGF, Address addr, SILType T) const override {
auto data = IGF.Builder.CreateLoad(projectData(IGF, addr));
if (!isPOD(ResilienceExpansion::Maximal))
- IGF.emitNativeStrongRelease(data);
+ IGF.emitNativeStrongRelease(data, IGF.getDefaultAtomicity());
}
void packIntoEnumPayload(IRGenFunction &IGF,
@@ -555,6 +559,7 @@
case SILFunctionType::Representation::Thin:
case SILFunctionType::Representation::Method:
+ case SILFunctionType::Representation::WitnessMethod:
case SILFunctionType::Representation::ObjCMethod:
case SILFunctionType::Representation::CFunctionPointer:
case SILFunctionType::Representation::Closure:
@@ -576,19 +581,6 @@
std::move(spareBits),
IsNotPOD);
}
- // Witness method values carry a reference to their originating witness table
- // as context.
- case SILFunctionType::Representation::WitnessMethod: {
- SpareBitVector spareBits;
- spareBits.append(IGM.getFunctionPointerSpareBits());
- spareBits.append(IGM.getWitnessTablePtrSpareBits());
- return FuncTypeInfo::create(CanSILFunctionType(T),
- IGM.WitnessFunctionPairTy,
- IGM.getPointerSize() * 2,
- IGM.getPointerAlignment(),
- std::move(spareBits),
- IsPOD);
- }
}
llvm_unreachable("bad function type representation");
}
@@ -911,7 +903,7 @@
switch (argConvention) {
case ParameterConvention::Indirect_In:
case ParameterConvention::Direct_Owned:
- if (!consumesContext) subIGF.emitNativeStrongRetain(rawData);
+ if (!consumesContext) subIGF.emitNativeStrongRetain(rawData, subIGF.getDefaultAtomicity());
break;
case ParameterConvention::Indirect_In_Guaranteed:
@@ -919,7 +911,7 @@
dependsOnContextLifetime = true;
if (outType->getCalleeConvention() ==
ParameterConvention::Direct_Unowned) {
- subIGF.emitNativeStrongRetain(rawData);
+ subIGF.emitNativeStrongRetain(rawData, subIGF.getDefaultAtomicity());
consumesContext = true;
}
break;
@@ -1060,7 +1052,7 @@
// so we can tail call. The safety of this assumes that neither this release
// nor any of the loads can throw.
if (consumesContext && !dependsOnContextLifetime && rawData)
- subIGF.emitNativeStrongRelease(rawData);
+ subIGF.emitNativeStrongRelease(rawData, subIGF.getDefaultAtomicity());
}
// Derive the callee function pointer. If we found a function
@@ -1157,7 +1149,7 @@
// If the parameters depended on the context, consume the context now.
if (rawData && consumesContext && dependsOnContextLifetime)
- subIGF.emitNativeStrongRelease(rawData);
+ subIGF.emitNativeStrongRelease(rawData, subIGF.getDefaultAtomicity());
// FIXME: Reabstract the result value as substituted.
@@ -1224,24 +1216,20 @@
argValTypes.push_back(argType);
argConventions.push_back(param.getConvention());
- CanType argLoweringTy;
+ auto argLoweringTy = argType.getSwiftRValueType();
switch (param.getConvention()) {
// Capture value parameters by value, consuming them.
case ParameterConvention::Direct_Owned:
case ParameterConvention::Direct_Unowned:
case ParameterConvention::Direct_Guaranteed:
- argLoweringTy = argType.getSwiftRValueType();
- break;
-
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
- argLoweringTy = argType.getSwiftRValueType();
break;
// Capture inout parameters by pointer.
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
- argLoweringTy = argType.getSwiftType();
+ argLoweringTy = CanInOutType::get(argLoweringTy);
break;
}
diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp
index 0e6f309..7f36897 100644
--- a/lib/IRGen/GenHeap.cpp
+++ b/lib/IRGen/GenHeap.cpp
@@ -426,12 +426,12 @@
void emitScalarRetain(IRGenFunction &IGF, llvm::Value *value,
Atomicity atomicity) const {
- IGF.emitNativeUnownedRetain(value);
+ IGF.emitNativeUnownedRetain(value, atomicity);
}
void emitScalarRelease(IRGenFunction &IGF, llvm::Value *value,
Atomicity atomicity) const {
- IGF.emitNativeUnownedRelease(value);
+ IGF.emitNativeUnownedRelease(value, atomicity);
}
void emitScalarFixLifetime(IRGenFunction &IGF, llvm::Value *value) const {
@@ -975,7 +975,7 @@
Builder.CreateStore(newValue, address);
// Release the old value.
- emitNativeStrongRelease(oldValue);
+ emitNativeStrongRelease(oldValue, getDefaultAtomicity());
}
/// Emit an initialize of a live value to the given retaining variable.
@@ -1106,31 +1106,35 @@
#undef DEFINE_BINARY_OPERATION
void IRGenFunction::emitUnownedRetain(llvm::Value *value,
- ReferenceCounting style) {
+ ReferenceCounting style,
+ Atomicity atomicity) {
assert(style == ReferenceCounting::Native &&
"only native references support scalar unowned reference-counting");
- emitNativeUnownedRetain(value);
+ emitNativeUnownedRetain(value, atomicity);
}
void IRGenFunction::emitUnownedRelease(llvm::Value *value,
- ReferenceCounting style) {
+ ReferenceCounting style,
+ Atomicity atomicity) {
assert(style == ReferenceCounting::Native &&
"only native references support scalar unowned reference-counting");
- emitNativeUnownedRelease(value);
+ emitNativeUnownedRelease(value, atomicity);
}
void IRGenFunction::emitStrongRetainUnowned(llvm::Value *value,
- ReferenceCounting style) {
+ ReferenceCounting style,
+ Atomicity atomicity) {
assert(style == ReferenceCounting::Native &&
"only native references support scalar unowned reference-counting");
- emitNativeStrongRetainUnowned(value);
+ emitNativeStrongRetainUnowned(value, atomicity);
}
void IRGenFunction::emitStrongRetainAndUnownedRelease(llvm::Value *value,
- ReferenceCounting style) {
+ ReferenceCounting style,
+ Atomicity atomicity) {
assert(style == ReferenceCounting::Native &&
"only native references support scalar unowned reference-counting");
- emitNativeStrongRetainAndUnownedRelease(value);
+ emitNativeStrongRetainAndUnownedRelease(value, atomicity);
}
/// Emit a release of a live value.
@@ -1154,7 +1158,7 @@
value = Builder.CreateBitCast(value, IGM.RefCountedPtrTy);
dest = Builder.CreateStructGEP(dest, 0, Size(0));
Builder.CreateStore(value, dest);
- emitNativeUnownedRetain(value);
+ emitNativeUnownedRetain(value, getDefaultAtomicity());
}
void IRGenFunction::emitNativeUnownedAssign(llvm::Value *value,
@@ -1163,8 +1167,8 @@
dest = Builder.CreateStructGEP(dest, 0, Size(0));
auto oldValue = Builder.CreateLoad(dest);
Builder.CreateStore(value, dest);
- emitNativeUnownedRetain(value);
- emitNativeUnownedRelease(oldValue);
+ emitNativeUnownedRetain(value, getDefaultAtomicity());
+ emitNativeUnownedRelease(oldValue, getDefaultAtomicity());
}
llvm::Value *IRGenFunction::emitNativeUnownedLoadStrong(Address src,
@@ -1172,7 +1176,7 @@
src = Builder.CreateStructGEP(src, 0, Size(0));
llvm::Value *value = Builder.CreateLoad(src);
value = Builder.CreateBitCast(value, type);
- emitNativeStrongRetainUnowned(value);
+ emitNativeStrongRetainUnowned(value, getDefaultAtomicity());
return value;
}
@@ -1181,14 +1185,14 @@
src = Builder.CreateStructGEP(src, 0, Size(0));
llvm::Value *value = Builder.CreateLoad(src);
value = Builder.CreateBitCast(value, type);
- emitNativeStrongRetainAndUnownedRelease(value);
+ emitNativeStrongRetainAndUnownedRelease(value, getDefaultAtomicity());
return value;
}
void IRGenFunction::emitNativeUnownedDestroy(Address ref) {
ref = Builder.CreateStructGEP(ref, 0, Size(0));
llvm::Value *value = Builder.CreateLoad(ref);
- emitNativeUnownedRelease(value);
+ emitNativeUnownedRelease(value, getDefaultAtomicity());
}
void IRGenFunction::emitNativeUnownedCopyInit(Address dest, Address src) {
@@ -1196,7 +1200,7 @@
dest = Builder.CreateStructGEP(dest, 0, Size(0));
llvm::Value *newValue = Builder.CreateLoad(src);
Builder.CreateStore(newValue, dest);
- emitNativeUnownedRetain(newValue);
+ emitNativeUnownedRetain(newValue, getDefaultAtomicity());
}
void IRGenFunction::emitNativeUnownedTakeInit(Address dest, Address src) {
@@ -1212,8 +1216,8 @@
llvm::Value *newValue = Builder.CreateLoad(src);
llvm::Value *oldValue = Builder.CreateLoad(dest);
Builder.CreateStore(newValue, dest);
- emitNativeUnownedRetain(newValue);
- emitNativeUnownedRelease(oldValue);
+ emitNativeUnownedRetain(newValue, getDefaultAtomicity());
+ emitNativeUnownedRelease(oldValue, getDefaultAtomicity());
}
void IRGenFunction::emitNativeUnownedTakeAssign(Address dest, Address src) {
@@ -1222,7 +1226,7 @@
llvm::Value *newValue = Builder.CreateLoad(src);
llvm::Value *oldValue = Builder.CreateLoad(dest);
Builder.CreateStore(newValue, dest);
- emitNativeUnownedRelease(oldValue);
+ emitNativeUnownedRelease(oldValue, getDefaultAtomicity());
}
llvm::Constant *IRGenModule::getFixLifetimeFn() {
@@ -1646,9 +1650,11 @@
}
#define DEFINE_VALUE_OP(ID) \
-void IRGenFunction::emit##ID(llvm::Value *value) { \
+void IRGenFunction::emit##ID(llvm::Value *value, Atomicity atomicity) { \
if (doesNotRequireRefCounting(value)) return; \
- emitUnaryRefCountCall(*this, IGM.get##ID##Fn(), value); \
+ emitUnaryRefCountCall(*this, (atomicity == Atomicity::Atomic) \
+ ? IGM.get##ID##Fn() : IGM.getNonAtomic##ID##Fn(), \
+ value); \
}
#define DEFINE_ADDR_OP(ID) \
void IRGenFunction::emit##ID(Address addr) { \
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index e16bbad..bb659fc 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -909,7 +909,7 @@
subIGF.emitObjCAutoreleaseCall(self);
}
// Release the context.
- subIGF.emitNativeStrongRelease(context);
+ subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
};
// Emit the call and produce the return value.
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index b559b52..1102627 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2259,10 +2259,23 @@
if (concreteConformance->getProtocol() != proto) {
concreteConformance = concreteConformance->getInheritedConformance(proto);
}
+
+ // Check immediately for an existing cache entry.
+ auto wtable = IGF.tryGetLocalTypeData(
+ srcType,
+ LocalTypeDataKind::forConcreteProtocolWitnessTable(concreteConformance));
+ if (wtable) return wtable;
+
auto &protoI = IGF.IGM.getProtocolInfo(proto);
auto &conformanceI =
protoI.getConformance(IGF.IGM, proto, concreteConformance);
- return conformanceI.getTable(IGF, srcType, srcMetadataCache);
+ wtable = conformanceI.getTable(IGF, srcType, srcMetadataCache);
+
+ IGF.setScopedLocalTypeData(
+ srcType,
+ LocalTypeDataKind::forConcreteProtocolWitnessTable(concreteConformance),
+ wtable);
+ return wtable;
}
/// Emit the witness table references required for the given type
@@ -2747,7 +2760,6 @@
// Build the value.
out.add(witness);
- out.add(wtable);
}
llvm::FunctionType *IRGenModule::getAssociatedTypeMetadataAccessFunctionTy() {
diff --git a/lib/IRGen/GenRecord.h b/lib/IRGen/GenRecord.h
index ba1efd6..2b7a803 100644
--- a/lib/IRGen/GenRecord.h
+++ b/lib/IRGen/GenRecord.h
@@ -489,14 +489,14 @@
Explosion &dest, Atomicity atomicity) const override {
for (auto &field : getFields())
cast<LoadableTypeInfo>(field.getTypeInfo())
- .copy(IGF, src, dest, Atomicity::Atomic);
+ .copy(IGF, src, dest, atomicity);
}
void consume(IRGenFunction &IGF, Explosion &src,
Atomicity atomicity) const override {
for (auto &field : getFields())
cast<LoadableTypeInfo>(field.getTypeInfo())
- .consume(IGF, src, Atomicity::Atomic);
+ .consume(IGF, src, atomicity);
}
void fixLifetime(IRGenFunction &IGF, Explosion &src) const override {
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index d66e20a..33cafb2 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -899,10 +899,10 @@
Address src(&*(it++), IGM.getPointerAlignment());
llvm::Value *newValue = IGF.Builder.CreateLoad(src, "new");
- IGF.emitNativeStrongRetain(newValue);
+ IGF.emitNativeStrongRetain(newValue, IGF.getDefaultAtomicity());
llvm::Value *oldValue = IGF.Builder.CreateLoad(dest, "old");
IGF.Builder.CreateStore(newValue, dest);
- IGF.emitNativeStrongRelease(oldValue);
+ IGF.emitNativeStrongRelease(oldValue, IGF.getDefaultAtomicity());
IGF.Builder.CreateRet(dest.getAddress());
});
@@ -925,7 +925,7 @@
llvm::Value *newValue = IGF.Builder.CreateLoad(src, "new");
llvm::Value *oldValue = IGF.Builder.CreateLoad(dest, "old");
IGF.Builder.CreateStore(newValue, dest);
- IGF.emitNativeStrongRelease(oldValue);
+ IGF.emitNativeStrongRelease(oldValue, IGF.getDefaultAtomicity());
IGF.Builder.CreateRet(dest.getAddress());
});
@@ -945,7 +945,7 @@
Address src(&*(it++), IGM.getPointerAlignment());
llvm::Value *newValue = IGF.Builder.CreateLoad(src, "new");
- IGF.emitNativeStrongRetain(newValue);
+ IGF.emitNativeStrongRetain(newValue, IGF.getDefaultAtomicity());
IGF.Builder.CreateStore(newValue, dest);
IGF.Builder.CreateRet(dest.getAddress());
@@ -960,7 +960,7 @@
IGM.VoidTy, argTys,
[&](IRGenFunction &IGF) {
Address arg(&*IGF.CurFn->arg_begin(), IGM.getPointerAlignment());
- IGF.emitNativeStrongRelease(IGF.Builder.CreateLoad(arg));
+ IGF.emitNativeStrongRelease(IGF.Builder.CreateLoad(arg), IGF.getDefaultAtomicity());
IGF.Builder.CreateRetVoid();
});
}
diff --git a/lib/IRGen/HeapTypeInfo.h b/lib/IRGen/HeapTypeInfo.h
index a21dc1e..15021eb 100644
--- a/lib/IRGen/HeapTypeInfo.h
+++ b/lib/IRGen/HeapTypeInfo.h
@@ -116,26 +116,32 @@
asDerived().emitScalarRelease(IGF, value, atomicity);
}
- void strongRetainUnowned(IRGenFunction &IGF, Explosion &e) const override {
+ void strongRetainUnowned(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
llvm::Value *value = e.claimNext();
- IGF.emitStrongRetainUnowned(value, asDerived().getReferenceCounting());
+ IGF.emitStrongRetainUnowned(value, asDerived().getReferenceCounting(),
+ atomicity);
}
void strongRetainUnownedRelease(IRGenFunction &IGF,
- Explosion &e) const override {
+ Explosion &e,
+ Atomicity atomicity) const override {
llvm::Value *value = e.claimNext();
IGF.emitStrongRetainAndUnownedRelease(value,
- asDerived().getReferenceCounting());
+ asDerived().getReferenceCounting(),
+ atomicity);
}
- void unownedRetain(IRGenFunction &IGF, Explosion &e) const override {
+ void unownedRetain(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
llvm::Value *value = e.claimNext();
- IGF.emitUnownedRetain(value, asDerived().getReferenceCounting());
+ IGF.emitUnownedRetain(value, asDerived().getReferenceCounting(), atomicity);
}
- void unownedRelease(IRGenFunction &IGF, Explosion &e) const override {
+ void unownedRelease(IRGenFunction &IGF, Explosion &e,
+ Atomicity atomicity) const override {
llvm::Value *value = e.claimNext();
- IGF.emitUnownedRelease(value, asDerived().getReferenceCounting());
+ IGF.emitUnownedRelease(value, asDerived().getReferenceCounting(), atomicity);
}
void unownedLoadStrong(IRGenFunction &IGF, Address src,
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 47b118a..0018616 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -569,8 +569,10 @@
void IRGenDebugInfo::createParameterType(
llvm::SmallVectorImpl<llvm::Metadata *> &Parameters, SILType type,
DeclContext *DeclCtx) {
- // FIXME: This use of getSwiftType() is extremely suspect.
- auto DbgTy = DebugTypeInfo::getFromTypeInfo(DeclCtx, type.getSwiftType(),
+ auto RealType = type.getSwiftRValueType();
+ if (type.isAddress())
+ RealType = CanInOutType::get(RealType);
+ auto DbgTy = DebugTypeInfo::getFromTypeInfo(DeclCtx, RealType,
IGM.getTypeInfo(type));
Parameters.push_back(getOrCreateType(DbgTy));
}
@@ -1590,7 +1592,7 @@
auto DT = getOrCreateDesugaredType(ObjectTy, DbgTy);
return createPointerSizedStruct(
Scope, MangledName, DT, File, 0, Flags,
- BaseTy->isUnspecializedGeneric() ? StringRef() : MangledName);
+ MangledName);
} else
return createOpaqueStruct(Scope, MangledName, File, 0, SizeInBits,
AlignInBits, Flags, MangledName);
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 686d442..e25c89e 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -72,6 +72,11 @@
return IGM.getSILTypes();
}
+// Returns the default atomicity of the module.
+Atomicity IRGenFunction::getDefaultAtomicity() {
+ return getSILModule().isDefaultAtomic() ? Atomicity::Atomic : Atomicity::NonAtomic;
+}
+
/// Call the llvm.memcpy intrinsic. The arguments need not already
/// be of i8* type.
void IRGenFunction::emitMemCpy(llvm::Value *dest, llvm::Value *src,
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index b23d42d..4782647 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -231,6 +231,9 @@
//--- Reference-counting methods -----------------------------------------------
public:
+ // Returns the default atomicity of the module.
+ Atomicity getDefaultAtomicity();
+
llvm::Value *emitUnmanagedAlloc(const HeapLayout &layout,
const llvm::Twine &name,
llvm::Constant *captureDescriptor,
@@ -248,11 +251,15 @@
llvm::Value *emitLoadRefcountedPtr(Address addr, ReferenceCounting style);
// - unowned references
- void emitUnownedRetain(llvm::Value *value, ReferenceCounting style);
- void emitUnownedRelease(llvm::Value *value, ReferenceCounting style);
- void emitStrongRetainUnowned(llvm::Value *value, ReferenceCounting style);
+ void emitUnownedRetain(llvm::Value *value, ReferenceCounting style,
+ Atomicity atomicity);
+ void emitUnownedRelease(llvm::Value *value, ReferenceCounting style,
+ Atomicity atomicity);
+ void emitStrongRetainUnowned(llvm::Value *value, ReferenceCounting style,
+ Atomicity atomicity);
void emitStrongRetainAndUnownedRelease(llvm::Value *value,
- ReferenceCounting style);
+ ReferenceCounting style,
+ Atomicity atomicity);
void emitUnownedInit(llvm::Value *val, Address dest, ReferenceCounting style);
void emitUnownedAssign(llvm::Value *value, Address dest,
ReferenceCounting style);
@@ -295,16 +302,15 @@
// - strong references
void emitNativeStrongAssign(llvm::Value *value, Address addr);
void emitNativeStrongInit(llvm::Value *value, Address addr);
- void emitNativeStrongRetain(llvm::Value *value,
- Atomicity atomicity = Atomicity::Atomic);
- void emitNativeStrongRelease(llvm::Value *value,
- Atomicity atomicity = Atomicity::Atomic);
+ void emitNativeStrongRetain(llvm::Value *value, Atomicity atomicity);
+ void emitNativeStrongRelease(llvm::Value *value, Atomicity atomicity);
void emitNativeSetDeallocating(llvm::Value *value);
// - unowned references
- void emitNativeUnownedRetain(llvm::Value *value);
- void emitNativeUnownedRelease(llvm::Value *value);
- void emitNativeStrongRetainUnowned(llvm::Value *value);
- void emitNativeStrongRetainAndUnownedRelease(llvm::Value *value);
+ void emitNativeUnownedRetain(llvm::Value *value, Atomicity atomicity);
+ void emitNativeUnownedRelease(llvm::Value *value, Atomicity atomicity);
+ void emitNativeStrongRetainUnowned(llvm::Value *value, Atomicity atomicity);
+ void emitNativeStrongRetainAndUnownedRelease(llvm::Value *value,
+ Atomicity atomicity);
void emitNativeUnownedInit(llvm::Value *val, Address dest);
void emitNativeUnownedAssign(llvm::Value *value, Address dest);
void emitNativeUnownedCopyInit(Address destAddr, Address srcAddr);
@@ -341,10 +347,8 @@
// Routines for an unknown reference-counting style (meaning,
// dynamically something compatible with either the ObjC or Swift styles).
// - strong references
- void emitUnknownStrongRetain(llvm::Value *value,
- Atomicity atomicity = Atomicity::Atomic);
- void emitUnknownStrongRelease(llvm::Value *valuei,
- Atomicity atomicity = Atomicity::Atomic);
+ void emitUnknownStrongRetain(llvm::Value *value, Atomicity atomicity);
+ void emitUnknownStrongRelease(llvm::Value *value, Atomicity atomicity);
// - unowned references
void emitUnknownUnownedInit(llvm::Value *val, Address dest);
void emitUnknownUnownedAssign(llvm::Value *value, Address dest);
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index d3359ba..e70a62c 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -273,10 +273,6 @@
FunctionPtrTy,
RefCountedPtrTy,
});
- WitnessFunctionPairTy = createStructType(*this, "swift.function", {
- FunctionPtrTy,
- WitnessTablePtrTy,
- });
OpaquePtrTy = llvm::StructType::create(LLVMContext, "swift.opaque")
->getPointerTo(DefaultAS);
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 2468b79..e5282b1 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -430,7 +430,6 @@
llvm::PointerType *UnownedReferencePtrTy;/// %swift.unowned_reference*
llvm::Constant *RefCountedNull; /// %swift.refcounted* null
llvm::StructType *FunctionPairTy; /// { i8*, %swift.refcounted* }
- llvm::StructType *WitnessFunctionPairTy; /// { i8*, %witness.table* }
llvm::FunctionType *DeallocatingDtorTy; /// void (%swift.refcounted*)
llvm::StructType *TypeMetadataStructTy; /// %swift.type = type { ... }
llvm::PointerType *TypeMetadataPtrTy;/// %swift.type*
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index dfff469..97e61fb 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -887,7 +887,8 @@
void visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *i);
void visitInitExistentialRefInst(InitExistentialRefInst *i);
void visitDeinitExistentialAddrInst(DeinitExistentialAddrInst *i);
-
+ void visitDeinitExistentialOpaqueInst(DeinitExistentialOpaqueInst *i);
+
void visitAllocExistentialBoxInst(AllocExistentialBoxInst *i);
void visitOpenExistentialBoxInst(OpenExistentialBoxInst *i);
void visitProjectExistentialBoxInst(ProjectExistentialBoxInst *i);
@@ -1887,14 +1888,11 @@
//
// We recover the witness table from the substitution that was used to
// produce the substituted callee type.
- //
- // There can be multiple substitutions, but the first one is the Self type.
- assert(subs.size() >= 1);
- assert(subs[0].getConformances().size() == 1);
-
- auto conformance = subs[0].getConformances()[0];
- assert(conformance.getRequirement() == proto); (void) proto;
- auto substSelfType = subs[0].getReplacement()->getCanonicalType();
+ auto subMap = origCalleeType->getGenericSignature()
+ ->getSubstitutionMap(subs);
+ auto origSelfType = proto->getSelfInterfaceType()->getCanonicalType();
+ auto substSelfType = origSelfType.subst(subMap)->getCanonicalType();
+ auto conformance = *subMap.lookupConformance(origSelfType, proto);
llvm::Value *argMetadata = IGF.emitTypeMetadataRef(substSelfType);
wtable = emitWitnessTableRef(IGF, substSelfType, &argMetadata,
@@ -1992,12 +1990,8 @@
if (origCalleeType->getRepresentation()
== SILFunctionType::Representation::WitnessMethod) {
- // @convention(witness_method) callees are exploded as a
- // triple consisting of the function, Self metadata, and
- // the Self witness table.
- witnessMetadata->SelfWitnessTable = calleeValues.claimNext();
- assert(witnessMetadata->SelfWitnessTable->getType() ==
- IGF.IGM.WitnessTablePtrTy);
+ witnessMetadata->SelfWitnessTable = emitWitnessTableForLoweredCallee(
+ IGF, origCalleeType, substitutions);
}
if (origCalleeType->getRepresentation()
@@ -2221,12 +2215,9 @@
case SILFunctionType::Representation::Closure:
case SILFunctionType::Representation::ObjCMethod:
break;
- case SILFunctionType::Representation::WitnessMethod: {
- llvm::Value *wtable = ex.claimNext();
- assert(wtable->getType() == IGF.IGM.WitnessTablePtrTy);
- context = wtable;
+ case SILFunctionType::Representation::WitnessMethod:
+ context = emitWitnessTableForLoweredCallee(IGF, fnType, subs);
break;
- }
case SILFunctionType::Representation::CFunctionPointer:
break;
case SILFunctionType::Representation::Thick:
@@ -2434,7 +2425,7 @@
defaultDest = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
}
- if (ty.getAs<BuiltinIntegerType>()) {
+ if (ty.is<BuiltinIntegerType>()) {
auto *discriminator = value.claimNext();
auto *i = IGF.Builder.CreateSwitch(discriminator, defaultDest,
dests.size());
@@ -2444,7 +2435,7 @@
// Get the value we're testing, which is a function.
llvm::Value *val;
llvm::BasicBlock *nextTest = nullptr;
- if (ty.getSwiftType()->is<SILFunctionType>()) {
+ if (ty.is<SILFunctionType>()) {
val = value.claimNext(); // Function pointer.
//values.claimNext(); // Ignore the data pointer.
} else {
@@ -2455,7 +2446,7 @@
auto casePair = dests[i];
llvm::Value *caseval;
auto casevalue = IGF.getLoweredExplosion(casePair.first);
- if (casePair.first->getType().getSwiftType()->is<SILFunctionType>()) {
+ if (casePair.first->getType().is<SILFunctionType>()) {
caseval = casevalue.claimNext(); // Function pointer.
//values.claimNext(); // Ignore the data pointer.
} else {
@@ -3013,7 +3004,7 @@
Explosion in = getLoweredExplosion(i->getOperand());
Explosion out;
cast<LoadableTypeInfo>(getTypeInfo(i->getOperand()->getType()))
- .copy(*this, in, out, irgen::Atomicity::Atomic);
+ .copy(*this, in, out, getDefaultAtomicity());
setLoweredExplosion(i, out);
}
@@ -3071,7 +3062,7 @@
void IRGenSILFunction::visitDestroyValueInst(swift::DestroyValueInst *i) {
Explosion in = getLoweredExplosion(i->getOperand());
cast<LoadableTypeInfo>(getTypeInfo(i->getOperand()->getType()))
- .consume(*this, in, irgen::Atomicity::Atomic);
+ .consume(*this, in, getDefaultAtomicity());
}
void IRGenSILFunction::visitStructInst(swift::StructInst *i) {
@@ -3276,21 +3267,16 @@
StringRef Name = getVarName(i);
DebugTypeInfo DbgTy;
SILType SILTy = SILVal->getType();
- // An inout/lvalue type that is described by a debug value has been
- // promoted by an optimization pass. Unwrap the type.
- bool Unwrap = true;
- auto RealTy = SILVal->getType().getSwiftType();
+ auto RealTy = SILVal->getType().getSwiftRValueType();
if (VarDecl *Decl = i->getDecl()) {
DbgTy = DebugTypeInfo::getLocalVariable(
CurSILFn->getDeclContext(), Decl, RealTy,
- getTypeInfo(SILVal->getType()), Unwrap);
+ getTypeInfo(SILVal->getType()), /*Unwrap=*/false);
} else if (i->getFunction()->isBare() &&
- !SILTy.getSwiftType()->hasArchetype() && !Name.empty()) {
+ !SILTy.hasArchetype() && !Name.empty()) {
// Preliminary support for .sil debug information.
DbgTy = DebugTypeInfo::getFromTypeInfo(CurSILFn->getDeclContext(), RealTy,
getTypeInfo(SILTy));
- if (Unwrap)
- DbgTy.unwrapLValueOrInOutType();
} else
return;
@@ -3317,7 +3303,9 @@
StringRef Name = getVarName(i);
auto Addr = getLoweredAddress(SILVal).getAddress();
SILType SILTy = SILVal->getType();
- auto RealType = SILTy.getSwiftType();
+ auto RealType = SILTy.getSwiftRValueType();
+ if (SILTy.isAddress())
+ RealType = CanInOutType::get(RealType);
// Unwrap implicitly indirect types and types that are passed by
// reference only at the SIL level and below.
//
@@ -3326,7 +3314,7 @@
// 'Unwrap' set to false.
bool Unwrap =
i->getVarInfo().Constant ||
- RealType->getLValueOrInOutObjectType()->is<ArchetypeType>();
+ SILTy.is<ArchetypeType>();
auto DbgTy = DebugTypeInfo::getLocalVariable(
CurSILFn->getDeclContext(), Decl, RealType,
getTypeInfo(SILVal->getType()), Unwrap);
@@ -3445,19 +3433,22 @@
visitStrongRetainUnownedInst(swift::StrongRetainUnownedInst *i) {
Explosion lowered = getLoweredExplosion(i->getOperand());
auto &ti = getReferentTypeInfo(*this, i->getOperand()->getType());
- ti.strongRetainUnowned(*this, lowered);
+ ti.strongRetainUnowned(*this, lowered, i->isAtomic() ? irgen::Atomicity::Atomic
+ : irgen::Atomicity::NonAtomic);
}
void IRGenSILFunction::visitUnownedRetainInst(swift::UnownedRetainInst *i) {
Explosion lowered = getLoweredExplosion(i->getOperand());
auto &ti = getReferentTypeInfo(*this, i->getOperand()->getType());
- ti.unownedRetain(*this, lowered);
+ ti.unownedRetain(*this, lowered, i->isAtomic() ? irgen::Atomicity::Atomic
+ : irgen::Atomicity::NonAtomic);
}
void IRGenSILFunction::visitUnownedReleaseInst(swift::UnownedReleaseInst *i) {
Explosion lowered = getLoweredExplosion(i->getOperand());
auto &ti = getReferentTypeInfo(*this, i->getOperand()->getType());
- ti.unownedRelease(*this, lowered);
+ ti.unownedRelease(*this, lowered, i->isAtomic() ? irgen::Atomicity::Atomic
+ : irgen::Atomicity::NonAtomic);
}
void IRGenSILFunction::visitLoadUnownedInst(swift::LoadUnownedInst *i) {
@@ -3597,14 +3588,10 @@
Pattern->getKind() != PatternKind::OptionalSome)
return;
- // Discard any inout or lvalue qualifiers. Since the object itself
- // is stored in the alloca, emitting it as a reference type would
- // be wrong.
- bool Unwrap = true;
SILType SILTy = i->getType();
- auto RealType = SILTy.getSwiftType().getLValueOrInOutObjectType();
+ auto RealType = SILTy.getSwiftRValueType();
auto DbgTy = DebugTypeInfo::getLocalVariable(CurSILFn->getDeclContext(),
- Decl, RealType, type, Unwrap);
+ Decl, RealType, type, false);
StringRef Name = getVarName(i);
if (auto DS = i->getDebugScope())
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
@@ -3785,10 +3772,13 @@
assert(i->getBoxType()->getLayout()->getFields().size() == 1
&& "box for a local variable should only have one field");
+ auto SILTy = i->getBoxType()->getFieldType(IGM.getSILModule(), 0);
+ auto RealType = SILTy.getSwiftRValueType();
+ if (SILTy.isAddress())
+ RealType = CanInOutType::get(RealType);
auto DbgTy = DebugTypeInfo::getLocalVariable(
CurSILFn->getDeclContext(), Decl,
- i->getBoxType()->getFieldType(IGM.getSILModule(), 0).getSwiftType(),
- type, /*Unwrap=*/false);
+ RealType, type, /*Unwrap=*/false);
if (isInlinedGeneric(Decl, i->getDebugScope()))
return;
@@ -4343,7 +4333,7 @@
llvm::Value *val;
const LoweredValue &lv = getLoweredValue(i->getOperand());
- if (i->getOperand()->getType().getSwiftType()->is<SILFunctionType>()) {
+ if (i->getOperand()->getType().is<SILFunctionType>()) {
Explosion values = lv.getExplosion(*this);
val = values.claimNext(); // Function pointer.
values.claimNext(); // Ignore the data pointer.
@@ -4511,6 +4501,11 @@
i->getOperand()->getType());
}
+void IRGenSILFunction::visitDeinitExistentialOpaqueInst(
+ swift::DeinitExistentialOpaqueInst *i) {
+ llvm_unreachable("unsupported instruction during IRGen");
+}
+
void IRGenSILFunction::visitOpenExistentialAddrInst(OpenExistentialAddrInst *i) {
SILType baseTy = i->getOperand()->getType();
Address base = getLoweredAddress(i->getOperand());
diff --git a/lib/IRGen/ReferenceTypeInfo.h b/lib/IRGen/ReferenceTypeInfo.h
index 56e3c33..816a240 100644
--- a/lib/IRGen/ReferenceTypeInfo.h
+++ b/lib/IRGen/ReferenceTypeInfo.h
@@ -49,20 +49,24 @@
/// Strongly retains a value that has come from a safe [unowned] reference.
/// This operation is not supported for all reference types.
- virtual void strongRetainUnowned(IRGenFunction &IGF, Explosion &in) const = 0;
+ virtual void strongRetainUnowned(IRGenFunction &IGF, Explosion &in,
+ Atomicity atomicity) const = 0;
/// Strongly retains a value that has come from a safe [unowned] reference.
/// This operation is not supported for all reference types.
virtual void strongRetainUnownedRelease(IRGenFunction &IGF,
- Explosion &in) const = 0;
+ Explosion &in,
+ Atomicity atomicity) const = 0;
/// Weakly retains a value in the manner of a safe [unowned] reference.
/// This operation is not supported for all reference types.
- virtual void unownedRetain(IRGenFunction &IGF, Explosion &in) const = 0;
+ virtual void unownedRetain(IRGenFunction &IGF, Explosion &in,
+ Atomicity atomicity) const = 0;
/// Weakly releases a value in the manner of a safe [unowned] reference.
/// This operation is not supported for all reference types.
- virtual void unownedRelease(IRGenFunction &IGF, Explosion &in) const = 0;
+ virtual void unownedRelease(IRGenFunction &IGF, Explosion &in,
+ Atomicity atomicity) const = 0;
/// Load a reference from a safe [unowned] reference in memory and
/// destroy the [unowned] location.
diff --git a/lib/IRGen/ScalarTypeInfo.h b/lib/IRGen/ScalarTypeInfo.h
index d2471e6..dd7dbc9 100644
--- a/lib/IRGen/ScalarTypeInfo.h
+++ b/lib/IRGen/ScalarTypeInfo.h
@@ -127,7 +127,7 @@
Explosion &out) const override {
addr = asDerived().projectScalar(IGF, addr);
llvm::Value *value = IGF.Builder.CreateLoad(addr);
- asDerived().emitScalarRetain(IGF, value, Atomicity::Atomic);
+ asDerived().emitScalarRetain(IGF, value, IGF.getDefaultAtomicity());
out.add(value);
}
@@ -153,7 +153,7 @@
// Release the old value if we need to.
if (!Derived::IsScalarPOD) {
- asDerived().emitScalarRelease(IGF, oldValue, Atomicity::Atomic);
+ asDerived().emitScalarRelease(IGF, oldValue, IGF.getDefaultAtomicity());
}
}
@@ -179,7 +179,7 @@
if (!Derived::IsScalarPOD) {
addr = asDerived().projectScalar(IGF, addr);
llvm::Value *value = IGF.Builder.CreateLoad(addr, "toDestroy");
- asDerived().emitScalarRelease(IGF, value, Atomicity::Atomic);
+ asDerived().emitScalarRelease(IGF, value, IGF.getDefaultAtomicity());
}
}
diff --git a/lib/IRGen/SwiftTargetInfo.cpp b/lib/IRGen/SwiftTargetInfo.cpp
index ea5464e..1c68338 100644
--- a/lib/IRGen/SwiftTargetInfo.cpp
+++ b/lib/IRGen/SwiftTargetInfo.cpp
@@ -158,6 +158,7 @@
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
configureARM(IGM, triple, target);
break;
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 0464ab1..52bf53c 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -191,6 +191,14 @@
bool addRelation(IndexSymbol &Info, SymbolRoleSet RelationRoles, Decl *D) {
assert(D);
+ auto Match = std::find_if(Info.Relations.begin(), Info.Relations.end(),
+ [D](IndexRelation R) { return R.decl == D; });
+ if (Match != Info.Relations.end()) {
+ Match->roles |= RelationRoles;
+ Info.roles |= RelationRoles;
+ return false;
+ }
+
StringRef Name, USR;
SymbolInfo SymInfo = getSymbolInfoForDecl(D);
@@ -400,7 +408,8 @@
}
bool isLocal(ValueDecl *D) const {
- return D->getDeclContext()->getLocalContext();
+ return D->getDeclContext()->getLocalContext() &&
+ (!isa<ParamDecl>(D) || cast<ParamDecl>(D)->getArgumentNameLoc().isValid());
}
void getModuleHash(SourceFileOrModule SFOrMod, llvm::raw_ostream &OS);
@@ -605,7 +614,7 @@
return false;
} else if (auto ParentED = dyn_cast<ExtensionDecl>(Parent)) {
- if (NominalTypeDecl *NTD = ParentED->getExtendedType()->getAnyNominal()) {
+ if (ParentED->getExtendedType()->getAnyNominal()) {
if (addRelation(Info, (SymbolRoleSet) SymbolRole::RelationChildOf, ParentED))
return false;
}
@@ -866,10 +875,14 @@
// Cannot be extension, which is not a ValueDecl.
- if (IsRef)
+ if (IsRef) {
Info.roles |= (unsigned)SymbolRole::Reference;
- else
+ auto Parent = getParentDecl();
+ if (Parent && isa<AbstractFunctionDecl>(Parent))
+ addRelation(Info, (unsigned)SymbolRole::RelationContainedBy, Parent);
+ } else {
Info.roles |= (unsigned)SymbolRole::Definition;
+ }
if (getNameAndUSR(D, /*ExtD=*/nullptr, Info.name, Info.USR))
return true;
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 1537c91..d59d1ba 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -112,10 +112,10 @@
info.SubKind = SymbolSubKind::SwiftSubscript;
break;
case DeclKind::Constructor: info.Kind = SymbolKind::Constructor; break;
- case DeclKind::Destructor: info.Kind = SymbolKind::Destructor; break;;
+ case DeclKind::Destructor: info.Kind = SymbolKind::Destructor; break;
case DeclKind::Param:
- llvm_unreachable("unexpected parameter seen while indexing");
-
+ info.Kind = SymbolKind::Parameter;
+ break;
case DeclKind::Func:
setFuncSymbolInfo(cast<FuncDecl>(D), info);
break;
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 870e1be..c0b384d 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -3,6 +3,7 @@
ParseDecl.cpp
ParseExpr.cpp
ParseGeneric.cpp
+ ParseIfConfig.cpp
ParsePattern.cpp
Parser.cpp
ParseSIL.cpp
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0b449e6..c61e690 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2727,32 +2727,31 @@
}
/// Parse a Decl item in decl list.
-static ParserStatus parseDeclItem(Parser &P,
- bool &PreviousHadSemi,
- Parser::ParseDeclOptions Options,
- llvm::function_ref<void(Decl*)> handler) {
- if (P.Tok.is(tok::semi)) {
+ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
+ Parser::ParseDeclOptions Options,
+ llvm::function_ref<void(Decl*)> handler) {
+ if (Tok.is(tok::semi)) {
// Consume ';' without preceding decl.
- P.diagnose(P.Tok, diag::unexpected_separator, ";")
- .fixItRemove(P.Tok.getLoc());
- P.consumeToken();
+ diagnose(Tok, diag::unexpected_separator, ";")
+ .fixItRemove(Tok.getLoc());
+ consumeToken();
// Return success because we already recovered.
return makeParserSuccess();
}
// If the previous declaration didn't have a semicolon and this new
// declaration doesn't start a line, complain.
- if (!PreviousHadSemi && !P.Tok.isAtStartOfLine() && !P.Tok.is(tok::unknown)) {
- auto endOfPrevious = P.getEndOfPreviousLoc();
- P.diagnose(endOfPrevious, diag::declaration_same_line_without_semi)
+ if (!PreviousHadSemi && !Tok.isAtStartOfLine() && !Tok.is(tok::unknown)) {
+ auto endOfPrevious = getEndOfPreviousLoc();
+ diagnose(endOfPrevious, diag::declaration_same_line_without_semi)
.fixItInsert(endOfPrevious, ";");
}
- auto Result = P.parseDecl(Options, handler);
+ auto Result = parseDecl(Options, handler);
if (Result.isParseError())
- P.skipUntilDeclRBrace(tok::semi, tok::pound_endif);
+ skipUntilDeclRBrace(tok::semi, tok::pound_endif);
SourceLoc SemiLoc;
- PreviousHadSemi = P.consumeIf(tok::semi, SemiLoc);
+ PreviousHadSemi = consumeIf(tok::semi, SemiLoc);
if (PreviousHadSemi && Result.isNonNull())
Result.get()->TrailingSemiLoc = SemiLoc;
return Result;
@@ -2769,7 +2768,7 @@
ParserStatus Status;
bool PreviousHadSemi = true;
while (Tok.isNot(tok::r_brace)) {
- Status |= parseDeclItem(*this, PreviousHadSemi, Options, handler);
+ Status |= parseDeclItem(PreviousHadSemi, Options, handler);
if (Tok.isAny(tok::eof, tok::pound_endif, tok::pound_else,
tok::pound_elseif)) {
IsInputIncomplete = true;
@@ -2999,94 +2998,6 @@
return makeParserSuccess();
}
-ParserResult<IfConfigDecl> Parser::parseDeclIfConfig(ParseDeclOptions Flags) {
- StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(),
- StructureMarkerKind::IfConfig);
-
- SmallVector<IfConfigDeclClause, 4> Clauses;
-
- bool foundActive = false;
- ConditionalCompilationExprState ConfigState;
- while (1) {
- bool isElse = Tok.is(tok::pound_else);
- SourceLoc ClauseLoc = consumeToken();
- Expr *Condition = nullptr;
-
- if (isElse) {
- ConfigState.setConditionActive(!foundActive);
- } else {
- // Evaluate the condition.
- llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
- ParserResult<Expr> Result = parseExprSequence(diag::expected_expr,
- /*isBasic*/true,
- /*isForDirective*/true);
- if (Result.isNull())
- return makeParserError();
-
- Condition = Result.get();
-
- // Evaluate the condition, to validate it.
- ConfigState = classifyConditionalCompilationExpr(Condition, Context,
- Diags);
- if (foundActive)
- ConfigState.setConditionActive(false);
- }
-
- foundActive |= ConfigState.isConditionActive();
-
- if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
- diagnose(Tok.getLoc(),
- diag::extra_tokens_conditional_compilation_directive);
- }
-
- Optional<Scope> scope;
- if (!ConfigState.isConditionActive())
- scope.emplace(this, getScopeInfo().getCurrentScope()->getKind(),
- /*inactiveConfigBlock=*/true);
-
- SmallVector<Decl*, 8> Decls;
- if (ConfigState.shouldParse()) {
- ParserStatus Status;
- bool PreviousHadSemi = true;
- while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif,
- tok::eof)) {
- if (Tok.is(tok::r_brace)) {
- diagnose(Tok.getLoc(),
- diag::unexpected_rbrace_in_conditional_compilation_block);
- // If we see '}', following declarations don't look like belong to
- // the current decl context; skip them.
- skipUntilConditionalBlockClose();
- break;
- }
- Status |= parseDeclItem(*this, PreviousHadSemi, Flags,
- [&](Decl *D) {Decls.push_back(D);});
- }
- } else {
- DiagnosticTransaction DT(Diags);
- skipUntilConditionalBlockClose();
- DT.abort();
- }
-
- Clauses.push_back(IfConfigDeclClause(ClauseLoc, Condition,
- Context.AllocateCopy(Decls),
- ConfigState.isConditionActive()));
-
- if (Tok.isNot(tok::pound_elseif) && Tok.isNot(tok::pound_else))
- break;
-
- if (isElse)
- diagnose(Tok, diag::expected_close_after_else_directive);
- }
-
- SourceLoc EndLoc;
- bool HadMissingEnd = parseEndIfDirective(EndLoc);
-
- IfConfigDecl *ICD = new (Context) IfConfigDecl(CurDeclContext,
- Context.AllocateCopy(Clauses),
- EndLoc, HadMissingEnd);
- return makeParserResult(ICD);
-}
-
/// \brief Parse a typealias decl.
///
/// \verbatim
@@ -3185,7 +3096,7 @@
///
/// \verbatim
/// decl-associatedtype:
-/// 'associatedtype' identifier inheritance? ('=' type)?
+/// 'associatedtype' identifier inheritance? ('=' type)? where-clause?
/// \endverbatim
ParserResult<TypeDecl> Parser::parseDeclAssociatedType(Parser::ParseDeclOptions Flags,
@@ -3239,15 +3150,32 @@
if (UnderlyingTy.isNull())
return Status;
}
-
- // Parse a 'where' clause if present. These are not supported, but we will
- // get better QoI this way.
+
+ TrailingWhereClause *TrailingWhere = nullptr;
+ // Parse a 'where' clause if present.
if (Tok.is(tok::kw_where)) {
- GenericParamList *unused = nullptr;
- auto whereStatus = parseFreestandingGenericWhereClause(
- unused, WhereClauseKind::AssociatedType);
- if (whereStatus.shouldStopParsing())
- return whereStatus;
+ SourceLoc whereLoc;
+ SmallVector<RequirementRepr, 4> requirements;
+ bool firstTypeInComplete;
+ auto whereStatus =
+ parseGenericWhereClause(whereLoc, requirements, firstTypeInComplete);
+ if (whereStatus.isSuccess()) {
+ TrailingWhere =
+ TrailingWhereClause::create(Context, whereLoc, requirements);
+ } else if (whereStatus.hasCodeCompletion()) {
+ // FIXME: this is completely (hah) cargo culted.
+ if (CodeCompletion && firstTypeInComplete) {
+ CodeCompletion->completeGenericParams(nullptr);
+ } else {
+ return makeParserCodeCompletionResult<AssociatedTypeDecl>();
+ }
+ }
+
+ if (Context.isSwiftVersion3()) {
+ diagnose(whereLoc, diag::associatedtype_where_swift_3);
+ // There's nothing to see here, move along.
+ TrailingWhere = nullptr;
+ }
}
if (!Flags.contains(PD_InProtocol)) {
@@ -3256,10 +3184,10 @@
Status.setIsParseError();
return Status;
}
-
- auto assocType = new (Context) AssociatedTypeDecl(CurDeclContext,
- AssociatedTypeLoc, Id, IdLoc,
- UnderlyingTy.getPtrOrNull());
+
+ auto assocType = new (Context)
+ AssociatedTypeDecl(CurDeclContext, AssociatedTypeLoc, Id, IdLoc,
+ UnderlyingTy.getPtrOrNull(), TrailingWhere);
assocType->getAttrs() = Attributes;
if (!Inherited.empty())
assocType->setInherited(Context.AllocateCopy(Inherited));
diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp
new file mode 100644
index 0000000..f6c064d
--- /dev/null
+++ b/lib/Parse/ParseIfConfig.cpp
@@ -0,0 +1,427 @@
+//===--- ParseDecl.cpp - Swift Language Parser for #if directives -- ------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// Conditional Compilation Block Parsing and AST Building
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Parse/Parser.h"
+#include "swift/Basic/Defer.h"
+#include "swift/Basic/LangOptions.h"
+#include "swift/Basic/Version.h"
+#include "swift/Parse/Lexer.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+using namespace swift;
+
+/// Parse and populate a list of #if/#elseif/#else/#endif clauses.
+/// Delegate callback function to parse elements in the blocks.
+template <typename ElemTy, unsigned N>
+static ParserStatus parseIfConfig(
+ Parser &P, SmallVectorImpl<IfConfigClause<ElemTy>> &Clauses,
+ SourceLoc &EndLoc, bool HadMissingEnd,
+ llvm::function_ref<void(SmallVectorImpl<ElemTy> &, bool)> parseElements) {
+ Parser::StructureMarkerRAII ParsingDecl(
+ P, P.Tok.getLoc(), Parser::StructureMarkerKind::IfConfig);
+
+ bool foundActive = false;
+ ConditionalCompilationExprState ConfigState;
+ while (1) {
+ bool isElse = P.Tok.is(tok::pound_else);
+ SourceLoc ClauseLoc = P.consumeToken();
+ Expr *Condition = nullptr;
+
+ // Parse and evaluate the directive.
+ if (isElse) {
+ ConfigState.setConditionActive(!foundActive);
+ } else {
+ llvm::SaveAndRestore<bool> S(P.InPoundIfEnvironment, true);
+ ParserResult<Expr> Result = P.parseExprSequence(diag::expected_expr,
+ /*isBasic*/true,
+ /*isForDirective*/true);
+ if (Result.isNull())
+ return makeParserError();
+
+ Condition = Result.get();
+
+ // Evaluate the condition, to validate it.
+ ConfigState = P.classifyConditionalCompilationExpr(Condition, P.Context,
+ P.Diags);
+ if (foundActive)
+ ConfigState.setConditionActive(false);
+ }
+
+ foundActive |= ConfigState.isConditionActive();
+
+ if (!P.Tok.isAtStartOfLine() && P.Tok.isNot(tok::eof)) {
+ P.diagnose(P.Tok.getLoc(),
+ diag::extra_tokens_conditional_compilation_directive);
+ }
+
+ // Parse elements
+ SmallVector<ElemTy, N> Elements;
+ if (ConfigState.shouldParse()) {
+ parseElements(Elements, ConfigState.isConditionActive());
+ } else {
+ DiagnosticTransaction DT(P.Diags);
+ P.skipUntilConditionalBlockClose();
+ DT.abort();
+ }
+
+ Clauses.push_back(IfConfigClause<ElemTy>(ClauseLoc, Condition,
+ P.Context.AllocateCopy(Elements),
+ ConfigState.isConditionActive()));
+
+ if (P.Tok.isNot(tok::pound_elseif, tok::pound_else))
+ break;
+
+ if (isElse)
+ P.diagnose(P.Tok, diag::expected_close_after_else_directive);
+ }
+
+ HadMissingEnd = P.parseEndIfDirective(EndLoc);
+ return makeParserSuccess();
+}
+
+ParserResult<IfConfigDecl> Parser::parseDeclIfConfig(ParseDeclOptions Flags) {
+ SmallVector<IfConfigClause<Decl *>, 4> Clauses;
+ SourceLoc EndLoc;
+ bool HadMissingEnd = false;
+ auto Status = parseIfConfig<Decl *, 8>(
+ *this, Clauses, EndLoc, HadMissingEnd,
+ [&](SmallVectorImpl<Decl *> &Decls, bool IsActive) {
+ Optional<Scope> scope;
+ if (!IsActive)
+ scope.emplace(this, getScopeInfo().getCurrentScope()->getKind(),
+ /*inactiveConfigBlock=*/true);
+
+ ParserStatus Status;
+ bool PreviousHadSemi = true;
+ while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif,
+ tok::eof)) {
+ if (Tok.is(tok::r_brace)) {
+ diagnose(Tok.getLoc(),
+ diag::unexpected_rbrace_in_conditional_compilation_block);
+ // If we see '}', following declarations don't look like belong to
+ // the current decl context; skip them.
+ skipUntilConditionalBlockClose();
+ break;
+ }
+ Status |= parseDeclItem(PreviousHadSemi, Flags,
+ [&](Decl *D) {Decls.push_back(D);});
+ }
+ });
+ if (Status.isError())
+ return makeParserErrorResult<IfConfigDecl>();
+
+ IfConfigDecl *ICD = new (Context) IfConfigDecl(CurDeclContext,
+ Context.AllocateCopy(Clauses),
+ EndLoc, HadMissingEnd);
+ return makeParserResult(ICD);
+}
+
+ParserResult<Stmt> Parser::parseStmtIfConfig(BraceItemListKind Kind) {
+ SmallVector<IfConfigClause<ASTNode>, 4> Clauses;
+ SourceLoc EndLoc;
+ bool HadMissingEnd = false;
+ auto Status = parseIfConfig<ASTNode, 16>(
+ *this, Clauses, EndLoc, HadMissingEnd,
+ [&](SmallVectorImpl<ASTNode> &Elements, bool IsActive) {
+ parseBraceItems(Elements, Kind, IsActive
+ ? BraceItemListKind::ActiveConditionalBlock
+ : BraceItemListKind::InactiveConditionalBlock);
+ });
+ if (Status.isError())
+ return makeParserErrorResult<Stmt>();
+
+ auto *ICS = new (Context) IfConfigStmt(Context.AllocateCopy(Clauses),
+ EndLoc, HadMissingEnd);
+ return makeParserResult(ICS);
+}
+
+// Evaluate a subset of expression types suitable for build configuration
+// conditional expressions. The accepted expression types are:
+// - The magic constants "true" and "false".
+// - Named decl ref expressions ("FOO")
+// - Parenthesized expressions ("(FOO)")
+// - Binary "&&" or "||" operations applied to other build configuration
+// conditional expressions
+// - Unary "!" expressions applied to other build configuration conditional
+// expressions
+// - Single-argument call expressions, where the function being invoked is a
+// supported target configuration (currently "os", "arch", and
+// "_compiler_version"), and whose argument is a named decl ref expression
+ConditionalCompilationExprState
+Parser::classifyConditionalCompilationExpr(Expr *condition,
+ ASTContext &Context,
+ DiagnosticEngine &D) {
+ assert(condition && "Cannot classify a NULL condition expression!");
+
+ // Evaluate a ParenExpr.
+ if (auto *PE = dyn_cast<ParenExpr>(condition))
+ return classifyConditionalCompilationExpr(PE->getSubExpr(), Context, D);
+
+ // Evaluate a "&&" or "||" expression.
+ if (auto *SE = dyn_cast<SequenceExpr>(condition)) {
+ // Check for '&&' or '||' as the expression type.
+ if (SE->getNumElements() < 3) {
+ D.diagnose(SE->getLoc(),
+ diag::unsupported_conditional_compilation_binary_expression);
+ return ConditionalCompilationExprState::error();
+ }
+ // Before type checking, chains of binary expressions will not be fully
+ // parsed, so associativity has not yet been encoded in the subtree.
+ auto elements = SE->getElements();
+ auto numElements = SE->getNumElements();
+ size_t iOperator = 1;
+ size_t iOperand = 2;
+
+ auto result = classifyConditionalCompilationExpr(elements[0], Context, D);
+
+ while (iOperand < numElements) {
+
+ if (auto *UDREOp = dyn_cast<UnresolvedDeclRefExpr>(elements[iOperator])) {
+ auto name = UDREOp->getName().getBaseName().str();
+
+ if (name.equals("||") || name.equals("&&")) {
+ auto rhs = classifyConditionalCompilationExpr(elements[iOperand],
+ Context, D);
+
+ if (name.equals("||")) {
+ result = result || rhs;
+ if (result.isConditionActive())
+ break;
+ }
+
+ if (name.equals("&&")) {
+ result = result && rhs;
+ if (!result.isConditionActive())
+ break;
+ }
+ } else {
+ D.diagnose(
+ SE->getLoc(),
+ diag::unsupported_conditional_compilation_binary_expression);
+ return ConditionalCompilationExprState::error();
+ }
+ } else {
+ // Swift3 didn't have this branch. the operator and the RHS are
+ // silently ignored.
+ if (!Context.isSwiftVersion3()) {
+ D.diagnose(
+ elements[iOperator]->getLoc(),
+ diag::unsupported_conditional_compilation_expression_type);
+ return ConditionalCompilationExprState::error();
+ } else {
+ SourceRange ignoredRange(elements[iOperator]->getLoc(),
+ elements[iOperand]->getEndLoc());
+ D.diagnose(
+ elements[iOperator]->getLoc(),
+ diag::swift3_unsupported_conditional_compilation_expression_type)
+ .highlight(ignoredRange);
+ }
+ }
+
+ iOperator += 2;
+ iOperand += 2;
+ }
+
+ return result;
+ }
+
+ // Evaluate a named reference expression.
+ if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(condition)) {
+ auto name = UDRE->getName().getBaseName().str();
+ return {Context.LangOpts.isCustomConditionalCompilationFlagSet(name),
+ ConditionalCompilationExprKind::DeclRef};
+ }
+
+ // Evaluate a Boolean literal.
+ if (auto *boolLit = dyn_cast<BooleanLiteralExpr>(condition)) {
+ return {boolLit->getValue(), ConditionalCompilationExprKind::Boolean};
+ }
+
+ // Evaluate a negation (unary "!") expression.
+ if (auto *PUE = dyn_cast<PrefixUnaryExpr>(condition)) {
+ // If the PUE is not a negation expression, return false
+ auto name =
+ cast<UnresolvedDeclRefExpr>(PUE->getFn())->getName().getBaseName().str();
+ if (name != "!") {
+ D.diagnose(PUE->getLoc(),
+ diag::unsupported_conditional_compilation_unary_expression);
+ return ConditionalCompilationExprState::error();
+ }
+
+ return !classifyConditionalCompilationExpr(PUE->getArg(), Context, D);
+ }
+
+ // Evaluate a target config call expression.
+ if (auto *CE = dyn_cast<CallExpr>(condition)) {
+ // look up target config, and compare value
+ auto fnNameExpr = dyn_cast<UnresolvedDeclRefExpr>(CE->getFn());
+
+ // Get the arg, which should be in a paren expression.
+ if (!fnNameExpr) {
+ D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression);
+ return ConditionalCompilationExprState::error();
+ }
+
+ auto fnName = fnNameExpr->getName().getBaseName().str();
+
+ auto *PE = dyn_cast<ParenExpr>(CE->getArg());
+ if (!PE) {
+ auto diag = D.diagnose(CE->getLoc(),
+ diag::platform_condition_expected_one_argument);
+ return ConditionalCompilationExprState::error();
+ }
+
+ if (!fnName.equals("arch") && !fnName.equals("os") &&
+ !fnName.equals("_endian") &&
+ !fnName.equals("_runtime") &&
+ !fnName.equals("swift") &&
+ !fnName.equals("_compiler_version")) {
+ D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression);
+ return ConditionalCompilationExprState::error();
+ }
+
+ if (fnName.equals("_compiler_version")) {
+ if (auto SLE = dyn_cast<StringLiteralExpr>(PE->getSubExpr())) {
+ if (SLE->getValue().empty()) {
+ D.diagnose(CE->getLoc(), diag::empty_version_string);
+ return ConditionalCompilationExprState::error();
+ }
+ auto versionRequirement =
+ version::Version::parseCompilerVersionString(SLE->getValue(),
+ SLE->getLoc(),
+ &D);
+ auto thisVersion = version::Version::getCurrentCompilerVersion();
+ auto VersionNewEnough = thisVersion >= versionRequirement;
+ return {VersionNewEnough,
+ ConditionalCompilationExprKind::CompilerVersion};
+ } else {
+ D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,
+ "string literal");
+ return ConditionalCompilationExprState::error();
+ }
+ } else if (fnName.equals("swift")) {
+ auto PUE = dyn_cast<PrefixUnaryExpr>(PE->getSubExpr());
+ if (!PUE) {
+ D.diagnose(PE->getSubExpr()->getLoc(),
+ diag::unsupported_platform_condition_argument,
+ "a unary comparison, such as '>=2.2'");
+ return ConditionalCompilationExprState::error();
+ }
+
+ auto prefix = dyn_cast<UnresolvedDeclRefExpr>(PUE->getFn());
+ auto versionArg = PUE->getArg();
+ auto versionStartLoc = versionArg->getStartLoc();
+ auto endLoc = Lexer::getLocForEndOfToken(Context.SourceMgr,
+ versionArg->getSourceRange().End);
+ CharSourceRange versionCharRange(Context.SourceMgr, versionStartLoc,
+ endLoc);
+ auto versionString = Context.SourceMgr.extractText(versionCharRange);
+
+ auto versionRequirement =
+ version::Version::parseVersionString(versionString,
+ versionStartLoc,
+ &D);
+
+ if (!versionRequirement.hasValue())
+ return ConditionalCompilationExprState::error();
+
+ auto thisVersion = Context.LangOpts.EffectiveLanguageVersion;
+
+ if (!prefix->getName().getBaseName().str().equals(">=")) {
+ D.diagnose(PUE->getFn()->getLoc(),
+ diag::unexpected_version_comparison_operator)
+ .fixItReplace(PUE->getFn()->getLoc(), ">=");
+ return ConditionalCompilationExprState::error();
+ }
+
+ auto VersionNewEnough = thisVersion >= versionRequirement.getValue();
+ return {VersionNewEnough,
+ ConditionalCompilationExprKind::LanguageVersion};
+ } else {
+ if (auto UDRE = dyn_cast<UnresolvedDeclRefExpr>(PE->getSubExpr())) {
+ // The sub expression should be an UnresolvedDeclRefExpr (we won't
+ // tolerate extra parens).
+ auto argumentIdent = UDRE->getName().getBaseName();
+ auto argument = argumentIdent.str();
+ PlatformConditionKind Kind =
+ llvm::StringSwitch<PlatformConditionKind>(fnName)
+ .Case("os", PlatformConditionKind::OS)
+ .Case("arch", PlatformConditionKind::Arch)
+ .Case("_endian", PlatformConditionKind::Endianness)
+ .Case("_runtime", PlatformConditionKind::Runtime);
+
+ // FIXME: Perform the replacement macOS -> OSX elsewhere.
+ if (Kind == PlatformConditionKind::OS && argument == "macOS")
+ argument = "OSX";
+
+ std::vector<StringRef> suggestions;
+ if (!LangOptions::checkPlatformConditionSupported(Kind, argument,
+ suggestions)) {
+ if (Kind == PlatformConditionKind::Runtime) {
+ // Error for _runtime()
+ D.diagnose(UDRE->getLoc(),
+ diag::unsupported_platform_runtime_condition_argument);
+ return ConditionalCompilationExprState::error();
+ }
+ StringRef DiagName;
+ switch (Kind) {
+ case PlatformConditionKind::OS:
+ DiagName = "operating system"; break;
+ case PlatformConditionKind::Arch:
+ DiagName = "architecture"; break;
+ case PlatformConditionKind::Endianness:
+ DiagName = "endianness"; break;
+ case PlatformConditionKind::Runtime:
+ llvm_unreachable("handled above");
+ }
+ D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
+ DiagName, fnName);
+ for (const StringRef &suggestion : suggestions) {
+ D.diagnose(UDRE->getLoc(), diag::note_typo_candidate, suggestion)
+ .fixItReplace(UDRE->getSourceRange(), suggestion);
+ }
+ }
+
+ auto target = Context.LangOpts.getPlatformConditionValue(Kind);
+ return {target == argument, ConditionalCompilationExprKind::DeclRef};
+ } else {
+ D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,
+ "identifier");
+ return ConditionalCompilationExprState::error();
+ }
+ }
+ }
+
+ // "#if 0" isn't valid, but it is common, so recognize it and handle it
+ // with a fixit elegantly.
+ if (auto *IL = dyn_cast<IntegerLiteralExpr>(condition))
+ if (IL->getDigitsText() == "0" || IL->getDigitsText() == "1") {
+ StringRef replacement = IL->getDigitsText() == "0" ? "false" :"true";
+ D.diagnose(IL->getLoc(), diag::unsupported_conditional_compilation_integer,
+ IL->getDigitsText(), replacement)
+ .fixItReplace(IL->getLoc(), replacement);
+ return {IL->getDigitsText() == "1",
+ ConditionalCompilationExprKind::Integer};
+ }
+
+
+ // If we've gotten here, it's an unsupported expression type.
+ D.diagnose(condition->getLoc(),
+ diag::unsupported_conditional_compilation_expression_type);
+ return ConditionalCompilationExprState::error();
+}
diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp
index 771cdda..dedf8c8 100644
--- a/lib/Parse/ParseSIL.cpp
+++ b/lib/Parse/ParseSIL.cpp
@@ -2133,9 +2133,9 @@
UNARY_INSTRUCTION(DestroyValue)
UNARY_INSTRUCTION(CondFail)
UNARY_INSTRUCTION(EndBorrowArgument)
- UNARY_INSTRUCTION(UnmanagedReleaseValue)
- UNARY_INSTRUCTION(UnmanagedRetainValue)
- UNARY_INSTRUCTION(UnmanagedAutoreleaseValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedRetainValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedAutoreleaseValue)
REFCOUNTING_INSTRUCTION(StrongPin)
REFCOUNTING_INSTRUCTION(StrongRetain)
REFCOUNTING_INSTRUCTION(StrongRelease)
@@ -3724,6 +3724,12 @@
ResultVal = B.createDeinitExistentialAddr(InstLoc, Val);
break;
}
+ case ValueKind::DeinitExistentialOpaqueInst: {
+ if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
+ return true;
+ ResultVal = B.createDeinitExistentialOpaque(InstLoc, Val);
+ break;
+ }
case ValueKind::InitExistentialAddrInst: {
CanType Ty;
SourceLoc TyLoc;
@@ -3758,7 +3764,7 @@
SourceLoc TyLoc;
if (parseTypedValueRef(Val, B) ||
- P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") ||
+ P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$") ||
parseASTType(FormalConcreteTy, TyLoc) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index ed621fd..f670b8b 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1486,358 +1486,6 @@
new (Context) GuardStmt(GuardLoc, Condition, Body.get()));
}
-
-// Evaluate a subset of expression types suitable for build configuration
-// conditional expressions. The accepted expression types are:
-// - The magic constants "true" and "false".
-// - Named decl ref expressions ("FOO")
-// - Parenthesized expressions ("(FOO)")
-// - Binary "&&" or "||" operations applied to other build configuration
-// conditional expressions
-// - Unary "!" expressions applied to other build configuration conditional
-// expressions
-// - Single-argument call expressions, where the function being invoked is a
-// supported target configuration (currently "os", "arch", and
-// "_compiler_version"), and whose argument is a named decl ref expression
-ConditionalCompilationExprState
-Parser::classifyConditionalCompilationExpr(Expr *condition,
- ASTContext &Context,
- DiagnosticEngine &D) {
- assert(condition && "Cannot classify a NULL condition expression!");
-
- // Evaluate a ParenExpr.
- if (auto *PE = dyn_cast<ParenExpr>(condition))
- return classifyConditionalCompilationExpr(PE->getSubExpr(), Context, D);
-
- // Evaluate a "&&" or "||" expression.
- if (auto *SE = dyn_cast<SequenceExpr>(condition)) {
- // Check for '&&' or '||' as the expression type.
- if (SE->getNumElements() < 3) {
- D.diagnose(SE->getLoc(),
- diag::unsupported_conditional_compilation_binary_expression);
- return ConditionalCompilationExprState::error();
- }
- // Before type checking, chains of binary expressions will not be fully
- // parsed, so associativity has not yet been encoded in the subtree.
- auto elements = SE->getElements();
- auto numElements = SE->getNumElements();
- size_t iOperator = 1;
- size_t iOperand = 2;
-
- auto result = classifyConditionalCompilationExpr(elements[0], Context, D);
-
- while (iOperand < numElements) {
-
- if (auto *UDREOp = dyn_cast<UnresolvedDeclRefExpr>(elements[iOperator])) {
- auto name = UDREOp->getName().getBaseName().str();
-
- if (name.equals("||") || name.equals("&&")) {
- auto rhs = classifyConditionalCompilationExpr(elements[iOperand],
- Context, D);
-
- if (name.equals("||")) {
- result = result || rhs;
- if (result.isConditionActive())
- break;
- }
-
- if (name.equals("&&")) {
- result = result && rhs;
- if (!result.isConditionActive())
- break;
- }
- } else {
- D.diagnose(
- SE->getLoc(),
- diag::unsupported_conditional_compilation_binary_expression);
- return ConditionalCompilationExprState::error();
- }
- } else {
- // Swift3 didn't have this branch. the operator and the RHS are
- // silently ignored.
- if (!Context.isSwiftVersion3()) {
- D.diagnose(
- elements[iOperator]->getLoc(),
- diag::unsupported_conditional_compilation_expression_type);
- return ConditionalCompilationExprState::error();
- } else {
- SourceRange ignoredRange(elements[iOperator]->getLoc(),
- elements[iOperand]->getEndLoc());
- D.diagnose(
- elements[iOperator]->getLoc(),
- diag::swift3_unsupported_conditional_compilation_expression_type)
- .highlight(ignoredRange);
- }
- }
-
- iOperator += 2;
- iOperand += 2;
- }
-
- return result;
- }
-
- // Evaluate a named reference expression.
- if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(condition)) {
- auto name = UDRE->getName().getBaseName().str();
- return {Context.LangOpts.isCustomConditionalCompilationFlagSet(name),
- ConditionalCompilationExprKind::DeclRef};
- }
-
- // Evaluate a Boolean literal.
- if (auto *boolLit = dyn_cast<BooleanLiteralExpr>(condition)) {
- return {boolLit->getValue(), ConditionalCompilationExprKind::Boolean};
- }
-
- // Evaluate a negation (unary "!") expression.
- if (auto *PUE = dyn_cast<PrefixUnaryExpr>(condition)) {
- // If the PUE is not a negation expression, return false
- auto name =
- cast<UnresolvedDeclRefExpr>(PUE->getFn())->getName().getBaseName().str();
- if (name != "!") {
- D.diagnose(PUE->getLoc(),
- diag::unsupported_conditional_compilation_unary_expression);
- return ConditionalCompilationExprState::error();
- }
-
- return !classifyConditionalCompilationExpr(PUE->getArg(), Context, D);
- }
-
- // Evaluate a target config call expression.
- if (auto *CE = dyn_cast<CallExpr>(condition)) {
- // look up target config, and compare value
- auto fnNameExpr = dyn_cast<UnresolvedDeclRefExpr>(CE->getFn());
-
- // Get the arg, which should be in a paren expression.
- if (!fnNameExpr) {
- D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression);
- return ConditionalCompilationExprState::error();
- }
-
- auto fnName = fnNameExpr->getName().getBaseName().str();
-
- auto *PE = dyn_cast<ParenExpr>(CE->getArg());
- if (!PE) {
- auto diag = D.diagnose(CE->getLoc(),
- diag::platform_condition_expected_one_argument);
- return ConditionalCompilationExprState::error();
- }
-
- if (!fnName.equals("arch") && !fnName.equals("os") &&
- !fnName.equals("_endian") &&
- !fnName.equals("_runtime") &&
- !fnName.equals("swift") &&
- !fnName.equals("_compiler_version")) {
- D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_expression);
- return ConditionalCompilationExprState::error();
- }
-
- if (fnName.equals("_compiler_version")) {
- if (auto SLE = dyn_cast<StringLiteralExpr>(PE->getSubExpr())) {
- if (SLE->getValue().empty()) {
- D.diagnose(CE->getLoc(), diag::empty_version_string);
- return ConditionalCompilationExprState::error();
- }
- auto versionRequirement =
- version::Version::parseCompilerVersionString(SLE->getValue(),
- SLE->getLoc(),
- &D);
- auto thisVersion = version::Version::getCurrentCompilerVersion();
- auto VersionNewEnough = thisVersion >= versionRequirement;
- return {VersionNewEnough,
- ConditionalCompilationExprKind::CompilerVersion};
- } else {
- D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,
- "string literal");
- return ConditionalCompilationExprState::error();
- }
- } else if (fnName.equals("swift")) {
- auto PUE = dyn_cast<PrefixUnaryExpr>(PE->getSubExpr());
- if (!PUE) {
- D.diagnose(PE->getSubExpr()->getLoc(),
- diag::unsupported_platform_condition_argument,
- "a unary comparison, such as '>=2.2'");
- return ConditionalCompilationExprState::error();
- }
-
- auto prefix = dyn_cast<UnresolvedDeclRefExpr>(PUE->getFn());
- auto versionArg = PUE->getArg();
- auto versionStartLoc = versionArg->getStartLoc();
- auto endLoc = Lexer::getLocForEndOfToken(Context.SourceMgr,
- versionArg->getSourceRange().End);
- CharSourceRange versionCharRange(Context.SourceMgr, versionStartLoc,
- endLoc);
- auto versionString = Context.SourceMgr.extractText(versionCharRange);
-
- auto versionRequirement =
- version::Version::parseVersionString(versionString,
- versionStartLoc,
- &D);
-
- if (!versionRequirement.hasValue())
- return ConditionalCompilationExprState::error();
-
- auto thisVersion = Context.LangOpts.EffectiveLanguageVersion;
-
- if (!prefix->getName().getBaseName().str().equals(">=")) {
- D.diagnose(PUE->getFn()->getLoc(),
- diag::unexpected_version_comparison_operator)
- .fixItReplace(PUE->getFn()->getLoc(), ">=");
- return ConditionalCompilationExprState::error();
- }
-
- auto VersionNewEnough = thisVersion >= versionRequirement.getValue();
- return {VersionNewEnough,
- ConditionalCompilationExprKind::LanguageVersion};
- } else {
- if (auto UDRE = dyn_cast<UnresolvedDeclRefExpr>(PE->getSubExpr())) {
- // The sub expression should be an UnresolvedDeclRefExpr (we won't
- // tolerate extra parens).
- auto argumentIdent = UDRE->getName().getBaseName();
- auto argument = argumentIdent.str();
-
- // Error for values that don't make sense if there's a clear definition
- // of the possible values (as there is for _runtime).
- if (fnName.equals("_runtime") &&
- !argument.equals("_ObjC") && !argument.equals("_Native")) {
- D.diagnose(CE->getLoc(),
- diag::unsupported_platform_runtime_condition_argument);
- return ConditionalCompilationExprState::error();
- }
-
- std::vector<StringRef> suggestions;
- SWIFT_DEFER {
- for (const StringRef& suggestion : suggestions) {
- D.diagnose(UDRE->getLoc(), diag::note_typo_candidate,
- suggestion)
- .fixItReplace(UDRE->getSourceRange(), suggestion);
- }
- };
- if (fnName == "os") {
- if (!LangOptions::checkPlatformConditionOS(argument,
- suggestions)) {
- D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
- "operating system", fnName);
- return ConditionalCompilationExprState::error();
- }
- } else if (fnName == "arch") {
- if (!LangOptions::isPlatformConditionArchSupported(argument,
- suggestions)) {
- D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
- "architecture", fnName);
- return ConditionalCompilationExprState::error();
- }
- } else if (fnName == "_endian") {
- if (!LangOptions::isPlatformConditionEndiannessSupported(argument,
- suggestions)) {
- D.diagnose(UDRE->getLoc(), diag::unknown_platform_condition_argument,
- "endianness", fnName);
- }
- }
-
- // FIXME: Perform the replacement macOS -> OSX elsewhere.
- if (fnName == "os" && argument == "macOS")
- argument = "OSX";
-
- auto target = Context.LangOpts.getPlatformConditionValue(fnName);
- return {target == argument, ConditionalCompilationExprKind::DeclRef};
- } else {
- D.diagnose(CE->getLoc(), diag::unsupported_platform_condition_argument,
- "identifier");
- return ConditionalCompilationExprState::error();
- }
- }
- }
-
- // "#if 0" isn't valid, but it is common, so recognize it and handle it
- // with a fixit elegantly.
- if (auto *IL = dyn_cast<IntegerLiteralExpr>(condition))
- if (IL->getDigitsText() == "0" || IL->getDigitsText() == "1") {
- StringRef replacement = IL->getDigitsText() == "0" ? "false" :"true";
- D.diagnose(IL->getLoc(), diag::unsupported_conditional_compilation_integer,
- IL->getDigitsText(), replacement)
- .fixItReplace(IL->getLoc(), replacement);
- return {IL->getDigitsText() == "1",
- ConditionalCompilationExprKind::Integer};
- }
-
-
- // If we've gotten here, it's an unsupported expression type.
- D.diagnose(condition->getLoc(),
- diag::unsupported_conditional_compilation_expression_type);
- return ConditionalCompilationExprState::error();
-}
-
-ParserResult<Stmt> Parser::parseStmtIfConfig(BraceItemListKind Kind) {
- StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(),
- StructureMarkerKind::IfConfig);
- SmallVector<IfConfigStmtClause, 4> Clauses;
-
- bool foundActive = false;
- ConditionalCompilationExprState ConfigState;
- while (1) {
- bool isElse = Tok.is(tok::pound_else);
- SourceLoc ClauseLoc = consumeToken();
- Expr *Condition = nullptr;
-
- if (isElse) {
- ConfigState.setConditionActive(!foundActive);
- } else {
- // Evaluate the condition.
- llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
- ParserResult<Expr> Result = parseExprSequence(diag::expected_expr,
- /*basic*/true,
- /*isForDirective*/true);
- if (Result.isNull())
- return makeParserError();
-
- Condition = Result.get();
-
- // Evaluate the condition, to validate it.
- ConfigState = classifyConditionalCompilationExpr(Condition, Context,
- Diags);
- if (foundActive)
- ConfigState.setConditionActive(false);
- }
-
- foundActive |= ConfigState.isConditionActive();
-
- if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
- diagnose(Tok.getLoc(),
- diag::extra_tokens_conditional_compilation_directive);
- }
-
- SmallVector<ASTNode, 16> Elements;
- if (ConfigState.shouldParse()) {
- parseBraceItems(Elements, Kind,
- ConfigState.isConditionActive()
- ? BraceItemListKind::ActiveConditionalBlock
- : BraceItemListKind::InactiveConditionalBlock);
- } else {
- DiagnosticTransaction DT(Diags);
- skipUntilConditionalBlockClose();
- DT.abort();
- }
-
- Clauses.push_back(IfConfigStmtClause(ClauseLoc, Condition,
- Context.AllocateCopy(Elements),
- ConfigState.isConditionActive()));
-
- if (Tok.isNot(tok::pound_elseif) && Tok.isNot(tok::pound_else))
- break;
-
- if (isElse)
- diagnose(Tok, diag::expected_close_after_else_directive);
- }
-
- SourceLoc EndLoc;
- bool HadMissingEnd = parseEndIfDirective(EndLoc);
-
- auto *ICS = new (Context) IfConfigStmt(Context.AllocateCopy(Clauses),
- EndLoc, HadMissingEnd);
- return makeParserResult(ICS);
-}
-
///
/// stmt-while:
/// (identifier ':')? 'while' expr-basic stmt-brace
diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp
index 66e142d..32521d1 100644
--- a/lib/PrintAsObjC/PrintAsObjC.cpp
+++ b/lib/PrintAsObjC/PrintAsObjC.cpp
@@ -15,6 +15,7 @@
#include "swift/AST/AST.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ForeignErrorConvention.h"
+#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
@@ -172,6 +173,23 @@
ASTVisitor::visit(const_cast<Decl *>(D));
}
+ void maybePrintObjCGenericParameters(const ClassDecl *importedClass) {
+ auto *clangDecl = importedClass->getClangDecl();
+ auto *objcClass = dyn_cast_or_null<clang::ObjCInterfaceDecl>(clangDecl);
+ if (!objcClass)
+ return;
+ if (!objcClass->getTypeParamList())
+ return;
+ assert(objcClass->getTypeParamList()->size() != 0);
+ os << "<";
+ interleave(*objcClass->getTypeParamList(),
+ [this](const clang::ObjCTypeParamDecl *param) {
+ os << param->getName();
+ },
+ [this] { os << ", "; });
+ os << ">";
+ }
+
void printAdHocCategory(iterator_range<const ValueDecl * const *> members) {
assert(members.begin() != members.end());
@@ -182,8 +200,10 @@
baseClass = extendedTy->getClassOrBoundGenericClass();
}
- os << "@interface " << getNameForObjC(baseClass)
- << " (SWIFT_EXTENSION(" << origDC->getParentModule()->getName() << "))\n";
+ os << "@interface " << getNameForObjC(baseClass);
+ maybePrintObjCGenericParameters(baseClass);
+ os << " (SWIFT_EXTENSION(" << origDC->getParentModule()->getName()
+ << "))\n";
printMembers</*allowDelayed*/true>(members);
os << "@end\n\n";
}
@@ -312,8 +332,9 @@
void visitExtensionDecl(ExtensionDecl *ED) {
auto baseClass = ED->getExtendedType()->getClassOrBoundGenericClass();
- os << "@interface " << getNameForObjC(baseClass)
- << " (SWIFT_EXTENSION(" << ED->getModuleContext()->getName() << "))";
+ os << "@interface " << getNameForObjC(baseClass);
+ maybePrintObjCGenericParameters(baseClass);
+ os << " (SWIFT_EXTENSION(" << ED->getModuleContext()->getName() << "))";
printProtocols(ED->getLocalProtocols(ConformanceLookupKind::OnlyExplicit));
os << "\n";
printMembers(ED->getMembers());
@@ -1574,6 +1595,30 @@
visitType(MT, optionalKind);
}
}
+
+ void visitGenericTypeParamType(GenericTypeParamType *type,
+ Optional<OptionalTypeKind> optionalKind) {
+ const GenericTypeParamDecl *decl = type->getDecl();
+ assert(decl && "can't print canonicalized GenericTypeParamType");
+
+ if (auto *extension = dyn_cast<ExtensionDecl>(decl->getDeclContext())) {
+ const ClassDecl *extendedClass =
+ extension->getAsClassOrClassExtensionContext();
+ assert(extendedClass->isGeneric());
+ assert(extension->getGenericParams()->size() ==
+ extendedClass->getGenericParams()->size() &&
+ "extensions with custom generic parameters?");
+ assert(extension->getGenericSignature()->getCanonicalSignature() ==
+ extendedClass->getGenericSignature()->getCanonicalSignature() &&
+ "constrained extensions or custom generic parameters?");
+ type = extendedClass->getGenericEnvironment()->getSugaredType(type);
+ decl = type->getDecl();
+ }
+
+ assert(decl->getClangDecl() && "can only handle imported ObjC generics");
+ os << cast<clang::ObjCTypeParamDecl>(decl->getClangDecl())->getName();
+ printNullability(optionalKind);
+ }
void printFunctionType(FunctionType *FT, char pointerSigil,
Optional<OptionalTypeKind> optionalKind) {
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index e528d87..eedca48 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -1139,23 +1139,30 @@
// non-NSError superclass constraint. Casts to archetypes thus must always be
// indirect.
if (auto archetype = targetType->getAs<ArchetypeType>()) {
- auto super = archetype->getSuperclass();
- if (super.isNull())
- return false;
-
// Only ever permit this if the source type is a reference type.
if (!objectType.isAnyClassReferenceType())
return false;
+
+ if (M.getASTContext().LangOpts.EnableObjCInterop) {
+ auto super = archetype->getSuperclass();
+ if (super.isNull())
+ return false;
- // A base class constraint that isn't NSError rules out the archetype being
- // bound to NSError.
- if (auto nserror = M.Types.getNSErrorType())
- return !super->isEqual(nserror);
- // If NSError wasn't loaded, any base class constraint must not be NSError.
- return true;
+ // A base class constraint that isn't NSError rules out the archetype being
+ // bound to NSError.
+ if (auto nserror = M.Types.getNSErrorType())
+ return !super->isEqual(nserror);
+ // If NSError wasn't loaded, any base class constraint must not be NSError.
+ return true;
+ } else {
+ // If ObjC bridging isn't enabled, we can do a scalar cast from any
+ // reference type to any class-constrained archetype.
+ return archetype->requiresClass();
+ }
}
- if (targetType == M.Types.getNSErrorType()) {
+ if (M.getASTContext().LangOpts.EnableObjCInterop
+ && targetType == M.Types.getNSErrorType()) {
// If we statically know the source is an NSError subclass, then the cast
// can go through the scalar path (and it's trivially true so can be
// killed).
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 8961f2d..e0dee29 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -245,7 +245,7 @@
}
// If we didn't find a retain to fold this into, emit the release.
- return createStrongRelease(Loc, Operand, Atomicity::Atomic);
+ return createStrongRelease(Loc, Operand, getDefaultAtomicity());
}
/// Emit a release_value instruction at the current location, attempting to
@@ -272,7 +272,7 @@
}
// If we didn't find a retain to fold this into, emit the release.
- return createReleaseValue(Loc, Operand, Atomicity::Atomic);
+ return createReleaseValue(Loc, Operand, getDefaultAtomicity());
}
PointerUnion<CopyValueInst *, DestroyValueInst *>
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index d1b799d..e6573ea 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -163,109 +163,24 @@
getGenericEnvironment(), type);
}
-namespace {
-template<typename SubstFn>
-struct SubstDependentSILType
- : CanTypeVisitor<SubstDependentSILType<SubstFn>, CanType>
-{
- SILModule &M;
- SubstFn Subst;
-
- SubstDependentSILType(SILModule &M, SubstFn Subst)
- : M(M), Subst(std::move(Subst))
- {}
-
- using super = CanTypeVisitor<SubstDependentSILType<SubstFn>, CanType>;
- using super::visit;
-
- CanType visitDependentMemberType(CanDependentMemberType t) {
- // If a dependent member type appears in lowered position, we need to lower
- // its context substitution against the associated type's abstraction
- // pattern.
- CanType astTy = Subst(t);
- auto origTy = AbstractionPattern::getOpaque();
-
- return M.Types.getLoweredType(origTy, astTy)
- .getSwiftRValueType();
- }
-
- CanType visitTupleType(CanTupleType t) {
- // Dependent members can appear in lowered position inside tuples.
-
- SmallVector<TupleTypeElt, 4> elements;
-
- for (auto &elt : t->getElements())
- elements.push_back(elt.getWithType(visit(CanType(elt.getType()))));
-
- return TupleType::get(elements, t->getASTContext())
- ->getCanonicalType();
- }
-
- CanType visitSILFunctionType(CanSILFunctionType t) {
- // Dependent members can appear in lowered position inside SIL functions.
-
- SmallVector<SILParameterInfo, 4> params;
- for (auto ¶m : t->getParameters())
- params.push_back(param.map([&](CanType pt) -> CanType {
- return visit(pt);
- }));
-
- SmallVector<SILResultInfo, 4> results;
- for (auto &result : t->getResults())
- results.push_back(result.map([&](CanType pt) -> CanType {
- return visit(pt);
- }));
-
- Optional<SILResultInfo> errorResult;
- if (t->hasErrorResult()) {
- errorResult = t->getErrorResult().map([&](CanType elt) -> CanType {
- return visit(elt);
- });
- }
-
- return SILFunctionType::get(t->getGenericSignature(),
- t->getExtInfo(),
- t->getCalleeConvention(),
- params, results, errorResult,
- t->getASTContext());
- }
-
- CanType visitType(CanType t) {
- // Other types get substituted into context normally.
- return Subst(t);
- }
-};
-
-template<typename SubstFn>
-SILType doSubstDependentSILType(SILModule &M,
- SubstFn Subst,
- SILType t) {
- CanType result = SubstDependentSILType<SubstFn>(M, std::move(Subst))
- .visit(t.getSwiftRValueType());
- return SILType::getPrimitiveType(result, t.getCategory());
-}
-
-} // end anonymous namespace
-
SILType SILFunction::mapTypeIntoContext(SILType type) const {
- return doSubstDependentSILType(getModule(),
- [&](CanType t) { return mapTypeIntoContext(t)->getCanonicalType(); },
- type);
+ if (auto *genericEnv = getGenericEnvironment())
+ return genericEnv->mapTypeIntoContext(getModule(), type);
+ return type;
}
SILType GenericEnvironment::mapTypeIntoContext(SILModule &M,
SILType type) const {
- return doSubstDependentSILType(M,
- [&](CanType t) {
- return mapTypeIntoContext(t)->getCanonicalType();
- },
- type);
+ auto genericSig = getGenericSignature()->getCanonicalSignature();
+ return type.subst(M,
+ QueryInterfaceTypeSubstitutions(this),
+ LookUpConformanceInSignature(*genericSig),
+ genericSig);
}
Type SILFunction::mapTypeOutOfContext(Type type) const {
return GenericEnvironment::mapTypeOutOfContext(
- getGenericEnvironment(),
- type);
+ getGenericEnvironment(), type);
}
bool SILFunction::isNoReturnFunction() const {
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 09cd8f2..3246a39 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -1760,268 +1760,6 @@
return result;
}
-namespace {
- class SILFunctionTypeSubstituter {
- TypeConverter &TC;
- CanSILFunctionType OrigFnType;
- ArrayRef<SILParameterInfo> OrigParams;
- ArrayRef<SILResultInfo> OrigResults;
- unsigned NextOrigParamIndex = 0;
- unsigned NextOrigResultIndex = 0;
- SmallVector<SILParameterInfo, 8> SubstParams;
- SmallVector<SILResultInfo, 8> SubstResults;
- const Optional<ForeignErrorConvention> &ForeignError;
-
- public:
- SILFunctionTypeSubstituter(
- TypeConverter &TC, CanSILFunctionType origFnType,
- const Optional<ForeignErrorConvention> &foreignError)
- : TC(TC), OrigFnType(origFnType),
- OrigParams(origFnType->getParameters()),
- OrigResults(origFnType->getResults()), ForeignError(foreignError) {}
-
- ArrayRef<SILResultInfo> getSubstResults() const {
- assert(NextOrigResultIndex == OrigResults.size() &&
- "didn't claim all results?!");
- return SubstResults;
- }
-
- void substResults(AbstractionPattern origType, CanType substType);
-
- ArrayRef<SILParameterInfo> getSubstParams() const {
- assert(NextOrigParamIndex == OrigParams.size() &&
- "didn't claim all parameters?!");
- return SubstParams;
- }
-
- void substInputs(AbstractionPattern origType, CanType substType) {
- maybeSkipForeignErrorParameter();
-
- // Decompose tuples.
- if (origType.isTuple()) {
- auto substTuple = cast<TupleType>(substType);
- assert(origType.getNumTupleElements() == substTuple->getNumElements());
- for (auto i : indices(substTuple.getElementTypes())) {
- substInputs(origType.getTupleElementType(i),
- substTuple.getElementType(i));
- }
- return;
- }
-
- // Every other type corresponds to a single parameter in the
- // original signature, since we're dealing with like-uncurried
- // types and thus don't have to worry about expanding archetypes
- // to unmaterializable parameter clauses in result function types.
- auto origParam = claimNextOrigParam();
-
- // If the type hasn't changed and doesn't rely on context, just use the
- // original parameter.
- if (origType.isExactType(substType) &&
- !origParam.getType()->hasTypeParameter()) {
- SubstParams.push_back(origParam);
- return;
- }
-
- // Otherwise, lower the substituted type using the abstraction
- // patterns of the original.
- auto &substTL = TC.getTypeLowering(origType, substType);
- auto substConvention = getSubstConvention(origParam.getConvention(),
- substTL.isTrivial());
- assert(isIndirectFormalParameter(substConvention)
- || !substTL.isAddressOnly());
- addSubstParam(substTL.getLoweredType().getSwiftRValueType(),
- substConvention);
- }
-
- private:
- void decomposeResult(AbstractionPattern origType, CanType substType);
-
- SILParameterInfo claimNextOrigParam() {
- maybeSkipForeignErrorParameter();
- return OrigParams[NextOrigParamIndex++];
- }
-
- SILResultInfo claimNextOrigResult() {
- return OrigResults[NextOrigResultIndex++];
- }
-
- void maybeSkipForeignErrorParameter() {
- if (!ForeignError ||
- NextOrigParamIndex != ForeignError->getErrorParameterIndex())
- return;
- SubstParams.push_back(OrigParams[NextOrigParamIndex++]);
- }
-
- void addSubstParam(CanType type, ParameterConvention conv) {
- SubstParams.push_back(SILParameterInfo(type, conv));
- }
-
- ParameterConvention getSubstConvention(ParameterConvention orig,
- bool isTrivial) {
- // We use the original convention, except that we have an
- // invariant that direct trivial parameters are always unowned.
- switch (orig) {
- case ParameterConvention::Direct_Owned:
- case ParameterConvention::Direct_Guaranteed:
- if (isTrivial) return ParameterConvention::Direct_Unowned;
- LLVM_FALLTHROUGH;
- case ParameterConvention::Direct_Unowned:
- case ParameterConvention::Indirect_Inout:
- case ParameterConvention::Indirect_InoutAliasable:
- case ParameterConvention::Indirect_In:
- case ParameterConvention::Indirect_In_Guaranteed:
- return orig;
- }
- llvm_unreachable("bad parameter convention");
- }
-
- ResultConvention getSubstConvention(ResultConvention orig,
- bool isTrivial) {
- // We use the original convention, except that we have an
- // invariant that direct trivial results are always unowned.
- switch (orig) {
- case ResultConvention::Owned:
- case ResultConvention::Autoreleased:
- if (isTrivial) return ResultConvention::Unowned;
- LLVM_FALLTHROUGH;
- case ResultConvention::Indirect:
- case ResultConvention::Unowned:
- case ResultConvention::UnownedInnerPointer:
- return orig;
- }
- llvm_unreachable("bad parameter convention");
- }
- };
-} // end anonymous namespace
-
-void SILFunctionTypeSubstituter::substResults(AbstractionPattern origResultType,
- CanType substResultType) {
- // Fast path: if the results of the original type are not type-dependent,
- // we can just copy them over.
- auto allResults = OrigFnType->getResults();
- if (std::find_if(allResults.begin(), allResults.end(),
- [&](SILResultInfo result) {
- return result.getType()->hasTypeParameter();
- }) == allResults.end()) {
- SubstResults.append(allResults.begin(), allResults.end());
- return;
- }
-
- // Okay, we need to walk the types and re-lower.
-
- // If we have a foreign-error convention that strips result
- // optionality, we need to wrap both the original and
- // substituted types in a level of optionality.
- if (ForeignError && ForeignError->stripsResultOptionality()) {
- origResultType =
- AbstractionPattern::getOptional(origResultType, OTK_Optional);
- substResultType =
- OptionalType::get(substResultType)->getCanonicalType();
- }
-
- decomposeResult(origResultType, substResultType);
-}
-
-void
-SILFunctionTypeSubstituter::decomposeResult(AbstractionPattern origResultType,
- CanType substResultType) {
- // If the result is a tuple, we need to expand it.
- if (origResultType.isTuple()) {
- auto substResultTupleType = cast<TupleType>(substResultType);
- for (auto eltIndex : indices(substResultTupleType.getElementTypes())) {
- auto origEltType = origResultType.getTupleElementType(eltIndex);
- auto substEltType = substResultTupleType.getElementType(eltIndex);
- decomposeResult(origEltType, substEltType);
- }
- return;
- }
-
- // Okay, the result is a single value, which will either be an
- // indirect result or not.
-
- // Grab the next result.
- SILResultInfo origResult = claimNextOrigResult();
-
- // If substitution is trivial, fast path.
- if (!origResult.getType()->hasTypeParameter()) {
- SubstResults.push_back(origResult);
- return;
- }
-
- // Lower the substituted result using the abstraction patterns
- // of the original result.
- auto &substResultTL = TC.getTypeLowering(origResultType, substResultType);
- auto loweredResultTy = substResultTL.getLoweredType().getSwiftRValueType();
-
- // Return the new type with the old convention.
- SILResultInfo substResult(loweredResultTy,
- getSubstConvention(origResult.getConvention(),
- substResultTL.isTrivial()));
- SubstResults.push_back(substResult);
-}
-
-/// Apply a substitution to the given SILFunctionType so that it has
-/// the form of the normal SILFunctionType for the substituted type,
-/// except using the original conventions.
-///
-/// This is equivalent to
-/// getLoweredType(origLoweredType,
-/// substLoweredType).castTo<SILFunctionType>()
-/// except that origFnType's conventions may not correspond to the
-/// standard conventions of the lowered type.
-CanSILFunctionType
-TypeConverter::substFunctionType(CanSILFunctionType origFnType,
- CanAnyFunctionType origLoweredType,
- CanAnyFunctionType substLoweredInterfaceType,
- const Optional<ForeignErrorConvention> &foreignError) {
- // FIXME: is this inefficient now?
- if (origLoweredType == substLoweredInterfaceType)
- return origFnType;
-
- // Use the generic parameters from the substituted type.
- CanGenericSignature genericSig;
- if (auto genSubstFn = dyn_cast<GenericFunctionType>(substLoweredInterfaceType))
- genericSig = genSubstFn.getGenericSignature();
-
- GenericContextScope scope(*this, genericSig);
- SILFunctionTypeSubstituter substituter(*this, origFnType, foreignError);
-
- AbstractionPattern origLoweredPattern(origLoweredType);
-
- // Map the results.
- substituter.substResults(origLoweredPattern.getFunctionResultType(),
- substLoweredInterfaceType.getResult());
-
- // Map the error result. Currently this is never dependent.
- Optional<SILResultInfo> substErrorResult
- = origFnType->getOptionalErrorResult();
- assert(!substErrorResult ||
- (!substErrorResult->getType()->hasTypeParameter() &&
- !substErrorResult->getType()->hasArchetype()));
-
- // Map the inputs.
- substituter.substInputs(origLoweredPattern.getFunctionInputType(),
- substLoweredInterfaceType.getInput());
-
- // Allow the substituted type to add thick-ness, but not remove it.
- assert(!origFnType->getExtInfo().hasContext()
- || substLoweredInterfaceType->getExtInfo().hasContext());
- assert(substLoweredInterfaceType->getExtInfo().getSILRepresentation()
- == substLoweredInterfaceType->getExtInfo().getSILRepresentation());
-
- auto rep = substLoweredInterfaceType->getExtInfo().getSILRepresentation();
- auto extInfo = origFnType->getExtInfo().withRepresentation(rep);
-
- // FIXME: Map into archetype context.
- return SILFunctionType::get(genericSig,
- extInfo,
- origFnType->getCalleeConvention(),
- substituter.getSubstParams(),
- substituter.getSubstResults(),
- substErrorResult,
- Context);
-}
-
/// Returns the SILParameterInfo for the given declaration's `self` parameter.
/// `constant` must refer to a method.
SILParameterInfo TypeConverter::getConstantSelfParameter(SILDeclRef constant) {
@@ -2129,27 +1867,38 @@
SILModule &TheSILModule;
TypeSubstitutionFn Subst;
LookupConformanceFn Conformances;
+ // The signature for the original type.
+ //
+ // Replacement types are lowered with respect to the current
+ // context signature.
+ CanGenericSignature Sig;
ASTContext &getASTContext() { return TheSILModule.getASTContext(); }
public:
SILTypeSubstituter(SILModule &silModule,
TypeSubstitutionFn Subst,
- LookupConformanceFn Conformances)
+ LookupConformanceFn Conformances,
+ CanGenericSignature Sig)
: TheSILModule(silModule),
Subst(Subst),
- Conformances(Conformances)
+ Conformances(Conformances),
+ Sig(Sig)
{}
// SIL type lowering only does special things to tuples and functions.
- /// Functions need to preserve their abstraction structure.
- CanSILFunctionType visitSILFunctionType(CanSILFunctionType origType,
- bool dropGenerics = false)
- {
- GenericContextScope scope(TheSILModule.Types,
- origType->getGenericSignature());
+ // When a function appears inside of another type, we only perform
+ // substitutions if it does not have a generic signature.
+ CanSILFunctionType visitSILFunctionType(CanSILFunctionType origType) {
+ if (origType->getGenericSignature())
+ return origType;
+ return substSILFunctionType(origType);
+ }
+
+ // Entry point for use by SILType::substGenericArgs().
+ CanSILFunctionType substSILFunctionType(CanSILFunctionType origType) {
SmallVector<SILResultInfo, 8> substResults;
substResults.reserve(origType->getNumResults());
for (auto origResult : origType->getResults()) {
@@ -2167,10 +1916,7 @@
substParams.push_back(subst(origParam));
}
- auto genericSig
- = (dropGenerics ? nullptr : origType->getGenericSignature());
-
- return SILFunctionType::get(genericSig,
+ return SILFunctionType::get(nullptr,
origType->getExtInfo(),
origType->getCalleeConvention(),
substParams, substResults,
@@ -2230,16 +1976,7 @@
CanType visitType(CanType origType) {
assert(!isa<AnyFunctionType>(origType));
assert(!isa<LValueType>(origType) && !isa<InOutType>(origType));
-
- CanGenericSignature genericSig =
- TheSILModule.Types.getCurGenericContext();
- AbstractionPattern abstraction(genericSig, origType);
-
- assert(TheSILModule.Types.getLoweredType(abstraction, origType)
- .getSwiftRValueType() == origType);
-
- CanType substType =
- origType.subst(Subst, Conformances, None)->getCanonicalType();
+ auto substType = origType.subst(Subst, Conformances)->getCanonicalType();
// If the substitution didn't change anything, we know that the
// original type was a lowered type, so we're good.
@@ -2247,6 +1984,7 @@
return origType;
}
+ AbstractionPattern abstraction(Sig, origType);
return TheSILModule.Types.getLoweredType(abstraction, substType)
.getSwiftRValueType();
}
@@ -2255,8 +1993,15 @@
SILType SILType::subst(SILModule &silModule,
TypeSubstitutionFn subs,
- LookupConformanceFn conformances) const {
- SILTypeSubstituter STST(silModule, subs, conformances);
+ LookupConformanceFn conformances,
+ CanGenericSignature genericSig) const {
+ if (!hasArchetype() && !hasTypeParameter())
+ return *this;
+
+ if (!genericSig)
+ genericSig = silModule.Types.getCurGenericContext();
+ SILTypeSubstituter STST(silModule, subs, conformances,
+ genericSig);
return STST.subst(*this);
}
@@ -2266,16 +2011,6 @@
LookUpConformanceInSubstitutionMap(subs));
}
-CanSILFunctionType SILType::substFuncType(SILModule &silModule,
- const SubstitutionMap &subs,
- CanSILFunctionType SrcTy,
- bool dropGenerics) {
- auto subFn = QuerySubstitutionMap{subs};
- auto lookupFn = LookUpConformanceInSubstitutionMap(subs);
- SILTypeSubstituter STST(silModule, subFn, lookupFn);
- return STST.visitSILFunctionType(SrcTy, dropGenerics);
-}
-
/// Apply a substitution to this polymorphic SILFunctionType so that
/// it has the form of the normal SILFunctionType for the substituted
/// type, except using the original conventions.
@@ -2313,9 +2048,9 @@
TypeSubstitutionFn subs,
LookupConformanceFn conformances) {
if (!isPolymorphic()) return CanSILFunctionType(this);
- SILTypeSubstituter substituter(silModule, subs, conformances);
- return substituter.visitSILFunctionType(CanSILFunctionType(this),
- /*dropGenerics*/ true);
+ SILTypeSubstituter substituter(silModule, subs, conformances,
+ getGenericSignature());
+ return substituter.substSILFunctionType(CanSILFunctionType(this));
}
/// Fast path for bridging types in a function type without uncurrying.
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index b8c1344..70da549 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -457,6 +457,7 @@
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, CheckedCastBranch)
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, SwitchEnum)
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, InitExistentialOpaque)
+CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, DeinitExistentialOpaque)
#undef CONSTANT_OR_TRIVIAL_OWNERSHIP_INST
#define ACCEPTS_ANY_OWNERSHIP_INST(INST) \
@@ -1785,6 +1786,12 @@
// If SILOwnership is not enabled, do not perform verification.
if (!getModule().getOptions().EnableSILOwnership)
return;
+
+ // If the given function has unqualified ownership, there is nothing to
+ // verify.
+ if (getFunction()->hasUnqualifiedOwnership())
+ return;
+
// If we are testing the verifier, bail so we only print errors once when
// performing a full verification, instead of additionally in the SILBuilder.
if (IsSILOwnershipVerifierTestingEnabled)
@@ -1808,6 +1815,21 @@
void SILValue::verifyOwnership(SILModule &Mod,
TransitivelyUnreachableBlocksInfo *TUB) const {
#ifndef NDEBUG
+ // If we are SILUndef, just bail. SILUndef can pair with anything. Any uses of
+ // the SILUndef will make sure that the matching checks out.
+ if (isa<SILUndef>(*this))
+ return;
+
+ // Since we do not have SILUndef, we now know that getFunction() should return
+ // a real function. Assert in case this assumption is no longer true.
+ SILFunction *F = (*this)->getFunction();
+ assert(F && "Instructions and arguments should have a function");
+
+ // If the given function has unqualified ownership, there is nothing further
+ // to verify.
+ if (F->hasUnqualifiedOwnership())
+ return;
+
if (TUB) {
SILValueOwnershipChecker(Mod, *TUB, *this).check();
} else {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index a9f2d52..654a13a 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1522,6 +1522,9 @@
void visitDeinitExistentialAddrInst(DeinitExistentialAddrInst *DEI) {
*this << getIDAndType(DEI->getOperand());
}
+ void visitDeinitExistentialOpaqueInst(DeinitExistentialOpaqueInst *DEI) {
+ *this << getIDAndType(DEI->getOperand());
+ }
void visitDeallocExistentialBoxInst(DeallocExistentialBoxInst *DEI) {
*this << getIDAndType(DEI->getOperand()) << ", $" << DEI->getConcreteType();
}
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index 95f249b..1a154c7 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -460,6 +460,10 @@
/// Error existentials.
static bool isBridgedErrorClass(SILModule &M,
Type t) {
+ // There's no bridging if ObjC interop is disabled.
+ if (!M.getASTContext().LangOpts.EnableObjCInterop)
+ return false;
+
if (!t)
return false;
@@ -565,21 +569,13 @@
// Apply generic arguments if the layout is generic.
if (!getGenericArgs().empty()) {
- // FIXME: Map the field type into the layout's generic context because
- // SIL TypeLowering currently expects to lower abstract generic parameters
- // with a generic context pushed, but nested generic contexts are not
- // supported by TypeLowering. If TypeLowering were properly
- // de-contextualized and plumbed through the generic signature, this could
- // be avoided.
- auto *env = getLayout()->getGenericSignature()
- .getGenericEnvironment(*M.getSwiftModule());
- auto substMap =
- env->getSubstitutionMap(getGenericArgs());
- fieldTy = env->mapTypeIntoContext(fieldTy)
- ->getCanonicalType();
-
- fieldTy = SILType::getPrimitiveObjectType(fieldTy)
- .subst(M, substMap)
+ auto sig = getLayout()->getGenericSignature();
+ auto subs = sig->getSubstitutionMap(getGenericArgs());
+ return SILType::getPrimitiveObjectType(fieldTy)
+ .subst(M,
+ QuerySubstitutionMap{subs},
+ LookUpConformanceInSubstitutionMap(subs),
+ sig)
.getSwiftRValueType();
}
return fieldTy;
diff --git a/lib/SIL/SILValue.cpp b/lib/SIL/SILValue.cpp
index 7de3009..f9bf589 100644
--- a/lib/SIL/SILValue.cpp
+++ b/lib/SIL/SILValue.cpp
@@ -331,6 +331,7 @@
NO_RESULT_OWNERSHIP_INST(AllocGlobal)
NO_RESULT_OWNERSHIP_INST(InjectEnumAddr)
NO_RESULT_OWNERSHIP_INST(DeinitExistentialAddr)
+NO_RESULT_OWNERSHIP_INST(DeinitExistentialOpaque)
NO_RESULT_OWNERSHIP_INST(CondFail)
// Terminators. These do not produce SILValue, so they do not have a
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index dfd06f9..541709a 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -1288,7 +1288,7 @@
PointerRVType->is<UnownedStorageType>(),
"load_unowned operand must be an unowned address");
require(PointerRVType->getReferenceStorageReferent()->getCanonicalType() ==
- LUI->getType().getSwiftType(),
+ LUI->getType().getSwiftRValueType(),
"Load operand type and result type mismatch");
}
@@ -1301,13 +1301,13 @@
PointerRVType->is<UnownedStorageType>(),
"store_unowned address operand must be an unowned address");
require(PointerRVType->getReferenceStorageReferent()->getCanonicalType() ==
- SUI->getSrc()->getType().getSwiftType(),
+ SUI->getSrc()->getType().getSwiftRValueType(),
"Store operand type and dest type mismatch");
}
void checkLoadWeakInst(LoadWeakInst *LWI) {
require(LWI->getType().isObject(), "Result of load must be an object");
- require(LWI->getType().getSwiftType()->getAnyOptionalObjectType(),
+ require(LWI->getType().getAnyOptionalObjectType(),
"Result of weak load must be an optional");
auto PointerType = LWI->getOperand()->getType();
auto PointerRVType = PointerType.getSwiftRValueType();
@@ -1315,14 +1315,14 @@
PointerRVType->is<WeakStorageType>(),
"load_weak operand must be a weak address");
require(PointerRVType->getReferenceStorageReferent()->getCanonicalType() ==
- LWI->getType().getSwiftType(),
+ LWI->getType().getSwiftRValueType(),
"Load operand type and result type mismatch");
}
void checkStoreWeakInst(StoreWeakInst *SWI) {
require(SWI->getSrc()->getType().isObject(),
"Can't store from an address source");
- require(SWI->getSrc()->getType().getSwiftType()->getAnyOptionalObjectType(),
+ require(SWI->getSrc()->getType().getAnyOptionalObjectType(),
"store_weak must be of an optional value");
auto PointerType = SWI->getDest()->getType();
auto PointerRVType = PointerType.getSwiftRValueType();
@@ -1330,7 +1330,7 @@
PointerRVType->is<WeakStorageType>(),
"store_weak address operand must be a weak address");
require(PointerRVType->getReferenceStorageReferent()->getCanonicalType() ==
- SWI->getSrc()->getType().getSwiftType(),
+ SWI->getSrc()->getType().getSwiftRValueType(),
"Store operand type and dest type mismatch");
}
@@ -1642,8 +1642,8 @@
"Tuple field count mismatch!");
for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) {
- require(TI->getElement(i)->getType().getSwiftType()
- ->isEqual(ResTy.getElementType(i)),
+ require(TI->getElement(i)->getType().getSwiftRValueType()
+ == ResTy.getElementType(i),
"Tuple element arguments do not match tuple type!");
}
}
@@ -2080,9 +2080,9 @@
require(EMI->getMember().getDecl()->isObjC(), "method must be @objc");
if (!EMI->getMember().getDecl()->isInstanceMember()) {
- require(operandType.getSwiftType()->is<MetatypeType>(),
+ require(operandType.is<MetatypeType>(),
"operand must have metatype type");
- require(operandType.getSwiftType()->castTo<MetatypeType>()
+ require(operandType.castTo<MetatypeType>()
->getInstanceType()->mayHaveSuperclass(),
"operand must have metatype of class or class-bounded type");
}
@@ -2153,7 +2153,7 @@
require(methodClass->getClassOrBoundGenericClass(),
"super_method must look up a class method");
- require(!methodClass->isEqual(operandType.getSwiftType()),
+ require(!methodClass->isEqual(operandType.getSwiftRValueType()),
"super_method operand should be a subtype of the "
"lookup class type");
}
@@ -2210,7 +2210,7 @@
CanType resultInstanceTy = OEI->getType().getSwiftRValueType();
- require(OEI->getType().isAddress(),
+ require(OEI->getType().isAddress() || !fnConv.useLoweredAddresses(),
"open_existential_box result must be an address");
auto archetype = getOpenedArchetypeOf(resultInstanceTy);
@@ -2358,7 +2358,7 @@
void checkInitExistentialRefInst(InitExistentialRefInst *IEI) {
SILType concreteType = IEI->getOperand()->getType();
- require(concreteType.getSwiftType()->isBridgeableObjectType(),
+ require(concreteType.getSwiftRValueType()->isBridgeableObjectType(),
"init_existential_ref operand must be a class instance");
require(IEI->getType().canUseExistentialRepresentation(F.getModule(),
ExistentialRepresentation::Class,
@@ -2390,10 +2390,19 @@
SILType exType = DEI->getOperand()->getType();
require(exType.isAddress(),
"deinit_existential_addr must be applied to an address");
- require(exType.canUseExistentialRepresentation(F.getModule(),
- ExistentialRepresentation::Opaque),
- "deinit_existential_addr must be applied to an opaque "
- "existential");
+ require(exType.canUseExistentialRepresentation(
+ F.getModule(), ExistentialRepresentation::Opaque),
+ "deinit_existential_addr must be applied to an opaque existential");
+ }
+
+ void checkDeinitExistentialOpaqueInst(DeinitExistentialOpaqueInst *DEI) {
+ SILType exType = DEI->getOperand()->getType();
+ require(!exType.isAddress(),
+ "deinit_existential_opaque must not be applied to an address");
+ require(
+ exType.canUseExistentialRepresentation(
+ F.getModule(), ExistentialRepresentation::Opaque),
+ "deinit_existential_opaque must be applied to an opaque existential");
}
void checkDeallocExistentialBoxInst(DeallocExistentialBoxInst *DEBI) {
@@ -2555,8 +2564,20 @@
CBI->getCastType(),
"success dest block argument of checked_cast_br must match type of "
"cast");
- require(CBI->getFailureBB()->args_empty(),
- "failure dest of checked_cast_br must take no arguments");
+ require(F.hasQualifiedOwnership() || CBI->getFailureBB()->args_empty(),
+ "failure dest of checked_cast_br in unqualified ownership sil must "
+ "take no arguments");
+#if 0
+ require(F.hasUnqualifiedOwnership() ||
+ CBI->getFailureBB()->args_size() == 1,
+ "failure dest of checked_cast_br must take one argument in "
+ "ownership qualified sil");
+ require(F.hasUnqualifiedOwnership() ||
+ CBI->getFailureBB()->args_begin()[0]->getType() ==
+ CBI->getOperand()->getType(),
+ "failure dest block argument must match type of original type in "
+ "ownership qualified sil");
+#endif
}
void checkCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
@@ -2738,7 +2759,7 @@
void checkIsNonnullInst(IsNonnullInst *II) {
// The operand must be a function type or a class type.
- auto OpTy = II->getOperand()->getType().getSwiftType();
+ auto OpTy = II->getOperand()->getType().getSwiftRValueType();
require(OpTy->mayHaveSuperclass() || OpTy->is<SILFunctionType>(),
"is_nonnull operand must be a class or function type");
}
@@ -2746,7 +2767,7 @@
void checkAddressToPointerInst(AddressToPointerInst *AI) {
require(AI->getOperand()->getType().isAddress(),
"address-to-pointer operand must be an address");
- require(AI->getType().getSwiftType()->isEqual(
+ require(AI->getType().getSwiftRValueType()->isEqual(
AI->getType().getASTContext().TheRawPointerType),
"address-to-pointer result type must be RawPointer");
}
@@ -2803,11 +2824,11 @@
}
void checkRefToRawPointerInst(RefToRawPointerInst *AI) {
- require(AI->getOperand()->getType().getSwiftType()
+ require(AI->getOperand()->getType().getSwiftRValueType()
->isAnyClassReferenceType(),
"ref-to-raw-pointer operand must be a class reference or"
" NativeObject");
- require(AI->getType().getSwiftType()->isEqual(
+ require(AI->getType().getSwiftRValueType()->isEqual(
AI->getType().getASTContext().TheRawPointerType),
"ref-to-raw-pointer result must be RawPointer");
}
@@ -2815,13 +2836,13 @@
void checkRawPointerToRefInst(RawPointerToRefInst *AI) {
verifyOpenedArchetype(AI, AI->getType().getSwiftRValueType());
require(AI->getType()
- .getSwiftType()->isBridgeableObjectType()
- || AI->getType().getSwiftType()->isEqual(
+ .getSwiftRValueType()->isBridgeableObjectType()
+ || AI->getType().getSwiftRValueType()->isEqual(
AI->getType().getASTContext().TheNativeObjectType)
- || AI->getType().getSwiftType()->isEqual(
+ || AI->getType().getSwiftRValueType()->isEqual(
AI->getType().getASTContext().TheUnknownObjectType),
"raw-pointer-to-ref result must be a class reference or NativeObject");
- require(AI->getOperand()->getType().getSwiftType()->isEqual(
+ require(AI->getOperand()->getType().getSwiftRValueType()->isEqual(
AI->getType().getASTContext().TheRawPointerType),
"raw-pointer-to-ref operand must be NativeObject");
}
@@ -2876,8 +2897,12 @@
requireObjectType(BuiltinRawPointerType, CI,
"thin_function_to_pointer result");
- require(opTI->getRepresentation() == SILFunctionType::Representation::Thin,
- "thin_function_to_pointer only works on thin functions");
+ auto rep = opTI->getRepresentation();
+ require(rep == SILFunctionTypeRepresentation::Thin ||
+ rep == SILFunctionTypeRepresentation::Method ||
+ rep == SILFunctionTypeRepresentation::WitnessMethod,
+ "thin_function_to_pointer only works on thin, method or "
+ "witness_method functions");
}
void checkPointerToThinFunctionInst(PointerToThinFunctionInst *CI) {
@@ -2886,8 +2911,12 @@
requireObjectType(BuiltinRawPointerType, CI->getOperand(),
"pointer_to_thin_function operand");
- require(resultTI->getRepresentation() == SILFunctionType::Representation::Thin,
- "pointer_to_thin_function only works on thin functions");
+ auto rep = resultTI->getRepresentation();
+ require(rep == SILFunctionTypeRepresentation::Thin ||
+ rep == SILFunctionTypeRepresentation::Method ||
+ rep == SILFunctionTypeRepresentation::WitnessMethod,
+ "pointer_to_thin_function only works on thin, method or "
+ "witness_method functions");
}
void checkCondFailInst(CondFailInst *CFI) {
@@ -3225,9 +3254,9 @@
require(DMBI->getMember().getDecl()->isObjC(), "method must be @objc");
if (!DMBI->getMember().getDecl()->isInstanceMember()) {
- require(operandType.getSwiftType()->is<MetatypeType>(),
+ require(operandType.getSwiftRValueType()->is<MetatypeType>(),
"operand must have metatype type");
- require(operandType.getSwiftType()->castTo<MetatypeType>()
+ require(operandType.getSwiftRValueType()->castTo<MetatypeType>()
->getInstanceType()->mayHaveSuperclass(),
"operand must have metatype of class or class-bound type");
}
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index 01dd21b..ea66f37 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -758,7 +758,7 @@
SILValue value) const override {
if (B.getFunction().hasQualifiedOwnership())
return B.createCopyValue(loc, value);
- B.createRetainValue(loc, value, Atomicity::Atomic);
+ B.createRetainValue(loc, value, B.getDefaultAtomicity());
return value;
}
@@ -891,7 +891,7 @@
SILValue value) const override {
if (B.getFunction().hasQualifiedOwnership())
return B.createCopyValue(loc, value);
- B.createRetainValue(loc, value, Atomicity::Atomic);
+ B.createRetainValue(loc, value, B.getDefaultAtomicity());
return value;
}
@@ -900,7 +900,7 @@
LoweringStyle style) const override {
if (B.getFunction().hasQualifiedOwnership())
return B.createCopyValue(loc, value);
- B.createRetainValue(loc, value, Atomicity::Atomic);
+ B.createRetainValue(loc, value, B.getDefaultAtomicity());
return value;
}
@@ -960,7 +960,7 @@
if (B.getFunction().hasQualifiedOwnership())
return B.createCopyValue(loc, value);
- B.createStrongRetain(loc, value, Atomicity::Atomic);
+ B.createStrongRetain(loc, value, B.getDefaultAtomicity());
return value;
}
@@ -985,7 +985,7 @@
if (B.getFunction().hasQualifiedOwnership())
return B.createCopyValue(loc, value);
- B.createUnownedRetain(loc, value, Atomicity::Atomic);
+ B.createUnownedRetain(loc, value, B.getDefaultAtomicity());
return value;
}
@@ -995,7 +995,7 @@
B.createDestroyValue(loc, value);
return;
}
- B.createUnownedRelease(loc, value, Atomicity::Atomic);
+ B.createUnownedRelease(loc, value, B.getDefaultAtomicity());
}
};
@@ -1105,25 +1105,12 @@
llvm_unreachable("destroy address");
}
- void emitDestroyRValue(SILBuilder &B, SILLocation loc,
- SILValue value) const override {
- llvm_unreachable("destroy value");
- }
-
void emitCopyInto(SILBuilder &B, SILLocation loc,
SILValue src, SILValue dest, IsTake_t isTake,
IsInitialization_t isInit) const override {
llvm_unreachable("copy into");
}
- // --- Same as NonTrivialLoadableTypeLowering
-
- void emitStoreOfCopy(SILBuilder &B, SILLocation loc,
- SILValue newValue, SILValue addr,
- IsInitialization_t isInit) const override {
- llvm_unreachable("store copy");
- }
-
// --- Same as LeafLoadableTypeLowering.
SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
@@ -2130,7 +2117,8 @@
CanSILFunctionType TypeConverter::
getMaterializeForSetCallbackType(AbstractStorageDecl *storage,
CanGenericSignature genericSig,
- Type selfType) {
+ Type selfType,
+ SILFunctionTypeRepresentation rep) {
auto &ctx = M.getASTContext();
// Get lowered formal types for callback parameters.
@@ -2168,9 +2156,8 @@
{ canSelfMetatypeType, ParameterConvention::Direct_Unowned },
};
ArrayRef<SILResultInfo> results = {};
- auto extInfo =
- SILFunctionType::ExtInfo()
- .withRepresentation(SILFunctionTypeRepresentation::Thin);
+
+ auto extInfo = SILFunctionType::ExtInfo().withRepresentation(rep);
if (genericSig && genericSig->areAllParamsConcrete())
genericSig = nullptr;
diff --git a/lib/SILGen/ManagedValue.cpp b/lib/SILGen/ManagedValue.cpp
index 14dd691..3268c90 100644
--- a/lib/SILGen/ManagedValue.cpp
+++ b/lib/SILGen/ManagedValue.cpp
@@ -60,7 +60,7 @@
void ManagedValue::copyInto(SILGenFunction &gen, SILValue dest,
SILLocation loc) {
auto &lowering = gen.getTypeLowering(getType());
- if (lowering.isAddressOnly()) {
+ if (lowering.isAddressOnly() && gen.silConv.useLoweredAddresses()) {
gen.B.createCopyAddr(loc, getValue(), dest, IsNotTake, IsInitialization);
return;
}
diff --git a/lib/SILGen/ManagedValue.h b/lib/SILGen/ManagedValue.h
index b3330b6..8c02138 100644
--- a/lib/SILGen/ManagedValue.h
+++ b/lib/SILGen/ManagedValue.h
@@ -230,12 +230,6 @@
return M;
}
- CanType getSwiftType() const {
- return isLValue()
- ? getType().getSwiftType()
- : getType().getSwiftRValueType();
- }
-
/// Emit a copy of this value with independent ownership.
ManagedValue copy(SILGenFunction &gen, SILLocation loc);
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index f2b4b55..dbc9b5d 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -42,7 +42,7 @@
if (member->isInstanceMember()) {
selfTy = ctx.TheUnknownObjectType;
} else {
- selfTy = proto->getType().getSwiftType();
+ selfTy = proto->getType().getSwiftRValueType();
}
auto extInfo = FunctionType::ExtInfo()
.withRepresentation(FunctionType::Representation::Thin);
@@ -99,7 +99,7 @@
selfTy = proto->getType().getSwiftRValueType();
assert(selfTy->is<ArchetypeType>() && "Dynamic lookup needs an archetype");
} else {
- selfTy = proto->getType().getSwiftType();
+ selfTy = proto->getType().getSwiftRValueType();
}
// Replace the 'self' parameter type in the method type with it.
@@ -1367,8 +1367,7 @@
// If the 'self' value is a metatype, update the target type
// accordingly.
- if (auto selfMetaTy
- = selfValue.getSwiftType()->getAs<AnyMetatypeType>()) {
+ if (auto selfMetaTy = selfValue.getType().getAs<AnyMetatypeType>()) {
resultTy = CanMetatypeType::get(resultTy,
selfMetaTy->getRepresentation());
}
@@ -1809,9 +1808,9 @@
};
TupleTypeElt TypeEltsArray[] = {
- EltsArray[0].getSwiftType(),
- EltsArray[1].getSwiftType(),
- EltsArray[2].getSwiftType()
+ EltsArray[0].getType().getSwiftRValueType(),
+ EltsArray[1].getType().getSwiftRValueType(),
+ EltsArray[2].getType().getSwiftRValueType()
};
ArrayRef<ManagedValue> Elts;
@@ -2486,7 +2485,7 @@
assert(lifetimeExtendedSelf
&& "did not save lifetime-extended self param");
if (!hasAlreadyLifetimeExtendedSelf) {
- B.createAutoreleaseValue(loc, lifetimeExtendedSelf, Atomicity::Atomic);
+ B.createAutoreleaseValue(loc, lifetimeExtendedSelf, B.getDefaultAtomicity());
hasAlreadyLifetimeExtendedSelf = true;
}
LLVM_FALLTHROUGH;
@@ -3453,7 +3452,7 @@
emittedArg = ManagedValue(erased, emittedArg.getCleanup());
}
- assert(isAnyObjectType(emittedArg.getSwiftType()));
+ assert(isAnyObjectType(emittedArg.getType().getSwiftRValueType()));
return emittedArg;
};
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 3ced3d4..e89eab2 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -35,7 +35,7 @@
ManagedValue swiftValue,
ProtocolConformance *conformance) {
// Dig out the nominal type we're bridging from.
- Type swiftValueType = swiftValue.getSwiftType()->getRValueType();
+ Type swiftValueType = swiftValue.getType().getSwiftRValueType();
// Find the _bridgeToObjectiveC requirement.
auto requirement = gen.SGM.getBridgeToObjectiveCRequirement(loc);
@@ -988,7 +988,7 @@
gen.emitBridgedToNativeValue(loc,
bridgedArgs[i],
SILFunctionTypeRepresentation::ObjCMethod,
- argTy.getSwiftType());
+ argTy.getSwiftRValueType());
SILValue argValue;
if (nativeInputs[i].isConsumed()) {
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index baad164..b791ed3 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -209,7 +209,7 @@
SILValue result = SILBuilder::createUnmanagedToRef(
loc, originalValue.getValue(),
SILType::getPrimitiveObjectType(unmanagedType.getReferentType()));
- SILBuilder::createUnmanagedRetainValue(loc, result);
+ SILBuilder::createUnmanagedRetainValue(loc, result, getDefaultAtomicity());
return gen.emitManagedRValueWithCleanup(result);
}
@@ -489,3 +489,25 @@
return gen.emitManagedRValueWithCleanup(result);
}
+ManagedValue SILGenBuilder::createUnconditionalCheckedCastOpaque(
+ SILLocation loc, ManagedValue operand, SILType type) {
+ SILValue result = SILBuilder::createUnconditionalCheckedCastOpaque(
+ loc, operand.forward(gen), type);
+ return gen.emitManagedRValueWithCleanup(result);
+}
+
+ManagedValue SILGenBuilder::createUnconditionalCheckedCast(SILLocation loc,
+ ManagedValue operand,
+ SILType type) {
+ SILValue result = SILBuilder::createUnconditionalCheckedCast(
+ loc, operand.forward(gen), type);
+ return gen.emitManagedRValueWithCleanup(result);
+}
+
+void SILGenBuilder::createCheckedCastBranch(SILLocation loc, bool isExact,
+ ManagedValue operand, SILType type,
+ SILBasicBlock *trueBlock,
+ SILBasicBlock *falseBlock) {
+ SILBuilder::createCheckedCastBranch(loc, isExact, operand.forward(gen), type,
+ trueBlock, falseBlock);
+}
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index f5bd0ab..3e4701c 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -211,6 +211,21 @@
ManagedValue formalAccessBufferForExpr(
SILLocation loc, SILType ty, const TypeLowering &lowering,
SGFContext context, std::function<void(SILValue)> rvalueEmitter);
+
+ using SILBuilder::createUnconditionalCheckedCastOpaque;
+ ManagedValue createUnconditionalCheckedCastOpaque(SILLocation loc,
+ ManagedValue operand,
+ SILType type);
+ using SILBuilder::createUnconditionalCheckedCast;
+ ManagedValue createUnconditionalCheckedCast(SILLocation loc,
+ ManagedValue operand,
+ SILType type);
+
+ using SILBuilder::createCheckedCastBranch;
+ void createCheckedCastBranch(SILLocation loc, bool isExact,
+ ManagedValue operand, SILType type,
+ SILBasicBlock *trueBlock,
+ SILBasicBlock *falseBlock);
};
} // namespace Lowering
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index 93e449a..10fa3b4 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -72,7 +72,8 @@
// The value was produced at +1; we can produce an unbalanced retain simply by
// disabling the cleanup. But this would violate ownership semantics. Instead,
// we must allow for the cleanup and emit a new unmanaged retain value.
- gen.B.createUnmanagedRetainValue(loc, args[0].getValue());
+ gen.B.createUnmanagedRetainValue(loc, args[0].getValue(),
+ gen.B.getDefaultAtomicity());
return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
@@ -85,7 +86,8 @@
// The value was produced at +1, so to produce an unbalanced
// release we need to leave the cleanup intact and then do a *second*
// release.
- gen.B.createUnmanagedReleaseValue(loc, args[0].getValue());
+ gen.B.createUnmanagedReleaseValue(loc, args[0].getValue(),
+ gen.B.getDefaultAtomicity());
return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
@@ -95,7 +97,8 @@
ArrayRef<ManagedValue> args,
CanFunctionType formalApplyType,
SGFContext C) {
- gen.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue());
+ gen.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue(),
+ gen.B.getDefaultAtomicity());
return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
}
@@ -127,7 +130,7 @@
// retain, so we have to leave the cleanup in place. TODO: try to
// emit the argument at +0.
SILValue result =
- gen.B.createStrongPin(loc, args[0].getValue(), Atomicity::Atomic);
+ gen.B.createStrongPin(loc, args[0].getValue(), gen.B.getDefaultAtomicity());
// The handle, if non-null, is effectively +1.
return gen.emitManagedRValueWithCleanup(result);
@@ -143,7 +146,7 @@
if (requireIsOptionalNativeObject(gen, loc, subs[0].getReplacement())) {
// Unpinning takes responsibility for the +1 handle.
- gen.B.createStrongUnpin(loc, args[0].forward(gen), Atomicity::Atomic);
+ gen.B.createStrongUnpin(loc, args[0].forward(gen), gen.B.getDefaultAtomicity());
}
return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc));
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 9438e8d..c160037 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -781,26 +781,25 @@
SILType existentialType = existentialValue.getType();
switch (existentialType.getPreferredExistentialRepresentation(SGM.M)) {
case ExistentialRepresentation::Opaque: {
+ SILValue archetypeValue;
if (existentialType.isAddress()) {
OpenedExistentialAccess allowedAccess =
getOpenedExistentialAccessFor(accessKind);
- SILValue archetypeValue = B.createOpenExistentialAddr(
- loc, existentialValue.forward(*this), loweredOpenedType,
- allowedAccess);
- if (existentialValue.hasCleanup()) {
- canConsume = true;
- // Leave a cleanup to deinit the existential container.
- enterDeinitExistentialCleanup(existentialValue.getValue(), CanType(),
- ExistentialRepresentation::Opaque);
- archetypeMV = emitManagedBufferWithCleanup(archetypeValue);
- } else {
- canConsume = false;
- archetypeMV = ManagedValue::forUnmanaged(archetypeValue);
- }
+ archetypeValue =
+ B.createOpenExistentialAddr(loc, existentialValue.forward(*this),
+ loweredOpenedType, allowedAccess);
} else {
- SILValue archetypeValue = B.createOpenExistentialOpaque(
+ archetypeValue = B.createOpenExistentialOpaque(
loc, existentialValue.forward(*this), loweredOpenedType);
- assert(!existentialValue.hasCleanup());
+ }
+
+ if (existentialValue.hasCleanup()) {
+ canConsume = true;
+ // Leave a cleanup to deinit the existential container.
+ enterDeinitExistentialCleanup(existentialValue.getValue(), CanType(),
+ ExistentialRepresentation::Opaque);
+ archetypeMV = emitManagedBufferWithCleanup(archetypeValue);
+ } else {
canConsume = false;
archetypeMV = ManagedValue::forUnmanaged(archetypeValue);
}
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index e4a5168..cbe0448 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -83,7 +83,7 @@
// A scalar value is being copied into the tuple, break it into elements
// and assign/init each element in turn.
SILValue value = valueMV.forward(SGF);
- auto sourceType = cast<TupleType>(valueMV.getSwiftType());
+ auto sourceType = valueMV.getType().castTo<TupleType>();
auto sourceSILType = value->getType();
for (unsigned i = 0, e = sourceType->getNumElements(); i != e; ++i) {
SILType fieldTy = sourceSILType.getTupleElementType(i);
@@ -813,9 +813,10 @@
// Reabstract to the substituted type, if needed.
CanType substEltTy =
- value.getSwiftType()->getTypeOfMember(SGF.SGM.M.getSwiftModule(),
- ElementDecl,
- ElementDecl->getArgumentInterfaceType())
+ value.getType().getSwiftRValueType()
+ ->getTypeOfMember(SGF.SGM.M.getSwiftModule(),
+ ElementDecl,
+ ElementDecl->getArgumentInterfaceType())
->getCanonicalType();
AbstractionPattern origEltTy =
@@ -1233,7 +1234,11 @@
case ExistentialRepresentation::Metatype:
llvm_unreachable("cannot cleanup existential");
case ExistentialRepresentation::Opaque:
- gen.B.createDeinitExistentialAddr(l, existentialAddr);
+ if (gen.silConv.useLoweredAddresses()) {
+ gen.B.createDeinitExistentialAddr(l, existentialAddr);
+ } else {
+ gen.B.createDeinitExistentialOpaque(l, existentialAddr);
+ }
break;
case ExistentialRepresentation::Boxed:
gen.B.createDeallocExistentialBox(l, concreteFormalType,
diff --git a/lib/SILGen/SILGenDynamicCast.cpp b/lib/SILGen/SILGenDynamicCast.cpp
index 1b717f2..da67262 100644
--- a/lib/SILGen/SILGenDynamicCast.cpp
+++ b/lib/SILGen/SILGenDynamicCast.cpp
@@ -100,6 +100,285 @@
abstraction, origTargetTL, ctx));
}
+ ManagedValue result;
+ if (Strategy == CastStrategy::Address) {
+ result = SGF.B.createUnconditionalCheckedCastOpaque(
+ Loc, operand, origTargetTL.getLoweredType());
+ } else {
+ result = SGF.B.createUnconditionalCheckedCast(
+ Loc, operand, origTargetTL.getLoweredType());
+ }
+
+ return RValue(SGF, Loc, TargetType,
+ finishFromResultScalar(hasAbstraction, result,
+ CastConsumptionKind::TakeAlways,
+ abstraction, origTargetTL, ctx));
+ }
+
+ /// Emit a conditional cast.
+ void emitConditional(
+ ManagedValue operand, CastConsumptionKind consumption, SGFContext ctx,
+ const std::function<void(ManagedValue)> &handleTrue,
+ const std::function<void(Optional<ManagedValue>)> &handleFalse) {
+ // The cast instructions don't know how to work with anything
+ // but the most general possible abstraction level.
+ AbstractionPattern abstraction =
+ SGF.SGM.Types.getMostGeneralAbstraction();
+ auto &origTargetTL = SGF.getTypeLowering(abstraction, TargetType);
+ auto &substTargetTL = SGF.getTypeLowering(TargetType);
+ bool hasAbstraction =
+ (origTargetTL.getLoweredType() != substTargetTL.getLoweredType());
+
+ SILBasicBlock *falseBB = SGF.B.splitBlockForFallthrough();
+ SILBasicBlock *trueBB = SGF.B.splitBlockForFallthrough();
+
+ // Emit the branch.
+ ManagedValue scalarOperandValue;
+ SILValue resultBuffer;
+ if (Strategy == CastStrategy::Address) {
+ assert(operand.getType().isAddress());
+ resultBuffer =
+ createAbstractResultBuffer(hasAbstraction, origTargetTL, ctx);
+ SGF.B.createCheckedCastAddrBranch(
+ Loc, consumption, operand.forward(SGF), SourceType, resultBuffer,
+ TargetType, trueBB, falseBB);
+ } else {
+ // Tolerate being passed an address here. It comes up during switch
+ // emission.
+ scalarOperandValue = std::move(operand);
+ if (scalarOperandValue.getType().isAddress()) {
+ scalarOperandValue = SGF.B.createLoadTake(Loc, scalarOperandValue);
+ }
+ SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, scalarOperandValue,
+ origTargetTL.getLoweredType(), trueBB,
+ falseBB);
+ }
+
+ // Emit the success block.
+ SGF.B.setInsertionPoint(trueBB);
+ {
+ FullExpr scope(SGF.Cleanups, CleanupLocation::get(Loc));
+
+ ManagedValue result;
+ if (Strategy == CastStrategy::Address) {
+ result = finishFromResultBuffer(hasAbstraction, resultBuffer,
+ abstraction, origTargetTL, ctx);
+ } else {
+ ManagedValue argument =
+ SGF.B.createOwnedPHIArgument(origTargetTL.getLoweredType());
+ result = finishFromResultScalar(hasAbstraction, argument, consumption,
+ abstraction, origTargetTL, ctx);
+ }
+
+ handleTrue(result);
+ assert(!SGF.B.hasValidInsertionPoint() && "handler did not end block");
+ }
+
+ // Emit the failure block.
+ SGF.B.setInsertionPoint(falseBB);
+ {
+ FullExpr scope(SGF.Cleanups, CleanupLocation::get(Loc));
+
+ // If we have an address only type, do not handle the consumption
+ // rules. These are handled for us by the user.
+ if (Strategy == CastStrategy::Address) {
+ handleFalse(None);
+ assert(!SGF.B.hasValidInsertionPoint() &&
+ "handler did not end block");
+ return;
+ }
+
+ // Otherwise, we use the following strategy:
+ //
+ // 1. If we have a take_always, we create a phi node argument for the
+ // failure case and a scope for that so that it is immediately
+ // destroyed.
+ //
+ // 2. If we have a take_on_success or copy_on_success, then on failure,
+ // we propagate through the default argument, but do not clean it up. On
+ // the false case, our user must treat the taken value as a new value.
+ if (shouldDestroyOnFailure(consumption)) {
+ {
+ FullExpr argScope(SGF.Cleanups, CleanupLocation::get(Loc));
+ SGF.B.createOwnedPHIArgument(scalarOperandValue.getType());
+ }
+ handleFalse(None);
+ assert(!SGF.B.hasValidInsertionPoint() &&
+ "handler did not end block");
+ return;
+ }
+
+ handleFalse(SGF.B.createOwnedPHIArgument(scalarOperandValue.getType()));
+ assert(!SGF.B.hasValidInsertionPoint() && "handler did not end block");
+ }
+ }
+
+ SILValue createAbstractResultBuffer(bool hasAbstraction,
+ const TypeLowering &origTargetTL,
+ SGFContext ctx) {
+ if (!hasAbstraction) {
+ if (auto emitInto = ctx.getEmitInto()) {
+ if (SILValue addr = emitInto->getAddressOrNull()) {
+ return addr;
+ }
+ }
+ }
+
+ return SGF.emitTemporaryAllocation(Loc, origTargetTL.getLoweredType());
+ }
+
+ ManagedValue finishFromResultBuffer(bool hasAbstraction, SILValue buffer,
+ AbstractionPattern abstraction,
+ const TypeLowering &origTargetTL,
+ SGFContext ctx) {
+ if (!hasAbstraction) {
+ if (auto emitInto = ctx.getEmitInto()) {
+ if (emitInto->getAddressOrNull()) {
+ emitInto->finishInitialization(SGF);
+ return ManagedValue::forInContext();
+ }
+ }
+ }
+
+ ManagedValue result;
+ if (!origTargetTL.isAddressOnly()) {
+ result = SGF.emitLoad(Loc, buffer, origTargetTL, ctx, IsTake);
+ } else {
+ result = SGF.emitManagedBufferWithCleanup(buffer, origTargetTL);
+ }
+
+ if (hasAbstraction) {
+ result =
+ SGF.emitOrigToSubstValue(Loc, result, abstraction, TargetType, ctx);
+ }
+ return result;
+ }
+
+ /// Our cast succeeded and gave us this abstracted value.
+ ManagedValue finishFromResultScalar(bool hasAbstraction, ManagedValue value,
+ CastConsumptionKind consumption,
+ AbstractionPattern abstraction,
+ const TypeLowering &origTargetTL,
+ SGFContext ctx) {
+ ManagedValue result = value;
+ // Copy the result if this is copy-on-success.
+ if (!shouldTakeOnSuccess(consumption))
+ result = result.copy(SGF, Loc);
+
+ // Re-abstract if necessary.
+ if (hasAbstraction) {
+ result =
+ SGF.emitOrigToSubstValue(Loc, result, abstraction, TargetType, ctx);
+ }
+
+ return result;
+ }
+
+ private:
+ CastStrategy computeStrategy() const {
+ if (canUseScalarCheckedCastInstructions(SGF.SGM.M, SourceType,
+ TargetType))
+ return CastStrategy::Scalar;
+ return CastStrategy::Address;
+ }
+ };
+} // end anonymous namespace
+
+void SILGenFunction::emitCheckedCastBranch(
+ SILLocation loc, Expr *source, Type targetType, SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse) {
+ CheckedCastEmitter emitter(*this, loc, source->getType(), targetType);
+ ManagedValue operand = emitter.emitOperand(source);
+ emitter.emitConditional(operand, CastConsumptionKind::TakeAlways, ctx,
+ handleTrue, handleFalse);
+}
+
+void SILGenFunction::emitCheckedCastBranch(
+ SILLocation loc, ConsumableManagedValue src, Type sourceType,
+ CanType targetType, SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse) {
+ CheckedCastEmitter emitter(*this, loc, sourceType, targetType);
+ emitter.emitConditional(src.getFinalManagedValue(),
+ src.getFinalConsumption(), ctx, handleTrue,
+ handleFalse);
+}
+
+namespace {
+ class CheckedCastEmitterOld {
+ SILGenFunction &SGF;
+ SILLocation Loc;
+ CanType SourceType;
+ CanType TargetType;
+
+ enum class CastStrategy : uint8_t {
+ Address,
+ Scalar,
+ };
+ CastStrategy Strategy;
+
+ public:
+ CheckedCastEmitterOld(SILGenFunction &SGF, SILLocation loc, Type sourceType,
+ Type targetType)
+ : SGF(SGF), Loc(loc), SourceType(sourceType->getCanonicalType()),
+ TargetType(targetType->getCanonicalType()),
+ Strategy(computeStrategy()) {}
+
+ bool isOperandIndirect() const { return Strategy == CastStrategy::Address; }
+
+ ManagedValue emitOperand(Expr *operand) {
+ AbstractionPattern mostGeneral =
+ SGF.SGM.Types.getMostGeneralAbstraction();
+ auto &origSourceTL = SGF.getTypeLowering(mostGeneral, SourceType);
+
+ SGFContext ctx;
+
+ std::unique_ptr<TemporaryInitialization> temporary;
+ if (isOperandIndirect() && SGF.silConv.useLoweredAddresses()) {
+ temporary = SGF.emitTemporary(Loc, origSourceTL);
+ ctx = SGFContext(temporary.get());
+ }
+
+ auto result =
+ SGF.emitRValueAsOrig(operand, mostGeneral, origSourceTL, ctx);
+
+ if (isOperandIndirect() && SGF.silConv.useLoweredAddresses()) {
+ // Force the result into the temporary if it's not already there.
+ if (!result.isInContext()) {
+ result.forwardInto(SGF, Loc, temporary->getAddress());
+ temporary->finishInitialization(SGF);
+ }
+ return temporary->getManagedAddress();
+ }
+
+ return result;
+ }
+
+ RValue emitUnconditionalCast(ManagedValue operand, SGFContext ctx) {
+ // The cast functions don't know how to work with anything but
+ // the most general possible abstraction level.
+ AbstractionPattern abstraction =
+ SGF.SGM.Types.getMostGeneralAbstraction();
+ auto &origTargetTL = SGF.getTypeLowering(abstraction, TargetType);
+ auto &substTargetTL = SGF.getTypeLowering(TargetType);
+ bool hasAbstraction =
+ (origTargetTL.getLoweredType() != substTargetTL.getLoweredType());
+
+ // If we're using checked_cast_addr, take the operand (which
+ // should be an address) and build into the destination buffer.
+ if (Strategy == CastStrategy::Address &&
+ SGF.silConv.useLoweredAddresses()) {
+ SILValue resultBuffer =
+ createAbstractResultBuffer(hasAbstraction, origTargetTL, ctx);
+ SGF.B.createUnconditionalCheckedCastAddr(
+ Loc, CastConsumptionKind::TakeAlways, operand.forward(SGF),
+ SourceType, resultBuffer, TargetType);
+ return RValue(SGF, Loc, TargetType,
+ finishFromResultBuffer(hasAbstraction, resultBuffer,
+ abstraction, origTargetTL, ctx));
+ }
+
SILValue resultScalar;
if (Strategy == CastStrategy::Address) {
resultScalar = SGF.B.createUnconditionalCheckedCastOpaque(
@@ -265,25 +544,22 @@
};
} // end anonymous namespace
-void SILGenFunction::emitCheckedCastBranch(SILLocation loc, Expr *source,
- Type targetType,
- SGFContext ctx,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse) {
- CheckedCastEmitter emitter(*this, loc, source->getType(), targetType);
+void SILGenFunction::emitCheckedCastBranchOld(
+ SILLocation loc, Expr *source, Type targetType, SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void()> handleFalse) {
+ CheckedCastEmitterOld emitter(*this, loc, source->getType(), targetType);
ManagedValue operand = emitter.emitOperand(source);
emitter.emitConditional(operand, CastConsumptionKind::TakeAlways, ctx,
handleTrue, handleFalse);
}
-void SILGenFunction::emitCheckedCastBranch(SILLocation loc,
- ConsumableManagedValue src,
- Type sourceType,
- CanType targetType,
- SGFContext ctx,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse) {
- CheckedCastEmitter emitter(*this, loc, sourceType, targetType);
+void SILGenFunction::emitCheckedCastBranchOld(
+ SILLocation loc, ConsumableManagedValue src, Type sourceType,
+ CanType targetType, SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void()> handleFalse) {
+ CheckedCastEmitterOld emitter(*this, loc, sourceType, targetType);
emitter.emitConditional(src.getFinalManagedValue(), src.getFinalConsumption(),
ctx, handleTrue, handleFalse);
}
@@ -459,53 +735,59 @@
ExitableFullExpr scope(SGF, CleanupLocation::get(loc));
auto operandCMV = ConsumableManagedValue::forOwned(operand);
- SGF.emitCheckedCastBranch(loc, operandCMV, operandType,
- resultObjectType, resultObjectCtx,
- // The success path.
- [&](ManagedValue objectValue) {
- // If we're not emitting into a temporary, just wrap up the result
- // in Some and go to the continuation block.
- if (!resultObjectTemp) {
- auto some = SGF.B.createEnum(loc, objectValue.forward(SGF),
- someDecl, resultTL.getLoweredType());
- SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, { some });
- return;
- }
+ assert(operandCMV.getFinalConsumption() == CastConsumptionKind::TakeAlways);
- // Otherwise, make sure the value is in the context.
- if (!objectValue.isInContext()) {
- objectValue.forwardInto(SGF, loc, resultObjectBuffer);
- }
- SGF.B.createInjectEnumAddr(loc, resultBuffer, someDecl);
- SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc);
- },
- // The failure path.
- [&] {
- auto noneDecl = SGF.getASTContext().getOptionalNoneDecl();
+ SGF.emitCheckedCastBranch(
+ loc, operandCMV, operandType, resultObjectType, resultObjectCtx,
+ // The success path.
+ [&](ManagedValue objectValue) {
+ // If we're not emitting into a temporary, just wrap up the result
+ // in Some and go to the continuation block.
+ if (!resultObjectTemp) {
+ auto some = SGF.B.createEnum(loc, objectValue.forward(SGF), someDecl,
+ resultTL.getLoweredType());
+ SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, {some});
+ return;
+ }
- // If we're not emitting into a temporary, just wrap up the result
- // in None and go to the continuation block.
- if (!resultObjectTemp) {
- auto none =
- SGF.B.createEnum(loc, nullptr, noneDecl, resultTL.getLoweredType());
- SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, { none });
-
- // Just construct the enum directly in the context.
- } else {
- SGF.B.createInjectEnumAddr(loc, resultBuffer, noneDecl);
+ // Otherwise, make sure the value is in the context.
+ if (!objectValue.isInContext()) {
+ objectValue.forwardInto(SGF, loc, resultObjectBuffer);
+ }
+ SGF.B.createInjectEnumAddr(loc, resultBuffer, someDecl);
SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc);
- }
- });
+ },
+ // The failure path.
+ [&](Optional<ManagedValue> Value) {
+ // We always are performing a take here, so Value should be None since
+ // the
+ // object should have been destroyed immediately in the fail block.
+ assert(!Value.hasValue() && "Expected a take_always consumption kind");
+ auto noneDecl = SGF.getASTContext().getOptionalNoneDecl();
+
+ // If we're not emitting into a temporary, just wrap up the result
+ // in None and go to the continuation block.
+ if (!resultObjectTemp) {
+ auto none = SGF.B.createEnum(loc, nullptr, noneDecl,
+ resultTL.getLoweredType());
+ SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, {none});
+
+ // Just construct the enum directly in the context.
+ } else {
+ SGF.B.createInjectEnumAddr(loc, resultBuffer, noneDecl);
+ SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc);
+ }
+ });
// Enter the continuation block.
- auto contBB = scope.exit();
+ SILBasicBlock *contBlock = scope.exit();
ManagedValue result;
if (resultObjectTemp) {
result = SGF.manageBufferForExprResult(resultBuffer, resultTL, C);
} else {
- auto argument = contBB->createPHIArgument(resultTL.getLoweredType(),
- ValueOwnershipKind::Owned);
+ auto argument = contBlock->createPHIArgument(resultTL.getLoweredType(),
+ ValueOwnershipKind::Owned);
result = SGF.emitManagedRValueWithCleanup(argument, resultTL);
}
@@ -543,15 +825,18 @@
auto i1Ty = SILType::getBuiltinIntegerType(1, SGF.getASTContext());
- SGF.emitCheckedCastBranch(loc, operand, targetType, SGFContext(),
- [&](ManagedValue value) {
- SILValue yes = SGF.B.createIntegerLiteral(loc, i1Ty, 1);
- SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, yes);
- },
- [&] {
- SILValue no = SGF.B.createIntegerLiteral(loc, i1Ty, 0);
- SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, no);
- });
+ // When we pass in an expr, we perform a take_always cast.
+ SGF.emitCheckedCastBranch(
+ loc, operand, targetType, SGFContext(),
+ [&](ManagedValue value) {
+ SILValue yes = SGF.B.createIntegerLiteral(loc, i1Ty, 1);
+ SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, yes);
+ },
+ [&](Optional<ManagedValue> Value) {
+ assert(!Value.hasValue() && "Expected take_always semantics");
+ SILValue no = SGF.B.createIntegerLiteral(loc, i1Ty, 0);
+ SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, no);
+ });
auto contBB = scope.exit();
auto isa = contBB->createPHIArgument(i1Ty, ValueOwnershipKind::Trivial);
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 4580307..7407c7a 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -290,7 +290,8 @@
ManagedValue SILGenFunction::emitManagedBufferWithCleanup(SILValue v,
const TypeLowering &lowering) {
- assert(lowering.getLoweredType().getAddressType() == v->getType());
+ assert(lowering.getLoweredType().getAddressType() == v->getType() ||
+ !silConv.useLoweredAddresses());
if (lowering.isTrivial())
return ManagedValue::forUnmanaged(v);
@@ -856,7 +857,7 @@
case AddressorKind::NativePinning:
// Emit the unpin immediately.
SGF.B.createStrongUnpin(loc, addressorResult.second.forward(SGF),
- Atomicity::Atomic);
+ SGF.B.getDefaultAtomicity());
break;
}
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 563f171..a11b63e 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -1408,11 +1408,22 @@
/// terminated.
/// \param handleFalse A callback to invoke in the failure path. The
/// current BB should be terminated.
- void emitCheckedCastBranch(SILLocation loc, ConsumableManagedValue src,
- Type sourceType, CanType targetType,
- SGFContext C,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse);
+ void emitCheckedCastBranch(
+ SILLocation loc, ConsumableManagedValue src, Type sourceType,
+ CanType targetType, SGFContext C,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse);
+
+ /// A form of checked cast branch that uses the old non-ownership preserving
+ /// semantics.
+ ///
+ /// The main difference is that this code does not pass the old argument as a
+ /// block argument in the failure case. This causes values to be double
+ /// consumed.
+ void emitCheckedCastBranchOld(SILLocation loc, Expr *source, Type targetType,
+ SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void()> handleFalse);
/// \brief Emit a conditional checked cast branch, starting from an
/// expression. Terminates the current BB.
@@ -1426,10 +1437,22 @@
/// terminated.
/// \param handleFalse A callback to invoke in the failure path. The
/// current BB should be terminated.
- void emitCheckedCastBranch(SILLocation loc, Expr *src,
- Type targetType, SGFContext C,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse);
+ void emitCheckedCastBranch(
+ SILLocation loc, Expr *src, Type targetType, SGFContext C,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse);
+
+ /// A form of checked cast branch that uses the old non-ownership preserving
+ /// semantics.
+ ///
+ /// The main difference is that this code does not pass the old argument as a
+ /// block argument in the failure case. This causes values to be double
+ /// consumed.
+ void emitCheckedCastBranchOld(SILLocation loc, ConsumableManagedValue src,
+ Type sourceType, CanType targetType,
+ SGFContext ctx,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void()> handleFalse);
/// Emit the control flow for an optional 'bind' operation, branching to the
/// active failure destination if the optional value addressed by optionalAddr
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 8c3e03f..ccdaf53 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -227,7 +227,8 @@
assert(temporary.getType().isAddress());
auto &tempTL = gen.getTypeLowering(temporary.getType());
- if (!tempTL.isAddressOnly() || !isFinal) {
+ if (!tempTL.isAddressOnly() || !isFinal ||
+ !gen.silConv.useLoweredAddresses()) {
if (isFinal) temporary.forward(gen);
temporary = gen.emitLoad(loc, temporary.getValue(), tempTL,
SGFContext(), IsTake_t(isFinal));
@@ -879,8 +880,14 @@
rawPointerTy, ValueOwnershipKind::Trivial);
// Cast the callback to the correct polymorphic function type.
+ SILFunctionTypeRepresentation rep;
+ if (isa<ProtocolDecl>(decl->getDeclContext()))
+ rep = SILFunctionTypeRepresentation::WitnessMethod;
+ else
+ rep = SILFunctionTypeRepresentation::Method;
+
auto origCallbackFnType = gen.SGM.Types.getMaterializeForSetCallbackType(
- decl, materialized.genericSig, materialized.origSelfType);
+ decl, materialized.genericSig, materialized.origSelfType, rep);
auto origCallbackType = SILType::getPrimitiveObjectType(origCallbackFnType);
callback = gen.B.createPointerToThinFunction(loc, callback, origCallbackType);
@@ -1094,7 +1101,7 @@
if (!isFinal)
baseValue = gen.B.createCopyValue(loc, baseValue);
- gen.B.createStrongUnpin(loc, baseValue, Atomicity::Atomic);
+ gen.B.createStrongUnpin(loc, baseValue, gen.B.getDefaultAtomicity());
}
void print(raw_ostream &OS) const override {
@@ -2138,7 +2145,7 @@
assert(unownedType->isLoadable(ResilienceExpansion::Maximal));
(void) unownedType;
- B.createStrongRetainUnowned(loc, src, Atomicity::Atomic);
+ B.createStrongRetainUnowned(loc, src, B.getDefaultAtomicity());
return B.createUnownedToRef(loc, src,
SILType::getPrimitiveObjectType(unownedType.getReferentType()));
}
@@ -2199,9 +2206,9 @@
auto unownedValue =
gen.B.emitLoadValueOperation(loc, src, LoadOwnershipQualifier::Take);
- gen.B.createStrongRetainUnowned(loc, unownedValue, Atomicity::Atomic);
+ gen.B.createStrongRetainUnowned(loc, unownedValue, gen.B.getDefaultAtomicity());
if (isTake)
- gen.B.createUnownedRelease(loc, unownedValue, Atomicity::Atomic);
+ gen.B.createUnownedRelease(loc, unownedValue, gen.B.getDefaultAtomicity());
return gen.B.createUnownedToRef(
loc, unownedValue,
SILType::getPrimitiveObjectType(unownedType.getReferentType()));
@@ -2264,7 +2271,7 @@
auto unownedValue =
gen.B.createRefToUnowned(loc, value, storageType.getObjectType());
- gen.B.createUnownedRetain(loc, unownedValue, Atomicity::Atomic);
+ gen.B.createUnownedRetain(loc, unownedValue, gen.B.getDefaultAtomicity());
emitUnloweredStoreOfCopy(gen.B, loc, unownedValue, dest, isInit);
gen.B.emitDestroyValueOperation(loc, value);
return;
@@ -2366,7 +2373,7 @@
(void) unownedType;
SILValue unowned = B.createRefToUnowned(loc, semanticValue, storageType);
- B.createUnownedRetain(loc, unowned, Atomicity::Atomic);
+ B.createUnownedRetain(loc, unowned, B.getDefaultAtomicity());
B.emitDestroyValueOperation(loc, semanticValue);
return unowned;
}
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 52aaa46..53326de 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -12,6 +12,147 @@
//
// Emission of materializeForSet.
//
+// There are two cases where materializeForSet is used for inout access:
+//
+// === Storage is virtually dispatched on a base class ===
+//
+// For example, suppose we have this setup, where a computed property in a
+// base class is overridden with a computed property in the derived class:
+//
+// class Base<T> { var x: T }
+// class Derived : Base<Int> { override var x: Int { ... } }
+// func operate(b: Base<Int>) {
+// b.x += 1
+// }
+//
+// As far as caller is concerned, the callback is invoked with the following
+// SIL type:
+//
+// @convention(method)
+// <T> (RawPointer, @inout UnsafeValueBuffer, @inout Base<T>, @thick Base<T>.Type) -> ()
+//
+// The caller will pass the first four formal parameters, followed by the
+// type metadata for 'T'.
+//
+// However if the dynamic type of the parameter 'b' is actually 'Derived',
+// then the actual callback has this SIL type:
+//
+// @convention(method)
+// (RawPointer, @inout UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> ()
+//
+// This is a fully concrete function type, with no additional generic metadata.
+//
+// These two callbacks are be ABI-compatible though, because IRGen makes three
+// guarantees:
+//
+// 1) Passing extra arguments (in this case, the type metadata for 'T') is a
+// no-op.
+//
+// 2) IRGen knows to recover the type metadata for 'T' from the
+// '@thick Base<T>.Type' parameter, instead of passing it separately.
+//
+// 3) The metatype for 'Derived' must be layout-compatible with 'Base<T>';
+// since the generic parameter 'T' is made concrete, we expect to find the
+// type metadata for 'Int' at the same offset within 'Derived.Type' as the
+// generic parameter 'T' in 'Base<T>.Type'.
+//
+// === Storage is virtually dispatched on a protocol ===
+//
+// For example,
+//
+// protocol BoxLike { associatedtype Element; var x: Element { get set } }
+// func operate<B : BoxLike>(b: B) where B.Element == Int {
+// b.x += 1
+// }
+//
+// As far as the caller is concerned, the callback is invoked with following
+// SIL type:
+//
+// <Self : BoxLike> (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> ()
+//
+// At the IRGen level, a call of a SIL function with the above type will pass
+// the four formal parameters, followed by the type metadata for 'Self', and
+// then followed by the protocol witness table for 'Self : BoxLike'.
+//
+// As in the class case, the callback won't have the same identical SIL type,
+// because it might have a different representation of 'Self'.
+//
+// So we must consider two separate cases:
+//
+// 1) The witness is a method of the concrete conforming type, eg,
+//
+// struct Box<T> : BoxLike { var x: T }
+//
+// Here, the actual callback will have the following type:
+//
+// @convention(method)
+// <T> (RawPointer, @inout UnsafeValueBuffer, @inout Box<T>, @thick Box<T>.Type) -> ()
+//
+// As with the class case, IRGen can already do the right thing -- the type
+// metadata for 'T' is recovered from the '@thick Box<T>.Type' parameter,
+// and the type metadata for 'Self' as well as the conformance
+// 'Self : BoxLike' are ignored.
+//
+// 2) The witness is a protocol extension method, possibly of some other protocol, eg,
+//
+// protocol SomeOtherProtocol { }
+// extension SomeOtherProtocol { var x: Element { ... } }
+// struct FunnyBox<T> : BoxLike, SomeOtherProtocol { typealias Element = T }
+//
+// Here, the actual callback will have the following type:
+//
+// @convention(method)
+// <Self : SomeOtherProtocol> (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> ()
+//
+// Here, the actual callback expects to receive the four formal parameters,
+// followed by the type metadata for 'Self', followed by the witness table
+// for the conformance 'Self : SomeOtherProtocol'. Note that the
+// conformance cannot be recovered from the thick metatype.
+//
+// This is *not* ABI-compatible with the type used at the call site,
+// because the caller is passing in the conformance of 'Self : BoxLike'
+// (the requirement's signature) but the callee is expecting
+// 'Self : SomeOtherProtocol' (the witness signature).
+//
+// For this reason the materializeForSet method in the protocol extension
+// of 'SomeOtherProtocol' cannot witness the materializeForSet requirement
+// of 'BoxLike'. So instead, the protocol witness thunk for
+// materializeForSet cannot delegate to the materializeForSet witness at
+// all; it's entirely open-coded, with its own callback that has the right
+// calling convention.
+//
+// === Storage has its own generic parameters ===
+//
+// One final special case is where the storage has its own generic parameters;
+// that is, a generic subscript.
+//
+// Suppose we have the following protocol:
+//
+// protocol GenericSubscript { subscript<T, U>(t: T) -> U { get set } }
+//
+// At the call site, the callback is invoked with the following signature:
+//
+// @convention(witness_method)
+// <Self : GenericSubscript, T, U> (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> ()
+//
+// If the witness is a member of a concrete type 'AnyDictionary', the actual
+// callback will have the following signature:
+//
+// @convention(method)
+// <T, U> (RawPointer, @inout UnsafeValueBuffer, @inout AnyDictionary, @thick SelfAnyDictionary.Type) -> ()
+//
+// These are ABI-compatible; the key is that witness_method passes the Self
+// metadata and conformance at the end, after the type metadata for innermost
+// generic parameters, and so everything lines up.
+//
+// === Summary ===
+//
+// To recap, we assume the following types are ABI-compatible:
+//
+// @convention(method) <T, U, V> (..., Foo<T, U>.Type)
+// @convention(witness_method) <T, U, V> (..., Foo<T, U>.Type)
+// @convention(witness_method) <Self : P, V> (..., Self.Type)
+//
//===----------------------------------------------------------------------===//
#include "SILGen.h"
@@ -21,10 +162,9 @@
#include "Scope.h"
#include "Initialization.h"
#include "swift/AST/AST.h"
-#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Types.h"
-#include "swift/AST/DiagnosticsCommon.h"
+#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Mangle.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ProtocolConformance.h"
@@ -125,11 +265,15 @@
SILType WitnessStorageType;
+ SILFunctionTypeRepresentation CallbackRepresentation;
+
private:
MaterializeForSetEmitter(SILGenModule &SGM, SILLinkage linkage,
FuncDecl *witness, SubstitutionList subs,
- Type selfInterfaceType, Type selfType)
+ GenericEnvironment *genericEnv,
+ Type selfInterfaceType, Type selfType,
+ SILFunctionTypeRepresentation callbackRepresentation)
: SGM(SGM),
Linkage(linkage),
RequirementStorage(nullptr),
@@ -138,11 +282,12 @@
WitnessStorage(witness->getAccessorStorageDecl()),
WitnessStoragePattern(AbstractionPattern::getInvalid()),
WitnessSubs(subs),
- GenericEnv(nullptr),
+ GenericEnv(genericEnv),
SelfInterfaceType(selfInterfaceType->getCanonicalType()),
SubstSelfType(selfType->getCanonicalType()),
TheAccessSemantics(AccessSemantics::Ordinary),
- IsSuper(false) {
+ IsSuper(false),
+ CallbackRepresentation(callbackRepresentation) {
// Determine the formal type of the 'self' parameter.
if (WitnessStorage->isStatic()) {
@@ -164,6 +309,9 @@
WitnessStorageType =
SGM.Types.getLoweredType(WitnessStoragePattern, SubstStorageType)
.getObjectType();
+
+ if (genericEnv)
+ GenericSig = genericEnv->getGenericSignature()->getCanonicalSignature();
}
public:
@@ -176,18 +324,8 @@
FuncDecl *requirement, FuncDecl *witness,
SubstitutionList witnessSubs) {
MaterializeForSetEmitter emitter(SGM, linkage, witness, witnessSubs,
- selfInterfaceType, selfType);
-
- if (conformance) {
- if (auto signature = conformance->getGenericSignature())
- emitter.GenericSig = signature->getCanonicalSignature();
- emitter.GenericEnv = genericEnv;
- } else {
- auto signature = requirement->getGenericSignatureOfContext();
- emitter.GenericSig = signature->getCanonicalSignature();
- emitter.GenericEnv = genericEnv;
- }
-
+ genericEnv, selfInterfaceType, selfType,
+ SILFunctionTypeRepresentation::WitnessMethod);
emitter.RequirementStorage = requirement->getAccessorStorageDecl();
// Determine the desired abstraction pattern of the storage type
@@ -214,15 +352,11 @@
Type selfType = witness->mapTypeIntoContext(selfInterfaceType);
SILDeclRef constant(witness);
- auto constantInfo = SGM.Types.getConstantInfo(constant);
-
MaterializeForSetEmitter emitter(SGM, constant.getLinkage(ForDefinition),
witness, witnessSubs,
- selfInterfaceType, selfType);
-
- if (auto signature = witness->getGenericSignatureOfContext())
- emitter.GenericSig = signature->getCanonicalSignature();
- emitter.GenericEnv = constantInfo.GenericEnv;
+ witness->getGenericEnvironment(),
+ selfInterfaceType, selfType,
+ SILFunctionTypeRepresentation::Method);
emitter.RequirementStorage = emitter.WitnessStorage;
emitter.RequirementStoragePattern = emitter.WitnessStoragePattern;
@@ -317,11 +451,8 @@
CanType witnessSelfType =
Witness->computeInterfaceSelfType()->getCanonicalType();
witnessSelfType = getSubstWitnessInterfaceType(witnessSelfType);
- if (auto selfTuple = dyn_cast<TupleType>(witnessSelfType)) {
- assert(selfTuple->getNumElements() == 1);
- witnessSelfType = selfTuple.getElementType(0);
- }
- witnessSelfType = witnessSelfType.getLValueOrInOutObjectType();
+ witnessSelfType = witnessSelfType->getInOutObjectType()
+ ->getCanonicalType();
// Eagerly loading here could cause an unnecessary
// load+materialize in some cases, but it's not really important.
@@ -387,9 +518,12 @@
/// Given part of the witness's interface type, produce its
/// substitution according to the witness substitutions.
CanType getSubstWitnessInterfaceType(CanType type) {
- auto subs = SubstSelfType->getRValueInstanceType()
- ->getMemberSubstitutionMap(SGM.SwiftModule, WitnessStorage);
- return type.subst(subs)->getCanonicalType();
+ if (auto *witnessSig = Witness->getGenericSignature()) {
+ auto subMap = witnessSig->getSubstitutionMap(WitnessSubs);
+ return type.subst(subMap, SubstFlags::UseErrorType)->getCanonicalType();
+ }
+
+ return type;
}
};
@@ -550,14 +684,23 @@
auto callbackType =
SGM.Types.getMaterializeForSetCallbackType(WitnessStorage,
GenericSig,
- SelfInterfaceType);
- auto callback =
- SGM.M.getOrCreateFunction(Witness, CallbackName, Linkage,
- callbackType, IsBare,
- F.isTransparent(),
- F.isFragile());
+ SelfInterfaceType,
+ CallbackRepresentation);
- callback->setGenericEnvironment(GenericEnv);
+ auto *genericEnv = GenericEnv;
+ if (GenericEnv && GenericEnv->getGenericSignature()->areAllParamsConcrete())
+ genericEnv = nullptr;
+
+ auto callback =
+ SGM.M.createFunction(Linkage, CallbackName, callbackType,
+ genericEnv, SILLocation(Witness),
+ IsBare, F.isTransparent(), F.isFragile(),
+ IsNotThunk,
+ /*ClassVisibility=*/SILFunction::NotRelevant,
+ /*InlineStrategy=*/InlineDefault,
+ /*EffectsKind=*/EffectsKind::Unspecified,
+ /*InsertBefore=*/&F);
+
callback->setDebugScope(new (SGM.M) SILDebugScope(Witness, callback));
PrettyStackTraceSILFunction X("silgen materializeForSet callback", callback);
@@ -680,7 +823,7 @@
break;
case AddressorKind::NativePinning:
- gen.B.createStrongUnpin(loc, owner, Atomicity::Atomic);
+ gen.B.createStrongUnpin(loc, owner, gen.B.getDefaultAtomicity());
break;
}
@@ -784,7 +927,7 @@
// ownership of it.
SILValue indicesV =
gen.B.createProjectValueBuffer(loc, indicesTy, callbackBuffer);
- if (indicesTL->isLoadable())
+ if (indicesTL->isLoadable() || !gen.silConv.useLoweredAddresses())
indicesV = indicesTL->emitLoad(gen.B, loc, indicesV,
LoadOwnershipQualifier::Take);
ManagedValue mIndices =
@@ -805,7 +948,7 @@
auto &valueTL = gen.getTypeLowering(lvalue.getTypeOfRValue());
value = gen.B.createPointerToAddress(
loc, value, valueTL.getLoweredType().getAddressType(), /*isStrict*/ true);
- if (valueTL.isLoadable())
+ if (valueTL.isLoadable() || !gen.silConv.useLoweredAddresses())
value = valueTL.emitLoad(gen.B, loc, value, LoadOwnershipQualifier::Take);
ManagedValue mValue = gen.emitManagedRValueWithCleanup(value, valueTL);
RValue rvalue(gen, loc, lvalue.getSubstFormalType(), mValue);
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index a2b74b6..c53f642 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -1527,16 +1527,16 @@
innerFailure = &specializedFailure;
// Perform a conditional cast branch.
- SGF.emitCheckedCastBranch(loc, castOperand,
- sourceType, targetType, SGFContext(),
- // Success block: recurse.
- [&](ManagedValue castValue) {
- handleCase(ConsumableManagedValue::forOwned(castValue),
- specializedRows, *innerFailure);
- assert(!SGF.B.hasValidInsertionPoint() && "did not end block");
- },
- // Failure block: branch out to the continuation block.
- [&] { (*innerFailure)(loc); });
+ SGF.emitCheckedCastBranchOld(
+ loc, castOperand, sourceType, targetType, SGFContext(),
+ // Success block: recurse.
+ [&](ManagedValue castValue) {
+ handleCase(ConsumableManagedValue::forOwned(castValue), specializedRows,
+ *innerFailure);
+ assert(!SGF.B.hasValidInsertionPoint() && "did not end block");
+ },
+ // Failure block: branch out to the continuation block.
+ [&] { (*innerFailure)(loc); });
}
/// Perform specialized dispatch for a sequence of EnumElementPattern or an
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index fb6d960..8092c04 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -1097,7 +1097,7 @@
SGF.B.createInitExistentialAddr(Loc, existentialBuf,
inputTupleType,
concreteTL.getLoweredType(),
- /*Conformances=*/{});
+ /*conformances=*/{});
auto tupleTemp = SGF.useBufferAsTemporary(tupleBuf, concreteTL);
translateAndImplodeInto(inputOrigType, inputTupleType,
@@ -1911,7 +1911,7 @@
SILValue outerConcreteResultAddr
= Gen.B.createInitExistentialAddr(Loc, outerResultAddr, innerSubstType,
Gen.getLoweredType(opaque, innerSubstType),
- /*Conformances=*/{});
+ /*conformances=*/{});
// Emit into that address.
planTupleIntoIndirectResult(innerOrigType, innerSubstType,
@@ -2517,7 +2517,8 @@
builder.addGenericParameter(newGenericParam);
Requirement newRequirement(RequirementKind::Conformance, newGenericParam,
openedExistential->getOpenedExistentialType());
- auto source = RequirementSource::forAbstract(builder);
+ auto source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
builder.addRequirement(newRequirement, source);
builder.finalize(SourceLoc(), {newGenericParam},
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index fb7a624..971662d 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -494,8 +494,6 @@
SGM.emitPropertyBehavior(vd);
if (vd->hasStorage()) {
assert(vd->isStatic() && "stored property in extension?!");
- ExtensionDecl *ext = cast<ExtensionDecl>(vd->getDeclContext());
- NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal();
return emitTypeMemberGlobalVariable(SGM, vd);
}
visitAbstractStorageDecl(vd);
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 064b980..aa2d3f1 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -374,17 +374,19 @@
bool IsOwnedSelf = SelfConvention == ParameterConvention::Direct_Owned;
// Emit matching release for owned self if we are moving the original call.
- if (!LeaveOriginal && IsOwnedSelf)
- SILBuilderWithScope(SemanticsCall)
- .createReleaseValue(SemanticsCall->getLoc(), Self, Atomicity::Atomic);
+ if (!LeaveOriginal && IsOwnedSelf) {
+ SILBuilderWithScope Builder(SemanticsCall);
+ Builder.createReleaseValue(SemanticsCall->getLoc(), Self, Builder.getDefaultAtomicity());
+ }
auto NewArrayStructValue = copyArrayLoad(Self, InsertBefore, DT);
// Retain the array.
- if (IsOwnedSelf)
- SILBuilderWithScope(InsertBefore, SemanticsCall)
- .createRetainValue(SemanticsCall->getLoc(), NewArrayStructValue,
- Atomicity::Atomic);
+ if (IsOwnedSelf) {
+ SILBuilderWithScope Builder(InsertBefore, SemanticsCall);
+ Builder.createRetainValue(SemanticsCall->getLoc(), NewArrayStructValue,
+ Builder.getDefaultAtomicity());
+ }
return NewArrayStructValue;
}
@@ -477,10 +479,11 @@
void swift::ArraySemanticsCall::removeCall() {
if (getSelfParameterConvention(SemanticsCall) ==
- ParameterConvention::Direct_Owned)
- SILBuilderWithScope(SemanticsCall)
- .createReleaseValue(SemanticsCall->getLoc(), getSelf(),
- Atomicity::Atomic);
+ ParameterConvention::Direct_Owned) {
+ SILBuilderWithScope Builder(SemanticsCall);
+ Builder.createReleaseValue(SemanticsCall->getLoc(), getSelf(),
+ Builder.getDefaultAtomicity());
+ }
switch (getKind()) {
default: break;
diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
index 8c0637f..44a04c6 100644
--- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
@@ -1004,7 +1004,7 @@
if (Ty.hasReferenceSemantics())
return true;
- if (Ty.getSwiftType() == Mod->getASTContext().TheRawPointerType)
+ if (Ty.getSwiftRValueType() == Mod->getASTContext().TheRawPointerType)
return true;
if (auto *Str = Ty.getStructOrBoundGenericStruct()) {
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index b53c482..9a6ed88 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -192,36 +192,22 @@
namespace {
/// \brief A SILCloner subclass which clones a closure function while converting
/// one or more captures from 'inout' (by-reference) to by-value.
-class ClosureCloner : public TypeSubstCloner<ClosureCloner> {
+class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
public:
friend class SILVisitor<ClosureCloner>;
friend class SILCloner<ClosureCloner>;
ClosureCloner(SILFunction *Orig, IsFragile_t Fragile,
StringRef ClonedName,
- SubstitutionMap &InterfaceSubs,
- SubstitutionList ApplySubs,
IndicesSet &PromotableIndices);
void populateCloned();
SILFunction *getCloned() { return &getBuilder().getFunction(); }
-protected:
- // FIXME: We intentionally call SILClonerWithScopes here to ensure
- // the debug scopes are set correctly for cloned
- // functions. TypeSubstCloner, SILClonerWithScopes, and
- // SILCloner desperately need refactoring and/or combining so
- // that the obviously right things are happening for cloning
- // vs. inlining.
- void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
- SILClonerWithScopes<ClosureCloner>::postProcess(Orig, Cloned);
- }
-
private:
static SILFunction *initCloned(SILFunction *Orig, IsFragile_t Fragile,
StringRef ClonedName,
- SubstitutionMap &InterfaceSubs,
IndicesSet &PromotableIndices);
void visitDebugValueAddrInst(DebugValueAddrInst *Inst);
@@ -316,13 +302,9 @@
ClosureCloner::ClosureCloner(SILFunction *Orig, IsFragile_t Fragile,
StringRef ClonedName,
- SubstitutionMap &InterfaceSubs,
- SubstitutionList ApplySubs,
IndicesSet &PromotableIndices)
- : TypeSubstCloner<ClosureCloner>(
- *initCloned(Orig, Fragile, ClonedName, InterfaceSubs,
- PromotableIndices),
- *Orig, ApplySubs),
+ : SILClonerWithScopes<ClosureCloner>(
+ *initCloned(Orig, Fragile, ClonedName, PromotableIndices)),
Orig(Orig), PromotableIndices(PromotableIndices) {
assert(Orig->getDebugScope()->Parent != getCloned()->getDebugScope()->Parent);
}
@@ -419,7 +401,6 @@
SILFunction*
ClosureCloner::initCloned(SILFunction *Orig, IsFragile_t Fragile,
StringRef ClonedName,
- SubstitutionMap &InterfaceSubs,
IndicesSet &PromotableIndices) {
SILModule &M = Orig->getModule();
@@ -436,9 +417,6 @@
OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
M.getASTContext());
- auto SubstTy = SILType::substFuncType(M, InterfaceSubs, ClonedTy,
- /* dropGenerics = */ false);
-
assert((Orig->isTransparent() || Orig->isBare() || Orig->getLocation())
&& "SILFunction missing location");
assert((Orig->isTransparent() || Orig->isBare() || Orig->getDebugScope())
@@ -446,7 +424,7 @@
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
auto *Fn = M.createFunction(
- Orig->getLinkage(), ClonedName, SubstTy, Orig->getGenericEnvironment(),
+ Orig->getLinkage(), ClonedName, ClonedTy, Orig->getGenericEnvironment(),
Orig->getLocation(), Orig->isBare(), IsNotTransparent, Fragile,
Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(),
Orig->getEffectsKind(), Orig, Orig->getDebugScope());
@@ -726,18 +704,6 @@
return false;
}
-static bool signatureHasDependentTypes(SILFunction *Callee) {
- SILFunctionConventions conventions = Callee->getConventions();
- if (conventions.getSILResultType().hasTypeParameter())
- return true;
-
- for (auto Param : conventions.funcTy->getParameters())
- if (conventions.getSILType(Param).hasTypeParameter())
- return true;
-
- return false;
-}
-
/// \brief Examine an alloc_box instruction, returning true if at least one
/// capture of the boxed variable is promotable. If so, then the pair of the
/// partial_apply instruction and the index of the box argument in the closure's
@@ -759,11 +725,6 @@
if (IM.count(PAI))
return false;
- // Bail if the signature has any dependent types as we do not
- // currently support these.
- if (signatureHasDependentTypes(PAI->getCalleeFunction()))
- return false;
-
SILModule &M = PAI->getModule();
auto closureType = PAI->getType().castTo<SILFunctionType>();
SILFunctionConventions closureConv(closureType, M);
@@ -864,13 +825,6 @@
IndicesSet &PromotableIndices) {
SILFunction *F = PAI->getFunction();
- // Create the substitution maps.
- auto ApplySubs = PAI->getSubstitutions();
-
- SubstitutionMap InterfaceSubs;
- if (auto genericSig = PAI->getOrigCalleeType()->getGenericSignature())
- InterfaceSubs = genericSig->getSubstitutionMap(ApplySubs);
-
// Create the Cloned Name for the function.
SILFunction *Orig = FRI->getReferencedFunction();
@@ -887,8 +841,7 @@
}
// Otherwise, create a new clone.
- ClosureCloner cloner(Orig, Fragile, ClonedName, InterfaceSubs,
- ApplySubs, PromotableIndices);
+ ClosureCloner cloner(Orig, Fragile, ClonedName, PromotableIndices);
cloner.populateCloned();
return cloner.getCloned();
}
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 24c9fe0..860c4fc 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -343,9 +343,9 @@
// Emit the retain that matches the captured argument by the partial_apply
// in the callee that is consumed by the partial_apply.
Builder.setInsertionPoint(AI.getInstruction());
- Builder.createRetainValue(Closure->getLoc(), Arg, Atomicity::Atomic);
+ Builder.createRetainValue(Closure->getLoc(), Arg, Builder.getDefaultAtomicity());
} else {
- Builder.createRetainValue(Closure->getLoc(), Arg, Atomicity::Atomic);
+ Builder.createRetainValue(Closure->getLoc(), Arg, Builder.getDefaultAtomicity());
}
}
@@ -364,9 +364,9 @@
// argument to AI.
if (CSDesc.isClosureConsumed() && CSDesc.closureHasRefSemanticContext()) {
Builder.setInsertionPoint(TAI->getNormalBB()->begin());
- Builder.createReleaseValue(Closure->getLoc(), Closure, Atomicity::Atomic);
+ Builder.createReleaseValue(Closure->getLoc(), Closure, Builder.getDefaultAtomicity());
Builder.setInsertionPoint(TAI->getErrorBB()->begin());
- Builder.createReleaseValue(Closure->getLoc(), Closure, Atomicity::Atomic);
+ Builder.createReleaseValue(Closure->getLoc(), Closure, Builder.getDefaultAtomicity());
Builder.setInsertionPoint(AI.getInstruction());
}
} else {
@@ -377,7 +377,7 @@
// right after NewAI. This is to balance the +1 from being an @owned
// argument to AI.
if (CSDesc.isClosureConsumed() && CSDesc.closureHasRefSemanticContext())
- Builder.createReleaseValue(Closure->getLoc(), Closure, Atomicity::Atomic);
+ Builder.createReleaseValue(Closure->getLoc(), Closure, Builder.getDefaultAtomicity());
}
// Replace all uses of the old apply with the new apply.
@@ -425,10 +425,10 @@
// Extend the lifetime of a captured argument to cover the callee.
SILBuilderWithScope Builder(getClosure());
- Builder.createRetainValue(getClosure()->getLoc(), Arg, Atomicity::Atomic);
+ Builder.createRetainValue(getClosure()->getLoc(), Arg, Builder.getDefaultAtomicity());
for (auto *I : CInfo->LifetimeFrontier) {
Builder.setInsertionPoint(I);
- Builder.createReleaseValue(getClosure()->getLoc(), Arg, Atomicity::Atomic);
+ Builder.createReleaseValue(getClosure()->getLoc(), Arg, Builder.getDefaultAtomicity());
}
}
@@ -647,7 +647,7 @@
if (isa<ReturnInst>(TI)) {
Builder.setInsertionPoint(TI);
Builder.createReleaseValue(Loc, SILValue(NewClosure),
- Atomicity::Atomic);
+ Builder.getDefaultAtomicity());
continue;
}
@@ -663,7 +663,7 @@
// value, we will retain the partial apply before we release it and
// potentially eliminate it.
Builder.setInsertionPoint(NoReturnApply.getInstruction());
- Builder.createReleaseValue(Loc, SILValue(NewClosure), Atomicity::Atomic);
+ Builder.createReleaseValue(Loc, SILValue(NewClosure), Builder.getDefaultAtomicity());
}
}
}
diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
index 6bf6614..4731fe0 100644
--- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp
+++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
@@ -77,6 +77,12 @@
return valueHashMap.find(value) != valueHashMap.end();
}
+ ValueStorage &getStorage(SILValue value) {
+ auto hashIter = valueHashMap.find(value);
+ assert(hashIter != valueHashMap.end() && "Missing SILValue");
+ return valueVector[hashIter->second].second;
+ }
+
ValueStorage &insertValue(SILValue value) {
auto hashResult =
valueHashMap.insert(std::make_pair(value, valueVector.size()));
@@ -87,10 +93,18 @@
return valueVector.back().second;
}
- ValueStorage &getStorage(SILValue value) {
- auto hashIter = valueHashMap.find(value);
+ // Replace entry for `oldValue` with an entry for `newValue` preserving the
+ // the mapped ValueStorage.
+ void replaceValue(SILValue oldValue, SILValue newValue) {
+ auto hashIter = valueHashMap.find(oldValue);
assert(hashIter != valueHashMap.end() && "Missing SILValue");
- return valueVector[hashIter->second].second;
+ unsigned idx = hashIter->second;
+ valueHashMap.erase(hashIter);
+
+ valueVector[idx].first = newValue;
+
+ auto hashResult = valueHashMap.insert(std::make_pair(newValue, idx));
+ assert(hashResult.second && "SILValue already mapped");
}
};
} // end anonymous namespace
@@ -117,7 +131,10 @@
AddressLoweringState(SILFunction *F) : F(F) {}
void markDeadInst(SILInstruction *inst) {
- assert(onlyHaveDebugUses(inst));
+#ifndef NDEBUG
+ for (Operand *use : inst->getUses())
+ assert(instsToDelete.count(use->getUser()));
+#endif
instsToDelete.insert(inst);
}
};
@@ -128,7 +145,7 @@
//===----------------------------------------------------------------------===//
namespace {
-/// Collect all Opaque/Resilient values, inserting them in a ValueStorageMap in
+/// Collect all opaque/resilient values, inserting them in `valueStorageMap` in
/// RPO order.
///
/// Collect all call arguments with formally indirect SIL argument convention in
@@ -152,7 +169,10 @@
};
} // end anonymous namespace
-/// Populate valueStorageMap. Find all Opaque/Resilient SILValues and add them
+/// Top-level entry: Populate `valueStorageMap`, `indirectResults`, and
+/// `indirectOperands`.
+///
+/// Find all Opaque/Resilient SILValues and add them
/// to valueStorageMap in RPO.
void OpaqueValueVisitor::mapValueStorage() {
for (auto *BB : postorderInfo.getReversePostOrder()) {
@@ -176,8 +196,12 @@
}
}
-/// Populate indirectOperands. Add an operand for each call argument with a
-/// formally indirect convention.
+/// Populate `indirectResults` and `indirectOperands`.
+///
+/// If this call has indirect formal results, add it to `indirectResults`.
+///
+/// Add each call operand with a formally indirect convention to
+/// `indirectOperands`.
void OpaqueValueVisitor::visitApply(ApplySite applySite) {
if (applySite.getSubstCalleeType()->hasIndirectFormalResults())
pass.indirectResults.push_back(applySite.getInstruction());
@@ -195,11 +219,14 @@
}
}
+/// If `value` is address-only add it to the `valueStorageMap`.
+///
/// TODO: Set ValueStorage.projectionFrom whenever there is a single
/// isComposingOperand() use and the aggregate's storage can be hoisted to a
/// dominating point.
void OpaqueValueVisitor::visitValue(SILValue value) {
- if (value->getType().isAddressOnly(pass.F->getModule())) {
+ if (value->getType().isObject()
+ && value->getType().isAddressOnly(pass.F->getModule())) {
if (pass.valueStorageMap.contains(value)) {
assert(isa<SILFunctionArgument>(
pass.valueStorageMap.getStorage(value).storageAddress));
@@ -241,6 +268,11 @@
unsigned insertIndirectResultParameters(unsigned argIdx, SILType resultType);
void allocateForValue(SILValue value, ValueStorage &storage);
void allocateForOperand(Operand *operand);
+ void canonicalizeResults(
+ ApplyInst *applyInst,
+ SmallVectorImpl<SILInstruction*> &directResultValues,
+ ArrayRef<Operand*> nonCanonicalUses);
+ void canonicalizeResults(ApplyInst *applyInst);
void allocateForResults(SILInstruction *origInst);
};
} // end anonymous namespace
@@ -280,14 +312,17 @@
// Create an AllocStack for every formally indirect argument.
for (Operand *operand : pass.indirectOperands)
allocateForOperand(operand);
+ pass.indirectOperands.clear();
// Create an AllocStack for every formally indirect result.
+ // This rewrites and potentially erases the original call.
for (SILInstruction *callInst : pass.indirectResults)
allocateForResults(callInst);
+ pass.indirectResults.clear();
}
-/// Replace each value-typed argument with an address-typed argument by
-/// inserting a temprorary load instruction.
+/// Replace each value-typed argument to the current function with an
+/// address-typed argument by inserting a temporary load instruction.
void OpaqueStorageAllocation::replaceFunctionArgs() {
// Insert temporary argument loads at the top of the function.
SILBuilder argBuilder(pass.F->getEntryBlock()->begin());
@@ -297,7 +332,7 @@
for (SILParameterInfo param :
pass.F->getLoweredFunctionType()->getParameters()) {
- if (param.isFormalIndirect()) {
+ if (param.isFormalIndirect() && !fnConv.isSILIndirect(param)) {
SILArgument *arg = pass.F->getArgument(argIdx);
SILType addrType = arg->getType().getAddressType();
@@ -326,7 +361,8 @@
/// Recursively insert function arguments for any @out result type at the
/// specified index. Return the index after the last inserted result argument.
///
-/// This is effectively moved from the old SILGen emitIndirectResultParameters.
+/// Note: This is effectively moved from the old SILGen
+/// emitIndirectResultParameters.
///
/// TODO: It might be faster to generate args directly from
/// SILFunctionConventions without drilling through the result SILType. But one
@@ -362,6 +398,7 @@
}
/// Utility to derive SILLocation.
+///
/// TODO: This should be a common utility.
static SILLocation getLocForValue(SILValue value) {
if (auto *instr = dyn_cast<SILInstruction>(value)) {
@@ -384,6 +421,11 @@
if (isa<TupleInst>(value))
return;
+ // Don't bother allocating storage for result tuples. Each element has its own
+ // storage.
+ if (isa<FullApplySite>(value))
+ return;
+
// Argument loads already have a storage address.
if (storage.storageAddress) {
assert(isa<SILFunctionArgument>(storage.storageAddress));
@@ -404,11 +446,16 @@
}
/// Deallocate temporary call-site stack storage.
+///
+/// `argLoad` is non-null for @out args that are loaded.
static void insertStackDeallocationAtCall(AllocStackInst *allocInst,
- SILInstruction *applyInst) {
+ SILInstruction *applyInst,
+ SILInstruction *argLoad) {
+ SILInstruction *lastUse = argLoad ? argLoad : applyInst;
+
switch (applyInst->getKind()) {
case ValueKind::ApplyInst: {
- SILBuilder deallocBuilder(&*std::next(applyInst->getIterator()));
+ SILBuilder deallocBuilder(&*std::next(lastUse->getIterator()));
deallocBuilder.createDeallocStack(allocInst->getLoc(), allocInst);
break;
}
@@ -425,6 +472,9 @@
/// Allocate storage for formally indirect arguments.
/// Update the operand to this address.
/// After this, the SIL argument types no longer match SIL function conventions.
+///
+/// Note: The temporary argument storage does not own its value. If the argument
+/// is owner, the stored value should already have been copied.
void OpaqueStorageAllocation::allocateForOperand(Operand *operand) {
SILInstruction *apply = operand->getUser();
SILValue argValue = operand->get();
@@ -433,77 +483,174 @@
AllocStackInst *allocInstr =
callBuilder.createAllocStack(apply->getLoc(), argValue->getType());
- // This is a store [init], but qualifications aren't allowed.
callBuilder.createStore(apply->getLoc(), argValue, allocInstr,
StoreOwnershipQualifier::Unqualified);
operand->set(allocInstr);
- insertStackDeallocationAtCall(allocInstr, apply);
+ insertStackDeallocationAtCall(allocInstr, apply, /*argLoad=*/nullptr);
+}
+
+// Canonicalize call result uses. Treat each result of a multi-result call as
+// independent values. Currently, SILGen may generate tuple_extract for each
+// result but generate a single destroy_value for the entire tuple of
+// results. This makes it impossible to reason about each call result as an
+// independent value according to the callee's function type.
+//
+// directResultValues has an entry for each tuple extract corresponding to
+// that result if one exists. This function will add an entry to
+// directResultValues whenever it needs to materialize a TupleExtractInst.
+void OpaqueStorageAllocation::canonicalizeResults(
+ ApplyInst *applyInst,
+ SmallVectorImpl<SILInstruction*> &directResultValues,
+ ArrayRef<Operand*> nonCanonicalUses) {
+
+ for (Operand *operand : nonCanonicalUses) {
+ auto *destroyInst = dyn_cast<DestroyValueInst>(operand->getUser());
+ if (!destroyInst)
+ llvm::report_fatal_error("Simultaneous use of multiple call results.");
+
+ for (unsigned resultIdx = 0, endIdx = directResultValues.size();
+ resultIdx < endIdx; ++resultIdx) {
+ SILInstruction *result = directResultValues[resultIdx];
+ if (!result) {
+ SILBuilder resultBuilder(std::next(SILBasicBlock::iterator(applyInst)));
+ result = resultBuilder.createTupleExtract(applyInst->getLoc(),
+ applyInst, resultIdx);
+ directResultValues[resultIdx] = result;
+ }
+ SILBuilder B(destroyInst);
+ auto &TL = pass.F->getModule().getTypeLowering(result->getType());
+ TL.emitDestroyValue(B, destroyInst->getLoc(), result);
+ }
+ destroyInst->eraseFromParent();
+ }
}
/// Allocate storage for formally indirect results at the given call site.
/// Create a new call instruction with indirect SIL arguments.
-void OpaqueStorageAllocation::allocateForResults(SILInstruction *origInst) {
- ApplySite apply(origInst);
+void OpaqueStorageAllocation::allocateForResults(SILInstruction *origCallInst) {
+ ApplySite apply(origCallInst);
+
+ SILFunctionConventions origFnConv = apply.getSubstCalleeConv();
+
+ // Gather the original direct return values.
+ // Canonicalize results so no user uses more than one result.
+ SmallVector<SILInstruction *, 8> origDirectResultValues(
+ origFnConv.getNumDirectSILResults());
+ SmallVector<Operand *, 4> nonCanonicalUses;
+ if (origCallInst->getType().is<TupleType>()) {
+ for (Operand *operand : origCallInst->getUses()) {
+ if (auto *extract = dyn_cast<TupleExtractInst>(operand->getUser()))
+ origDirectResultValues[extract->getFieldNo()] = extract;
+ else
+ nonCanonicalUses.push_back(operand);
+ }
+ if (!nonCanonicalUses.empty()) {
+ auto *applyInst = cast<ApplyInst>(origCallInst);
+ canonicalizeResults(applyInst, origDirectResultValues, nonCanonicalUses);
+ }
+ } else {
+ // A call with no indirect results should not have been added to
+ // pass.indirectResults.
+ assert(origDirectResultValues.size() == 1);
+ if (!origCallInst->use_empty()) {
+ origDirectResultValues[0] = origCallInst;
+ // Tuple extract values were already mapped. The call itself was not.
+ pass.valueStorageMap.insertValue(origCallInst);
+ }
+ }
+
+ // Prepare to emit a new call instruction.
+ SILLocation loc = origCallInst->getLoc();
+ SILBuilder callBuilder(origCallInst);
+
+ // Lambda to allocate and map storage for an indirect result.
+ // Note: origDirectResultValues contains null for unused results.
+ auto mapIndirectArg = [&](SILInstruction *origDirectResultVal,
+ SILType argTy) {
+ if (origDirectResultVal
+ && pass.valueStorageMap.contains(origDirectResultVal)) {
+ // Pass the local storage address as the indirect result address.
+ return
+ pass.valueStorageMap.getStorage(origDirectResultVal).storageAddress;
+ }
+ // Allocate temporary call-site storage for an unused or loadable result.
+ auto *allocInst =
+ callBuilder.createAllocStack(loc, argTy);
+ LoadInst *loadInst = nullptr;
+ if (origDirectResultVal) {
+ // TODO: Find the try_apply's result block.
+ // Build results outside-in to next stack allocations.
+ SILBuilder resultBuilder(
+ std::next(SILBasicBlock::iterator(origCallInst)));
+ // This is a formally indirect argument, but is loadable.
+ loadInst = resultBuilder.createLoad(loc, allocInst,
+ LoadOwnershipQualifier::Unqualified);
+ origDirectResultVal->replaceAllUsesWith(loadInst);
+ pass.markDeadInst(origDirectResultVal);
+ }
+ insertStackDeallocationAtCall(allocInst, origCallInst, loadInst);
+ return SILValue(allocInst);
+ };
+
+ // The new call instruction's SIL calling convention.
SILFunctionConventions loweredFnConv(
apply.getSubstCalleeType(),
SILModuleConventions::getLoweredAddressConventions());
- SILLocation loc = origInst->getLoc();
- SILBuilder callBuilder(origInst);
+ // The new call instruction's SIL argument list.
+ SmallVector<SILValue, 8> newCallArgs(loweredFnConv.getNumSILArguments());
- SmallVector<SILValue, 8> args(loweredFnConv.getNumSILArguments());
- unsigned firstResultIdx = loweredFnConv.getSILArgIndexOfFirstIndirectResult();
+ // Map the original result indices to new result indices.
+ SmallVector<unsigned, 8> newDirectResultIndices(
+ origFnConv.getNumDirectSILResults());
+ // Indices used to populate newDirectResultIndices.
+ unsigned oldDirectResultIdx = 0, newDirectResultIdx = 0;
- // Find the storage location of each indirect result and populate the SIL
- // argument vector.
- SmallVector<TupleExtractInst *, 4> concreteResults;
- if (origInst->getType().is<TupleType>()) {
- for (Operand *operand : origInst->getUses()) {
- if (auto *extract = dyn_cast<TupleExtractInst>(operand->getUser())) {
- unsigned argIdx = firstResultIdx + extract->getFieldNo();
- assert(argIdx < loweredFnConv.getSILArgIndexOfFirstParam());
- if (!extract->getType().isAddressOnly(pass.F->getModule())) {
- concreteResults.push_back(extract);
- continue;
- }
- auto addr = pass.valueStorageMap.getStorage(extract).storageAddress;
- assert(addr);
- args[argIdx] = addr;
+ // The index of the next indirect result argument.
+ unsigned newResultArgIdx =
+ loweredFnConv.getSILArgIndexOfFirstIndirectResult();
+
+ // Visit each result. Redirect results that are now indirect.
+ // Result that remain direct will be redirected later.
+ // Populate newCallArgs and newDirectResultIndices.
+ for_each(
+ apply.getSubstCalleeType()->getResults(),
+ origDirectResultValues,
+ [&](SILResultInfo resultInfo, SILInstruction *origDirectResultVal) {
+ // Assume that all original results are direct in SIL.
+ assert(!origFnConv.isSILIndirect(resultInfo));
+
+ if (loweredFnConv.isSILIndirect(resultInfo)) {
+ newCallArgs[newResultArgIdx++] =
+ mapIndirectArg(origDirectResultVal,
+ loweredFnConv.getSILType(resultInfo));;
+ newDirectResultIndices[oldDirectResultIdx++] = newDirectResultIdx;
+ } else {
+ newDirectResultIndices[oldDirectResultIdx++] = newDirectResultIdx++;
}
- }
- } else {
- auto addr = pass.valueStorageMap.getStorage(origInst).storageAddress;
- assert(addr);
- args[firstResultIdx] = addr;
- }
- // Allocate storage for any unused or concrete results. One for each missing
- // entry in the SIL arguments list.
- unsigned argIdx = firstResultIdx;
- for (SILType resultTy : loweredFnConv.getIndirectSILResultTypes()) {
- if (!args[argIdx]) {
- AllocStackInst *allocInstr = callBuilder.createAllocStack(loc, resultTy);
- args[argIdx] = allocInstr;
- insertStackDeallocationAtCall(allocInstr, origInst);
- }
- ++argIdx;
- }
+ // replaceAllUses will be called later to handle direct results that
+ // remain direct results of the new call instruction.
+ });
+
// Append the existing call arguments to the SIL argument list. They were
// already lowered to addresses by allocateForOperand.
- assert(argIdx == loweredFnConv.getSILArgIndexOfFirstParam());
+ assert(newResultArgIdx == loweredFnConv.getSILArgIndexOfFirstParam());
unsigned origArgIdx = apply.getSubstCalleeConv().getSILArgIndexOfFirstParam();
- for (unsigned endIdx = args.size(); argIdx < endIdx; ++argIdx, ++origArgIdx) {
- args[argIdx] = apply.getArgument(origArgIdx);
+ for (unsigned endIdx = newCallArgs.size(); newResultArgIdx < endIdx;
+ ++newResultArgIdx, ++origArgIdx) {
+ newCallArgs[newResultArgIdx] = apply.getArgument(origArgIdx);
}
+
// Create a new apply with indirect result operands.
- SILInstruction *callInst;
- switch (origInst->getKind()) {
+ SILInstruction *newCallInst;
+ switch (origCallInst->getKind()) {
case ValueKind::ApplyInst:
- callInst = callBuilder.createApply(
+ newCallInst = callBuilder.createApply(
loc, apply.getCallee(), apply.getSubstCalleeSILType(),
- loweredFnConv.getSILResultType(), apply.getSubstitutions(), args,
- cast<ApplyInst>(origInst)->isNonThrowing());
+ loweredFnConv.getSILResultType(), apply.getSubstitutions(), newCallArgs,
+ cast<ApplyInst>(origCallInst)->isNonThrowing());
break;
case ValueKind::TryApplyInst:
// TODO: insert dealloc in the catch block.
@@ -513,23 +660,48 @@
default:
llvm_unreachable("not implemented for this instruction!");
}
- if (pass.valueStorageMap.contains(origInst)) {
- pass.valueStorageMap.insertValue(callInst);
- pass.valueStorageMap.getStorage(callInst).storageAddress =
- pass.valueStorageMap.getStorage(origInst).storageAddress;
- // origInst remains in the map but has no users.
+
+ // Replace all unmapped uses of the original call with uses of the new call.
+ //
+ // TODO: handle bbargs from try_apply.
+ SILBuilder resultBuilder(
+ std::next(SILBasicBlock::iterator(origCallInst)));
+ SmallVector<Operand*, 8> origUses(origCallInst->getUses());
+ for (Operand *operand : origUses) {
+ auto *extractInst = dyn_cast<TupleExtractInst>(operand->getUser());
+ if (!extractInst) {
+ assert(origFnConv.getNumDirectSILResults() == 1);
+ assert(pass.valueStorageMap.contains(origCallInst));
+ continue;
+ }
+ unsigned origResultIdx = extractInst->getFieldNo();
+ auto resultInfo = origFnConv.getResults()[origResultIdx];
+
+ if (extractInst->getType().isAddressOnly(pass.F->getModule())) {
+ assert(loweredFnConv.isSILIndirect(resultInfo));
+ assert(pass.valueStorageMap.contains(extractInst));
+ continue;
+ }
+ if (loweredFnConv.isSILIndirect(resultInfo)) {
+ // This loadable indirect use should already be
+ // redirected to a load from the argument storage and marked dead.
+ assert(extractInst->use_empty());
+ continue;
+ }
+ // Either the new call instruction has only a single direct result, or we
+ // map the original tuple field to the new tuple field.
+ SILInstruction *newValue = newCallInst;
+ if (loweredFnConv.getNumDirectSILResults() > 1) {
+ assert(newCallInst->getType().is<TupleType>());
+ newValue = resultBuilder.createTupleExtract(
+ extractInst->getLoc(), newCallInst,
+ newDirectResultIndices[origResultIdx]);
+ }
+ extractInst->replaceAllUsesWith(newValue);
+ extractInst->eraseFromParent();
}
- origInst->replaceAllUsesWith(callInst);
- pass.markDeadInst(origInst);
- // Load concrete args, and mark the extract for deletion.
- for (TupleExtractInst *extract : concreteResults) {
- unsigned argIdx = firstResultIdx + extract->getFieldNo();
- SILValue arg = args[argIdx];
- LoadInst *loadArg = callBuilder.createLoad(
- extract->getLoc(), arg, LoadOwnershipQualifier::Unqualified);
- extract->replaceAllUsesWith(loadArg);
- pass.markDeadInst(extract);
- }
+ if (!pass.valueStorageMap.contains(origCallInst))
+ pass.markDeadInst(origCallInst);
}
//===----------------------------------------------------------------------===//
@@ -553,15 +725,21 @@
void rewriteFunction() {
for (auto &valueStorageI : pass.valueStorageMap) {
+ SILValue valueDef = valueStorageI.first;
valueStorage = valueStorageI.second;
- DEBUG(llvm::dbgs() << "VALUE "; valueStorageI.first->dump());
+ DEBUG(llvm::dbgs() << "VALUE "; valueDef->dump());
DEBUG(if (valueStorage.storageAddress) {
- llvm::dbgs() << "STORAGE ";
+ llvm::dbgs() << " STORAGE ";
valueStorage.storageAddress->dump();
});
- for (Operand *currOper : valueStorageI.first->getUses()) {
+ SmallVector<Operand*, 8> uses(valueDef->getUses());
+ for (Operand *oper : uses) {
+ currOper = oper;
visit(currOper->getUser());
}
+ currOper = nullptr;
+ if (auto *defInst = dyn_cast<SILInstruction>(valueDef))
+ visit(defInst);
}
}
@@ -572,19 +750,24 @@
}
void beforeVisit(ValueBase *V) {
- DEBUG(llvm::dbgs() << "REWRITE "; V->dump());
+ DEBUG(llvm::dbgs() << " REWRITE "; V->dump());
auto *I = cast<SILInstruction>(V);
B.setInsertionPoint(I);
B.setCurrentDebugScope(I->getDebugScope());
}
void visitApplyInst(ApplyInst *applyInst) {
- DEBUG(llvm::dbgs() << "CALL "; applyInst->dump();
- llvm::dbgs() << "OPERAND "; currOper->get()->dump());
- llvm_unreachable("Unhandled call result.");
+ if (currOper) {
+ DEBUG(llvm::dbgs() << " CALL "; applyInst->dump();
+ llvm::dbgs() << " OPERAND "; currOper->get()->dump());
+ llvm_unreachable("Unhandled call result.");
+ }
}
void visitCopyValueInst(CopyValueInst *copyInst) {
+ if (!currOper)
+ return;
+
SILValue srcAddr =
pass.valueStorageMap.getStorage(copyInst->getOperand()).storageAddress;
SILValue destAddr =
@@ -593,40 +776,126 @@
IsInitialization);
}
+ void visitDebugValueInst(DebugValueInst *debugInst) {
+ SILValue addr =
+ pass.valueStorageMap.getStorage((debugInst->getOperand())).storageAddress;
+ B.createDebugValueAddr(debugInst->getLoc(), addr);
+ pass.markDeadInst(debugInst);
+ }
+
void visitDestroyValueInst(DestroyValueInst *destroyInst) {
- SILValue src = destroyInst->getOperand();
+ assert(currOper->get() == destroyInst->getOperand());
+ SILValue src = currOper->get();
SILValue addr = pass.valueStorageMap.getStorage(src).storageAddress;
B.createDestroyAddr(destroyInst->getLoc(), addr);
pass.markDeadInst(destroyInst);
}
+ void visitLoadInst(LoadInst *loadInst) {
+ assert(!currOper);
+ // Bitwise copy the value. Two locations now share ownership. This is
+ // modeled as a take-init.
+ SILValue addr = pass.valueStorageMap.getStorage(loadInst).storageAddress;
+ if (addr != loadInst->getOperand()) {
+ B.createCopyAddr(loadInst->getLoc(), loadInst->getOperand(), addr,
+ IsTake, IsInitialization);
+ }
+ }
+
void visitReturnInst(ReturnInst *returnInst) {
+ assert(currOper->get() == returnInst->getOperand());
+
+ auto insertPt = SILBasicBlock::iterator(returnInst);
+ auto bbStart = returnInst->getParent()->begin();
+ while (insertPt != bbStart) {
+ --insertPt;
+ if (!isa<DeallocStackInst>(*insertPt))
+ break;
+ }
+ B.setInsertionPoint(insertPt);
+
+ // Gather direct function results.
+ unsigned numOrigDirectResults =
+ pass.F->getConventions().getNumDirectSILResults();
+ SmallVector<SILValue, 8> origDirectResultValues;
+ if (numOrigDirectResults == 1)
+ origDirectResultValues.push_back(currOper->get());
+ else {
+ auto *tupleInst = cast<TupleInst>(currOper->get());
+ origDirectResultValues.append(tupleInst->getElements().begin(),
+ tupleInst->getElements().end());
+ assert(origDirectResultValues.size() == numOrigDirectResults);
+ }
+
+ SILFunctionConventions origFnConv(pass.F->getConventions());
SILFunctionConventions loweredFnConv(
pass.F->getLoweredFunctionType(),
SILModuleConventions::getLoweredAddressConventions());
- unsigned resultArgIdx = loweredFnConv.getSILArgIndexOfFirstIndirectResult();
- auto copyResult = [&](SILValue result) {
- SILArgument *resultArg = B.getFunction().getArgument(resultArgIdx);
- SILValue resultAddr =
- pass.valueStorageMap.getStorage(result).storageAddress;
- B.createCopyAddr(returnInst->getLoc(), resultAddr, resultArg, IsTake,
- IsInitialization);
- };
- unsigned numIndirectResults = loweredFnConv.getNumIndirectSILResults();
- if (numIndirectResults == 1) {
- copyResult(returnInst->getOperand());
- } else {
- for (unsigned endIdx = resultArgIdx + numIndirectResults;
- resultArgIdx < endIdx; ++resultArgIdx) {
- auto *tupleInst = cast<TupleInst>(returnInst->getOperand());
- copyResult(tupleInst->getElement(resultArgIdx));
- }
- }
- SILType emptyTy = B.getModule().Types.getLoweredType(
+ // Convert each result.
+ SmallVector<SILValue, 8> newDirectResults;
+ unsigned newResultArgIdx =
+ loweredFnConv.getSILArgIndexOfFirstIndirectResult();
+
+ for_each(
+ pass.F->getLoweredFunctionType()->getResults(),
+ origDirectResultValues,
+ [&](SILResultInfo resultInfo, SILValue origDirectResultVal)
+ {
+ // Assume that all original results are direct in SIL.
+ assert(!origFnConv.isSILIndirect(resultInfo));
+ if (loweredFnConv.isSILIndirect(resultInfo)) {
+ assert(newResultArgIdx < loweredFnConv.getSILArgIndexOfFirstParam());
+ SILArgument *resultArg = B.getFunction().getArgument(newResultArgIdx);
+ if (pass.valueStorageMap.contains(origDirectResultVal)) {
+ // Copy the result from local storage into the result argument.
+ SILValue resultAddr =
+ pass.valueStorageMap.getStorage(origDirectResultVal)
+ .storageAddress;
+
+ B.createCopyAddr(returnInst->getLoc(), resultAddr, resultArg,
+ IsTake, IsInitialization);
+ ++newResultArgIdx;
+ }
+ else {
+ // Sore the result into the result argument.
+ B.createStore(returnInst->getLoc(), origDirectResultVal,
+ resultArg, StoreOwnershipQualifier::Init);
+ llvm_unreachable("untested."); //!!!
+ }
+ } else {
+ // Record the direct result for populating the result tuple.
+ newDirectResults.push_back(origDirectResultVal);
+ }
+ });
+ assert(newDirectResults.size() == loweredFnConv.getNumDirectSILResults());
+ SILValue newReturnVal;
+ if (newDirectResults.empty()) {
+ SILType emptyTy = B.getModule().Types.getLoweredType(
TupleType::getEmpty(B.getModule().getASTContext()));
- auto *tupleInst = B.createTuple(returnInst->getLoc(), emptyTy, {});
- returnInst->setOperand(tupleInst);
+ newReturnVal = B.createTuple(returnInst->getLoc(), emptyTy, {});
+ } else if (newDirectResults.size() == 1) {
+ newReturnVal = newDirectResults[0];
+ } else {
+ newReturnVal = B.createTuple(returnInst->getLoc(),
+ loweredFnConv.getSILResultType(),
+ newDirectResults);
+ }
+ returnInst->setOperand(newReturnVal);
+ }
+
+ void visitStoreInst(StoreInst *storeInst) {
+ assert(currOper->get() == storeInst->getSrc());
+ SILValue srcAddr =
+ pass.valueStorageMap.getStorage(currOper->get()).storageAddress;
+ assert(storeInst->getOwnershipQualifier() ==
+ StoreOwnershipQualifier::Unqualified);
+
+ // Bitwise copy the value. Two locations now share ownership. This is
+ // modeled as a take-init.
+ B.createCopyAddr(storeInst->getLoc(), srcAddr, storeInst->getDest(),
+ IsTake, IsInitialization);
+ pass.markDeadInst(storeInst);
}
void visitTupleInst(TupleInst *tupleInst) {
@@ -635,15 +904,16 @@
}
void visitTupleExtractInst(TupleExtractInst *extractInst) {
- // Tuple element instructions don't require rewrite. They are dead.
- llvm_unreachable("Untested.");
- return;
+ // TupleExtract merely names a storage location. It doesn't need to be
+ // rewritten.
+ assert(extractInst->use_empty()
+ || pass.valueStorageMap.getStorage(extractInst).storageAddress);
}
};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
-// AddressLowering: Top Level Function Transform.
+// AddressLowering: Top-Level Function Transform.
//===----------------------------------------------------------------------===//
namespace {
@@ -658,14 +928,14 @@
} // end anonymous namespace
void AddressLowering::runOnFunction(SILFunction *F) {
- DEBUG(llvm::dbgs() << "LOWER "; F->dump());
-
AddressLoweringState pass(F);
// Rewrite function args and insert alloc_stack/dealloc_stack.
OpaqueStorageAllocation allocator(pass);
allocator.allocateOpaqueStorage();
+ DEBUG(llvm::dbgs() << "\nREWRITING: " << F->getName(); F->dump());
+
// Rewrite instructions with address-only operands or results.
AddressOnlyRewriter(pass).rewriteFunction();
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 794592e..3d8f05c 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -145,7 +145,7 @@
// by apply instructions.
bool needsReleases = false;
CanSILFunctionType PAITy =
- dyn_cast<SILFunctionType>(PAI->getCallee()->getType().getSwiftType());
+ PAI->getCallee()->getType().getAs<SILFunctionType>();
// Emit a destroy value for each captured closure argument.
ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
@@ -228,7 +228,7 @@
if (!TmpType.isAddressOnly(PAI->getModule())) {
auto *Load = Builder.createLoad(PAI->getLoc(), Op,
LoadOwnershipQualifier::Unqualified);
- Builder.createReleaseValue(PAI->getLoc(), Load, Atomicity::Atomic);
+ Builder.createReleaseValue(PAI->getLoc(), Load, Builder.getDefaultAtomicity());
} else {
Builder.createDestroyAddr(PAI->getLoc(), Op);
}
@@ -320,20 +320,20 @@
for (auto Arg : ToBeReleasedArgs) {
Builder.emitDestroyValueOperation(PAI->getLoc(), Arg);
}
- Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic);
+ Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
Builder.setInsertionPoint(TAI->getErrorBB()->begin());
// Release the non-consumed parameters.
for (auto Arg : ToBeReleasedArgs) {
Builder.emitDestroyValueOperation(PAI->getLoc(), Arg);
}
- Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic);
+ Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
Builder.setInsertionPoint(AI.getInstruction());
} else {
// Release the non-consumed parameters.
for (auto Arg : ToBeReleasedArgs) {
Builder.emitDestroyValueOperation(PAI->getLoc(), Arg);
}
- Builder.createStrongRelease(AI.getLoc(), PAI, Atomicity::Atomic);
+ Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
}
SilCombiner->replaceInstUsesWith(*AI.getInstruction(), NAI.getInstruction());
@@ -519,7 +519,7 @@
Builder.createDestroyAddr(FAS.getLoc(), Arg);
break;
case ParameterConvention::Direct_Owned:
- Builder.createReleaseValue(FAS.getLoc(), Arg, Atomicity::Atomic);
+ Builder.createReleaseValue(FAS.getLoc(), Arg, Builder.getDefaultAtomicity());
break;
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_Inout:
@@ -961,7 +961,7 @@
// In we find arguments that are not the 'self' argument and if
// they are of the Self type then we abort the optimization.
for (auto Arg : AI.getArgumentsWithoutSelf()) {
- if (Arg->getType().getSwiftType().getLValueOrInOutObjectType() ==
+ if (Arg->getType().getSwiftRValueType() ==
AI.getArguments().back()->getType().getSwiftRValueType())
return nullptr;
}
@@ -1044,7 +1044,7 @@
// Emit a retain for the @owned return.
SILBuilderWithScope Builder(Call);
- Builder.createRetainValue(Call->getLoc(), OnX, Atomicity::Atomic);
+ Builder.createRetainValue(Call->getLoc(), OnX, Builder.getDefaultAtomicity());
// Emit a release for the @owned parameter, or none for a @guaranteed
// parameter.
@@ -1056,7 +1056,7 @@
ParamInfo == ParameterConvention::Direct_Guaranteed);
if (ParamInfo == ParameterConvention::Direct_Owned)
- Builder.createReleaseValue(Call->getLoc(), OnX, Atomicity::Atomic);
+ Builder.createReleaseValue(Call->getLoc(), OnX, Builder.getDefaultAtomicity());
}
/// Replace an application of a cast composition f_inverse(f(x)) by x.
@@ -1097,14 +1097,16 @@
// X might not be strong_retain/release'able. Replace it by a
// retain/release_value on X instead.
if (isa<StrongRetainInst>(User)) {
- SILBuilderWithScope(User).createRetainValue(User->getLoc(), X,
- Atomicity::Atomic);
+ SILBuilderWithScope Builder(User);
+ Builder.createRetainValue(User->getLoc(), X,
+ cast<StrongRetainInst>(User)->getAtomicity());
eraseInstFromFunction(*User);
continue;
}
if (isa<StrongReleaseInst>(User)) {
- SILBuilderWithScope(User).createReleaseValue(User->getLoc(), X,
- Atomicity::Atomic);
+ SILBuilderWithScope Builder(User);
+ Builder.createReleaseValue(User->getLoc(), X,
+ cast<StrongReleaseInst>(User)->getAtomicity());
eraseInstFromFunction(*User);
continue;
}
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
index c72cbb7..5949dfd 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
@@ -35,7 +35,7 @@
if (auto *URCI = dyn_cast<UncheckedRefCastInst>(RRPI->getOperand())) {
// (ref_to_raw_pointer (unchecked_ref_cast x))
// -> (ref_to_raw_pointer x)
- if (URCI->getOperand()->getType().getSwiftType()
+ if (URCI->getOperand()->getType().getSwiftRValueType()
->isAnyClassReferenceType()) {
RRPI->setOperand(URCI->getOperand());
return URCI->use_empty() ? eraseInstFromFunction(*URCI) : nullptr;
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
index bb59509..b8b7dfe 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
@@ -86,7 +86,7 @@
// is going away so we need to release the stored value now.
Builder.setInsertionPoint(SingleStore);
Builder.createReleaseValue(AEBI->getLoc(), SingleStore->getSrc(),
- Atomicity::Atomic);
+ SingleRelease->getAtomicity());
// Erase the instruction that stores into the box and the release that
// releases the box, and finally, release the box.
@@ -494,19 +494,19 @@
// reduced to a retain_value on the payload.
if (EI->hasOperand()) {
return Builder.createReleaseValue(RVI->getLoc(), EI->getOperand(),
- Atomicity::Atomic);
+ RVI->getAtomicity());
}
}
// ReleaseValueInst of an unowned type is an unowned_release.
if (OperandTy.is<UnownedStorageType>())
return Builder.createUnownedRelease(RVI->getLoc(), Operand,
- Atomicity::Atomic);
+ RVI->getAtomicity());
// ReleaseValueInst of a reference type is a strong_release.
if (OperandTy.isReferenceCounted(RVI->getModule()))
return Builder.createStrongRelease(RVI->getLoc(), Operand,
- Atomicity::Atomic);
+ RVI->getAtomicity());
// ReleaseValueInst of a trivial type is a no-op.
if (OperandTy.isTrivial(RVI->getModule()))
@@ -532,19 +532,19 @@
// reduced to a retain_value on the payload.
if (EI->hasOperand()) {
return Builder.createRetainValue(RVI->getLoc(), EI->getOperand(),
- Atomicity::Atomic);
+ RVI->getAtomicity());
}
}
// RetainValueInst of an unowned type is an unowned_retain.
if (OperandTy.is<UnownedStorageType>())
return Builder.createUnownedRetain(RVI->getLoc(), Operand,
- Atomicity::Atomic);
+ RVI->getAtomicity());
// RetainValueInst of a reference type is a strong_release.
if (OperandTy.isReferenceCounted(RVI->getModule())) {
return Builder.createStrongRetain(RVI->getLoc(), Operand,
- Atomicity::Atomic);
+ RVI->getAtomicity());
}
// RetainValueInst of a trivial type is a no-op + use propagation.
diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
index 572b588..92c338d 100644
--- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
@@ -558,9 +558,9 @@
// can simply ask SSAUpdater for the reaching store.
SILValue RelVal = SSAUp.GetValueAtEndOfBlock(RelPoint->getParent());
if (StVal->getType().isReferenceCounted(RelPoint->getModule()))
- B.createStrongRelease(Loc, RelVal, Atomicity::Atomic);
+ B.createStrongRelease(Loc, RelVal, B.getDefaultAtomicity());
else
- B.createReleaseValue(Loc, RelVal, Atomicity::Atomic);
+ B.createReleaseValue(Loc, RelVal, B.getDefaultAtomicity());
}
}
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index 05586c1..ce6a1d1 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -760,19 +760,19 @@
Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call)));
Builder.createReleaseValue(RegularLocation(SourceLoc()),
F->getArguments()[AD.Index],
- Atomicity::Atomic);
+ Builder.getDefaultAtomicity());
} else {
SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB();
Builder.setInsertionPoint(&*NormalBB->begin());
Builder.createReleaseValue(RegularLocation(SourceLoc()),
F->getArguments()[AD.Index],
- Atomicity::Atomic);
+ Builder.getDefaultAtomicity());
SILBasicBlock *ErrorBB = dyn_cast<TryApplyInst>(Call)->getErrorBB();
Builder.setInsertionPoint(&*ErrorBB->begin());
Builder.createReleaseValue(RegularLocation(SourceLoc()),
F->getArguments()[AD.Index],
- Atomicity::Atomic);
+ Builder.getDefaultAtomicity());
}
}
@@ -790,12 +790,12 @@
if (isa<ApplyInst>(Call)) {
Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call)));
Builder.createRetainValue(RegularLocation(SourceLoc()), Call,
- Atomicity::Atomic);
+ Builder.getDefaultAtomicity());
} else {
SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB();
Builder.setInsertionPoint(&*NormalBB->begin());
Builder.createRetainValue(RegularLocation(SourceLoc()),
- NormalBB->getArgument(0), Atomicity::Atomic);
+ NormalBB->getArgument(0), Builder.getDefaultAtomicity());
}
}
diff --git a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
index dbd8b80..0ec3d33 100644
--- a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
+++ b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
@@ -67,6 +67,7 @@
bool visitUnmanagedRetainValueInst(UnmanagedRetainValueInst *URVI);
bool visitUnmanagedReleaseValueInst(UnmanagedReleaseValueInst *URVI);
bool visitUnmanagedAutoreleaseValueInst(UnmanagedAutoreleaseValueInst *UAVI);
+ bool visitCheckedCastBranchInst(CheckedCastBranchInst *CBI);
};
} // end anonymous namespace
@@ -144,7 +145,7 @@
bool OwnershipModelEliminatorVisitor::visitCopyUnownedValueInst(
CopyUnownedValueInst *CVI) {
B.createStrongRetainUnowned(CVI->getLoc(), CVI->getOperand(),
- Atomicity::Atomic);
+ B.getDefaultAtomicity());
// Users of copy_value_unowned expect an owned value. So we need to convert
// our unowned value to a ref.
auto *UTRI =
@@ -178,7 +179,7 @@
// Now that we have set the unqualified ownership flag, destroy value
// operation will delegate to the appropriate strong_release, etc.
B.createAutoreleaseValue(UAVI->getLoc(), UAVI->getOperand(),
- Atomicity::Atomic);
+ UAVI->getAtomicity());
UAVI->eraseFromParent();
return true;
}
@@ -195,6 +196,24 @@
return true;
}
+bool OwnershipModelEliminatorVisitor::visitCheckedCastBranchInst(
+ CheckedCastBranchInst *CBI) {
+ // In ownership qualified SIL, checked_cast_br must pass its argument to the
+ // fail case so we can clean it up. In non-ownership qualified SIL, we expect
+ // no argument from the checked_cast_br in the default case. The way that we
+ // handle this transformation is that:
+ //
+ // 1. We replace all uses of the argument to the false block with a use of the
+ // checked cast branch's operand.
+ // 2. We delete the argument from the false block.
+ SILBasicBlock *FailureBlock = CBI->getFailureBB();
+ if (FailureBlock->getNumArguments() == 0)
+ return false;
+ FailureBlock->getArgument(0)->replaceAllUsesWith(CBI->getOperand());
+ FailureBlock->eraseArgument(0);
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// Top Level Entry Point
//===----------------------------------------------------------------------===//
@@ -224,9 +243,8 @@
}
if (MadeChange) {
- // If we made any changes, we just changed instructions, so invalidate
- // that analysis.
- invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
+ invalidateAnalysis(
+ SILAnalysis::InvalidationKind::BranchesAndInstructions);
}
}
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index ebd9d0c..fb14a28 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -547,6 +547,10 @@
(ModuleName == STDLIB_NAME || ModuleName == SWIFT_ONONE_SUPPORT))
return false;
+ // Do not inline into thunks.
+ if (AI.getFunction()->isThunk())
+ return false;
+
// Always inline generic functions which are marked as
// AlwaysInline or transparent.
if (Callee->getInlineStrategy() == AlwaysInline || Callee->isTransparent())
diff --git a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp
index ece72e4..797002c 100644
--- a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp
@@ -161,7 +161,8 @@
// Do what a release would do before calling the deallocator: set the object
// in deallocating state, which means set the RC_DEALLOCATING_FLAG flag.
- B.createSetDeallocating(ReleaseInst->getLoc(), object, Atomicity::Atomic);
+ B.createSetDeallocating(ReleaseInst->getLoc(), object,
+ cast<RefCountingInst>(ReleaseInst)->getAtomicity());
// Create the call to the destructor with the allocated object as self
// argument.
diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
index d1c8b95..41f663d 100644
--- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
+++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
@@ -73,17 +73,19 @@
++NumRefCountOpsSimplified;
+ auto *RCI = cast<RefCountingInst>(I);
+
// If we have a retain value...
if (isa<RetainValueInst>(I)) {
// And our payload is refcounted, insert a strong_retain onto the
// payload.
if (UEDITy.isReferenceCounted(Mod)) {
- Builder.createStrongRetain(I->getLoc(), UEDI, Atomicity::Atomic);
+ Builder.createStrongRetain(I->getLoc(), UEDI, RCI->getAtomicity());
return;
}
// Otherwise, insert a retain_value on the payload.
- Builder.createRetainValue(I->getLoc(), UEDI, Atomicity::Atomic);
+ Builder.createRetainValue(I->getLoc(), UEDI, RCI->getAtomicity());
return;
}
@@ -94,13 +96,13 @@
// If our payload has reference semantics, insert the strong release.
if (UEDITy.isReferenceCounted(Mod)) {
- Builder.createStrongRelease(I->getLoc(), UEDI, Atomicity::Atomic);
+ Builder.createStrongRelease(I->getLoc(), UEDI, RCI->getAtomicity());
return;
}
// Otherwise if our payload is non-trivial but lacking reference semantics,
// insert the release_value.
- Builder.createReleaseValue(I->getLoc(), UEDI, Atomicity::Atomic);
+ Builder.createReleaseValue(I->getLoc(), UEDI, RCI->getAtomicity());
}
//===----------------------------------------------------------------------===//
@@ -1545,9 +1547,9 @@
//
// TODO: Which debug loc should we use here? Using one of the locs from the
// delete list seems reasonable for now...
- SILBuilder(getBB()->begin()).createRetainValue(DeleteList[0]->getLoc(),
- EnumValue,
- Atomicity::Atomic);
+ SILBuilder Builder(getBB()->begin());
+ Builder.createRetainValue(DeleteList[0]->getLoc(), EnumValue,
+ cast<RefCountingInst>(DeleteList[0])->getAtomicity());
for (auto *I : DeleteList)
I->eraseFromParent();
++NumSunk;
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index 57e7554..28d247e 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -1875,23 +1875,6 @@
if (!TargetFnTy || !TargetFnTy->hasErrorResult())
return false;
- // Check if the converted function type has the same number of arguments.
- // Currently this is always the case, but who knows what convert_function can
- // do in the future?
- unsigned numParams = OrigFnTy->getParameters().size();
- if (TargetFnTy->getParameters().size() != numParams)
- return false;
-
- // Check that the argument types are matching.
- SILModuleConventions silConv(TAI->getModule());
- for (unsigned Idx = 0; Idx < numParams; Idx++) {
- if (!canCastValueToABICompatibleType(
- TAI->getModule(),
- silConv.getSILType(OrigFnTy->getParameters()[Idx]),
- silConv.getSILType(TargetFnTy->getParameters()[Idx])))
- return false;
- }
-
// Look through the conversions and find the real callee.
Callee = getActualCallee(CFI->getConverted());
CalleeType = Callee->getType();
@@ -1936,12 +1919,6 @@
auto ResultTy = calleeConv.getSILResultType();
auto OrigResultTy = TAI->getNormalBB()->getArgument(0)->getType();
- // Bail if the cast between the actual and expected return types cannot
- // be handled.
- if (!canCastValueToABICompatibleType(TAI->getModule(),
- ResultTy, OrigResultTy))
- return false;
-
SILBuilderWithScope Builder(TAI);
auto TargetFnTy = CalleeFnTy;
@@ -1959,28 +1936,14 @@
}
SILFunctionConventions origConv(OrigFnTy, TAI->getModule());
- unsigned numArgs = TAI->getNumArguments();
-
- // First check if it is possible to convert all arguments.
- // Currently we believe that castValueToABICompatibleType can handle all
- // cases, so this check should never fail. We just do it to be absolutely
- // sure that we don't crash.
- for (unsigned i = 0; i < numArgs; ++i) {
- if (!canCastValueToABICompatibleType(TAI->getModule(),
- origConv.getSILArgumentType(i),
- targetConv.getSILArgumentType(i))) {
- return false;
- }
- }
-
SmallVector<SILValue, 8> Args;
+ unsigned numArgs = TAI->getNumArguments();
for (unsigned i = 0; i < numArgs; ++i) {
auto Arg = TAI->getArgument(i);
// Cast argument if required.
Arg = castValueToABICompatibleType(&Builder, TAI->getLoc(), Arg,
origConv.getSILArgumentType(i),
- targetConv.getSILArgumentType(i))
- .getValue();
+ targetConv.getSILArgumentType(i));
Args.push_back(Arg);
}
@@ -1998,8 +1961,7 @@
auto *NormalBB = TAI->getNormalBB();
auto CastedResult = castValueToABICompatibleType(&Builder, Loc, NewAI,
- ResultTy, OrigResultTy)
- .getValue();
+ ResultTy, OrigResultTy);
Builder.createBranch(Loc, NormalBB, { CastedResult });
TAI->eraseFromParent();
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 604969f..cf0eea1 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -143,9 +143,9 @@
(next == Continue->end()) ? nullptr : dyn_cast<StrongReleaseInst>(next);
if (Release && Release->getOperand() == CMI->getOperand()) {
VirtBuilder.createStrongRelease(Release->getLoc(), CMI->getOperand(),
- Atomicity::Atomic);
+ Release->getAtomicity());
IdenBuilder.createStrongRelease(Release->getLoc(), DownCastedClassInstance,
- Atomicity::Atomic);
+ Release->getAtomicity());
Release->eraseFromParent();
}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 4fa1094..318d777 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -546,31 +546,6 @@
return false;
}
- // Type of the actual function to be called.
- CanSILFunctionType GenCalleeType = F->getLoweredFunctionType();
-
- // Type of the actual function to be called with substitutions applied.
- CanSILFunctionType SubstCalleeType = GenCalleeType;
-
- // For polymorphic functions, bail if the number of substitutions is
- // not the same as the number of expected generic parameters.
- if (GenCalleeType->isPolymorphic()) {
- // First, find proper list of substitutions for the concrete
- // method to be called.
- SmallVector<Substitution, 4> Subs;
- getSubstitutionsForCallee(Mod, GenCalleeType,
- ClassOrMetatypeType.getSwiftRValueType(),
- AI, Subs);
- SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Subs);
- }
-
- // Check if the optimizer knows how to cast the return type.
- SILType ReturnType =
- SILFunctionConventions(SubstCalleeType, Mod).getSILResultType();
-
- if (!canCastValueToABICompatibleType(Mod, ReturnType, AI.getType()))
- return false;
-
return true;
}
@@ -612,8 +587,7 @@
for (auto ResultTy : substConv.getIndirectSILResultTypes()) {
NewArgs.push_back(
castValueToABICompatibleType(&B, AI.getLoc(), *IndirectResultArgIter,
- IndirectResultArgIter->getType(), ResultTy)
- .getValue());
+ IndirectResultArgIter->getType(), ResultTy));
++IndirectResultArgIter;
}
@@ -623,8 +597,7 @@
auto paramType = substConv.getSILType(param);
NewArgs.push_back(
castValueToABICompatibleType(&B, AI.getLoc(), *ParamArgIter,
- ParamArgIter->getType(), paramType)
- .getValue());
+ ParamArgIter->getType(), paramType));
++ParamArgIter;
}
@@ -634,7 +607,7 @@
NewArgs.push_back(castValueToABICompatibleType(&B, AI.getLoc(),
ClassOrMetatype,
ClassOrMetatypeType,
- SelfParamTy).getValue());
+ SelfParamTy));
SILType ResultTy = substConv.getSILResultType();
@@ -707,7 +680,7 @@
// Check if any casting is required for the return value.
ResultValue = castValueToABICompatibleType(&B, NewAI.getLoc(), ResultValue,
- ResultTy, AI.getType()).getValue();
+ ResultTy, AI.getType());
DEBUG(llvm::dbgs() << " SUCCESS: " << F->getName() << "\n");
NumClassDevirt++;
@@ -871,75 +844,6 @@
origSubs, isDefaultWitness, NewSubs);
}
-/// Check if an upcast is legal.
-/// The logic in this function is heavily based on the checks in
-/// the SILVerifier.
-bool swift::isLegalUpcast(SILType FromTy, SILType ToTy) {
- if (ToTy.is<MetatypeType>()) {
- CanType InstTy(ToTy.castTo<MetatypeType>()->getInstanceType());
- if (!FromTy.is<MetatypeType>())
- return false;
- CanType OpInstTy(FromTy.castTo<MetatypeType>()->getInstanceType());
- auto InstClass = InstTy->getClassOrBoundGenericClass();
- if (!InstClass)
- return false;
-
- bool CanBeUpcasted =
- InstClass->usesObjCGenericsModel()
- ? InstClass->getDeclaredTypeInContext()->isBindableToSuperclassOf(
- OpInstTy, nullptr)
- : InstTy->isExactSuperclassOf(OpInstTy, nullptr);
-
- return CanBeUpcasted;
- }
-
- // Upcast from Optional<B> to Optional<A> is legal as long as B is a
- // subclass of A.
- if (ToTy.getSwiftRValueType().getAnyOptionalObjectType() &&
- FromTy.getSwiftRValueType().getAnyOptionalObjectType()) {
- ToTy = SILType::getPrimitiveObjectType(
- ToTy.getSwiftRValueType().getAnyOptionalObjectType());
- FromTy = SILType::getPrimitiveObjectType(
- FromTy.getSwiftRValueType().getAnyOptionalObjectType());
- }
-
- auto ToClass = ToTy.getClassOrBoundGenericClass();
- if (!ToClass)
- return false;
- bool CanBeUpcasted =
- ToClass->usesObjCGenericsModel()
- ? ToClass->getDeclaredTypeInContext()->isBindableToSuperclassOf(
- FromTy.getSwiftRValueType(), nullptr)
- : ToTy.isExactSuperclassOf(FromTy);
-
- return CanBeUpcasted;
-}
-
-/// Check if we can pass/convert all arguments of the original apply
-/// as required by the found devirtualized method.
-/// FIXME: This method was introduced as a workaround. We need to
-/// revisit it and check if it is still needed.
-static bool
-canPassOrConvertAllArguments(ApplySite AI,
- CanSILFunctionType SubstCalleeCanType) {
- SILFunctionConventions substConv(SubstCalleeCanType, AI.getModule());
- unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
- for (auto arg : AI.getArguments()) {
- // Check if we can cast the provided argument into the required
- // parameter type.
- auto FromTy = arg->getType();
- auto ToTy = substConv.getSILArgumentType(substArgIdx++);
- // If types are the same, no conversion will be required.
- if (FromTy == ToTy)
- continue;
- // Otherwise, it should be possible to upcast the arguments.
- if (!isLegalUpcast(FromTy, ToTy))
- return false;
- }
- assert(substArgIdx == substConv.getNumSILArguments());
- return true;
-}
-
/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
@@ -963,11 +867,6 @@
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
- // Bail if some of the arguments cannot be converted into
- // types required by the found devirtualized method.
- if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
- return ApplySite();
-
// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
@@ -979,7 +878,8 @@
for (auto arg : AI.getArguments()) {
auto paramType = substConv.getSILArgumentType(substArgIdx++);
if (arg->getType() != paramType)
- arg = B.createUpcast(AI.getLoc(), arg, paramType);
+ arg = castValueToABICompatibleType(&B, AI.getLoc(), arg,
+ arg->getType(), paramType);
Arguments.push_back(arg);
}
assert(substArgIdx == substConv.getNumSILArguments());
@@ -1030,26 +930,6 @@
return false;
}
- // Collect all the required substitutions.
- //
- // The complete set of substitutions may be different, e.g. because the found
- // witness thunk F may have been created by a specialization pass and have
- // additional generic parameters.
- SmallVector<Substitution, 4> NewSubs;
-
- getWitnessMethodSubstitutions(AI, F, WMI->getConformance(), NewSubs);
-
- // Figure out the exact bound type of the function to be called by
- // applying all substitutions.
- auto &Module = AI.getModule();
- auto CalleeCanType = F->getLoweredFunctionType();
- auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
-
- // Bail if some of the arguments cannot be converted into
- // types required by the found devirtualized method.
- if (!canPassOrConvertAllArguments(AI, SubstCalleeCanType))
- return false;
-
return true;
}
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index 7100496..2adfd48 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -52,7 +52,8 @@
// Initialize SpecializedType iff the specialization is allowed.
ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *OrigF,
SubstitutionList ParamSubs) {
- if (!OrigF->shouldOptimize()) {
+ if (!OrigF->shouldOptimize() ||
+ OrigF->hasSemanticsAttr("optimize.sil.specialize.generic.never")) {
DEBUG(llvm::dbgs() << " Cannot specialize function " << OrigF->getName()
<< " marked to be excluded from optimizations.\n");
return;
@@ -97,9 +98,8 @@
}
SILModule &M = OrigF->getModule();
- SubstitutedType = SILType::substFuncType(M, InterfaceSubs,
- OrigF->getLoweredFunctionType(),
- /*dropGenerics = */ true);
+ SubstitutedType = OrigF->getLoweredFunctionType()->substGenericArgs(
+ M, InterfaceSubs);
NumFormalIndirectResults = SubstitutedType->getNumIndirectFormalResults();
Conversions.resize(NumFormalIndirectResults
@@ -213,9 +213,7 @@
auto OrigFnTy = OrigF->getLoweredFunctionType();
// First substitute concrete types into the existing function type.
- auto FnTy = OrigFnTy->substGenericArgs(
- M, QuerySubstitutionMap{SubstMap},
- LookUpConformanceInSubstitutionMap(SubstMap));
+ auto FnTy = OrigFnTy->substGenericArgs(M, SubstMap);
if ((SpecializedGenericSig &&
SpecializedGenericSig->areAllParamsConcrete()) ||
@@ -294,7 +292,8 @@
// First, add the old generic signature.
Builder.addGenericSignature(OrigGenSig);
- auto Source = RequirementSource::forAbstract(Builder);
+ auto Source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
// For each substitution with a concrete type as a replacement,
// add a new concrete type equality requirement.
for (auto &Req : Requirements) {
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 8fe8ec5..750ea7f 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -44,10 +44,10 @@
// If Ptr is refcounted itself, create the strong_retain and
// return.
if (Ptr->getType().isReferenceCounted(B.getModule()))
- return B.createStrongRetain(Loc, Ptr, Atomicity::Atomic);
+ return B.createStrongRetain(Loc, Ptr, B.getDefaultAtomicity());
// Otherwise, create the retain_value.
- return B.createRetainValue(Loc, Ptr, Atomicity::Atomic);
+ return B.createRetainValue(Loc, Ptr, B.getDefaultAtomicity());
}
/// Creates a decrement on \p Ptr before insertion point \p InsertPt that
@@ -61,10 +61,10 @@
// If Ptr has reference semantics itself, create a strong_release.
if (Ptr->getType().isReferenceCounted(B.getModule()))
- return B.createStrongRelease(Loc, Ptr, Atomicity::Atomic);
+ return B.createStrongRelease(Loc, Ptr, B.getDefaultAtomicity());
// Otherwise create a release value.
- return B.createReleaseValue(Loc, Ptr, Atomicity::Atomic);
+ return B.createReleaseValue(Loc, Ptr, B.getDefaultAtomicity());
}
/// \brief Perform a fast local check to see if the instruction is dead.
@@ -475,80 +475,63 @@
///
/// NOTE: The implementation of this function is very closely related to the
/// rules checked by SILVerifier::requireABICompatibleFunctionTypes.
-Optional<SILValue> swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
+SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc,
SILValue Value,
- SILType SrcTy, SILType DestTy,
- bool CheckOnly) {
+ SILType SrcTy, SILType DestTy) {
// No cast is required if types are the same.
if (SrcTy == DestTy)
return Value;
- SILValue CastedValue;
+ assert(SrcTy.isAddress() == DestTy.isAddress() &&
+ "Addresses aren't compatible with values");
if (SrcTy.isAddress() && DestTy.isAddress()) {
// Cast between two addresses and that's it.
- if (CheckOnly)
- return Value;
- CastedValue = B->createUncheckedAddrCast(Loc, Value, DestTy);
- return CastedValue;
+ return B->createUncheckedAddrCast(Loc, Value, DestTy);
}
- if (SrcTy.isAddress() != DestTy.isAddress()) {
- // Addresses aren't compatible with values.
- if (CheckOnly)
- return None;
- llvm_unreachable("Addresses aren't compatible with values");
- return SILValue();
- }
-
- auto &M = B->getModule();
-
- // Check if src and dest types are optional.
- auto OptionalSrcTy = SrcTy.getSwiftRValueType()
- .getAnyOptionalObjectType();
- auto OptionalDestTy = DestTy.getSwiftRValueType()
- .getAnyOptionalObjectType();
-
// If both types are classes and dest is the superclass of src,
// simply perform an upcast.
- if (SrcTy.getSwiftRValueType()->mayHaveSuperclass() &&
- DestTy.getSwiftRValueType()->mayHaveSuperclass() &&
- DestTy.isExactSuperclassOf(SrcTy)) {
- if (CheckOnly)
- return Value;
- CastedValue = B->createUpcast(Loc, Value, DestTy);
- return CastedValue;
+ if (DestTy.isExactSuperclassOf(SrcTy)) {
+ return B->createUpcast(Loc, Value, DestTy);
}
- SILType OptionalSrcLoweredTy;
- SILType OptionalDestLoweredTy;
+ if (SrcTy.isHeapObjectReferenceType() &&
+ DestTy.isHeapObjectReferenceType()) {
+ return B->createUncheckedRefCast(Loc, Value, DestTy);
+ }
- if (OptionalSrcTy)
- OptionalSrcLoweredTy = M.Types.getLoweredType(OptionalSrcTy);
+ if (auto mt1 = dyn_cast<AnyMetatypeType>(SrcTy.getSwiftRValueType())) {
+ if (auto mt2 = dyn_cast<AnyMetatypeType>(DestTy.getSwiftRValueType())) {
+ if (mt1->getRepresentation() == mt2->getRepresentation()) {
+ // If B.Type needs to be casted to A.Type and
+ // A is a superclass of B, then it can be done by means
+ // of a simple upcast.
+ if (mt2.getInstanceType()->isExactSuperclassOf(
+ mt1.getInstanceType(), nullptr)) {
+ return B->createUpcast(Loc, Value, DestTy);
+ }
+
+ // Cast between two metatypes and that's it.
+ return B->createUncheckedBitCast(Loc, Value, DestTy);
+ }
+ }
+ }
- if (OptionalDestTy)
- OptionalDestLoweredTy = M.Types.getLoweredType(OptionalDestTy);
+ // Check if src and dest types are optional.
+ auto OptionalSrcTy = SrcTy.getAnyOptionalObjectType();
+ auto OptionalDestTy = DestTy.getAnyOptionalObjectType();
// Both types are optional.
if (OptionalDestTy && OptionalSrcTy) {
// If both wrapped types are classes and dest is the superclass of src,
// simply perform an upcast.
- if (OptionalDestTy->mayHaveSuperclass() &&
- OptionalSrcTy->mayHaveSuperclass() &&
- OptionalDestLoweredTy.isExactSuperclassOf(OptionalSrcLoweredTy)) {
+ if (OptionalDestTy.isExactSuperclassOf(OptionalSrcTy)) {
// Insert upcast.
- if (CheckOnly)
- return Value;
- CastedValue = B->createUpcast(Loc, Value, DestTy);
- return CastedValue;
+ return B->createUpcast(Loc, Value, DestTy);
}
- if (CheckOnly)
- return castValueToABICompatibleType(B, Loc, Value,
- OptionalSrcLoweredTy,
- OptionalDestLoweredTy, CheckOnly);
-
// Unwrap the original optional value.
auto *SomeDecl = B->getASTContext().getOptionalSomeDecl();
auto *NoneBB = B->getFunction().createBasicBlock();
@@ -570,10 +553,10 @@
// Cast the unwrapped value.
auto CastedUnwrappedValue =
castValueToABICompatibleType(B, Loc, UnwrappedValue,
- OptionalSrcLoweredTy,
- OptionalDestLoweredTy).getValue();
+ OptionalSrcTy,
+ OptionalDestTy);
// Wrap into optional.
- CastedValue = B->createOptionalSome(Loc, CastedUnwrappedValue, DestTy);
+ auto CastedValue = B->createOptionalSome(Loc, CastedUnwrappedValue, DestTy);
B->createBranch(Loc, ContBB, {CastedValue});
// Handle the None case.
@@ -582,19 +565,15 @@
B->createBranch(Loc, ContBB, {CastedValue});
B->setInsertionPoint(ContBB->begin());
- CastedValue = ContBB->getArgument(0);
- return CastedValue;
+ return ContBB->getArgument(0);
}
// Src is not optional, but dest is optional.
if (!OptionalSrcTy && OptionalDestTy) {
- auto OptionalSrcCanTy =
- OptionalType::get(SrcTy.getSwiftRValueType())->getCanonicalType();
- auto LoweredOptionalSrcType = M.Types.getLoweredType(OptionalSrcCanTy);
- if (CheckOnly)
- return castValueToABICompatibleType(B, Loc, Value,
- LoweredOptionalSrcType, DestTy,
- CheckOnly);
+ auto OptionalSrcCanTy = OptionalType::get(SrcTy.getSwiftRValueType())
+ ->getCanonicalType();
+ auto LoweredOptionalSrcType = SILType::getPrimitiveObjectType(
+ OptionalSrcCanTy);
// Wrap the source value into an optional first.
SILValue WrappedValue = B->createOptionalSome(Loc, Value,
@@ -605,127 +584,33 @@
DestTy);
}
- // Both types are not optional.
- if (SrcTy.getSwiftRValueType()->mayHaveSuperclass() &&
- DestTy.getSwiftRValueType()->mayHaveSuperclass()) {
- if (CheckOnly)
- return Value;
-
- if (DestTy.isExactSuperclassOf(SrcTy)) {
- // Insert upcast.
- CastedValue = B->createUpcast(Loc, Value, DestTy);
- return CastedValue;
- }
-
- // Cast the reference.
- CastedValue = B->createUncheckedBitCast(Loc, Value, DestTy);
- return CastedValue;
- }
-
- // If B.Type needs to be casted to A.Type and
- // A is a superclass of B, then it can be done by means
- // of a simple upcast.
- if (isa<AnyMetatypeType>(SrcTy.getSwiftRValueType()) &&
- isa<AnyMetatypeType>(DestTy.getSwiftRValueType()) &&
- SrcTy.isClassOrClassMetatype() && DestTy.isClassOrClassMetatype() &&
- DestTy.getMetatypeInstanceType(M).isExactSuperclassOf(
- SrcTy.getMetatypeInstanceType(M))) {
- if (CheckOnly)
- return Value;
- CastedValue = B->createUpcast(Loc, Value, DestTy);
- return CastedValue;
- }
-
- if (auto mt1 = dyn_cast<AnyMetatypeType>(SrcTy.getSwiftRValueType())) {
- if (auto mt2 = dyn_cast<AnyMetatypeType>(DestTy.getSwiftRValueType())) {
- if (mt1->getRepresentation() == mt2->getRepresentation()) {
- // Cast between two metatypes and that's it.
- if (CheckOnly)
- return Value;
- CastedValue = B->createUncheckedBitCast(Loc, Value, DestTy);
- return CastedValue;
- }
- }
- }
-
- if (SrcTy.isAddress() && DestTy.isAddress()) {
- if (CheckOnly)
- return Value;
- CastedValue = B->createUncheckedAddrCast(Loc, Value, DestTy);
- return CastedValue;
- }
-
- if (SrcTy.isHeapObjectReferenceType() && DestTy.isHeapObjectReferenceType()) {
- if (CheckOnly)
- return Value;
- CastedValue = B->createUncheckedRefCast(Loc, Value, DestTy);
- return CastedValue;
- }
-
// Handle tuple types.
// Extract elements, cast each of them, create a new tuple.
- if (auto tup = SrcTy.getAs<TupleType>()) {
- SmallVector<CanType, 1> aElements, bElements;
- auto atypes = tup.getElementTypes();
- aElements.append(atypes.begin(), atypes.end());
- auto btypes = DestTy.getAs<TupleType>().getElementTypes();
- bElements.append(btypes.begin(), btypes.end());
-
- if (CheckOnly && aElements.size() != bElements.size())
- return None;
-
- assert (aElements.size() == bElements.size() &&
- "Tuple types should have the same number of elements");
-
+ if (auto SrcTupleTy = SrcTy.getAs<TupleType>()) {
SmallVector<SILValue, 8> ExpectedTuple;
- for (unsigned i : indices(aElements)) {
- auto aa = M.Types.getLoweredType(aElements[i]),
- bb = M.Types.getLoweredType(bElements[i]);
-
- if (CheckOnly) {
- if (!castValueToABICompatibleType(B, Loc, Value, aa, bb, CheckOnly).hasValue())
- return None;
- continue;
- }
-
+ for (unsigned i = 0, e = SrcTupleTy->getNumElements(); i < e; i++) {
SILValue Element = B->createTupleExtract(Loc, Value, i);
// Cast the value if necessary.
- Element = castValueToABICompatibleType(B, Loc, Element, aa, bb).getValue();
+ Element = castValueToABICompatibleType(B, Loc, Element,
+ SrcTy.getTupleElementType(i),
+ DestTy.getTupleElementType(i));
ExpectedTuple.push_back(Element);
}
- if (CheckOnly)
- return Value;
-
- CastedValue = B->createTuple(Loc, DestTy, ExpectedTuple);
- return CastedValue;
+ return B->createTuple(Loc, DestTy, ExpectedTuple);
}
// Function types are interchangeable if they're also ABI-compatible.
if (SrcTy.getAs<SILFunctionType>()) {
if (DestTy.getAs<SILFunctionType>()) {
- if (CheckOnly)
- return Value;
// Insert convert_function.
- CastedValue = B->createConvertFunction(Loc, Value, DestTy);
- return CastedValue;
+ return B->createConvertFunction(Loc, Value, DestTy);
}
}
- if (CheckOnly)
- return None;
+ llvm::errs() << "Source type: " << SrcTy << "\n";
+ llvm::errs() << "Destination type: " << DestTy << "\n";
llvm_unreachable("Unknown combination of types for casting");
- return SILValue();
-}
-
-bool swift::canCastValueToABICompatibleType(SILModule &M,
- SILType SrcTy, SILType DestTy) {
- SILBuilder B(*M.begin());
- SILLocation Loc = ArtificialUnreachableLocation();
- auto Result = castValueToABICompatibleType(&B, Loc, SILValue(),
- SrcTy, DestTy,
- /* CheckOnly */ true);
- return Result.hasValue();
}
ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *ABI, unsigned Index){
@@ -1070,7 +955,7 @@
SILBuilderWithScope Builder(PAI);
SILLocation Loc = PAI->getLoc();
CanSILFunctionType PAITy =
- dyn_cast<SILFunctionType>(PAI->getCallee()->getType().getSwiftType());
+ PAI->getCallee()->getType().getAs<SILFunctionType>();
// Emit a destroy value for each captured closure argument.
ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
@@ -1502,7 +1387,7 @@
"Parameter should be @owned");
// Emit a retain.
- Builder.createRetainValue(Loc, SrcOp, Atomicity::Atomic);
+ Builder.createRetainValue(Loc, SrcOp, Builder.getDefaultAtomicity());
Args.push_back(InOutOptionalParam);
Args.push_back(SrcOp);
@@ -1515,18 +1400,18 @@
if (auto *UCCAI = dyn_cast<UnconditionalCheckedCastAddrInst>(Inst)) {
assert(UCCAI->getConsumptionKind() == CastConsumptionKind::TakeAlways);
if (UCCAI->getConsumptionKind() == CastConsumptionKind::TakeAlways) {
- Builder.createReleaseValue(Loc, SrcOp, Atomicity::Atomic);
+ Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
}
}
if (auto *CCABI = dyn_cast<CheckedCastAddrBranchInst>(Inst)) {
if (CCABI->getConsumptionKind() == CastConsumptionKind::TakeAlways) {
- Builder.createReleaseValue(Loc, SrcOp, Atomicity::Atomic);
+ Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
} else if (CCABI->getConsumptionKind() ==
CastConsumptionKind::TakeOnSuccess) {
// Insert a release in the success BB.
Builder.setInsertionPoint(SuccessBB->begin());
- Builder.createReleaseValue(Loc, SrcOp, Atomicity::Atomic);
+ Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
}
}
@@ -1748,17 +1633,17 @@
}
if (needRetainBeforeCall)
- Builder.createRetainValue(Loc, Src, Atomicity::Atomic);
+ Builder.createRetainValue(Loc, Src, Builder.getDefaultAtomicity());
// Generate a code to invoke the bridging function.
auto *NewAI = Builder.createApply(Loc, FnRef, SubstFnTy, ResultTy, Subs, Src,
false);
if (needReleaseAfterCall) {
- Builder.createReleaseValue(Loc, Src, Atomicity::Atomic);
+ Builder.createReleaseValue(Loc, Src, Builder.getDefaultAtomicity());
} else if (needReleaseInSucc) {
SILBuilder SuccBuilder(SuccessBB->begin());
- SuccBuilder.createReleaseValue(Loc, Src, Atomicity::Atomic);
+ SuccBuilder.createReleaseValue(Loc, Src, SuccBuilder.getDefaultAtomicity());
}
SILInstruction *NewI = NewAI;
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index 4cea2bd..a01756c 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -337,6 +337,7 @@
case ValueKind::DeallocStackInst:
case ValueKind::DeallocValueBufferInst:
case ValueKind::DeinitExistentialAddrInst:
+ case ValueKind::DeinitExistentialOpaqueInst:
case ValueKind::DestroyAddrInst:
case ValueKind::ProjectValueBufferInst:
case ValueKind::ProjectBoxInst:
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 401e1f9..7d87dfa 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -7,6 +7,7 @@
CSApply.cpp
CSDiag.cpp
CSGen.cpp
+ CSPropagate.cpp
CSRanking.cpp
CSSimplify.cpp
CSSolver.cpp
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index de33fab..4f27b76 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -3495,11 +3495,13 @@
Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
// If we end up here, we should have diagnosed somewhere else
// already.
- if (!SuppressDiagnostics) {
- cs.TC.diagnose(expr->getLoc(), diag::pattern_in_expr,
+ Expr *simplified = simplifyExprType(expr);
+ if (!SuppressDiagnostics
+ && !simplified->getType()->is<UnresolvedType>()) {
+ cs.TC.diagnose(simplified->getLoc(), diag::pattern_in_expr,
expr->getSubPattern()->getKind());
}
- return expr;
+ return simplified;
}
Expr *visitBindOptionalExpr(BindOptionalExpr *expr) {
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 9c00226..1730ae3 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -5752,13 +5752,13 @@
}
};
+ auto dc = env->getOwningDeclContext();
RequirementsListener genericReqListener;
- auto result =
- TC.checkGenericArguments(env->getOwningDeclContext(), argExpr->getLoc(),
- AFD->getLoc(), AFD->getInterfaceType(),
- env->getGenericSignature(), substitutions, nullptr,
- ConformanceCheckFlags::SuppressDependencyTracking,
- &genericReqListener);
+ auto result = TC.checkGenericArguments(
+ dc, argExpr->getLoc(), AFD->getLoc(), AFD->getInterfaceType(),
+ env->getGenericSignature(), QueryTypeSubstitutionMap{substitutions},
+ LookUpConformanceInModule{dc->getParentModule()}, nullptr,
+ ConformanceCheckFlags::SuppressDependencyTracking, &genericReqListener);
return !result.second;
}
@@ -5915,14 +5915,6 @@
if (auto fn = fnType->getAs<AnyFunctionType>()) {
using Closeness = CalleeCandidateInfo::ClosenessResultTy;
- auto isGenericType = [](Type type) -> bool {
- if (type->hasError() || type->hasTypeVariable() ||
- type->hasUnresolvedType())
- return false;
-
- return type->isCanonical() && type->isUnspecializedGeneric();
- };
-
calleeInfo.filterList([&](UncurriedCandidate candidate) -> Closeness {
auto resultType = candidate.getResultType();
if (!resultType)
@@ -5933,8 +5925,7 @@
// because there is no easy way to do that, and candidate set is going
// to be pruned by matching of the argument types later on anyway, so
// it's better to over report than to be too conservative.
- if ((isGenericType(resultType) && isGenericType(fn->getResult())) ||
- resultType->isEqual(fn->getResult()))
+ if (resultType->isEqual(fn->getResult()))
return {CC_ExactMatch, {}};
return {CC_GeneralMismatch, {}};
@@ -6086,9 +6077,13 @@
if (callExpr->isImplicit() && overloadName == "~=") {
// This binop was synthesized when typechecking an expression pattern.
- auto diag = diagnose(lhsExpr->getLoc(),
- diag::cannot_match_expr_pattern_with_value,
- lhsType, rhsType);
+ auto diag = lhsType->is<UnresolvedType>()
+ ? diagnose(lhsExpr->getLoc(),
+ diag::cannot_match_unresolved_expr_pattern_with_value,
+ rhsType)
+ : diagnose(lhsExpr->getLoc(),
+ diag::cannot_match_expr_pattern_with_value,
+ lhsType, rhsType);
diag.highlight(lhsExpr->getSourceRange());
diag.highlight(rhsExpr->getSourceRange());
if (auto optUnwrappedType = rhsType->getOptionalObjectType()) {
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index a90ec12..f84b7dd 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2670,8 +2670,13 @@
Type visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
// If there are UnresolvedPatterns floating around after name binding,
- // they are pattern productions in invalid positions.
- return ErrorType::get(CS.getASTContext());
+ // they are pattern productions in invalid positions. However, we will
+ // diagnose that condition elsewhere; to avoid unnecessary noise errors,
+ // just plop an open type variable here.
+
+ auto locator = CS.getConstraintLocator(expr);
+ auto typeVar = CS.createTypeVariable(locator, TVO_CanBindToLValue);
+ return typeVar;
}
/// Get the type T?
@@ -3056,7 +3061,11 @@
if (result)
this->optimizeConstraints(result);
-
+
+ // If the experimental constraint propagation pass is enabled, run it.
+ if (TC.Context.LangOpts.EnableConstraintPropagation)
+ propagateConstraints();
+
return result;
}
diff --git a/lib/Sema/CSPropagate.cpp b/lib/Sema/CSPropagate.cpp
new file mode 100644
index 0000000..79d0723
--- /dev/null
+++ b/lib/Sema/CSPropagate.cpp
@@ -0,0 +1,25 @@
+//===--- CSPropagate.cpp - Constraint Propagation -------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the constraint propagation algorithm in the solver.
+//
+//===----------------------------------------------------------------------===//
+#include "ConstraintGraph.h"
+#include "ConstraintSystem.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+using namespace swift;
+using namespace constraints;
+
+void ConstraintSystem::propagateConstraints() {
+}
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index d9ce9c6..d337194 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -3351,6 +3351,10 @@
Type type2,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator) {
+ // There's no bridging without ObjC interop.
+ if (!TC.Context.LangOpts.EnableObjCInterop)
+ return SolutionKind::Error;
+
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
/// Form an unresolved result.
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 94d4dee..8a72947 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -889,7 +889,7 @@
hasNonDependentMemberRelationalConstraints = true;
// Handle unspecialized types directly.
- if (!defaultType->isUnspecializedGeneric()) {
+ if (!defaultType->hasUnboundGenericType()) {
if (!exactTypes.insert(defaultType->getCanonicalType()).second)
continue;
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 82a3e5b..ef5f386 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2060,6 +2060,10 @@
/// \returns a possibly-sanitized initializer, or null if an error occurred.
Type generateConstraints(Pattern *P, ConstraintLocatorBuilder locator);
+ /// \brief Propagate constraints in an effort to enforce local
+ /// consistency to reduce the time to solve the system.
+ void propagateConstraints();
+
/// \brief The result of attempting to resolve a constraint or set of
/// constraints.
enum class SolutionKind : char {
diff --git a/lib/Sema/GenericTypeResolver.h b/lib/Sema/GenericTypeResolver.h
index 69d0ef5..63af3fb 100644
--- a/lib/Sema/GenericTypeResolver.h
+++ b/lib/Sema/GenericTypeResolver.h
@@ -144,8 +144,37 @@
virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp);
- virtual Type resolveDependentMemberType(Type baseTy,
- DeclContext *DC,
+ virtual Type resolveDependentMemberType(Type baseTy, DeclContext *DC,
+ SourceRange baseRange,
+ ComponentIdentTypeRepr *ref);
+
+ virtual Type resolveSelfAssociatedType(Type selfTy,
+ AssociatedTypeDecl *assocType);
+
+ virtual Type resolveTypeOfContext(DeclContext *dc);
+
+ virtual Type resolveTypeOfDecl(TypeDecl *decl);
+
+ virtual bool areSameType(Type type1, Type type2);
+
+ virtual void recordParamType(ParamDecl *decl, Type ty);
+};
+
+/// Generic type resolver that only handles what can appear in a protocol
+/// definition, i.e. Self, and Self.A.B.C dependent types.
+///
+/// This should only be used when resolving/validating where clauses in
+/// protocols.
+class ProtocolRequirementTypeResolver : public GenericTypeResolver {
+ ProtocolDecl *Proto;
+
+public:
+ explicit ProtocolRequirementTypeResolver(ProtocolDecl *proto)
+ : Proto(proto) {}
+
+ virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp);
+
+ virtual Type resolveDependentMemberType(Type baseTy, DeclContext *DC,
SourceRange baseRange,
ComponentIdentTypeRepr *ref);
diff --git a/lib/Sema/ITCDecl.cpp b/lib/Sema/ITCDecl.cpp
index f3bd518..430e43a 100644
--- a/lib/Sema/ITCDecl.cpp
+++ b/lib/Sema/ITCDecl.cpp
@@ -60,6 +60,10 @@
}
}
}
+
+ if (!isa<EnumDecl>(typeDecl)) {
+ options |= TR_NonEnumInheritanceClauseOuterLayer;
+ }
} else {
auto ext = decl.get<ExtensionDecl *>();
inheritanceClause = ext->getInherited();
@@ -100,7 +104,7 @@
// FIXME: Declaration validation is overkill. Sink it down into type
// resolution when it is actually needed.
if (auto nominal = dyn_cast<NominalTypeDecl>(dc))
- TC.validateDecl(nominal);
+ TC.validateDeclForNameLookup(nominal);
else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
TC.validateExtension(ext);
}
@@ -311,7 +315,7 @@
} else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
if (ext->isBeingValidated())
return true;
- if (ext->validated())
+ if (ext->hasValidationStarted())
return false;
} else {
break;
@@ -329,7 +333,7 @@
if (auto typeAliasDecl = dyn_cast<TypeAliasDecl>(typeDecl)) {
if (typeAliasDecl->getDeclContext()->isModuleScopeContext() &&
typeAliasDecl->getGenericParams() == nullptr) {
- typeAliasDecl->setHasCompletedValidation();
+ typeAliasDecl->setValidationStarted();
TypeResolutionOptions options;
if (typeAliasDecl->getFormalAccess() <= Accessibility::FilePrivate)
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index a9195ab..d8169a2 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -1769,6 +1769,10 @@
// Add the requirements to the builder.
for (auto &req : resolvedRequirements)
Builder.addRequirement(&req);
+
+ // Check the result.
+ Builder.finalize(attr->getLocation(), genericSig->getGenericParams(),
+ /*allowConcreteGenericParams=*/true);
}
static Accessibility getAccessForDiagnostics(const ValueDecl *D) {
diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp
index 4d8b110..bb4c21b 100644
--- a/lib/Sema/TypeCheckCaptures.cpp
+++ b/lib/Sema/TypeCheckCaptures.cpp
@@ -192,7 +192,9 @@
// If VD is a noescape decl, then the closure we're computing this for
// must also be noescape.
- if (VD->hasInterfaceType() &&
+ if (AFR.hasType() &&
+ !AFR.getType()->hasError() &&
+ VD->hasInterfaceType() &&
VD->getInterfaceType()->is<AnyFunctionType>() &&
VD->getInterfaceType()->castTo<AnyFunctionType>()->isNoEscape() &&
!capture.isNoEscape() &&
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 2ec4bdc..11fa677 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -3365,16 +3365,18 @@
// We can conditionally cast from NSError to an Error-conforming
// type. This is handled in the runtime, so it doesn't need a special cast
// kind.
- if (auto errorTypeProto = Context.getProtocol(KnownProtocolKind::Error)) {
- if (conformsToProtocol(toType, errorTypeProto, dc,
- (ConformanceCheckFlags::InExpression|
- ConformanceCheckFlags::Used)))
- if (auto NSErrorTy = getNSErrorType(dc))
- if (isSubtypeOf(fromType, NSErrorTy, dc)
- // Don't mask "always true" warnings if NSError is cast to
- // Error itself.
- && !isSubtypeOf(fromType, toType, dc))
- return CheckedCastKind::ValueCast;
+ if (Context.LangOpts.EnableObjCInterop) {
+ if (auto errorTypeProto = Context.getProtocol(KnownProtocolKind::Error)) {
+ if (conformsToProtocol(toType, errorTypeProto, dc,
+ (ConformanceCheckFlags::InExpression|
+ ConformanceCheckFlags::Used)))
+ if (auto NSErrorTy = getNSErrorType(dc))
+ if (isSubtypeOf(fromType, NSErrorTy, dc)
+ // Don't mask "always true" warnings if NSError is cast to
+ // Error itself.
+ && !isSubtypeOf(fromType, toType, dc))
+ return CheckedCastKind::ValueCast;
+ }
}
// The runtime doesn't support casts to CF types and always lets them succeed.
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 80fc5d4..d324496 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -979,21 +979,14 @@
return true;
}
-/// Validate the given pattern binding declaration.
-static void validatePatternBindingDecl(TypeChecker &tc,
- PatternBindingDecl *binding,
- unsigned entryNumber) {
+/// Validate the \c entryNumber'th entry in \c binding.
+static void validatePatternBindingEntry(TypeChecker &tc,
+ PatternBindingDecl *binding,
+ unsigned entryNumber) {
// If the pattern already has a type, we're done.
- if (binding->getPattern(entryNumber)->hasType() ||
- binding->isBeingValidated())
+ if (binding->getPattern(entryNumber)->hasType())
return;
- binding->setIsBeingValidated();
-
- // On any path out of this function, make sure to mark the binding as done
- // being type checked.
- SWIFT_DEFER { binding->setIsBeingValidated(false); };
-
// Resolve the pattern.
auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
binding->getDeclContext(),
@@ -1078,6 +1071,19 @@
tc.checkTypeModifyingDeclAttributes(var);
}
+/// Validate the entries in the given pattern binding declaration.
+static void validatePatternBindingEntries(TypeChecker &tc,
+ PatternBindingDecl *binding) {
+ if (binding->hasValidationStarted())
+ return;
+
+ binding->setIsBeingValidated();
+ SWIFT_DEFER { binding->setIsBeingValidated(false); };
+
+ for (unsigned i = 0, e = binding->getNumPatternEntries(); i != e; ++i)
+ validatePatternBindingEntry(tc, binding, i);
+}
+
void swift::makeFinal(ASTContext &ctx, ValueDecl *D) {
if (D && !D->isFinal()) {
D->getAttrs().add(new (ctx) FinalAttr(/*IsImplicit=*/true));
@@ -1256,7 +1262,9 @@
if (!ED->getExtendedType().isNull() &&
!ED->getExtendedType()->hasError()) {
if (NominalTypeDecl *nominal = ED->getExtendedType()->getAnyNominal()) {
- validateDecl(nominal);
+ validateDeclForNameLookup(nominal);
+ if (ED->hasDefaultAccessibility())
+ return;
maxAccess = std::max(nominal->getFormalAccess(),
Accessibility::FilePrivate);
}
@@ -3430,7 +3438,7 @@
checkDeclAttributesEarly(PGD);
checkDeclAttributes(PGD);
- if (PGD->isInvalid() || PGD->isBeingValidated())
+ if (PGD->isInvalid() || PGD->hasValidationStarted())
return;
PGD->setIsBeingValidated();
SWIFT_DEFER { PGD->setIsBeingValidated(false); };
@@ -3753,8 +3761,7 @@
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
// Check all the pattern/init pairs in the PBD.
- for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i)
- validatePatternBindingDecl(TC, PBD, i);
+ validatePatternBindingEntries(TC, PBD);
if (PBD->isBeingValidated())
return;
@@ -3982,7 +3989,7 @@
}
void visitAssociatedTypeDecl(AssociatedTypeDecl *assocType) {
- if (!assocType->hasInterfaceType())
+ if (!assocType->hasValidationStarted())
TC.validateDecl(assocType);
}
@@ -4334,9 +4341,28 @@
TC.checkDeclAttributesEarly(PD);
TC.computeAccessibility(PD);
- if (!IsSecondPass)
+ if (!IsSecondPass) {
checkUnsupportedNestedType(PD);
+ for (auto member : PD->getMembers()) {
+ if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
+ if (auto whereClause = assocType->getTrailingWhereClause()) {
+ DeclContext *lookupDC = assocType->getDeclContext();
+
+ ProtocolRequirementTypeResolver resolver(PD);
+ TypeResolutionOptions options;
+
+ for (auto &req : whereClause->getRequirements()) {
+ if (!TC.validateRequirement(whereClause->getWhereLoc(), req,
+ lookupDC, options, &resolver))
+ // FIXME handle error?
+ continue;
+ }
+ }
+ }
+ }
+ }
+
if (IsSecondPass) {
checkAccessibility(TC, PD);
for (auto member : PD->getMembers()) {
@@ -5011,6 +5037,10 @@
return false;
if (func->isGeneric() != parentFunc->isGeneric())
return false;
+ } else if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
+ auto parentCtor = cast<ConstructorDecl>(parentDecl);
+ if (ctor->isGeneric() != parentCtor->isGeneric())
+ return false;
} else if (auto var = dyn_cast<VarDecl>(decl)) {
auto parentVar = cast<VarDecl>(parentDecl);
if (var->isStatic() != parentVar->isStatic())
@@ -6908,8 +6938,12 @@
// Handling validation failure due to re-entrancy is left
// up to the caller, who must call hasValidSignature() to
// check that validateDecl() returned a fully-formed decl.
- if (D->isBeingValidated())
+ if (D->hasValidationStarted()) {
+ // If this isn't reentrant (i.e. D has already been validated), the
+ // signature better be valid.
+ assert(D->isBeingValidated() || D->hasValidSignature());
return;
+ }
PrettyStackTraceDecl StackTrace("validating", D);
@@ -6952,40 +6986,48 @@
llvm_unreachable("handled above");
case DeclKind::AssociatedType: {
- if (D->hasInterfaceType())
- return;
-
auto assocType = cast<AssociatedTypeDecl>(D);
assocType->setIsBeingValidated();
SWIFT_DEFER { assocType->setIsBeingValidated(false); };
+ validateAccessibility(assocType);
+
checkDeclAttributesEarly(assocType);
checkInheritanceClause(assocType);
// Check the default definition, if there is one.
TypeLoc &defaultDefinition = assocType->getDefaultDefinitionLoc();
- if (!defaultDefinition.isNull() &&
- validateType(defaultDefinition, assocType->getDeclContext())) {
- defaultDefinition.setInvalidType(Context);
- }
+ if (!defaultDefinition.isNull()) {
+ if (validateType(defaultDefinition, assocType->getDeclContext())) {
+ defaultDefinition.setInvalidType(Context);
+ } else {
+ // associatedtype X = X is invalid
+ auto mentionsItself =
+ defaultDefinition.getType().findIf([&](Type type) {
+ if (auto DMT = type->getAs<ArchetypeType>()) {
+ return DMT->getAssocType() == assocType;
+ }
+ return false;
+ });
+ if (mentionsItself) {
+ diagnose(defaultDefinition.getLoc(), diag::recursive_type_reference,
+ assocType->getDescriptiveKind(), assocType->getName());
+ diagnose(assocType, diag::type_declared_here);
+ }
+ }
+ }
// Finally, set the interface type.
- assocType->computeType();
+ if (!assocType->hasInterfaceType())
+ assocType->computeType();
checkDeclAttributes(assocType);
break;
}
case DeclKind::TypeAlias: {
- // Type aliases may not have an underlying type yet.
auto typeAlias = cast<TypeAliasDecl>(D);
-
- if (typeAlias->hasCompletedValidation())
- return;
-
- typeAlias->setHasCompletedValidation();
-
// Check generic parameters, if needed.
typeAlias->setIsBeingValidated();
SWIFT_DEFER { typeAlias->setIsBeingValidated(false); };
@@ -7017,8 +7059,6 @@
case DeclKind::Struct:
case DeclKind::Class: {
auto nominal = cast<NominalTypeDecl>(D);
- if (nominal->hasInterfaceType())
- return;
nominal->computeType();
// Check generic parameters, if needed.
@@ -7056,9 +7096,8 @@
case DeclKind::Protocol: {
auto proto = cast<ProtocolDecl>(D);
- if (proto->hasInterfaceType())
- return;
- proto->computeType();
+ if (!proto->hasInterfaceType())
+ proto->computeType();
// Validate the generic type signature, which is just <Self : P>.
proto->setIsBeingValidated();
@@ -7110,8 +7149,7 @@
diagnose(VD, diag::pattern_used_in_type, VD->getName());
} else {
- for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i)
- validatePatternBindingDecl(*this, PBD, i);
+ validatePatternBindingEntries(*this, PBD);
}
auto parentPattern = VD->getParentPattern();
@@ -7221,23 +7259,17 @@
}
case DeclKind::Func: {
- if (D->hasInterfaceType())
- return;
typeCheckDecl(D, true);
break;
}
case DeclKind::Subscript:
case DeclKind::Constructor:
- if (D->hasInterfaceType())
- return;
typeCheckDecl(D, true);
break;
case DeclKind::Destructor:
case DeclKind::EnumElement: {
- if (D->hasInterfaceType())
- return;
if (auto container = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
validateDecl(container);
typeCheckDecl(D, true);
@@ -7251,6 +7283,40 @@
assert(D->hasValidSignature());
}
+void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
+ switch (D->getKind()) {
+ case DeclKind::Protocol: {
+ auto proto = cast<ProtocolDecl>(D);
+ if (proto->hasInterfaceType())
+ return;
+ proto->computeType();
+
+ validateAccessibility(proto);
+
+ // Record inherited protocols.
+ resolveInheritedProtocols(proto);
+
+ for (auto member : proto->getMembers()) {
+ if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
+ validateDeclForNameLookup(ATD);
+ }
+ }
+ break;
+ }
+ case DeclKind::AssociatedType: {
+ auto assocType = cast<AssociatedTypeDecl>(D);
+ if (assocType->hasInterfaceType())
+ return;
+ assocType->computeType();
+ validateAccessibility(assocType);
+ break;
+ }
+
+ default:
+ validateDecl(D);
+ break;
+ }
+}
void TypeChecker::validateAccessibility(ValueDecl *D) {
if (D->hasAccessibility())
@@ -7394,9 +7460,7 @@
// Local function used to infer requirements from the extended type.
auto inferExtendedTypeReqs = [&](GenericSignatureBuilder &builder) {
- builder.inferRequirements(TypeLoc::withoutLoc(extInterfaceType),
- /*minDepth=*/0,
- /*maxDepth=*/genericParams->getDepth());
+ builder.inferRequirements(TypeLoc::withoutLoc(extInterfaceType));
};
// Validate the generic type signature.
@@ -7430,12 +7494,11 @@
} // namespace swift
void TypeChecker::validateExtension(ExtensionDecl *ext) {
- // If we already validated this extension, there's nothing more to do.
- if (ext->validated())
+ // If we're currently validating, or have already validated this extension,
+ // there's nothing more to do now.
+ if (ext->hasValidationStarted())
return;
- ext->setValidated();
-
ext->setIsBeingValidated();
SWIFT_DEFER { ext->setIsBeingValidated(false); };
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 737fa2f..a0dc719 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -128,6 +128,43 @@
GenericEnv, type));
}
+Type ProtocolRequirementTypeResolver::resolveGenericTypeParamType(
+ GenericTypeParamType *gp) {
+ assert(gp->isEqual(Proto->getSelfInterfaceType()) &&
+ "found non-Self-shaped GTPT when resolving protocol requirement");
+ return gp;
+}
+
+Type ProtocolRequirementTypeResolver::resolveDependentMemberType(
+ Type baseTy, DeclContext *DC, SourceRange baseRange,
+ ComponentIdentTypeRepr *ref) {
+ return DependentMemberType::get(baseTy, ref->getIdentifier());
+}
+
+Type ProtocolRequirementTypeResolver::resolveSelfAssociatedType(
+ Type selfTy, AssociatedTypeDecl *assocType) {
+ assert(selfTy->isEqual(Proto->getSelfInterfaceType()));
+ return assocType->getDeclaredInterfaceType();
+}
+
+Type ProtocolRequirementTypeResolver::resolveTypeOfContext(DeclContext *dc) {
+ return dc->getSelfInterfaceType();
+}
+
+Type ProtocolRequirementTypeResolver::resolveTypeOfDecl(TypeDecl *decl) {
+ return decl->getDeclaredInterfaceType();
+}
+
+bool ProtocolRequirementTypeResolver::areSameType(Type type1, Type type2) {
+ return type1->isEqual(type2);
+}
+
+void ProtocolRequirementTypeResolver::recordParamType(ParamDecl *decl,
+ Type type) {
+ llvm_unreachable(
+ "recording a param type of a protocol requirement doesn't make sense");
+}
+
Type CompleteGenericTypeResolver::resolveGenericTypeParamType(
GenericTypeParamType *gp) {
assert(gp->getDecl() && "Missing generic parameter declaration");
@@ -276,8 +313,6 @@
builder->addGenericParameter(param);
}
- unsigned depth = genericParams->getDepth();
-
// Now, check the inheritance clauses of each parameter.
for (auto param : *genericParams) {
checkInheritanceClause(param, resolver);
@@ -287,9 +322,7 @@
// Infer requirements from the inherited types.
for (const auto &inherited : param->getInherited()) {
- builder->inferRequirements(inherited,
- /*minDepth=*/depth,
- /*maxDepth=*/depth);
+ builder->inferRequirements(inherited);
}
}
}
@@ -298,73 +331,76 @@
// Add the requirements clause to the builder, validating the types in
// the requirements clause along the way.
for (auto &req : genericParams->getRequirements()) {
- if (req.isInvalid())
+ if (validateRequirement(genericParams->getWhereLoc(), req, lookupDC,
+ options, resolver))
continue;
- switch (req.getKind()) {
- case RequirementReprKind::TypeConstraint: {
- // Validate the types.
- if (validateType(req.getSubjectLoc(), lookupDC, options, resolver)) {
- req.setInvalid();
- continue;
- }
-
- if (validateType(req.getConstraintLoc(), lookupDC, options,
- resolver)) {
- req.setInvalid();
- continue;
- }
-
- // FIXME: Feels too early to perform this check.
- if (!req.getConstraint()->isExistentialType() &&
- !req.getConstraint()->getClassOrBoundGenericClass()) {
- diagnose(genericParams->getWhereLoc(),
- diag::requires_conformance_nonprotocol,
- req.getSubjectLoc(), req.getConstraintLoc());
- req.getConstraintLoc().setInvalidType(Context);
- req.setInvalid();
- continue;
- }
-
- break;
- }
-
- case RequirementReprKind::LayoutConstraint: {
- // Validate the types.
- if (validateType(req.getSubjectLoc(), lookupDC, options, resolver)) {
- req.setInvalid();
- continue;
- }
-
- if (req.getLayoutConstraintLoc().isNull()) {
- req.setInvalid();
- continue;
- }
-
- break;
- }
-
- case RequirementReprKind::SameType:
- if (validateType(req.getFirstTypeLoc(), lookupDC, options,
- resolver)) {
- req.setInvalid();
- continue;
- }
-
- if (validateType(req.getSecondTypeLoc(), lookupDC, options,
- resolver)) {
- req.setInvalid();
- continue;
- }
-
- break;
- }
-
if (builder && builder->addRequirement(&req))
req.setInvalid();
}
}
+bool TypeChecker::validateRequirement(SourceLoc whereLoc, RequirementRepr &req,
+ DeclContext *lookupDC,
+ TypeResolutionOptions options,
+ GenericTypeResolver *resolver) {
+ if (req.isInvalid())
+ return true;
+
+ switch (req.getKind()) {
+ case RequirementReprKind::TypeConstraint: {
+ // Validate the types.
+ if (validateType(req.getSubjectLoc(), lookupDC, options, resolver)) {
+ req.setInvalid();
+ return true;
+ }
+
+ if (validateType(req.getConstraintLoc(), lookupDC, options, resolver)) {
+ req.setInvalid();
+ return true;
+ }
+
+ // FIXME: Feels too early to perform this check.
+ if (!req.getConstraint()->isExistentialType() &&
+ !req.getConstraint()->getClassOrBoundGenericClass()) {
+ diagnose(whereLoc, diag::requires_conformance_nonprotocol,
+ req.getSubjectLoc(), req.getConstraintLoc());
+ req.getConstraintLoc().setInvalidType(Context);
+ req.setInvalid();
+ return true;
+ }
+ return false;
+ }
+
+ case RequirementReprKind::LayoutConstraint: {
+ // Validate the types.
+ if (validateType(req.getSubjectLoc(), lookupDC, options, resolver)) {
+ req.setInvalid();
+ return true;
+ }
+
+ if (req.getLayoutConstraintLoc().isNull()) {
+ req.setInvalid();
+ return true;
+ }
+ return false;
+ }
+
+ case RequirementReprKind::SameType: {
+ if (validateType(req.getFirstTypeLoc(), lookupDC, options, resolver)) {
+ req.setInvalid();
+ return true;
+ }
+
+ if (validateType(req.getSecondTypeLoc(), lookupDC, options, resolver)) {
+ req.setInvalid();
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
void
TypeChecker::prepareGenericParamList(GenericParamList *gp,
DeclContext *dc) {
@@ -488,10 +524,7 @@
// Infer requirements from it.
if (builder && genericParams &&
fn->getBodyResultTypeLoc().getTypeRepr()) {
- unsigned depth = genericParams->getDepth();
- builder->inferRequirements(fn->getBodyResultTypeLoc(),
- /*minDepth=*/depth,
- /*maxDepth=*/depth);
+ builder->inferRequirements(fn->getBodyResultTypeLoc());
}
}
}
@@ -827,10 +860,7 @@
// Infer requirements from it.
if (genericParams && builder &&
subscript->getElementTypeLoc().getTypeRepr()) {
- unsigned depth = genericParams->getDepth();
- builder->inferRequirements(subscript->getElementTypeLoc(),
- /*minDepth=*/depth,
- /*maxDepth=*/depth);
+ builder->inferRequirements(subscript->getElementTypeLoc());
}
// Check the indices.
@@ -1089,34 +1119,29 @@
std::pair<bool, bool> TypeChecker::checkGenericArguments(
DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner,
- GenericSignature *genericSig, const TypeSubstitutionMap &substitutions,
+ GenericSignature *genericSig, TypeSubstitutionFn substitutions,
+ LookupConformanceFn conformances,
UnsatisfiedDependency *unsatisfiedDependency,
ConformanceCheckOptions conformanceOptions,
GenericRequirementsCheckListener *listener) {
- // Check each of the requirements.
- ModuleDecl *module = dc->getParentModule();
- for (const auto &req : genericSig->getRequirements()) {
- Type firstType = req.getFirstType().subst(
- QueryTypeSubstitutionMap{substitutions},
- LookUpConformanceInModule(module));
- if (firstType.isNull()) {
+ for (const auto &rawReq : genericSig->getRequirements()) {
+ auto req = rawReq.subst(substitutions, conformances);
+ if (!req) {
// Another requirement will fail later; just continue.
continue;
}
- Type secondType;
- if (req.getKind() != RequirementKind::Layout)
- secondType = req.getSecondType();
- if (secondType) {
- secondType = secondType.subst(QueryTypeSubstitutionMap{substitutions},
- LookUpConformanceInModule(module));
- if (secondType.isNull()) {
- // Another requirement will fail later; just continue.
+ auto kind = req->getKind();
+ Type rawFirstType = rawReq.getFirstType();
+ Type firstType = req->getFirstType();
+ Type rawSecondType, secondType;
+ if (kind != RequirementKind::Layout) {
+ rawSecondType = rawReq.getSecondType();
+ secondType = req->getSecondType().subst(substitutions, conformances);
+ if (!secondType)
continue;
- }
}
- auto kind = req.getKind();
if (listener && !listener->shouldCheck(kind, firstType, secondType))
continue;
@@ -1157,10 +1182,10 @@
diagnose(loc, diag::type_does_not_inherit, owner, firstType,
secondType);
- diagnose(noteLoc, diag::type_does_not_inherit_requirement,
- req.getFirstType(), req.getSecondType(),
+ diagnose(noteLoc, diag::type_does_not_inherit_requirement, rawFirstType,
+ rawSecondType,
genericSig->gatherGenericParamBindingsText(
- {req.getFirstType(), req.getSecondType()}, substitutions));
+ {rawFirstType, rawSecondType}, substitutions));
return std::make_pair(false, false);
}
@@ -1171,10 +1196,10 @@
// FIXME: Better location info for both diagnostics.
diagnose(loc, diag::types_not_equal, owner, firstType, secondType);
- diagnose(noteLoc, diag::types_not_equal_requirement, req.getFirstType(),
- req.getSecondType(),
+ diagnose(noteLoc, diag::types_not_equal_requirement, rawFirstType,
+ rawSecondType,
genericSig->gatherGenericParamBindingsText(
- {req.getFirstType(), req.getSecondType()}, substitutions));
+ {rawFirstType, rawSecondType}, substitutions));
return std::make_pair(false, false);
}
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 0a3131e..b2fa7ec 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -394,7 +394,7 @@
// Unresolved member syntax '.Element' forms an EnumElement pattern. The
// element will be resolved when we type-check the pattern.
Pattern *visitUnresolvedMemberExpr(UnresolvedMemberExpr *ume) {
- // We the unresolved member has an argument, turn it into a subpattern.
+ // If the unresolved member has an argument, turn it into a subpattern.
Pattern *subPattern = nullptr;
if (auto arg = ume->getArgument()) {
subPattern = getSubExprPattern(arg);
@@ -402,11 +402,11 @@
// FIXME: Compound names.
return new (TC.Context) EnumElementPattern(
- TypeLoc(), ume->getDotLoc(),
+ ume->getDotLoc(),
ume->getNameLoc().getBaseNameLoc(),
ume->getName().getBaseName(),
- nullptr,
- subPattern);
+ subPattern,
+ ume);
}
// Member syntax 'T.Element' forms a pattern if 'T' is an enum and the
@@ -1004,6 +1004,7 @@
TypeResolutionOptions options,
GenericTypeResolver *resolver,
TypeLoc tyLoc) {
+recur:
if (tyLoc.isNull()) {
tyLoc = TypeLoc::withoutLoc(type);
}
@@ -1377,6 +1378,14 @@
return true;
}
+
+ // If we have the original expression parse tree, try reinterpreting
+ // it as an expr-pattern if enum element lookup failed, since `.foo`
+ // could also refer to a static member of the context type.
+ } else if (EEP->hasUnresolvedOriginalExpr()) {
+ P = new (Context) ExprPattern(EEP->getUnresolvedOriginalExpr(),
+ nullptr, nullptr);
+ goto recur;
}
diagnose(EEP->getLoc(), diag::enum_element_pattern_member_not_found,
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 17e3471..ddf4d8a 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1073,7 +1073,8 @@
// Next, add each of the requirements (mapped from the requirement's
// interface types into the abstract type parameters).
- auto source = RequirementSource::forAbstract(builder);
+ auto source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
for (auto &reqReq : reqSig->getRequirements()) {
switch (reqReq.getKind()) {
case RequirementKind::Conformance: {
@@ -1782,12 +1783,15 @@
void emitDelayedDiags();
ConformanceChecker(TypeChecker &tc, NormalProtocolConformance *conformance,
- bool suppressDiagnostics = true)
- : WitnessChecker(tc, conformance->getProtocol(), conformance->getType(),
- conformance->getDeclContext()),
- Conformance(conformance),
- Loc(conformance->getLoc()),
- SuppressDiagnostics(suppressDiagnostics) { }
+ bool suppressDiagnostics = true)
+ : WitnessChecker(tc, conformance->getProtocol(), conformance->getType(),
+ conformance->getDeclContext()),
+ Conformance(conformance), Loc(conformance->getLoc()),
+ SuppressDiagnostics(suppressDiagnostics) {
+ // The protocol may have only been validatedDeclForNameLookup'd until
+ // here, so fill in any information that's missing.
+ tc.validateDecl(conformance->getProtocol());
+ }
/// Resolve all of the type witnesses.
void resolveTypeWitnesses();
@@ -1806,6 +1810,10 @@
/// directly as possible.
void resolveSingleTypeWitness(AssociatedTypeDecl *assocType);
+ /// Check all of the protocols requirements are actually satisfied by a
+ /// the chosen type witnesses.
+ void ensureRequirementsAreSatisfied();
+
/// Check the entire protocol conformance, ensuring that all
/// witnesses are resolved and emitting any diagnostics.
void checkConformance();
@@ -4447,6 +4455,28 @@
addUsedConformances(conformance, visited);
}
+void ConformanceChecker::ensureRequirementsAreSatisfied() {
+ auto proto = Conformance->getProtocol();
+ // Some other problem stopped the signature being computed.
+ if (!proto->isRequirementSignatureComputed())
+ return;
+
+ auto reqSig = proto->getRequirementSignature();
+
+ auto substitutions = SubstitutionMap::getProtocolSubstitutions(
+ proto, Conformance->getType(), ProtocolConformanceRef(Conformance));
+
+ auto result = TC.checkGenericArguments(
+ Conformance->getDeclContext(), Loc, Loc,
+ // FIXME: maybe this should be the conformance's type
+ proto->getDeclaredInterfaceType(), reqSig,
+ QuerySubstitutionMap{substitutions},
+ LookUpConformanceInSubstitutionMap{substitutions}, nullptr);
+
+ // Errors are emitted inside the checker.
+ (void)result;
+}
+
#pragma mark Protocol conformance checking
void ConformanceChecker::checkConformance() {
assert(!Conformance->isComplete() && "Conformance is already complete");
@@ -4462,6 +4492,10 @@
// Resolve all of the type witnesses.
resolveTypeWitnesses();
+ // Resolution attempts to have the witnesses be correct by construction, but
+ // this isn't guaranteed, so let's double check.
+ ensureRequirementsAreSatisfied();
+
// Ensure the conforming type is used.
//
// FIXME: This feels like the wrong place for this, but if we don't put
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 29e54c8..e0ee038 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -575,8 +575,9 @@
for (auto tyR : genericArgs)
args.push_back(tyR);
+ auto argumentOptions = options - TR_NonEnumInheritanceClauseOuterLayer;
auto result = applyUnboundGenericArguments(type, genericDecl, loc, dc, args,
- options, resolver,
+ argumentOptions, resolver,
unsatisfiedDependency);
if (!result)
return result;
@@ -675,9 +676,11 @@
assert(genericSig != nullptr);
auto substitutions = BGT->getContextSubstitutions(BGT->getDecl());
- auto result = checkGenericArguments(
- dc, loc, noteLoc, UGT, genericSig,
- substitutions, unsatisfiedDependency);
+ auto result =
+ checkGenericArguments(dc, loc, noteLoc, UGT, genericSig,
+ QueryTypeSubstitutionMap{substitutions},
+ LookUpConformanceInModule{dc->getParentModule()},
+ unsatisfiedDependency);
// Unsatisfied dependency case.
if (result.first)
@@ -726,7 +729,7 @@
return nullptr;
} else {
// Validate the declaration.
- TC.validateDecl(typeDecl);
+ TC.validateDeclForNameLookup(typeDecl);
}
// If we didn't bail out with an unsatisfiedDependency,
@@ -1086,7 +1089,26 @@
dyn_cast<GenericIdentTypeRepr>(comp), options,
resolver, unsatisfiedDependency);
- if (!type || type->hasError())
+ if (!type)
+ return type;
+
+ auto hasError = type->hasError();
+ if (options & TR_NonEnumInheritanceClauseOuterLayer) {
+ auto protocolOrClass =
+ hasError ? (isa<ProtocolDecl>(typeDecl) || isa<ClassDecl>(typeDecl))
+ : (type->is<ProtocolType>() || type->is<ClassType>());
+ if (!protocolOrClass) {
+ auto diagnosedType = hasError ? typeDecl->getDeclaredInterfaceType() : type;
+ if (diagnosedType && /*FIXME:*/!hasError) {
+ TC.diagnose(comp->getIdLoc(),
+ diag::inheritance_from_non_protocol_or_class,
+ diagnosedType);
+ return ErrorType::get(diagnosedType);
+ }
+ }
+ }
+
+ if (hasError)
return type;
// If this is the first result we found, record it.
@@ -1318,6 +1340,16 @@
return ErrorType::get(TC.Context);
}
+ if (options & TR_NonEnumInheritanceClauseOuterLayer) {
+ auto protocolOrClass =
+ memberType->is<ProtocolType>() || memberType->is<ClassType>();
+ if (!protocolOrClass) {
+ TC.diagnose(comp->getIdLoc(),
+ diag::inheritance_from_non_protocol_or_class, memberType);
+ return ErrorType::get(memberType);
+ }
+ }
+
// If there are generic arguments, apply them now.
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
memberType = TC.applyGenericArguments(
@@ -1357,8 +1389,9 @@
// All remaining components use qualified lookup.
+ auto parentOptions = options - TR_NonEnumInheritanceClauseOuterLayer;
// Resolve the parent type.
- Type parentTy = resolveIdentTypeComponent(TC, DC, parentComps, options,
+ Type parentTy = resolveIdentTypeComponent(TC, DC, parentComps, parentOptions,
diagnoseErrors, resolver,
unsatisfiedDependency);
if (!parentTy || parentTy->hasError()) return parentTy;
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index 7d001ab..e681c7a 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -348,7 +348,7 @@
}
// Cannot extend a bound generic type.
- if (extendedType->isSpecialized() && extendedType->getAnyNominal()) {
+ if (extendedType->isSpecialized()) {
TC.diagnose(ED->getLoc(), diag::extension_specialization,
extendedType->getAnyNominal()->getName())
.highlight(ED->getExtendedTypeLoc().getSourceRange());
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index a331c60..aa56685 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -437,6 +437,11 @@
/// Whether we are checking the outermost type of a computed property setter's newValue
TR_ImmediateSetterNewValue = 0x1000000,
+
+ /// Whether we are checking the outermost layer of types in an inheritance
+ /// clause on something other than an enum (i.e. V, but not U or W, in class
+ /// T: U.V<W>)
+ TR_NonEnumInheritanceClauseOuterLayer = 0x2000000,
};
/// Option set describing how type resolution should work.
@@ -838,6 +843,9 @@
void validateDecl(OperatorDecl *decl);
void validateDecl(PrecedenceGroupDecl *decl);
+ /// Perform just enough validation for looking up names using the Decl.
+ void validateDeclForNameLookup(ValueDecl *D);
+
/// Resolves the accessibility of the given declaration.
void validateAccessibility(ValueDecl *D);
@@ -1065,7 +1073,7 @@
}
virtual void resolveDeclSignature(ValueDecl *VD) override {
- validateDecl(VD);
+ validateDeclForNameLookup(VD);
}
virtual void bindExtension(ExtensionDecl *ext) override;
@@ -1185,6 +1193,11 @@
/// \param nominal The generic type.
void validateGenericTypeSignature(GenericTypeDecl *nominal);
+ bool validateRequirement(SourceLoc whereLoc, RequirementRepr &req,
+ DeclContext *lookupDC,
+ TypeResolutionOptions options = None,
+ GenericTypeResolver *resolver = nullptr);
+
/// Check the given set of generic arguments against the requirements in a
/// generic signature.
///
@@ -1207,7 +1220,8 @@
/// - (false, false) on failure
std::pair<bool, bool> checkGenericArguments(
DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner,
- GenericSignature *genericSig, const TypeSubstitutionMap &substitutions,
+ GenericSignature *genericSig, TypeSubstitutionFn substitutions,
+ LookupConformanceFn conformances,
UnsatisfiedDependency *unsatisfiedDependency,
ConformanceCheckOptions conformanceOptions = ConformanceCheckFlags::Used,
GenericRequirementsCheckListener *listener = nullptr);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 98f18bb..65e5ea5 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1321,11 +1321,10 @@
IdentifierID IID;
TypeID TID = 0;
bool isType = (recordID == XREF_TYPE_PATH_PIECE);
- bool onlyInNominal = false;
bool inProtocolExt = false;
bool isStatic = false;
if (isType)
- XRefTypePathPieceLayout::readRecord(scratch, IID, onlyInNominal);
+ XRefTypePathPieceLayout::readRecord(scratch, IID, inProtocolExt);
else
XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
isStatic);
@@ -1496,13 +1495,12 @@
Identifier memberName;
Optional<swift::CtorInitializerKind> ctorInit;
bool isType = false;
- bool onlyInNominal = false;
bool inProtocolExt = false;
bool isStatic = false;
switch (recordID) {
case XREF_TYPE_PATH_PIECE: {
IdentifierID IID;
- XRefTypePathPieceLayout::readRecord(scratch, IID, onlyInNominal);
+ XRefTypePathPieceLayout::readRecord(scratch, IID, inProtocolExt);
memberName = getIdentifier(IID);
isType = true;
break;
@@ -1548,7 +1546,7 @@
return nullptr;
}
- auto members = nominal->lookupDirect(memberName, onlyInNominal);
+ auto members = nominal->lookupDirect(memberName);
values.append(members.begin(), members.end());
filterValues(filterTy, M, genericSig, isType, inProtocolExt, isStatic,
ctorInit, values);
@@ -2551,10 +2549,14 @@
if (declOrOffset.isComplete())
return declOrOffset;
- auto assocType = createDecl<AssociatedTypeDecl>(DC, SourceLoc(),
- getIdentifier(nameID),
- SourceLoc(), this,
- defaultDefinitionID);
+ // The where-clause information is pushed up into the protocol
+ // (specifically, into its requirement signature) and
+ // serialized/deserialized there, so the actual Decl doesn't need to store
+ // it.
+ TrailingWhereClause *trailingWhere = nullptr;
+ auto assocType = createDecl<AssociatedTypeDecl>(
+ DC, SourceLoc(), getIdentifier(nameID), SourceLoc(), trailingWhere,
+ this, defaultDefinitionID);
declOrOffset = assocType;
assocType->computeType();
@@ -3467,7 +3469,6 @@
DeclTypeCursor.GetCurrentBitNo()));
nominal->addExtension(extension);
- extension->setValidated(true);
break;
}
@@ -3529,7 +3530,9 @@
if (DAttrs)
declOrOffset.get()->getAttrs().setRawAttributeChain(DAttrs);
- return declOrOffset;
+ auto decl = declOrOffset.get();
+ decl->setValidationStarted();
+ return decl;
}
/// Translate from the Serialization function type repr enum values to the AST
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 3153e1e..25c7df7 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -982,6 +982,10 @@
Ty,
ctxConformances);
break;
+ case ValueKind::InitExistentialOpaqueInst:
+ ResultVal = Builder.createInitExistentialOpaque(Loc, Ty, ConcreteTy,
+ operand, ctxConformances);
+ break;
case ValueKind::InitExistentialMetatypeInst:
ResultVal = Builder.createInitExistentialMetatype(Loc, operand, Ty,
ctxConformances);
@@ -1343,16 +1347,17 @@
UNARY_INSTRUCTION(CondFail)
REFCOUNTING_INSTRUCTION(RetainValue)
- UNARY_INSTRUCTION(UnmanagedRetainValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedRetainValue)
UNARY_INSTRUCTION(CopyValue)
UNARY_INSTRUCTION(CopyUnownedValue)
UNARY_INSTRUCTION(DestroyValue)
REFCOUNTING_INSTRUCTION(ReleaseValue)
- UNARY_INSTRUCTION(UnmanagedReleaseValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedReleaseValue)
REFCOUNTING_INSTRUCTION(AutoreleaseValue)
- UNARY_INSTRUCTION(UnmanagedAutoreleaseValue)
+ REFCOUNTING_INSTRUCTION(UnmanagedAutoreleaseValue)
REFCOUNTING_INSTRUCTION(SetDeallocating)
UNARY_INSTRUCTION(DeinitExistentialAddr)
+ UNARY_INSTRUCTION(DeinitExistentialOpaque)
UNARY_INSTRUCTION(EndBorrowArgument)
UNARY_INSTRUCTION(DestroyAddr)
UNARY_INSTRUCTION(IsNonnull)
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index df0d237..85f57eb 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1803,18 +1803,17 @@
return;
}
+ bool isProtocolExt = D->getDeclContext()->getAsProtocolExtensionContext();
if (auto type = dyn_cast<TypeDecl>(D)) {
abbrCode = DeclTypeAbbrCodes[XRefTypePathPieceLayout::Code];
XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addIdentifierRef(type->getName()),
- isa<ProtocolDecl>(
- type->getDeclContext()));
+ isProtocolExt);
return;
}
auto val = cast<ValueDecl>(D);
auto ty = val->getInterfaceType()->getCanonicalType();
- bool isProtocolExt = D->getDeclContext()->getAsProtocolExtensionContext();
abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(ty),
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 08b5c75..5e60637 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -315,7 +315,7 @@
FuncTable[Ctx.getIdentifier(F.getName())] = NextFuncID++;
Funcs.push_back(Out.GetCurrentBitNo());
unsigned abbrCode = SILAbbrCodes[SILFunctionLayout::Code];
- TypeID FnID = S.addTypeRef(F.getLoweredType().getSwiftType());
+ TypeID FnID = S.addTypeRef(F.getLoweredType().getSwiftRValueType());
DEBUG(llvm::dbgs() << "SILFunction " << F.getName() << " @ BitNo "
<< Out.GetCurrentBitNo() << " abbrCode " << abbrCode
<< " FnID " << FnID << "\n");
@@ -581,7 +581,7 @@
break;
}
case ValueKind::InitExistentialOpaqueInst: {
- auto &IEOI = cast<InitExistentialRefInst>(SI);
+ auto &IEOI = cast<InitExistentialOpaqueInst>(SI);
operand = IEOI.getOperand();
Ty = IEOI.getType();
FormalConcreteType = IEOI.getFormalConcreteType();
@@ -1047,6 +1047,7 @@
case ValueKind::DeallocStackInst:
case ValueKind::DeallocRefInst:
case ValueKind::DeinitExistentialAddrInst:
+ case ValueKind::DeinitExistentialOpaqueInst:
case ValueKind::DestroyAddrInst:
case ValueKind::IsNonnullInst:
case ValueKind::LoadInst:
@@ -1785,7 +1786,7 @@
void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) {
GlobalVarList[Ctx.getIdentifier(g.getName())] = NextGlobalVarID++;
GlobalVarOffset.push_back(Out.GetCurrentBitNo());
- TypeID TyID = S.addTypeRef(g.getLoweredType().getSwiftType());
+ TypeID TyID = S.addTypeRef(g.getLoweredType().getSwiftRValueType());
DeclID dID = S.addDeclRef(g.getDecl());
SILGlobalVarLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILGlobalVarLayout::Code],
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index dc0d4ac..f193f73 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -96,7 +96,7 @@
// FIXME: Which name should we be using here? Do we care about CPU subtypes?
// FIXME: At the very least, don't hardcode "arch".
llvm::SmallString<16> archFile{
- ctx.LangOpts.getPlatformConditionValue("arch")};
+ ctx.LangOpts.getPlatformConditionValue(PlatformConditionKind::Arch)};
llvm::SmallString<16> archDocFile{archFile};
if (!archFile.empty()) {
archFile += '.';
diff --git a/lib/Syntax/CMakeLists.txt b/lib/Syntax/CMakeLists.txt
index 6508584..1d20b1b 100644
--- a/lib/Syntax/CMakeLists.txt
+++ b/lib/Syntax/CMakeLists.txt
@@ -12,4 +12,5 @@
SyntaxFactory.cpp
SyntaxData.cpp
TypeSyntax.cpp
+ UnknownSyntax.cpp
)
diff --git a/lib/Syntax/DeclSyntax.cpp b/lib/Syntax/DeclSyntax.cpp
index f2fe755..c26d20e 100644
--- a/lib/Syntax/DeclSyntax.cpp
+++ b/lib/Syntax/DeclSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- DeclSyntax.cpp - Declaration Syntax Implementation -----*- C++ -*-===//
+//===--- DeclSyntax.cpp - Declaration Syntax Implementation ---------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -36,14 +36,16 @@
UnknownDeclSyntaxData::UnknownDeclSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent)
- : DeclSyntaxData(Raw, Parent, IndexInParent) {
- assert(Raw->Kind == SyntaxKind::UnknownStmt);
+ : UnknownSyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Kind == SyntaxKind::UnknownDecl);
}
RC<UnknownDeclSyntaxData>
UnknownDeclSyntaxData::make(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent) {
+ auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownDecl, Raw->Layout,
+ Raw->Presence);
return RC<UnknownDeclSyntaxData> {
new UnknownDeclSyntaxData {
Raw, Parent, IndexInParent
@@ -55,7 +57,7 @@
UnknownDeclSyntax::UnknownDeclSyntax(const RC<SyntaxData> Root,
const UnknownDeclSyntaxData *Data)
- : DeclSyntax(Root, Data) {}
+ : UnknownSyntax(Root, Data) {}
#pragma mark - declaration-members Data
diff --git a/lib/Syntax/ExprSyntax.cpp b/lib/Syntax/ExprSyntax.cpp
index 9df2740..b7d8be9 100644
--- a/lib/Syntax/ExprSyntax.cpp
+++ b/lib/Syntax/ExprSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- ExprSyntax.cpp - Swift Expression Syntax Impl. ---------*- C++ -*-===//
+//===--- ExprSyntax.cpp - Swift Expression Syntax Impl. -------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/Syntax/ExprSyntax.h"
+#include "swift/Syntax/GenericSyntax.h"
using namespace swift;
using namespace swift::syntax;
@@ -41,7 +42,7 @@
UnknownExprSyntaxData::UnknownExprSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent)
- : ExprSyntaxData(Raw, Parent, IndexInParent) {
+ : UnknownSyntaxData(Raw, Parent, IndexInParent) {
assert(Raw->Kind == SyntaxKind::UnknownExpr);
}
@@ -49,9 +50,11 @@
UnknownExprSyntaxData::make(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent) {
+ auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownExpr, Raw->Layout,
+ Raw->Presence);
return RC<UnknownExprSyntaxData> {
new UnknownExprSyntaxData {
- Raw, Parent, IndexInParent
+ UnknownRaw, Parent, IndexInParent
}
};
}
@@ -60,7 +63,7 @@
UnknownExprSyntax::UnknownExprSyntax(const RC<SyntaxData> Root,
const UnknownExprSyntaxData *Data)
- : ExprSyntax(Root, Data) {}
+ : UnknownSyntax(Root, Data) {}
#pragma mark - integer-literal-expression Data
@@ -97,7 +100,6 @@
return make(Raw);
}
-
#pragma mark - integer-literal-expression API
IntegerLiteralExprSyntax::
@@ -111,3 +113,428 @@
return Data->replaceChild<IntegerLiteralExprSyntax>(NewDigits,
Cursor::Digits);
}
+
+#pragma mark - symbolic-reference Data
+
+SymbolicReferenceExprSyntaxData::
+SymbolicReferenceExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
+ CursorIndex IndexInParent)
+ : ExprSyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Layout.size() == 2);
+ syntax_assert_child_token(Raw,
+ SymbolicReferenceExprSyntax::Cursor::Identifier, tok::identifier);
+ syntax_assert_child_kind(Raw,
+ SymbolicReferenceExprSyntax::Cursor::GenericArgumentClause,
+ SyntaxKind::GenericArgumentClause);
+}
+
+RC<SymbolicReferenceExprSyntaxData>
+SymbolicReferenceExprSyntaxData::make(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<SymbolicReferenceExprSyntaxData> {
+ new SymbolicReferenceExprSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<SymbolicReferenceExprSyntaxData>
+SymbolicReferenceExprSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::SymbolicReferenceExpr,
+ {
+ TokenSyntax::missingToken(tok::identifier, ""),
+ RawSyntax::missing(SyntaxKind::GenericArgumentClause),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - symbolic-reference API
+
+SymbolicReferenceExprSyntax::
+SymbolicReferenceExprSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : ExprSyntax(Root, Data) {}
+
+RC<TokenSyntax> SymbolicReferenceExprSyntax::getIdentifier() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Identifier));
+}
+
+SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax::
+withIdentifier(RC<TokenSyntax> NewIdentifier) const {
+ assert(NewIdentifier->getTokenKind() == tok::identifier);
+ return Data->replaceChild<SymbolicReferenceExprSyntax>(NewIdentifier,
+ Cursor::Identifier);
+}
+
+llvm::Optional<GenericArgumentClauseSyntax>
+SymbolicReferenceExprSyntax::getGenericArgumentClause() const {
+ auto RawClause = getRaw()->getChild(Cursor::GenericArgumentClause);
+ if (RawClause->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<SymbolicReferenceExprSyntax>();
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedGenericArgClause);
+ SyntaxData::realizeSyntaxNode<GenericArgumentClauseSyntax>(ChildPtr,
+ RawClause, MyData,
+ cursorIndex(Cursor::GenericArgumentClause));
+
+ return llvm::Optional<GenericArgumentClauseSyntax> {
+ GenericArgumentClauseSyntax {
+ Root,
+ MyData->CachedGenericArgClause.get()
+ }
+ };
+}
+
+SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax::
+withGenericArgumentClause(GenericArgumentClauseSyntax NewGenericArgs) const {
+ return Data->replaceChild<SymbolicReferenceExprSyntax>(
+ NewGenericArgs.getRaw(), Cursor::GenericArgumentClause);
+}
+
+#pragma mark - function-call-argument Data
+
+FunctionCallArgumentSyntaxData::
+FunctionCallArgumentSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ syntax_assert_child_token(Raw, FunctionCallArgumentSyntax::Cursor::Label,
+ tok::identifier);
+ syntax_assert_child_token_text(Raw,
+ FunctionCallArgumentSyntax::Cursor::Colon,
+ tok::colon, ":");
+ assert(
+ Raw->getChild(FunctionCallArgumentSyntax::Cursor::Expression)->isExpr());
+
+ syntax_assert_child_token_text(Raw,
+ FunctionCallArgumentSyntax::Cursor::Comma,
+ tok::comma, ",");
+}
+
+RC<FunctionCallArgumentSyntaxData>
+FunctionCallArgumentSyntaxData::make(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<FunctionCallArgumentSyntaxData> {
+ new FunctionCallArgumentSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionCallArgumentSyntaxData> FunctionCallArgumentSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgument,
+ {
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::colon, ":"),
+ RawSyntax::missing(SyntaxKind::MissingExpr),
+ TokenSyntax::missingToken(tok::comma, ",")
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - function-call-argument API
+
+FunctionCallArgumentSyntax::
+FunctionCallArgumentSyntax(const RC<SyntaxData> Root, const DataType *Data)
+ : Syntax(Root, Data) {}
+
+RC<TokenSyntax> FunctionCallArgumentSyntax::getLabel() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Label));
+}
+
+FunctionCallArgumentSyntax
+FunctionCallArgumentSyntax::withLabel(RC<TokenSyntax> NewLabel) const {
+ assert(NewLabel->getTokenKind() == tok::identifier);
+ return Data->replaceChild<FunctionCallArgumentSyntax>(NewLabel,
+ Cursor::Label);
+}
+
+RC<TokenSyntax> FunctionCallArgumentSyntax::getColonToken() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Colon));
+}
+
+FunctionCallArgumentSyntax
+FunctionCallArgumentSyntax::withColonToken(RC<TokenSyntax> NewColon) const {
+ syntax_assert_token_is(NewColon, tok::colon, ":");
+ return Data->replaceChild<FunctionCallArgumentSyntax>(NewColon,
+ Cursor::Colon);
+}
+
+llvm::Optional<ExprSyntax> FunctionCallArgumentSyntax::getExpression() const {
+
+ auto RawExpression = getRaw()->getChild(Cursor::Expression);
+ if (RawExpression->isMissing()) {
+ return llvm::None;
+ }
+
+ auto *MyData = getUnsafeData<FunctionCallArgumentSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedExpression);
+
+ SyntaxData::realizeSyntaxNode<ExprSyntax>(ChildPtr, RawExpression, MyData,
+ cursorIndex(Cursor::Expression));
+
+ return ExprSyntax { Root, MyData->CachedExpression.get() };
+}
+
+FunctionCallArgumentSyntax
+FunctionCallArgumentSyntax::withExpression(ExprSyntax NewExpression) const {
+ return Data->replaceChild<FunctionCallArgumentSyntax>(NewExpression.getRaw(),
+ Cursor::Expression);
+}
+
+RC<TokenSyntax> FunctionCallArgumentSyntax::getTrailingComma() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::Comma));
+}
+
+FunctionCallArgumentSyntax FunctionCallArgumentSyntax::
+withTrailingComma(RC<TokenSyntax> NewTrailingComma) const {
+ syntax_assert_token_is(NewTrailingComma, tok::comma, ",");
+ return Data->replaceChild<FunctionCallArgumentSyntax>(NewTrailingComma,
+ FunctionCallArgumentSyntax::Cursor::Comma);
+}
+
+#pragma mark - function-call-argument-list Data
+
+FunctionCallArgumentListSyntaxData::
+FunctionCallArgumentListSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+#ifndef NDEBUG
+ for (auto Child : Raw->Layout) {
+ assert(Child->Kind == SyntaxKind::FunctionCallArgument);
+ }
+#endif
+ for (size_t i = 0; i < Raw->Layout.size(); ++i) {
+ CachedArguments.emplace_back(nullptr);
+ }
+}
+
+RC<FunctionCallArgumentListSyntaxData>
+FunctionCallArgumentListSyntaxData::make(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<FunctionCallArgumentListSyntaxData> {
+ new FunctionCallArgumentListSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionCallArgumentListSyntaxData>
+FunctionCallArgumentListSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgumentList, {},
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+#pragma mark - function-call-argument-list API
+
+FunctionCallArgumentListSyntax::
+FunctionCallArgumentListSyntax(const RC<SyntaxData> Root,
+ const DataType *Data)
+ : Syntax(Root, Data) {}
+
+size_t
+FunctionCallArgumentListSyntax::getNumArguments() const {
+ return getRaw()->Layout.size();
+}
+
+FunctionCallArgumentSyntax
+FunctionCallArgumentListSyntax::getArgument(size_t Index) const {
+ assert(Index <= getRaw()->Layout.size());
+
+ auto RawArg = getRaw()->Layout[Index];
+
+ auto *MyData = getUnsafeData<FunctionCallArgumentListSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ MyData->CachedArguments.data() + Index);
+
+ SyntaxData::realizeSyntaxNode<FunctionCallArgumentSyntax>(ChildPtr, RawArg,
+ MyData,
+ Index);
+
+ return FunctionCallArgumentSyntax {
+ Root,
+ MyData->CachedArguments[Index].get()
+ };
+}
+
+FunctionCallArgumentListSyntax
+FunctionCallArgumentListSyntax::withAdditionalArgument(
+ FunctionCallArgumentSyntax AdditionalArgument) const {
+ auto NewRaw = getRaw()->append(AdditionalArgument.getRaw());
+ return Data->replaceSelf<FunctionCallArgumentListSyntax>(NewRaw);
+}
+
+#pragma mark - function-call-expression Data
+
+RC<FunctionCallArgumentListSyntaxData> CachedArgumentList;
+
+FunctionCallExprSyntaxData::FunctionCallExprSyntaxData(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent)
+ : ExprSyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->Layout.size() == 4);
+ assert(Raw->getChild(FunctionCallExprSyntax::Cursor::CalledExpression)
+ ->isExpr());
+ syntax_assert_child_token_text(Raw, FunctionCallExprSyntax::Cursor::LeftParen,
+ tok::l_paren, "(");
+ syntax_assert_child_kind(Raw, FunctionCallExprSyntax::Cursor::ArgumentList,
+ SyntaxKind::FunctionCallArgumentList);
+ syntax_assert_child_token_text(Raw,
+ FunctionCallExprSyntax::Cursor::RightParen,
+ tok::r_paren, ")");
+}
+
+RC<FunctionCallExprSyntaxData>
+FunctionCallExprSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+ return RC<FunctionCallExprSyntaxData> {
+ new FunctionCallExprSyntaxData {
+ Raw, Parent, IndexInParent
+ }
+ };
+}
+
+RC<FunctionCallExprSyntaxData> FunctionCallExprSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallExpr,
+ {
+ RawSyntax::missing(SyntaxKind::MissingExpr),
+ TokenSyntax::missingToken(tok::l_paren, "("),
+ RawSyntax::missing(SyntaxKind::FunctionCallArgumentList),
+ TokenSyntax::missingToken(tok::r_paren, ")"),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
+
+#pragma mark - function-call-expression API
+
+FunctionCallExprSyntax::FunctionCallExprSyntax(const RC<SyntaxData> Root,
+ const DataType *Data)
+ : ExprSyntax(Root, Data) {}
+
+ExprSyntax FunctionCallExprSyntax::getCalledExpression() const {
+ auto RawArg = getRaw()->getChild(Cursor::CalledExpression);
+
+ auto *MyData = getUnsafeData<FunctionCallExprSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedCalledExpression);
+
+ SyntaxData::realizeSyntaxNode<ExprSyntax>(
+ ChildPtr, RawArg, MyData, cursorIndex(Cursor::CalledExpression));
+
+ return ExprSyntax {
+ Root,
+ MyData->CachedCalledExpression.get(),
+ };
+}
+
+FunctionCallExprSyntax FunctionCallExprSyntax::
+withCalledExpression(ExprSyntax NewBaseExpression) const {
+ return Data->replaceChild<FunctionCallExprSyntax>(NewBaseExpression.getRaw(),
+ Cursor::CalledExpression);
+}
+
+RC<TokenSyntax> FunctionCallExprSyntax::getLeftParen() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::LeftParen));
+}
+
+FunctionCallExprSyntax
+FunctionCallExprSyntax::withLeftParen(RC<TokenSyntax> NewLeftParen) const {
+ syntax_assert_token_is(NewLeftParen, tok::l_paren, "(");
+ return Data->replaceChild<FunctionCallExprSyntax>(NewLeftParen,
+ Cursor::LeftParen);
+}
+
+FunctionCallArgumentListSyntax FunctionCallExprSyntax::getArgumentList() const {
+ auto RawArg = getRaw()->getChild(Cursor::ArgumentList);
+
+ auto *MyData = getUnsafeData<FunctionCallExprSyntax>();
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ &MyData->CachedArgumentList);
+
+ SyntaxData::realizeSyntaxNode<FunctionCallArgumentListSyntax>(
+ ChildPtr, RawArg, MyData, cursorIndex(Cursor::ArgumentList));
+
+ return FunctionCallArgumentListSyntax {
+ Root,
+ MyData->CachedArgumentList.get(),
+ };
+}
+
+FunctionCallExprSyntax FunctionCallExprSyntax::
+withArgumentList(FunctionCallArgumentListSyntax NewArgumentList) const {
+ return Data->replaceChild<FunctionCallExprSyntax>(NewArgumentList.getRaw(),
+ Cursor::ArgumentList);
+}
+
+RC<TokenSyntax> FunctionCallExprSyntax::getRightParen() const {
+ return cast<TokenSyntax>(getRaw()->getChild(Cursor::RightParen));
+}
+
+FunctionCallExprSyntax
+FunctionCallExprSyntax::withRightParen(RC<TokenSyntax> NewRightParen) const {
+ syntax_assert_token_is(NewRightParen, tok::r_paren, ")");
+ return Data->replaceChild<FunctionCallExprSyntax>(NewRightParen,
+ Cursor::RightParen);
+}
+
+#pragma mark - function-call-expression Builder
+
+FunctionCallExprSyntaxBuilder::FunctionCallExprSyntaxBuilder()
+ : CallLayout(FunctionCallExprSyntaxData::makeBlank()->getRaw()->Layout),
+ ListLayout(
+ FunctionCallArgumentListSyntaxData::makeBlank()->getRaw()->Layout) {}
+
+FunctionCallExprSyntaxBuilder &
+FunctionCallExprSyntaxBuilder::useLeftParen(RC<TokenSyntax> LeftParen) {
+ syntax_assert_token_is(LeftParen, tok::l_paren, "(");
+ CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::LeftParen)]
+ = LeftParen;
+ return *this;
+}
+
+FunctionCallExprSyntaxBuilder &FunctionCallExprSyntaxBuilder::
+appendArgument(FunctionCallArgumentSyntax AdditionalArgument) {
+ ListLayout.push_back(AdditionalArgument.getRaw());
+ return *this;
+}
+
+FunctionCallExprSyntaxBuilder &FunctionCallExprSyntaxBuilder::
+useCalledExpression(ExprSyntax CalledExpression) {
+ CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::CalledExpression)]
+ = CalledExpression.getRaw();
+ return *this;
+}
+
+FunctionCallExprSyntaxBuilder &
+FunctionCallExprSyntaxBuilder::useRightParen(RC<TokenSyntax> RightParen) {
+ syntax_assert_token_is(RightParen, tok::r_paren, ")");
+ CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::RightParen)]
+ = RightParen;
+ return *this;
+}
+
+FunctionCallExprSyntax FunctionCallExprSyntaxBuilder::build() const {
+ auto RawArgs = RawSyntax::make(SyntaxKind::FunctionCallArgumentList,
+ ListLayout, SourcePresence::Present);
+ auto RawCall = RawSyntax::make(SyntaxKind::FunctionCallExpr, CallLayout,
+ SourcePresence::Present)
+ ->replaceChild(FunctionCallExprSyntax::Cursor::ArgumentList, RawArgs);
+ auto Data = FunctionCallExprSyntaxData::make(RawCall);
+ return { Data, Data.get() };
+}
diff --git a/lib/Syntax/Format.cpp b/lib/Syntax/Format.cpp
index 94433ac..1da34c7 100644
--- a/lib/Syntax/Format.cpp
+++ b/lib/Syntax/Format.cpp
@@ -1,4 +1,4 @@
-//===--- Format.cpp - Declaration Syntax Formatting Impl. -------*- C++ -*-===//
+//===--- Format.cpp - Declaration Syntax Formatting Impl. -----------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Syntax/GenericSyntax.cpp b/lib/Syntax/GenericSyntax.cpp
index 84ca22e..e48e33a 100644
--- a/lib/Syntax/GenericSyntax.cpp
+++ b/lib/Syntax/GenericSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- GenericSyntax.cpp - Swift Generic Syntax Implementation *- C++ -*-===//
+//===--- GenericSyntax.cpp - Swift Generic Syntax Implementation ----------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Syntax/LegacyASTTransformer.cpp b/lib/Syntax/LegacyASTTransformer.cpp
index f6c4edd..4356df0 100644
--- a/lib/Syntax/LegacyASTTransformer.cpp
+++ b/lib/Syntax/LegacyASTTransformer.cpp
@@ -1,4 +1,4 @@
-//===--- LegacyASTTransformer.cpp - Swift lib/AST -> lib/Syntax -*- C++ -*-===//
+//===--- LegacyASTTransformer.cpp - Swift lib/AST -> lib/Syntax -----------===//
//
// This source file is part of the Swift.org open source project
//
@@ -19,6 +19,7 @@
#include "swift/Syntax/StmtSyntax.h"
#include "swift/Syntax/SyntaxFactory.h"
#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
using namespace swift;
using namespace swift::syntax;
@@ -500,7 +501,7 @@
RC<SyntaxData>
LegacyASTTransformer::visitWhileStmt(WhileStmt *S,
const SyntaxData *Parent,
- const CursorIndex IndexInParent) {
+ const CursorIndex IndexInParent) {
return getUnknownStmt(S);
}
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 1d37ee8..30d5508 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- RawSyntax.cpp - Swift Raw Syntax Implementation --------*- C++ -*-===//
+//===--- RawSyntax.cpp - Swift Raw Syntax Implementation ------------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Syntax/Status.md b/lib/Syntax/Status.md
index 97fba0c..1c8a324 100644
--- a/lib/Syntax/Status.md
+++ b/lib/Syntax/Status.md
@@ -72,6 +72,16 @@
- octal-literal
- `IntegerLiteralExprSyntax`
+- function-call-argument
+ - `FunctionCallArgumentSyntax`
+
+- function-call-argument-list
+ - `FunctionCallArgumentListSyntax`
+
+- function-call-expression
+- function-call-argument-clause
+ - `FunctionCallExprSyntax`
+
### Types
- type
@@ -105,6 +115,15 @@
- metatype-type
- `MetatypeTypeSyntax`
+- tuple-type
+ - `TupleTypeSyntax`
+
+- tuple-type-element
+ - `TupleTypeElementSyntax`
+
+- tuple-type-element-list
+ - `TupleTypeElementListSyntax`
+
### Type Attributes
- attribute
@@ -181,165 +200,163 @@
## Unrepresented Grammar Productions
-- argument-names
+These are categorized somewhat by difficulty and priority.
+
+### Easy
+
- array-literal
- array-literal-items
- as-pattern
-- availability-argument
-- availability-arguments
-- availability-condition
-- binary-expression
-- binary-expressions
-- binary-operator
-- branch-statement
-- capture-list
-- capture-list-item
-- capture-list-items
-- capture-specifier
- case-condition
-- case-item-list
- case-label
-- catch-clause
-- catch-clauses
-- class-declaration
-- closure-expression
-- closure-parameter
-- closure-parameter-clause
-- closure-parameter-list
-- closure-signature
-- compilation-condition
-- compiler-control-statement
-- condition
-- condition-list
-- conditional-compilation-block
-- conditional-operator
-- constant-declaration
-- declaration-modifier
- declaration-modifiers
-- defer-statement
-- deinitializer-declaration
-- dictionary-literal
-- dictionary-literal-item
-- dictionary-literal-items
-- didSet-clause
-- do-statement
+ - declaration-modifier
- dynamic-type-expression
-- else-clause
-- else-directive-clause
-- elseif-directive-clause
-- elseif-directive-clauses
-- enum-case-pattern
-- enum-declaration
-- explicit-member-expression
-- expression-list
-- expression-pattern
-- extension-declaration
-- extension-members
- floating-point-literal
-- for-in-statement
- forced-value-expression
-- function-body
-- function-call-argument
-- function-call-argument-clause
-- function-call-argument-list
-- function-call-expression
-- function-declaration
-- function-result
-- function-signature
-- getter-clause
-- getter-keyword-clause
-- getter-setter-block
-- getter-setter-keyword-block
-- guard-statement
- identifier-list
-- if-directive-clause
-- if-statement
- implicit-member-expression
-- import-declaration
- import-path
- in-out-expression
-- infix-operator-declaration
-- infix-operator-group
-- initializer-declaration
-- initializer-head
-- interpolated-string-literal
- interpolated-text
- interpolated-text-item
- is-pattern
- key-path-expression
- line-control-statement
-- operator-declaration
-- optional-binding-condition
- optional-chaining-expression
- optional-pattern
-- parameter
-- parameter-clause
-- parameter-list
- parenthesized-expression
-- pattern
-- pattern-initializer
-- pattern-initializer-list
- platform-condition
- platform-version
-- playground-literal
- postfix-operator-declaration
- precedence-group-assignment
- precedence-group-associativity
-- precedence-group-attribute
-- precedence-group-attributes
-- precedence-group-declaration
- precedence-group-names
-- precedence-group-relation
-- prefix-expression
-- prefix-operator
-- prefix-operator-declaration
-- primary-expression
-- protocol-associated-type-declaration
-- protocol-composition-type
-- protocol-declaration
-- repeat-while-statement
-- selector-expression
-- setter-clause
-- setter-keyword-clause
-- setter-name
- statement-label
- static-string-literal
-- string-literal
-- subscript-declaration
- swift-version
-- switch-case
-- switch-cases
-- switch-statement
- throw-statement
-- tuple-element
-- tuple-element-list
-- tuple-expression
-- tuple-pattern
-- tuple-pattern-element
-- tuple-pattern-element-list
-- tuple-type
-- tuple-type-element
-- tuple-type-element-list
-- type-casting-operator
-- type-casting-pattern
- value-binding-pattern
-- variable-declaration
- where-clause
-- where-expression
+- dictionary-literal
+ - dictionary-literal-items
+ - dictionary-literal-item
+- capture-list
+ - capture-list-items
+ - capture-list-item
+- defer-statement
+
+### Medium
+
+- else-directive-clause
+- elseif-directive-clauses
+ - elseif-directive-clause
+- precedence-group-declaration
+- precedence-group-relation
+- expression-list
+- availability-condition
+ - availability-arguments
+ - availability-argument
+- switch-cases
+ - switch-case
+- constant-declaration
+- catch-clauses
+ - catch-clause
+- variable-declaration
+- do-statement
+- for-in-statement
+- guard-statement
+- case-item-list
+- import-declaration
+- if-directive-clause
+- if-statement
+ - else-clause
+- protocol-associated-type-declaration
+- repeat-while-statement
- while-statement
+- tuple-expression
+ - tuple-element-list
+ - tuple-element
+- tuple-pattern
+ - tuple-pattern-element-list
+ - tuple-pattern-element
+- switch-statement
+- explicit-member-expression
+- optional-binding-condition
+- operator-declaration
+- selector-expression
+- protocol-composition-type
+- conditional-operator
+- deinitializer-declaration
+- didSet-clause
- willSet-clause
-- willSet-didSet-block
+- pattern-initializer-list
+ - pattern-initializer
+- prefix-expression
+- prefix-operator-declaration
+- infix-operator-declaration
+ - infix-operator-group
+- binary-expression
+
+### Hard
+
+- protocol-declaration
+- closure-expression
+ - closure-signature
+ - closure-parameter-clause
+ - closure-parameter-list
+ - closure-parameter
+- extension-declaration
+- enum-declaration
+- class-declaration
+- getter-setter-block
+ - getter-setter-keyword-block
+ - getter-keyword-clause
+ - getter-clause
+ - setter-keyword-clause
+ - setter-clause
+ - setter-name
+- subscript-declaration
+- function-declaration
+ - function-body
+ - function-result
+ - function-signature
+ - parameter-clause
+ - parameter-list
+ - parameter
+- enum-case-pattern
+- initializer-declaration
+ - initializer-head
+- interpolated-string-literal
+- conditional-compilation-block
## Trivial and Intermediate Grammar Productions
+- binary-expressions
+- binary-operator
+- compilation-condition
+- capture-specifier
+- precedence-group-attributes
+- precedence-group-attribute
+- prefix-operator
+- type-casting-operator
+- willSet-didSet-block
- architecture
+- string-literal
+- argument-names
- array-literal-item
+- type-casting-pattern
- assignment-operator
+- expression-pattern
- binary-digit
- binary-literal-character
- binary-literal-characters
+- branch-statement
- class-member
- class-requirement
+- condition
+- condition-list
+- compiler-control-statement
- control-transfer-statement
- decimal-digit
- decimal-digits
@@ -369,6 +386,7 @@
- identifier-characters
- identifier-head
- if-directive
+- where-expression
- implicit-parameter-name
- initializer
- initializer-body
@@ -388,6 +406,7 @@
- operator-character
- operator-characters
- operator-head
+- pattern
- postfix-expression
- postfix-operator
- postfix-self-expression
@@ -396,6 +415,7 @@
- protocol-member
- protocol-member-declaration
- protocol-members
+- extension-members
- protocol-method-declaration
- protocol-property-declaration
- protocol-subscript-declaration
@@ -407,6 +427,7 @@
- raw-value-style-enum-case
- raw-value-style-enum-case-clause
- raw-value-style-enum-case-list
+- playground-literal
- raw-value-style-enum-member
- raw-value-style-enum-members
- requirement
@@ -436,9 +457,5 @@
- variable-declaration-head
- wildcard-expression
- wildcard-pattern
-
-## Intermediate Grammar Productions
-
-These productions don't need to be represented directly in a class hierarchy.
-
+- primary-expression
- generic-argument
diff --git a/lib/Syntax/StmtSyntax.cpp b/lib/Syntax/StmtSyntax.cpp
index 7f32017..89b272c 100644
--- a/lib/Syntax/StmtSyntax.cpp
+++ b/lib/Syntax/StmtSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- StmtSyntax.cpp - Swift Statement Syntax Implementation -*- C++ -*-===//
+//===--- StmtSyntax.cpp - Swift Statement Syntax Implementation -----------===//
//
// This source file is part of the Swift.org open source project
//
@@ -27,7 +27,7 @@
UnknownStmtSyntaxData::UnknownStmtSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent)
- : StmtSyntaxData(Raw, Parent, IndexInParent) {
+ : UnknownSyntaxData(Raw, Parent, IndexInParent) {
assert(Raw->Kind == SyntaxKind::UnknownStmt);
}
@@ -35,9 +35,11 @@
UnknownStmtSyntaxData::make(RC<RawSyntax> Raw,
const SyntaxData *Parent,
CursorIndex IndexInParent) {
+ auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownStmt, Raw->Layout,
+ Raw->Presence);
return RC<UnknownStmtSyntaxData> {
new UnknownStmtSyntaxData {
- Raw, Parent, IndexInParent
+ UnknownRaw, Parent, IndexInParent
}
};
}
@@ -46,7 +48,7 @@
UnknownStmtSyntax::UnknownStmtSyntax(const RC<SyntaxData> Root,
const UnknownStmtSyntaxData *Data)
- : StmtSyntax(Root, Data) {}
+ : UnknownSyntax(Root, Data) {}
#pragma mark fallthrough-statement Data
diff --git a/lib/Syntax/Syntax.cpp b/lib/Syntax/Syntax.cpp
index 0d7cc30..bd4d914 100644
--- a/lib/Syntax/Syntax.cpp
+++ b/lib/Syntax/Syntax.cpp
@@ -1,4 +1,4 @@
-//===--- Syntax.cpp - Swift Syntax Implementation ---------------*- C++ -*-===//
+//===--- Syntax.cpp - Swift Syntax Implementation -------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -55,16 +55,7 @@
return Data->isExpr();
}
-#pragma mark - unknown-syntax API
-
-UnknownSyntax::UnknownSyntax(const RC<SyntaxData> Root,
- UnknownSyntaxData *Data)
- : Syntax(Root, Data) {}
-
-UnknownSyntax UnknownSyntax::make(RC<RawSyntax> Raw) {
- auto Data = UnknownSyntaxData::make(Raw);
- return UnknownSyntax {
- Data, Data.get()
- };
+bool Syntax::isUnknown() const {
+ return Data->isUnknown();
}
diff --git a/lib/Syntax/SyntaxData.cpp b/lib/Syntax/SyntaxData.cpp
index 56ecd4b..bc21dbf 100644
--- a/lib/Syntax/SyntaxData.cpp
+++ b/lib/Syntax/SyntaxData.cpp
@@ -1,4 +1,4 @@
-//===--- SyntaxData.cpp - Swift Syntax Data Implementation ------*- C++ -*-===//
+//===--- SyntaxData.cpp - Swift Syntax Data Implementation ----------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -15,6 +15,7 @@
#include "swift/Syntax/GenericSyntax.h"
#include "swift/Syntax/TypeSyntax.h"
#include "swift/Syntax/StmtSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
using namespace swift;
using namespace swift::syntax;
@@ -61,21 +62,10 @@
return Raw->isExpr();
}
+bool SyntaxData::isUnknown() const {
+ return Raw->isUnknown();
+}
+
void SyntaxData::dump(llvm::raw_ostream &OS) const {
Raw->dump(OS, 0);
}
-
-#pragma mark - unknown-syntax Data
-
-RC<UnknownSyntaxData> UnknownSyntaxData::make(RC<RawSyntax> Raw,
- const SyntaxData *Parent,
- CursorIndex IndexInParent) {
- return RC<UnknownSyntaxData> {
- new UnknownSyntaxData { Raw, Parent, IndexInParent }
- };
-}
-
-bool UnknownSyntaxData::classof(const SyntaxData *SD) {
- return SD->getKind() == SyntaxKind::Unknown;
-}
-
diff --git a/lib/Syntax/SyntaxFactory.cpp b/lib/Syntax/SyntaxFactory.cpp
index be37ef9..cd495f2 100644
--- a/lib/Syntax/SyntaxFactory.cpp
+++ b/lib/Syntax/SyntaxFactory.cpp
@@ -1,4 +1,4 @@
-//===--- SyntaxFactory.cpp - Swift Syntax Builder Implementation *- C++ -*-===//
+//===--- SyntaxFactory.cpp - Swift Syntax Builder Implementation ----------===//
//
// This source file is part of the Swift.org open source project
//
@@ -18,6 +18,7 @@
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxFactory.h"
#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
using namespace swift;
using namespace swift::syntax;
@@ -324,6 +325,8 @@
#pragma mark - Expressions
+#pragma mark - integer-literal-expression
+
IntegerLiteralExprSyntax
SyntaxFactory::makeIntegerLiteralExpr(RC<TokenSyntax> Sign,
RC<TokenSyntax> Digits) {
@@ -348,6 +351,101 @@
return { Data, Data.get() };
}
+#pragma mark - symbolic-reference
+
+SymbolicReferenceExprSyntax
+SyntaxFactory::makeSymbolicReferenceExpr(RC<TokenSyntax> Identifier,
+ llvm::Optional<GenericArgumentClauseSyntax> GenericArgs) {
+ auto Raw = RawSyntax::make(SyntaxKind::SymbolicReferenceExpr,
+ {
+ Identifier,
+ GenericArgs.hasValue()
+ ? GenericArgs.getValue().getRaw()
+ : RawSyntax::missing(SyntaxKind::GenericArgumentClause)
+ },
+ SourcePresence::Present);
+ auto Data = SymbolicReferenceExprSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+SymbolicReferenceExprSyntax SyntaxFactory::makeBlankSymbolicReferenceExpr() {
+ auto Data = SymbolicReferenceExprSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+#pragma mark - function-call-argument
+
+FunctionCallArgumentSyntax SyntaxFactory::makeBlankFunctionCallArgument() {
+ auto Data = FunctionCallArgumentSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+FunctionCallArgumentSyntax
+SyntaxFactory::makeFunctionCallArgument(RC<TokenSyntax> Label,
+ RC<TokenSyntax> Colon,
+ ExprSyntax ExpressionArgument,
+ RC<TokenSyntax> TrailingComma) {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgument,
+ {
+ Label,
+ Colon,
+ ExpressionArgument.getRaw(),
+ TrailingComma
+ },
+ SourcePresence::Present);
+ auto Data = FunctionCallArgumentSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+#pragma mark - function-call-argument-list
+
+/// Make a function call argument list with the given arguments.
+FunctionCallArgumentListSyntax
+SyntaxFactory::makeFunctionCallArgumentList(
+ std::vector<FunctionCallArgumentSyntax> Arguments) {
+ RawSyntax::LayoutList Layout;
+ for (const auto &Arg : Arguments) {
+ Layout.push_back(Arg.getRaw());
+ }
+
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgumentList, Layout,
+ SourcePresence::Present);
+ auto Data = FunctionCallArgumentListSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+
+FunctionCallArgumentListSyntax
+SyntaxFactory::makeBlankFunctionCallArgumentList() {
+ auto Data = FunctionCallArgumentListSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
+#pragma mark - function-call-expression
+
+FunctionCallExprSyntax
+SyntaxFactory::makeFunctionCallExpr(ExprSyntax CalledExpr,
+ RC<TokenSyntax> LeftParen,
+ FunctionCallArgumentListSyntax Arguments,
+ RC<TokenSyntax> RightParen) {
+ auto Raw = RawSyntax::make(SyntaxKind::FunctionCallExpr,
+ {
+ CalledExpr.getRaw(),
+ LeftParen,
+ Arguments.getRaw(),
+ RightParen
+ },
+ SourcePresence::Present);
+ auto Data = FunctionCallExprSyntaxData::make(Raw);
+ return { Data, Data.get() };
+}
+
+
+FunctionCallExprSyntax SyntaxFactory::makeBlankFunctionCallExpr() {
+ auto Data = FunctionCallExprSyntaxData::makeBlank();
+ return { Data, Data.get() };
+}
+
#pragma mark - Tokens
@@ -771,16 +869,7 @@
}
TypeAttributeSyntax SyntaxFactory::makeBlankTypeAttribute() {
- auto Raw = RawSyntax::make(SyntaxKind::TypeAttribute,
- {
- TokenSyntax::missingToken(tok::at_sign, "@"),
- TokenSyntax::missingToken(tok::identifier, ""),
- TokenSyntax::missingToken(tok::l_paren, "("),
- RawSyntax::missing(SyntaxKind::BalancedTokens),
- TokenSyntax::missingToken(tok::r_paren, ")"),
- },
- SourcePresence::Present);
- auto Data = TypeAttributeSyntaxData::make(Raw);
+ auto Data = TypeAttributeSyntaxData::makeBlank();
return TypeAttributeSyntax { Data, Data.get() };
}
@@ -798,10 +887,7 @@
}
BalancedTokensSyntax SyntaxFactory::makeBlankBalancedTokens() {
- auto Raw = RawSyntax::make(SyntaxKind::BalancedTokens,
- {},
- SourcePresence::Present);
- auto Data = BalancedTokensSyntaxData::make(Raw);
+ auto Data = BalancedTokensSyntaxData::makeBlank();
return BalancedTokensSyntax { Data, Data.get() };
}
diff --git a/lib/Syntax/TokenSyntax.cpp b/lib/Syntax/TokenSyntax.cpp
index 297fb34..2212236 100644
--- a/lib/Syntax/TokenSyntax.cpp
+++ b/lib/Syntax/TokenSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- TokenSyntax.cpp - Swift Token Syntax Implementation ----*- C++ -*-===//
+//===--- TokenSyntax.cpp - Swift Token Syntax Implementation --------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Syntax/Trivia.cpp b/lib/Syntax/Trivia.cpp
index ce1008c..f57738e 100644
--- a/lib/Syntax/Trivia.cpp
+++ b/lib/Syntax/Trivia.cpp
@@ -1,4 +1,4 @@
-//===--- Syntax.cpp - Swift Syntax Trivia Implementation --------*- C++ -*-===//
+//===--- Trivia.cpp - Swift Syntax Trivia Implementation ------------------===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/lib/Syntax/TypeSyntax.cpp b/lib/Syntax/TypeSyntax.cpp
index 5b9d158..d36ecae 100644
--- a/lib/Syntax/TypeSyntax.cpp
+++ b/lib/Syntax/TypeSyntax.cpp
@@ -1,4 +1,4 @@
-//===--- TypeSyntax.cpp - Swift Type Syntax Implementation ------*- C++ -*-===//
+//===--- TypeSyntax.cpp - Swift Type Syntax Implementation ----------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -118,6 +118,19 @@
};
}
+RC<TypeAttributeSyntaxData> TypeAttributeSyntaxData::makeBlank() {
+ auto Raw = RawSyntax::make(SyntaxKind::TypeAttribute,
+ {
+ TokenSyntax::missingToken(tok::at_sign, "@"),
+ TokenSyntax::missingToken(tok::identifier, ""),
+ TokenSyntax::missingToken(tok::l_paren, "("),
+ RawSyntax::missing(SyntaxKind::BalancedTokens),
+ TokenSyntax::missingToken(tok::r_paren, ")"),
+ },
+ SourcePresence::Present);
+ return make(Raw);
+}
+
#pragma mark - type-attribute API
TypeAttributeSyntax::TypeAttributeSyntax(RC<SyntaxData> Root,
diff --git a/lib/Syntax/UnknownSyntax.cpp b/lib/Syntax/UnknownSyntax.cpp
new file mode 100644
index 0000000..6533926
--- /dev/null
+++ b/lib/Syntax/UnknownSyntax.cpp
@@ -0,0 +1,99 @@
+//===--- UnknownSyntax.cpp - Swift Unknown Syntax Implementation ---------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/UnknownSyntax.h"
+
+using namespace swift;
+using namespace swift::syntax;
+
+#pragma mark - unknown-syntax Data
+
+UnknownSyntaxData::UnknownSyntaxData(const RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ const CursorIndex IndexInParent)
+ : SyntaxData(Raw, Parent, IndexInParent) {
+ assert(Raw->isUnknown());
+ for (auto RawChild : Raw->Layout) {
+ if (!RawChild->isToken()) {
+ CachedChildren.emplace_back(nullptr);
+ }
+ }
+}
+
+RC<UnknownSyntaxData> UnknownSyntaxData::make(RC<RawSyntax> Raw,
+ const SyntaxData *Parent,
+ CursorIndex IndexInParent) {
+
+ auto UnknownRaw = RawSyntax::make(SyntaxKind::Unknown, Raw->Layout,
+ Raw->Presence);
+
+ return RC<UnknownSyntaxData> {
+ new UnknownSyntaxData { UnknownRaw, Parent, IndexInParent }
+ };
+}
+
+#pragma mark - unknown-syntax API
+
+UnknownSyntax::UnknownSyntax(const RC<SyntaxData> Root,
+ const UnknownSyntaxData *Data)
+ : Syntax(Root, Data) {}
+
+size_t UnknownSyntax::getNumChildren() const {
+ size_t Count = 0;
+ for (auto Child : getRaw()->Layout) {
+ if (Child->isToken()) {
+ continue;
+ }
+ ++Count;
+ }
+ return Count;
+}
+
+Syntax UnknownSyntax::getChild(const size_t N) const {
+ auto *MyData = getUnsafeData<UnknownSyntax>();
+
+ if (auto RealizedChild = MyData->CachedChildren[N]) {
+ return Syntax { Root, RealizedChild.get() };
+ }
+
+ assert(N < getNumChildren());
+ assert(N < getRaw()->Layout.size());
+
+ CursorIndex ChildLayoutIndex = 0;
+
+ for (size_t LayoutIndex = 0, Left = N;
+ LayoutIndex < getRaw()->Layout.size();
+ ++LayoutIndex) {
+ auto Child = getRaw()->Layout[LayoutIndex];
+ if (Child->isToken()) {
+ continue;
+ }
+ ChildLayoutIndex = LayoutIndex;
+ if (Left == 0) {
+ break;
+ }
+ --Left;
+ }
+
+ auto RawChild = getRaw()->Layout[ChildLayoutIndex];
+ assert(RawChild->Kind != SyntaxKind::Token);
+
+ auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
+ MyData->CachedChildren.data() + N);
+
+ SyntaxData::realizeSyntaxNode<Syntax>(ChildPtr, RawChild, MyData,
+ ChildLayoutIndex);
+
+ return Syntax { Root, MyData->CachedChildren[N].get() };
+}
+
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 7b59508..95f102b 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -745,6 +745,9 @@
LLVM_ATTRIBUTE_NOINLINE
bool tryIncrementSlow(RefCountBits oldbits);
+ LLVM_ATTRIBUTE_NOINLINE
+ bool tryIncrementNonAtomicSlow(RefCountBits oldbits);
+
public:
enum Initialized_t { Initialized };
@@ -859,6 +862,19 @@
return true;
}
+ bool tryIncrementNonAtomic() {
+ auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
+ if (!oldbits.hasSideTable() && oldbits.getIsDeiniting())
+ return false;
+
+ auto newbits = oldbits;
+ bool fast = newbits.incrementStrongExtraRefCount(1);
+ if (!fast)
+ return tryIncrementNonAtomicSlow(oldbits);
+ refCounts.store(newbits, std::memory_order_relaxed);
+ return true;
+ }
+
// Simultaneously clear the pinned flag and decrement the reference
// count. Call _swift_release_dealloc() if the reference count goes to zero.
//
@@ -881,6 +897,11 @@
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
+ bool decrementShouldDeinitNonAtomic(uint32_t dec) {
+ return doDecrementNonAtomic<DontClearPinnedFlag, DontPerformDeinit>(dec);
+ }
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
void decrementAndMaybeDeinit(uint32_t dec) {
doDecrement<DontClearPinnedFlag, DoPerformDeinit>(dec);
}
@@ -979,7 +1000,12 @@
// object may have a side table entry.
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
bool doDecrementSideTable(RefCountBits oldbits, uint32_t dec);
-
+
+ // Second slow path of doDecrementNonAtomic, where the
+ // object may have a side table entry.
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
+ bool doDecrementNonAtomicSideTable(RefCountBits oldbits, uint32_t dec);
+
// First slow path of doDecrement, where the object may need to be deinited.
// Side table is handled in the second slow path, doDecrementSideTable().
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1021,6 +1047,42 @@
return deinitNow;
}
+
+ // First slow path of doDecrementNonAtomic, where the object may need to be deinited.
+ // Side table is handled in the second slow path, doDecrementNonAtomicSideTable().
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
+ bool doDecrementNonAtomicSlow(RefCountBits oldbits, uint32_t dec) {
+ bool deinitNow;
+ auto newbits = oldbits;
+
+ bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
+ if (fast) {
+ // Decrement completed normally. New refcount is not zero.
+ deinitNow = false;
+ }
+ else if (oldbits.hasSideTable()) {
+ // Decrement failed because we're on some other slow path.
+ return doDecrementNonAtomicSideTable<clearPinnedFlag,
+ performDeinit>(oldbits, dec);
+ }
+ else {
+ // Decrement underflowed. Begin deinit.
+ // LIVE -> DEINITING
+ deinitNow = true;
+ assert(!oldbits.getIsDeiniting()); // FIXME: make this an error?
+ newbits = oldbits; // Undo failed decrement of newbits.
+ newbits.setStrongExtraRefCount(0);
+ newbits.setIsDeiniting(true);
+ if (clearPinnedFlag)
+ newbits.setIsPinned(false);
+ }
+ refCounts.store(newbits, std::memory_order_relaxed);
+ if (performDeinit && deinitNow) {
+ _swift_release_dealloc(getHeapObject());
+ }
+
+ return deinitNow;
+ }
public: // FIXME: access control hack
@@ -1045,8 +1107,6 @@
return false; // don't deinit
}
-
- private:
// This is independently specialized below for inline and out-of-line use.
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1072,6 +1132,18 @@
std::memory_order_relaxed));
}
+ void incrementUnownedNonAtomic(uint32_t inc) {
+ auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
+ if (oldbits.hasSideTable())
+ return oldbits.getSideTable()->incrementUnownedNonAtomic(inc);
+
+ auto newbits = oldbits;
+ assert(newbits.getUnownedRefCount() != 0);
+ newbits.incrementUnownedRefCount(inc);
+ // FIXME: overflow check?
+ refCounts.store(newbits, std::memory_order_relaxed);
+ }
+
// Decrement the unowned reference count.
// Return true if the caller should free the object.
bool decrementUnownedShouldFree(uint32_t dec) {
@@ -1086,7 +1158,7 @@
newbits = oldbits;
newbits.decrementUnownedRefCount(dec);
if (newbits.getUnownedRefCount() == 0) {
- // DEINITED -> FREED or DEINITED -> DEAD
+ // DEINITED -> FREED, or DEINITED -> DEAD
// Caller will free the object. Weak decrement is handled by
// HeapObjectSideTableEntry::decrementUnownedShouldFree.
assert(newbits.getIsDeiniting());
@@ -1100,6 +1172,29 @@
return performFree;
}
+ bool decrementUnownedShouldFreeNonAtomic(uint32_t dec) {
+ auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
+
+ if (oldbits.hasSideTable())
+ return oldbits.getSideTable()->decrementUnownedShouldFreeNonAtomic(dec);
+
+ bool performFree;
+ auto newbits = oldbits;
+ newbits.decrementUnownedRefCount(dec);
+ if (newbits.getUnownedRefCount() == 0) {
+ // DEINITED -> FREED, or DEINITED -> DEAD
+ // Caller will free the object. Weak decrement is handled by
+ // HeapObjectSideTableEntry::decrementUnownedShouldFreeNonAtomic.
+ assert(newbits.getIsDeiniting());
+ performFree = true;
+ } else {
+ performFree = false;
+ }
+ // FIXME: underflow check?
+ refCounts.store(newbits, std::memory_order_relaxed);
+ return performFree;
+ }
+
// Return unowned reference count.
// Note that this is not equal to the number of outstanding unowned pointers.
uint32_t getUnownedCount() const {
@@ -1146,6 +1241,16 @@
return performFree;
}
+
+ bool decrementWeakShouldCleanUpNonAtomic() {
+ auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
+
+ auto newbits = oldbits;
+ auto performFree = newbits.decrementWeakRefCount();
+ refCounts.store(newbits, std::memory_order_relaxed);
+
+ return performFree;
+ }
// Return weak reference count.
// Note that this is not equal to the number of outstanding weak pointers.
@@ -1226,9 +1331,13 @@
return refCounts.doDecrement<clearPinnedFlag, performDeinit>(dec);
}
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
+ bool decrementNonAtomicStrong(uint32_t dec) {
+ return refCounts.doDecrementNonAtomic<clearPinnedFlag, performDeinit>(dec);
+ }
+
void decrementFromOneNonAtomic() {
- // FIXME: can there be a non-atomic implementation?
- decrementStrong<DontClearPinnedFlag, DontPerformDeinit>(1);
+ decrementNonAtomicStrong<DontClearPinnedFlag, DontPerformDeinit>(1);
}
bool isDeiniting() const {
@@ -1243,6 +1352,16 @@
return refCounts.tryIncrementAndPin();
}
+ bool tryIncrementNonAtomic() {
+ return refCounts.tryIncrementNonAtomic();
+ }
+
+ bool tryIncrementAndPinNonAtomic() {
+ return refCounts.tryIncrementAndPinNonAtomic();
+ }
+
+ // Return weak reference count.
+ // Note that this is not equal to the number of outstanding weak pointers.
uint32_t getCount() const {
return refCounts.getCount();
}
@@ -1257,6 +1376,10 @@
return refCounts.incrementUnowned(inc);
}
+ void incrementUnownedNonAtomic(uint32_t inc) {
+ return refCounts.incrementUnownedNonAtomic(inc);
+ }
+
bool decrementUnownedShouldFree(uint32_t dec) {
bool shouldFree = refCounts.decrementUnownedShouldFree(dec);
if (shouldFree) {
@@ -1268,6 +1391,17 @@
return shouldFree;
}
+ bool decrementUnownedShouldFreeNonAtomic(uint32_t dec) {
+ bool shouldFree = refCounts.decrementUnownedShouldFreeNonAtomic(dec);
+ if (shouldFree) {
+ // DEINITED -> FREED
+ // Caller will free the object.
+ decrementWeakNonAtomic();
+ }
+
+ return shouldFree;
+ }
+
uint32_t getUnownedCount() const {
return refCounts.getUnownedCount();
}
@@ -1301,6 +1435,19 @@
delete this;
}
+ void decrementWeakNonAtomic() {
+ // FIXME: assertions
+ // FIXME: optimize barriers
+ bool cleanup = refCounts.decrementWeakShouldCleanUpNonAtomic();
+ if (!cleanup)
+ return;
+
+ // Weak ref count is now zero. Delete the side table entry.
+ // FREED -> DEAD
+ assert(refCounts.getUnownedCount() == 0);
+ delete this;
+ }
+
uint32_t getWeakCount() const {
return refCounts.getWeakCount();
}
@@ -1327,12 +1474,12 @@
// Use slow path if we can't guarantee atomicity.
if (oldbits.hasSideTable() || oldbits.getUnownedRefCount() != 1)
- return doDecrementSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
+ return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
auto newbits = oldbits;
bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
if (!fast)
- return doDecrementSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
+ return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
refCounts.store(newbits, std::memory_order_relaxed);
return false; // don't deinit
@@ -1359,12 +1506,28 @@
template <>
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
+inline bool RefCounts<InlineRefCountBits>::
+doDecrementNonAtomicSideTable(InlineRefCountBits oldbits, uint32_t dec) {
+ auto side = oldbits.getSideTable();
+ return side->decrementNonAtomicStrong<clearPinnedFlag, performDeinit>(dec);
+}
+
+template <>
+template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
inline bool RefCounts<SideTableRefCountBits>::
doDecrementSideTable(SideTableRefCountBits oldbits, uint32_t dec) {
swift::crash("side table refcount must not have "
"a side table entry of its own");
}
+template <>
+template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
+inline bool RefCounts<SideTableRefCountBits>::
+doDecrementNonAtomicSideTable(SideTableRefCountBits oldbits, uint32_t dec) {
+ swift::crash("side table refcount must not have "
+ "a side table entry of its own");
+}
+
template <> inline
HeapObject* RefCounts<InlineRefCountBits>::getHeapObject() const {
diff --git a/stdlib/public/core/Dump.swift b/stdlib/public/core/Dump.swift
index d4a2ae6..c7a6399 100644
--- a/stdlib/public/core/Dump.swift
+++ b/stdlib/public/core/Dump.swift
@@ -12,6 +12,7 @@
/// Dumps an object's contents using its mirror to the specified output stream.
@discardableResult
+@_semantics("optimize.sil.specialize.generic.never")
public func dump<T, TargetStream : TextOutputStream>(
_ value: T,
to target: inout TargetStream,
@@ -37,6 +38,7 @@
/// Dumps an object's contents using its mirror to standard output.
@discardableResult
+@_semantics("optimize.sil.specialize.generic.never")
public func dump<T>(
_ value: T,
name: String? = nil,
@@ -55,6 +57,7 @@
}
/// Dump an object's contents. User code should use dump().
+@_semantics("optimize.sil.specialize.generic.never")
internal func _dump_unlocked<TargetStream : TextOutputStream>(
_ value: Any,
to target: inout TargetStream,
@@ -153,6 +156,7 @@
/// Dump information about an object's superclass, given a mirror reflecting
/// that superclass.
+@_semantics("optimize.sil.specialize.generic.never")
internal func _dumpSuperclass_unlocked<TargetStream : TextOutputStream>(
mirror: Mirror,
to target: inout TargetStream,
diff --git a/stdlib/public/core/OutputStream.swift b/stdlib/public/core/OutputStream.swift
index 7384fb6..8ab4443 100644
--- a/stdlib/public/core/OutputStream.swift
+++ b/stdlib/public/core/OutputStream.swift
@@ -250,6 +250,7 @@
func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?
/// Do our best to print a value that cannot be printed directly.
+@_semantics("optimize.sil.specialize.generic.never")
internal func _adHocPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ mirror: Mirror, _ target: inout TargetStream,
isDebugPrint: Bool
@@ -344,6 +345,7 @@
}
@inline(never)
+@_semantics("optimize.sil.specialize.generic.never")
@_semantics("stdlib_binary_only")
internal func _print_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ target: inout TargetStream
@@ -400,6 +402,7 @@
// `debugPrint`
//===----------------------------------------------------------------------===//
+@_semantics("optimize.sil.specialize.generic.never")
@inline(never)
public func _debugPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ target: inout TargetStream
@@ -423,6 +426,7 @@
_adHocPrint_unlocked(value, mirror, &target, isDebugPrint: true)
}
+@_semantics("optimize.sil.specialize.generic.never")
internal func _dumpPrint_unlocked<T, TargetStream : TextOutputStream>(
_ value: T, _ mirror: Mirror, _ target: inout TargetStream
) {
diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
index 9a31ee7..9154c75 100644
--- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
@@ -86,7 +86,7 @@
/// byteArray += someBytes[n..<someBytes.count]
% if mutable:
///
-/// Assigning into a ranged subscript of an `{$Self}` instance copies bytes
+/// Assigning into a ranged subscript of an `${Self}` instance copies bytes
/// into the memory. The next `n` bytes of the memory that `someBytes`
/// references are copied in this code:
///
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index 19bb361..fbe690a 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -164,10 +164,15 @@
set(section_magic_begin_obj "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/section_magic_begin-${arch_suffix}.dir/swift_sections.S${CMAKE_C_OUTPUT_EXTENSION}")
set(section_magic_end_obj "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/section_magic_end-${arch_suffix}.dir/swift_sections.S${CMAKE_C_OUTPUT_EXTENSION}")
+ set(ld_EXECUTABLE ${CMAKE_LINKER})
+ if(${SWIFT_SDK_${prefix}_ARCH_${arch}_LINKER})
+ set(ld_EXECUTABLE ${SWIFT_SDK_${prefix}_ARCH_${arch}_LINKER})
+ endif()
+
add_custom_command_target(section_magic_${arch_suffix}_begin_object
COMMAND
# Merge ImageInspectionInit.o + swift_sections.S(BEGIN) => swift_begin.o
- ${CMAKE_LINKER} -r -o "${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
+ ${ld_EXECUTABLE} -r -o "${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
"${section_magic_begin_obj}" "${section_magic_loader_obj}"
OUTPUT
"${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp
index 3797b6c..3a3bd61 100644
--- a/stdlib/public/runtime/HeapObject.cpp
+++ b/stdlib/public/runtime/HeapObject.cpp
@@ -344,6 +344,32 @@
}
}
+void swift::swift_nonatomic_unownedRetain(HeapObject *object)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+
+ object->refCounts.incrementUnownedNonAtomic(1);
+}
+
+void swift::swift_nonatomic_unownedRelease(HeapObject *object)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+
+ // Only class objects can be unowned-retained and unowned-released.
+ assert(object->metadata->isClassObject());
+ assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
+
+ if (object->refCounts.decrementUnownedShouldFreeNonAtomic(1)) {
+ auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);
+
+ SWIFT_RT_ENTRY_CALL(swift_slowDealloc)
+ (object, classMetadata->getInstanceSize(),
+ classMetadata->getInstanceAlignMask());
+ }
+}
+
void swift::swift_unownedRetain_n(HeapObject *object, int n)
SWIFT_CC(RegisterPreservingCC_IMPL) {
if (!isValidPointerForNativeRetain(object))
@@ -369,6 +395,31 @@
}
}
+void swift::swift_nonatomic_unownedRetain_n(HeapObject *object, int n)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+
+ object->refCounts.incrementUnownedNonAtomic(n);
+}
+
+void swift::swift_nonatomic_unownedRelease_n(HeapObject *object, int n)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+
+ // Only class objects can be unowned-retained and unowned-released.
+ assert(object->metadata->isClassObject());
+ assert(static_cast<const ClassMetadata*>(object->metadata)->isTypeMetadata());
+
+ if (object->refCounts.decrementUnownedShouldFreeNonAtomic(n)) {
+ auto classMetadata = static_cast<const ClassMetadata*>(object->metadata);
+ SWIFT_RT_ENTRY_CALL(swift_slowDealloc)
+ (object, classMetadata->getInstanceSize(),
+ classMetadata->getInstanceAlignMask());
+ }
+}
+
HeapObject *swift::swift_tryPin(HeapObject *object)
SWIFT_CC(RegisterPreservingCC_IMPL) {
assert(isValidPointerForNativeRetain(object));
@@ -449,6 +500,17 @@
swift::swift_abortRetainUnowned(object);
}
+void swift::swift_nonatomic_unownedRetainStrong(HeapObject *object)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+ assert(object->refCounts.getUnownedCount() &&
+ "object is not currently unowned-retained");
+
+ if (! object->refCounts.tryIncrementNonAtomic())
+ swift::swift_abortRetainUnowned(object);
+}
+
void swift::swift_unownedRetainStrongAndRelease(HeapObject *object)
SWIFT_CC(RegisterPreservingCC_IMPL) {
if (!isValidPointerForNativeRetain(object))
@@ -465,6 +527,22 @@
(void) dealloc;
}
+void swift::swift_nonatomic_unownedRetainStrongAndRelease(HeapObject *object)
+ SWIFT_CC(RegisterPreservingCC_IMPL) {
+ if (!isValidPointerForNativeRetain(object))
+ return;
+ assert(object->refCounts.getUnownedCount() &&
+ "object is not currently unowned-retained");
+
+ if (! object->refCounts.tryIncrementNonAtomic())
+ swift::swift_abortRetainUnowned(object);
+
+ // This should never cause a deallocation.
+ bool dealloc = object->refCounts.decrementUnownedShouldFreeNonAtomic(1);
+ assert(!dealloc && "retain-strong-and-release caused dealloc?");
+ (void) dealloc;
+}
+
void swift::swift_unownedCheck(HeapObject *object) {
if (!isValidPointerForNativeRetain(object)) return;
assert(object->refCounts.getUnownedCount() &&
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index aab8c9d..7d2257d 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -2819,7 +2819,7 @@
/// The number of bytes remaining.
size_t Remaining;
};
-}
+} // end anonymous namespace
// A statically-allocated pool. It's zero-initialized, so this
// doesn't cost us anything in binary size.
diff --git a/stdlib/public/runtime/MetadataImpl.h b/stdlib/public/runtime/MetadataImpl.h
index 28d79f1..a9ca348 100644
--- a/stdlib/public/runtime/MetadataImpl.h
+++ b/stdlib/public/runtime/MetadataImpl.h
@@ -191,6 +191,11 @@
static constexpr size_t stride = sizeof(T);
static constexpr bool isPOD = false;
static constexpr bool isBitwiseTakable = true;
+#ifdef SWIFT_STDLIB_USE_NONATOMIC_RC
+ static constexpr bool isAtomic = false;
+#else
+ static constexpr bool isAtomic = true;
+#endif
static void destroy(T *addr) {
Impl::release(*addr);
@@ -262,12 +267,20 @@
struct SwiftRetainableBox :
RetainableBoxBase<SwiftRetainableBox, HeapObject*> {
static HeapObject *retain(HeapObject *obj) {
- swift_retain(obj);
+ if (isAtomic) {
+ swift_retain(obj);
+ } else {
+ swift_nonatomic_retain(obj);
+ }
return obj;
}
static void release(HeapObject *obj) {
- swift_release(obj);
+ if (isAtomic) {
+ swift_release(obj);
+ } else {
+ swift_nonatomic_release(obj);
+ }
}
};
@@ -275,12 +288,20 @@
struct SwiftUnownedRetainableBox :
RetainableBoxBase<SwiftUnownedRetainableBox, HeapObject*> {
static HeapObject *retain(HeapObject *obj) {
- swift_unownedRetain(obj);
+ if (isAtomic) {
+ swift_unownedRetain(obj);
+ } else {
+ swift_nonatomic_unownedRetain(obj);
+ }
return obj;
}
static void release(HeapObject *obj) {
- swift_unownedRelease(obj);
+ if (isAtomic) {
+ swift_unownedRelease(obj);
+ } else {
+ swift_nonatomic_unownedRelease(obj);
+ }
}
#if SWIFT_OBJC_INTEROP
@@ -468,7 +489,11 @@
swift_unknownRetain(obj);
return obj;
#else
- swift_retain(static_cast<HeapObject *>(obj));
+ if (isAtomic) {
+ swift_retain(static_cast<HeapObject *>(obj));
+ } else {
+ swift_nonatomic_retain(static_cast<HeapObject *>(obj));
+ }
return static_cast<HeapObject *>(obj);
#endif
}
@@ -477,7 +502,11 @@
#if SWIFT_OBJC_INTEROP
swift_unknownRelease(obj);
#else
- swift_release(static_cast<HeapObject *>(obj));
+ if (isAtomic) {
+ swift_release(static_cast<HeapObject *>(obj));
+ } else {
+ swift_nonatomic_release(static_cast<HeapObject *>(obj));
+ }
#endif
}
};
diff --git a/stdlib/public/runtime/RefCount.cpp b/stdlib/public/runtime/RefCount.cpp
index 920df04..1d1b22b 100644
--- a/stdlib/public/runtime/RefCount.cpp
+++ b/stdlib/public/runtime/RefCount.cpp
@@ -2,11 +2,11 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@@ -55,6 +55,16 @@
template bool RefCounts<SideTableRefCountBits>::tryIncrementSlow(SideTableRefCountBits oldbits);
template <typename RefCountBits>
+bool RefCounts<RefCountBits>::tryIncrementNonAtomicSlow(RefCountBits oldbits) {
+ if (oldbits.hasSideTable())
+ return oldbits.getSideTable()->tryIncrementNonAtomic();
+ else
+ swift::swift_abortRetainOverflow();
+}
+template bool RefCounts<InlineRefCountBits>::tryIncrementNonAtomicSlow(InlineRefCountBits oldbits);
+template bool RefCounts<SideTableRefCountBits>::tryIncrementNonAtomicSlow(SideTableRefCountBits oldbits);
+
+template <typename RefCountBits>
bool RefCounts<RefCountBits>::tryIncrementAndPinSlow(RefCountBits oldbits) {
if (oldbits.hasSideTable())
return oldbits.getSideTable()->tryIncrementAndPin();
@@ -66,8 +76,10 @@
template <typename RefCountBits>
bool RefCounts<RefCountBits>::tryIncrementAndPinNonAtomicSlow(RefCountBits oldbits) {
- // No nonatomic implementation provided.
- return tryIncrementAndPinSlow(oldbits);
+ if (oldbits.hasSideTable())
+ return oldbits.getSideTable()->tryIncrementAndPinNonAtomic();
+ else
+ swift::swift_abortRetainOverflow();
}
template bool RefCounts<InlineRefCountBits>::tryIncrementAndPinNonAtomicSlow(InlineRefCountBits oldbits);
template bool RefCounts<SideTableRefCountBits>::tryIncrementAndPinNonAtomicSlow(SideTableRefCountBits oldbits);
diff --git a/stdlib/public/runtime/WeakReference.h b/stdlib/public/runtime/WeakReference.h
index aa8f4f4..34dd52e 100644
--- a/stdlib/public/runtime/WeakReference.h
+++ b/stdlib/public/runtime/WeakReference.h
@@ -2,11 +2,11 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
index 747e0bb..3cff8ce 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
@@ -79,7 +79,16 @@
- Name: accessorsOnlyRenamedRetypedClass
PropertyKind: Class
SwiftImportAsAccessors: true
+ Protocols:
+ - Name: ProtoWithVersionedUnavailableMember
+ Methods:
+ - Selector: requirement
+ MethodKind: Instance
+ ResultType: 'ForwardClass * _Nullable'
Functions:
- Name: acceptDoublePointer
SwiftName: 'acceptPointer(_:)'
Nullability: [ O ]
+ Tags:
+ - Name: SomeCStruct
+ SwiftName: ImportantCStruct
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
index b0a6023..06e48f9 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
@@ -2,6 +2,8 @@
void acceptDoublePointer(double* _Nonnull ptr) __attribute__((swift_name("accept(_:)")));
+void oldAcceptDoublePointer(double* _Nonnull ptr) __attribute__((availability(swift, unavailable, replacement="acceptDoublePointer")));
+
#ifdef __OBJC__
__attribute__((objc_root_class))
@@ -13,5 +15,8 @@
-(nonnull id)methodWithA:(nonnull id)a;
@end
+#endif // __OBJC__
+
#import <APINotesFrameworkTest/Properties.h>
-#endif
+#import <APINotesFrameworkTest/Protocols.h>
+#import <APINotesFrameworkTest/Types.h>
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Properties.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Properties.h
index 93ab5b0..9d21bde 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Properties.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Properties.h
@@ -1,3 +1,4 @@
+#ifdef __OBJC__
#pragma clang assume_nonnull begin
__attribute__((objc_root_class))
@@ -33,3 +34,4 @@
@end
#pragma clang assume_nonnull end
+#endif // __OBJC__
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h
new file mode 100644
index 0000000..6a8840c
--- /dev/null
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h
@@ -0,0 +1,11 @@
+#ifdef __OBJC__
+#pragma clang assume_nonnull begin
+
+@class ForwardClass; // used by API notes
+
+@protocol ProtoWithVersionedUnavailableMember
+- (nullable id)requirement;
+@end
+
+#pragma clang assume_nonnull end
+#endif // __OBJC__
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h
new file mode 100644
index 0000000..c44439f
--- /dev/null
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Types.h
@@ -0,0 +1,7 @@
+#pragma clang assume_nonnull begin
+
+struct __attribute__((swift_name("VeryImportantCStruct"))) SomeCStruct {
+ int field;
+};
+
+#pragma clang assume_nonnull end
diff --git a/test/APINotes/versioned-objc.swift b/test/APINotes/versioned-objc.swift
new file mode 100644
index 0000000..4ff367c
--- /dev/null
+++ b/test/APINotes/versioned-objc.swift
@@ -0,0 +1,16 @@
+// RUN: rm -rf %t && mkdir -p %t
+
+// RUN: not %target-swift-frontend -typecheck -F %S/Inputs/custom-frameworks -swift-version 4 %s 2>&1 | %FileCheck -check-prefix=CHECK-DIAGS -check-prefix=CHECK-DIAGS-4 %s
+// RUN: not %target-swift-frontend -typecheck -F %S/Inputs/custom-frameworks -swift-version 3 %s 2>&1 | %FileCheck -check-prefix=CHECK-DIAGS -check-prefix=CHECK-DIAGS-3 %s
+
+// REQUIRES: objc_interop
+
+import APINotesFrameworkTest
+
+// CHECK-DIAGS-4-NOT: versioned-objc.swift:[[@LINE-1]]:
+class ProtoWithVersionedUnavailableMemberImpl: ProtoWithVersionedUnavailableMember {
+ // CHECK-DIAGS-3: versioned-objc.swift:[[@LINE-1]]:7: error: type 'ProtoWithVersionedUnavailableMemberImpl' cannot conform to protocol 'ProtoWithVersionedUnavailableMember' because it has requirements that cannot be satisfied
+ func requirement() -> Any? { return nil }
+}
+
+let unrelatedDiagnostic: Int = nil
diff --git a/test/APINotes/versioned.swift b/test/APINotes/versioned.swift
index 85dd3e2..a3d7353 100644
--- a/test/APINotes/versioned.swift
+++ b/test/APINotes/versioned.swift
@@ -18,19 +18,41 @@
func testRenamedTopLevel() {
var value = 0.0
- // CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE+1]]
+ // CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE+1]]:
accept(&value)
// CHECK-DIAGS-3: versioned.swift:[[@LINE-1]]:3: error: 'accept' has been renamed to 'acceptPointer(_:)'
// CHECK-DIAGS-3: note: 'accept' was introduced in Swift 4
- // CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE+1]]
+ // CHECK-DIAGS-3-NOT: versioned.swift:[[@LINE+1]]:
acceptPointer(&value)
// CHECK-DIAGS-4: versioned.swift:[[@LINE-1]]:3: error: 'acceptPointer' has been renamed to 'accept(_:)'
// CHECK-DIAGS-4: note: 'acceptPointer' was obsoleted in Swift 4
acceptDoublePointer(&value)
// CHECK-DIAGS: versioned.swift:[[@LINE-1]]:3: error: 'acceptDoublePointer' has been renamed to
- // CHECK-DIAGS-4: 'accept(_:)'
- // CHECK-DIAGS-3: 'acceptPointer(_:)'
+ // CHECK-DIAGS-4-SAME: 'accept(_:)'
+ // CHECK-DIAGS-3-SAME: 'acceptPointer(_:)'
// CHECK-DIAGS: note: 'acceptDoublePointer' was obsoleted in Swift 3
+
+ oldAcceptDoublePointer(&value)
+ // CHECK-DIAGS: versioned.swift:[[@LINE-1]]:3: error: 'oldAcceptDoublePointer' has been renamed to
+ // CHECK-DIAGS-4-SAME: 'accept(_:)'
+ // CHECK-DIAGS-3-SAME: 'acceptPointer(_:)'
+ // CHECK-DIAGS: note: 'oldAcceptDoublePointer' has been explicitly marked unavailable here
+
+ _ = SomeCStruct()
+ // CHECK-DIAGS: versioned.swift:[[@LINE-1]]:7: error: 'SomeCStruct' has been renamed to
+ // CHECK-DIAGS-4-SAME: 'VeryImportantCStruct'
+ // CHECK-DIAGS-3-SAME: 'ImportantCStruct'
+ // CHECK-DIAGS: note: 'SomeCStruct' was obsoleted in Swift 3
+
+ // CHECK-DIAGS-3-NOT: versioned.swift:[[@LINE+1]]:
+ _ = ImportantCStruct()
+ // CHECK-DIAGS-4: versioned.swift:[[@LINE-1]]:7: error: 'ImportantCStruct' has been renamed to 'VeryImportantCStruct'
+ // CHECK-DIAGS-4: note: 'ImportantCStruct' was obsoleted in Swift 4
+
+ // CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE+1]]:
+ _ = VeryImportantCStruct()
+ // CHECK-DIAGS-3: versioned.swift:[[@LINE-1]]:7: error: 'VeryImportantCStruct' has been renamed to 'ImportantCStruct'
+ // CHECK-DIAGS-3: note: 'VeryImportantCStruct' was introduced in Swift 4
}
diff --git a/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some-Bridging-Header.h b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some-Bridging-Header.h
new file mode 100644
index 0000000..dc2b560
--- /dev/null
+++ b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some-Bridging-Header.h
@@ -0,0 +1,7 @@
+#import <Some/Submodule.h>
+
+@interface Thing
++ (void)fn:(KLASS*)arg;
+@end
+
+void bar(TYPE t);
diff --git a/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Some.h b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Some.h
new file mode 100644
index 0000000..ea7c87e
--- /dev/null
+++ b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Some.h
@@ -0,0 +1,2 @@
+typedef int TYPE;
+@class KLASS;
diff --git a/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Submodule.h b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Submodule.h
new file mode 100644
index 0000000..5d5f8f0
--- /dev/null
+++ b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Headers/Submodule.h
@@ -0,0 +1 @@
+int foo();
diff --git a/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Modules/module.modulemap b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Modules/module.modulemap
new file mode 100644
index 0000000..ccbb89c
--- /dev/null
+++ b/test/ClangImporter/MixedSource/Inputs/defer-supermodule-import/Some.framework/Modules/module.modulemap
@@ -0,0 +1,8 @@
+framework module Some {
+ header "Some.h"
+ export *
+ module Submodule {
+ header "Submodule.h"
+ export *
+ }
+}
diff --git a/test/ClangImporter/MixedSource/defer-supermodule-import.swift b/test/ClangImporter/MixedSource/defer-supermodule-import.swift
new file mode 100644
index 0000000..0e6d505
--- /dev/null
+++ b/test/ClangImporter/MixedSource/defer-supermodule-import.swift
@@ -0,0 +1,21 @@
+// RUN: not %target-swift-frontend -F %S/Inputs/defer-supermodule-import -import-objc-header %S/Inputs/defer-supermodule-import/Some-Bridging-Header.h -typecheck %s 2>&1 | %FileCheck -check-prefix=HEADER-ERROR %s
+// HEADER-ERROR: Some-Bridging-Header.h:4:13: error: expected a type
+// HEADER-ERROR: Some-Bridging-Header.h:7:10: error: declaration of 'TYPE' must be imported from module 'Some' before it is required
+// REQUIRES: objc_interop
+
+// The bug we're testing here is that:
+//
+// - Given a supermodule defining some types
+// - Given a submodule of that supermodule
+// - Given an _erroneous_ bridging header that imports the _submodule_ and tries
+// to use the _supermodule's_ types
+//
+// That we emit an error. Previously we did not: Swift's "implicit supermodule
+// import" rule would fire _eagerly_, so by the time the submodule import was
+// complete the supermodule was also imported and the bridging header would pass
+// through without flagging the error. This made it possible to write textual
+// bridging headers that would not, themselves, be considered valid objc code as
+// far as clang (or more importantly: clang's PCH-generating pass) was
+// concerned.
+
+print(bar(foo()))
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index 838a3b6..d6abc11 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -266,10 +266,8 @@
// Make sure we cannot infer an () argument from an empty parameter list.
func acceptNothingToInt (_: () -> Int) {}
func testAcceptNothingToInt(ac1: @autoclosure () -> Int) {
- // expected-note@-1{{parameter 'ac1' is implicitly non-escaping because it was declared @autoclosure}}
acceptNothingToInt({ac1($0)})
// expected-error@-1{{contextual closure type '() -> Int' expects 0 arguments, but 1 was used in closure body}}
- // FIXME: expected-error@-2{{closure use of non-escaping parameter 'ac1' may allow it to escape}}
}
// <rdar://problem/23570873> QoI: Poor error calling map without being able to infer "U" (closure result inference)
diff --git a/test/Constraints/generic_super_constraint.swift b/test/Constraints/generic_super_constraint.swift
index 8e29a49..c227519 100644
--- a/test/Constraints/generic_super_constraint.swift
+++ b/test/Constraints/generic_super_constraint.swift
@@ -4,11 +4,14 @@
class Derived: Base<Int> { }
func foo<T>(_ x: T) -> Derived where T: Base<Int>, T: Derived {
+ // expected-warning@-1{{redundant superclass constraint 'T' : 'Base<Int>'}}
+ // expected-note@-2{{superclass constraint 'T' : 'Derived' written here}}
return x
}
// FIXME: Should not be an error
-// expected-error@+1{{cannot be a subclass of both 'Base<T>' and 'Derived'}}
+// expected-error@+2{{generic parameter 'U' cannot be a subclass of both 'Derived' and 'Base<T>'}}
+// expected-note@+1{{superclass constraint 'U' : 'Base<T>' written here}}
func bar<T, U>(_ x: U, y: T) -> (Derived, Int) where U: Base<T>, U: Derived {
// FIXME
// expected-error@+1{{cannot convert return expression}}
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 3b07ff8..1183a45 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -114,7 +114,8 @@
()
case Watch.Edition: // TODO: should warn that cast can't succeed with currently known conformances
()
-case .HairForceOne: // expected-error{{enum case 'HairForceOne' not found in type 'HairType'}}
+// TODO: Bad error message
+case .HairForceOne: // expected-error{{cannot convert}}
()
default:
break
@@ -254,3 +255,53 @@
if case let doesNotExist as SomeClass:AlsoDoesNotExist {}
// expected-error@-1 {{use of undeclared type 'AlsoDoesNotExist'}}
// expected-error@-2 {{variable binding in a condition requires an initializer}}
+
+// `.foo` and `.bar(...)` pattern syntax should also be able to match
+// static members as expr patterns
+
+struct StaticMembers: Equatable {
+ init() {}
+ init(_: Int) {}
+ init?(opt: Int) {}
+ static var prop = StaticMembers()
+ static var optProp: Optional = StaticMembers()
+
+ static func method(_: Int) -> StaticMembers { return prop }
+ static func method(withLabel: Int) -> StaticMembers { return prop }
+ static func optMethod(_: Int) -> StaticMembers? { return optProp }
+
+ static func ==(x: StaticMembers, y: StaticMembers) -> Bool { return true }
+}
+
+let staticMembers = StaticMembers()
+let optStaticMembers: Optional = StaticMembers()
+
+switch staticMembers {
+ case .init: break // expected-error{{cannot match values of type 'StaticMembers'}}
+ case .init(opt:): break // expected-error{{cannot match values of type 'StaticMembers'}}
+ case .init(): break
+
+ case .init(0): break
+ case .init(_): break // expected-error{{'_' can only appear in a pattern}}
+ case .init(let x): break // expected-error{{cannot appear in an expression}}
+ case .init(opt: 0): break // expected-error{{not unwrapped}}
+
+ case .prop: break
+ // TODO: repeated error message
+ case .optProp: break // expected-error* {{not unwrapped}}
+
+ case .method: break // expected-error{{cannot match}}
+ case .method(0): break
+ case .method(_): break // expected-error{{'_' can only appear in a pattern}}
+ case .method(let x): break // expected-error{{cannot appear in an expression}}
+
+ case .method(withLabel:): break // expected-error{{cannot match}}
+ case .method(withLabel: 0): break
+ case .method(withLabel: _): break // expected-error{{'_' can only appear in a pattern}}
+ case .method(withLabel: let x): break // expected-error{{cannot appear in an expression}}
+
+ case .optMethod: break // expected-error{{cannot match}}
+ case .optMethod(0): break // expected-error{{not unwrapped}}
+}
+
+_ = 0
diff --git a/test/DebugInfo/linetable.swift b/test/DebugInfo/linetable.swift
index e282ca4..b4706cb 100644
--- a/test/DebugInfo/linetable.swift
+++ b/test/DebugInfo/linetable.swift
@@ -1,7 +1,7 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests %s -emit-ir -g -o - | %FileCheck %s
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests %s -S -g -o - | %FileCheck %s --check-prefix ASM-CHECK
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
import Swift
func markUsed<T>(_ t: T) {}
diff --git a/test/Demangle/Inputs/simplified-manglings.txt b/test/Demangle/Inputs/simplified-manglings.txt
index 20cb0b9..6eea81b 100644
--- a/test/Demangle/Inputs/simplified-manglings.txt
+++ b/test/Demangle/Inputs/simplified-manglings.txt
@@ -136,9 +136,9 @@
_TtGSaGSqC5sugar7MyClass__ ---> [MyClass?]
_TtaC9typealias5DWARF9DIEOffset ---> DWARF.DIEOffset
_Ttas3Int ---> Int
-_TTRXFo_dSc_dSb_XFo_iSc_iSb_ ---> thunk
-_TTRXFo_dSi_dGSqSi__XFo_iSi_iGSqSi__ ---> thunk
-_TTRGrXFo_iV18switch_abstraction1A_ix_XFo_dS0__ix_ ---> thunk
+_TTRXFo_dSc_dSb_XFo_iSc_iSb_ ---> thunk for @callee_owned (@unowned UnicodeScalar) -> (@unowned Bool)
+_TTRXFo_dSi_dGSqSi__XFo_iSi_iGSqSi__ ---> thunk for @callee_owned (@unowned Int) -> (@unowned Int?)
+_TTRGrXFo_iV18switch_abstraction1A_ix_XFo_dS0__ix_ ---> thunk for @callee_owned (@in A) -> (@out A)
_TFCF5types1gFT1bSb_T_L0_10Collection3zimfT_T_ ---> (g(b : Bool) -> ()).(Collection #2).zim() -> ()
_TFF17capture_promotion22test_capture_promotionFT_FT_SiU_FT_Si_promote0 ---> (test_capture_promotion() -> () -> Int).(closure #1)
_TFIVs8_Processi10_argumentsGSaSS_U_FT_GSaSS_ ---> _Process.(variable initialization expression)._arguments
@@ -160,7 +160,7 @@
_TTSgSi__xyz ---> _TTSgSi__xyz
_TTSg5Si___TTSg5Si___TFSqcfT_GSqx_ ---> specialized specialized Optional.init() -> A?
_TTSg5Vs5UInt8___TFV10specialize3XXXcfT1tx_GS0_x_ ---> specialized XXX.init(t : A) -> XXX<A>
-_TPA__TTRXFo_oSSoSS_dSb_XFo_iSSiSS_dSb_31 ---> partial apply for thunk
+_TPA__TTRXFo_oSSoSS_dSb_XFo_iSSiSS_dSb_31 ---> partial apply for thunk for @callee_owned (@owned String, @owned String) -> (@unowned Bool)
_TiC4Meow5MyCls9subscriptFT1iSi_Sf ---> MyCls.subscript(i : Int) -> Float
_TF8manglingX22egbpdajGbuEbxfgehfvwxnFT_T_ ---> ليهمابتكلموشعربي؟() -> ()
_TF8manglingX24ihqwcrbEcvIaIdqgAFGpqjyeFT_T_ ---> 他们为什么不说中文() -> ()
@@ -180,8 +180,8 @@
_TTSf1cl35_TFF7specgen6callerFSiT_U_FTSiSi_T_Si___TF7specgen12take_closureFFTSiSi_T_T_ ---> specialized take_closure((Int, Int) -> ()) -> ()
_TTSf1cl35_TFF7specgen6callerFSiT_U_FTSiSi_T_Si___TTSg5Si___TF7specgen12take_closureFFTSiSi_T_T_ ---> specialized specialized take_closure((Int, Int) -> ()) -> ()
_TTSg5Si___TTSf1cl35_TFF7specgen6callerFSiT_U_FTSiSi_T_Si___TF7specgen12take_closureFFTSiSi_T_T_ ---> specialized specialized take_closure((Int, Int) -> ()) -> ()
-_TTSf1cpfr24_TF8capturep6helperFSiT__n___TTRXFo_dSi_dT__XFo_iSi_dT__ ---> specialized thunk
-_TTSf1cpfr24_TF8capturep6helperFSiT__n___TTRXFo_dSi_DT__XFo_iSi_DT__ ---> specialized thunk
+_TTSf1cpfr24_TF8capturep6helperFSiT__n___TTRXFo_dSi_dT__XFo_iSi_dT__ ---> specialized thunk for @callee_owned (@unowned Int) -> (@unowned ())
+_TTSf1cpfr24_TF8capturep6helperFSiT__n___TTRXFo_dSi_DT__XFo_iSi_DT__ ---> specialized thunk for @callee_owned (@unowned Int) -> (@unowned_inner_pointer ())
_TTSf1cpi0_cpfl0_cpse0v4u123_cpg53globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8_cpfr36_TFtest_capture_propagation2_closure___TF7specgen12take_closureFFTSiSi_T_T_ ---> specialized take_closure((Int, Int) -> ()) -> ()
_TTSf0gs___TFVs11_StringCore15_invariantCheckfT_T_ ---> specialized _StringCore._invariantCheck() -> ()
_TTSf2g___TTSf2s_d___TFVs11_StringCoreCfVs13_StringBufferS_ ---> specialized specialized _StringCore.init(_StringBuffer) -> _StringCore
@@ -198,6 +198,8 @@
_TFC3red11BaseClassEHcfzT1aSi_S0_ ---> BaseClassEH.init(a : Int) throws -> BaseClassEH
_TFe27mangling_generic_extensionsR_S_8RunciblerVS_3Foog1aSi ---> Foo<A where ...>.a.getter
_TFe27mangling_generic_extensionsR_S_8RunciblerVS_3Foog1bx ---> Foo<A where ...>.b.getter
-_TTRXFo_iT__iT_zoPs5Error__XFo__dT_zoPS___ ---> thunk
+_TTRXFo_iT__iT_zoPs5Error__XFo__dT_zoPS___ ---> thunk for @callee_owned (@in ()) -> (@out (), @error @owned Error)
_TFE1a ---> _TFE1a
_TFC4testP33_83378C430F65473055F1BD53F3ADCDB71C5doFoofT_T_ ---> C.doFoo() -> ()
+_TTRXFo_oCSo13SKPhysicsBodydVSC7CGPointdVSC8CGVectordGSpV10ObjectiveC8ObjCBool___XFdCb_dS_dS0_dS1_dGSpS3____ ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
+_T0So13SKPhysicsBodyCSC7CGPointVSC8CGVectorVSpy10ObjectiveC8ObjCBoolVGIxxyyy_AbdFSpyAIGIyByyyy_TR ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
diff --git a/test/Generics/associated_type_typo.swift b/test/Generics/associated_type_typo.swift
index e287aff..5b91c77 100644
--- a/test/Generics/associated_type_typo.swift
+++ b/test/Generics/associated_type_typo.swift
@@ -37,9 +37,9 @@
// CHECK-GENERIC-LABEL: .typoAssoc4@
// CHECK-GENERIC-NEXT: Requirements:
-// CHECK-GENERIC-NEXT: τ_0_0 : P2 [Explicit @ {{.*}}:21]
-// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [Explicit @ {{.*}}:21 -> Protocol requirement (P2)]
-// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [Explicit @ {{.*}}:53]
+// CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
+// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (P2)]
+// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [τ_0_0[.P2].AssocP2.assoc: Explicit @ {{.*}}:53]
// CHECK-GENERIC-NEXT: Potential archetypes
// <rdar://problem/19620340>
diff --git a/test/Generics/associated_type_where_clause.swift b/test/Generics/associated_type_where_clause.swift
new file mode 100644
index 0000000..3717b18
--- /dev/null
+++ b/test/Generics/associated_type_where_clause.swift
@@ -0,0 +1,128 @@
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify -swift-version 4
+
+func needsSameType<T>(_: T.Type, _: T.Type) {}
+
+protocol Foo {}
+func needsFoo<T: Foo>(_: T.Type) {}
+
+protocol Foo2 {}
+func needsFoo2<T: Foo2>(_: T.Type) {}
+
+extension Int: Foo, Foo2 {}
+extension Float: Foo {}
+
+protocol Conforms {
+ associatedtype T where T: Foo
+}
+func needsConforms<X: Conforms>(_: X.Type) {
+ needsFoo(X.T.self)
+}
+struct ConcreteConforms: Conforms { typealias T = Int }
+struct ConcreteConforms2: Conforms { typealias T = Int }
+struct ConcreteConformsNonFoo2: Conforms { typealias T = Float }
+
+protocol NestedConforms {
+ associatedtype U where U: Conforms, U.T: Foo2
+
+ func foo(_: U)
+}
+extension NestedConforms { func foo(_: U) {} }
+func needsNestedConforms<X: NestedConforms>(_: X.Type) {
+ needsConforms(X.U.self)
+ needsFoo(X.U.T.self)
+ needsFoo2(X.U.T.self)
+}
+struct ConcreteNestedConforms: NestedConforms {
+ typealias U = ConcreteConforms
+}
+struct ConcreteNestedConformsInfer: NestedConforms {
+ func foo(_: ConcreteConforms) {}
+}
+struct BadConcreteNestedConforms: NestedConforms {
+ // expected-error@-1 {{type 'ConcreteConformsNonFoo2.T' (aka 'Float') does not conform to protocol 'Foo2'}}
+ typealias U = ConcreteConformsNonFoo2
+}
+struct BadConcreteNestedConformsInfer: NestedConforms {
+ // expected-error@-1 {{type 'ConcreteConformsNonFoo2.T' (aka 'Float') does not conform to protocol 'Foo2'}}
+ func foo(_: ConcreteConformsNonFoo2) {}
+}
+
+protocol NestedConformsDefault {
+ associatedtype U = ConcreteConforms where U: Conforms, U.T: Foo2
+}
+struct ConcreteNestedConformsDefaultDefaulted: NestedConformsDefault {}
+struct ConcreteNestedConformsDefault: NestedConformsDefault {
+ typealias U = ConcreteConforms2
+}
+func needsNestedConformsDefault<X: NestedConformsDefault>(_: X.Type) {
+ needsConforms(X.U.self)
+ needsFoo(X.U.T.self)
+ needsFoo2(X.U.T.self)
+}
+
+protocol NestedSameType {
+ associatedtype U: Conforms where U.T == Int
+
+ func foo(_: U)
+}
+extension NestedSameType { func foo(_: U) {} }
+func needsNestedSameType<X: NestedSameType>(_: X.Type) {
+ needsConforms(X.U.self)
+ needsSameType(X.U.T.self, Int.self)
+}
+struct BadConcreteNestedSameType: NestedSameType {
+ // expected-error@-1 {{'NestedSameType' requires the types 'ConcreteConformsNonFoo2.T' (aka 'Float') and 'Int' be equivalent}}
+ // expected-note@-2 {{requirement specified as 'Self.U.T' == 'Int' [with Self = BadConcreteNestedSameType]}}
+ typealias U = ConcreteConformsNonFoo2
+}
+struct BadConcreteNestedSameTypeInfer: NestedSameType {
+ // expected-error@-1 {{'NestedSameType' requires the types 'ConcreteConformsNonFoo2.T' (aka 'Float') and 'Int' be equivalent}}
+ // expected-note@-2 {{requirement specified as 'Self.U.T' == 'Int' [with Self = BadConcreteNestedSameTypeInfer]}}
+ func foo(_: ConcreteConformsNonFoo2) {}
+}
+
+protocol NestedSameTypeDefault {
+ associatedtype U: Conforms = ConcreteConforms where U.T == Int
+
+ func foo(_: U)
+}
+extension NestedSameTypeDefault { func foo(_: U) {} }
+func needsNestedSameTypeDefault<X: NestedSameTypeDefault>(_: X.Type) {
+ needsConforms(X.U.self)
+ needsSameType(X.U.T.self, Int.self)
+}
+struct ConcreteNestedSameTypeDefaultDefaulted: NestedSameTypeDefault {}
+struct ConcreteNestedSameTypeDefault: NestedSameTypeDefault {
+ typealias U = ConcreteConforms2
+}
+struct ConcreteNestedSameTypeDefaultInfer: NestedSameTypeDefault {
+ func foo(_: ConcreteConforms2) {}
+}
+
+protocol Inherits: NestedConforms {
+ associatedtype X: Conforms where X.T == U.T
+
+ func bar(_: X)
+}
+extension Inherits { func bar(_: X) {} }
+func needsInherits<X: Inherits>(_: X.Type) {
+ needsConforms(X.U.self)
+ needsConforms(X.X.self)
+ needsSameType(X.U.T.self, X.X.T.self)
+}
+struct ConcreteInherits: Inherits {
+ typealias U = ConcreteConforms
+ typealias X = ConcreteConforms
+}
+struct ConcreteInheritsDiffer: Inherits {
+ typealias U = ConcreteConforms
+ typealias X = ConcreteConforms2
+}
+/*
+FIXME: the sametype requirement gets dropped from the requirement signature
+(enumerateRequirements doesn't yield it), so this doesn't error as it should.
+struct BadConcreteInherits: Inherits {
+ typealias U = ConcreteConforms
+ typealias X = ConcreteConformsNonFoo2
+}
+*/
diff --git a/test/Generics/invalid.swift b/test/Generics/invalid.swift
index 917b013..d817ae1 100644
--- a/test/Generics/invalid.swift
+++ b/test/Generics/invalid.swift
@@ -9,7 +9,7 @@
protocol he where A : B { // expected-error {{'where' clause cannot be attached to a protocol declaration}}
- associatedtype vav where A : B // expected-error {{'where' clause cannot be attached to an associated type declaration}}
+ associatedtype vav where A : B // expected-error {{where clauses on associated types are fragile; use '-swift-version 4' to experiment.}}
}
diff --git a/test/Generics/protocol_type_aliases.swift b/test/Generics/protocol_type_aliases.swift
index 3e62aa4..bc580c9 100644
--- a/test/Generics/protocol_type_aliases.swift
+++ b/test/Generics/protocol_type_aliases.swift
@@ -15,9 +15,9 @@
// CHECK-LABEL: .requirementOnNestedTypeAlias@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : Q [Explicit @ 22:51]
-// CHECK-NEXT: τ_0_0[.Q].B : P [Explicit @ 22:51 -> Protocol requirement (Q)]
-// CHECK-NEXT: τ_0_0[.Q].B[.P].A == Int [Explicit @ 22:62]
+// CHECK-NEXT: τ_0_0 : Q [τ_0_0: Explicit @ 22:51]
+// CHECK-NEXT: τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (Q)]
+// CHECK-NEXT: τ_0_0[.Q].B[.P].A == Int [τ_0_0[.Q].B[.P].X: Explicit @ 22:62]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q, τ_0_0.B.A == Int>
func requirementOnNestedTypeAlias<T>(_: T) where T: Q, T.B.X == Int {}
@@ -34,19 +34,19 @@
// CHECK-LABEL: .requirementOnConcreteNestedTypeAlias@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : Q2 [Explicit @ 42:59]
-// CHECK-NEXT: τ_0_0[.Q2].B : P2 [Explicit @ 42:59 -> Protocol requirement (Q2)]
-// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [Explicit @ 42:69]
-// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [Nested type match]
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (Q2)]
+// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit @ 42:69]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Nested type match]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
// CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : Q2 [Explicit @ 51:67]
-// CHECK-NEXT: τ_0_0[.Q2].B : P2 [Explicit @ 51:67 -> Protocol requirement (Q2)]
-// CHECK-NEXT: τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [Explicit]
-// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [Nested type match]
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 51:67]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (Q2)]
+// CHECK-NEXT: τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Nested type match]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>
func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> == T.B.X {}
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index 2491c55..dc1be46 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -57,7 +57,7 @@
class Box<T : Fox> {
// CHECK-LABEL: .unpack@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : Fox [Explicit]
+// CHECK-NEXT: τ_0_0 : Fox [τ_0_0: Explicit]
func unpack(_ x: X1<T>) {}
}
@@ -77,11 +77,15 @@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(_ v: V<T>) {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'Carnivora'}}
+// expected-note@-2{{superclass constraint 'T' : 'Canidae' written here}}
// CHECK-LABEL: .inferSuperclassRequirement2@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'Carnivora'}}
+// expected-note@-2{{superclass constraint 'T' : 'Canidae' written here}}
// ----------------------------------------------------------------------------
// Same-type requirements
@@ -111,27 +115,27 @@
// CHECK-LABEL: .inferSameType1@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : P3 [Inferred @ {{.*}}:32]
-// CHECK-NEXT: τ_0_1 : P4 [Inferred @ {{.*}}:32]
-// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [Inferred @ {{.*}}:32 -> Protocol requirement (P3) -> Protocol requirement (P2)]
-// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [Inferred @ {{.*}}:32 -> Protocol requirement (P3)]
-// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [Inferred]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (P3) -> Protocol requirement (P2)]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (P3)]
+// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
// CHECK-LABEL: .inferSameType2@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : P3 [Explicit @ {{.*}}:25]
-// CHECK-NEXT: τ_0_1 : P4 [Explicit @ {{.*}}:33]
-// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [Explicit @ {{.*}}:25 -> Protocol requirement (P3) -> Protocol requirement (P2)]
-// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [Explicit @ {{.*}}:25 -> Protocol requirement (P3)]
-// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [Explicit]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (P3) -> Protocol requirement (P2)]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (P3)]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// CHECK-LABEL: .inferSameType3@
// CHECK-NEXT: Requirements:
-// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [Explicit @ {{.*}}:25]
-// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [Explicit @ {{.*}}:74]
-// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [Explicit @ {{.*}}:66]
+// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [τ_0_0: Explicit @ {{.*}}:74]
+// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [τ_0_0[.PCommonAssoc1].CommonAssoc: Explicit @ {{.*}}:66]
// CHECK-NEXT: Potential archetypes
func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
@@ -177,6 +181,8 @@
// CHECK-LABEL: sameTypeConcrete2@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.B == X3, τ_0_0.C == X3>
func sameTypeConcrete2<T : P9 & P10>(_: T) where T.B : X3, T.C == T.B, T.C == X3 { }
+// expected-warning@-1{{redundant superclass constraint 'T.B' : 'X3'}}
+// expected-note@-2{{same-type constraint 'T.C' == 'X3' written here}}
// Note: a standard-library-based stress test to make sure we don't inject
// any additional requirements.
@@ -189,6 +195,13 @@
func f() { }
}
+// CHECK-LABEL: X14.recursiveConcreteSameType
+// CHECK: Generic signature: <T, V where T == CountableRange<Int>>
+// CHECK-NEXT: Canonical generic signature: <τ_0_0, τ_1_0 where τ_0_0 == CountableRange<Int>>
+struct X14<T: Collection> where T.Iterator == IndexingIterator<T> {
+ func recursiveConcreteSameType<V>(_: V) where T == CountableRange<Int> { }
+}
+
// rdar://problem/30478915
protocol P11 {
associatedtype A
diff --git a/test/Generics/superclass_constraint.swift b/test/Generics/superclass_constraint.swift
index eac9a3e..4eb15ab 100644
--- a/test/Generics/superclass_constraint.swift
+++ b/test/Generics/superclass_constraint.swift
@@ -13,8 +13,13 @@
class Other { }
-func f1<T : A>(_: T) where T : Other {} // expected-error{{generic parameter 'T' cannot be a subclass of both 'A' and 'Other'}}
+func f1<T : A>(_: T) where T : Other {} // expected-error{{generic parameter 'T' cannot be a subclass of both 'Other' and 'A'}}
+// expected-note@-1{{superclass constraint 'T' : 'A' written here}}
+
func f2<T : A>(_: T) where T : B {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'A'}}
+// expected-note@-2{{superclass constraint 'T' : 'B' written here}}
+
class GA<T> {}
class GB<T> : GA<T> {}
@@ -27,10 +32,16 @@
func f6<U : GA<T>, T : P>(_: T, _: U) {}
func f7<U, T>(_: T, _: U) where U : GA<T>, T : P {}
-func f8<T : GA<A>>(_: T) where T : GA<B> {} // expected-error{{generic parameter 'T' cannot be a subclass of both 'GA<A>' and 'GA<B>'}}
+func f8<T : GA<A>>(_: T) where T : GA<B> {} // expected-error{{generic parameter 'T' cannot be a subclass of both 'GA<B>' and 'GA<A>'}}
+// expected-note@-1{{superclass constraint 'T' : 'GA<A>' written here}}
func f9<T : GA<A>>(_: T) where T : GB<A> {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'GA<A>'}}
+// expected-note@-2{{superclass constraint 'T' : 'GB<A>' written here}}
+
func f10<T : GB<A>>(_: T) where T : GA<A> {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'GA<A>'}}
+// expected-note@-2{{superclass constraint 'T' : 'GB<A>' written here}}
func f11<T : GA<T>>(_: T) { } // expected-error{{superclass constraint 'T' : 'GA<T>' is recursive}}
func f12<T : GA<U>, U : GB<T>>(_: T, _: U) { } // expected-error{{superclass constraint 'U' : 'GB<T>' is recursive}} // expected-error{{superclass constraint 'T' : 'GA<U>' is recursive}}
@@ -64,15 +75,15 @@
// CHECK: superclassConformance1
// CHECK: Requirements:
-// CHECK-NEXT: τ_0_0 : C [Explicit @ {{.*}}:46]
-// CHECK-NEXT: τ_0_0 : P3 [Explicit @ {{.*}}:46 -> Superclass (C: P3)]
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:46]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:46 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance1<T>(t: T) where T : C, T : P3 {}
// CHECK: superclassConformance2
// CHECK: Requirements:
-// CHECK-NEXT: τ_0_0 : C [Explicit @ {{.*}}:46]
-// CHECK-NEXT: τ_0_0 : P3 [Explicit @ {{.*}}:46 -> Superclass (C: P3)]
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:46]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:46 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance2<T>(t: T) where T : C, T : P3 {}
@@ -82,23 +93,27 @@
// CHECK: superclassConformance3
// CHECK: Requirements:
-// CHECK-NEXT: τ_0_0 : C2 [Explicit @ {{.*}}:46]
-// CHECK-NEXT: τ_0_0 : P4 [Explicit @ {{.*}}:46 -> Superclass (C2: P4)]
+// CHECK-NEXT: τ_0_0 : C2 [τ_0_0: Explicit @ {{.*}}:46]
+// CHECK-NEXT: τ_0_0 : P4 [τ_0_0: Explicit @ {{.*}}:61 -> Superclass (C2: P4)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
+// expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
+// expected-note@-2{{superclass constraint 'T' : 'C2' written here}}
protocol P5: A { } // expected-error{{non-class type 'P5' cannot inherit from class 'A'}}
-protocol P6: A, Other { } // expected-error{{protocol 'P6' cannot be a subclass of both 'A' and 'Other'}}
+protocol P6: A, Other { } // expected-error{{protocol 'P6' cannot be a subclass of both 'Other' and 'A'}}
// expected-error@-1{{non-class type 'P6' cannot inherit from class 'A'}}
// expected-error@-2{{non-class type 'P6' cannot inherit from class 'Other'}}
+// expected-note@-3{{superclass constraint 'Self' : 'A' written here}}
func takeA(_: A) { }
func takeP5<T: P5>(_ t: T) {
takeA(t) // okay
}
-protocol P7 { // expected-error{{'Self.Assoc' cannot be a subclass of both 'A' and 'Other'}}
+protocol P7 { // expected-error{{'Self.Assoc' cannot be a subclass of both 'Other' and 'A'}}
associatedtype Assoc: A, Other
// FIXME: expected-error@-1{{multiple inheritance from classes 'A' and 'Other'}}
+ // FIXME weird location: expected-note@-3{{superclass constraint 'Self.Assoc' : 'A' written here}}
}
diff --git a/test/IDE/print_ast_tc_decls_errors.swift b/test/IDE/print_ast_tc_decls_errors.swift
index f226d8a..2affaa9 100644
--- a/test/IDE/print_ast_tc_decls_errors.swift
+++ b/test/IDE/print_ast_tc_decls_errors.swift
@@ -157,7 +157,7 @@
// NO-TYREPR: {{^}}protocol ProtocolWithInheritance4 : <<error type>>, FooProtocol {{{$}}
// TYREPR: {{^}}protocol ProtocolWithInheritance4 : FooClass, FooProtocol {{{$}}
-protocol ProtocolWithInheritance5 : FooClass, BarClass {} // expected-error {{non-class type 'ProtocolWithInheritance5' cannot inherit from class 'FooClass'}} expected-error {{non-class type 'ProtocolWithInheritance5' cannot inherit from class 'BarClass'}} expected-error{{protocol 'ProtocolWithInheritance5' cannot be a subclass of both 'FooClass' and 'BarClass'}}
+protocol ProtocolWithInheritance5 : FooClass, BarClass {} // expected-error {{non-class type 'ProtocolWithInheritance5' cannot inherit from class 'FooClass'}} expected-error {{non-class type 'ProtocolWithInheritance5' cannot inherit from class 'BarClass'}} expected-error{{protocol 'ProtocolWithInheritance5' cannot be a subclass of both 'BarClass' and 'FooClass'}} // expected-note{{superclass constraint 'Self' : 'FooClass' written here}}
// NO-TYREPR: {{^}}protocol ProtocolWithInheritance5 : <<error type>>, <<error type>> {{{$}}
// TYREPR: {{^}}protocol ProtocolWithInheritance5 : FooClass, BarClass {{{$}}
diff --git a/test/IDE/print_usrs.swift b/test/IDE/print_usrs.swift
index aafed58..e05000d 100644
--- a/test/IDE/print_usrs.swift
+++ b/test/IDE/print_usrs.swift
@@ -173,9 +173,9 @@
set {}
}
- // CHECK: [[@LINE+1]]:3 c:objc(cs)ObjCClass1(cm)initWithX:{{$}}
+ // CHECK: [[@LINE+1]]:3 c:objc(cs)ObjCClass1(im)initWithX:{{$}}
init(x: Int) {}
- // CHECK: [[@LINE+1]]:3 c:objc(cs)ObjCClass1(cm)init{{$}}
+ // CHECK: [[@LINE+1]]:3 c:objc(cs)ObjCClass1(im)init{{$}}
init() {}
// CHECK: [[@LINE+1]]:8 c:objc(cs)ObjCClass1(im)instanceFunc1:{{$}}
diff --git a/test/IDE/range_info_basics.swift b/test/IDE/range_info_basics.swift
index 9a0b919..9483408 100644
--- a/test/IDE/range_info_basics.swift
+++ b/test/IDE/range_info_basics.swift
@@ -159,7 +159,7 @@
// CHECK4-NEXT: <Content>aaa = aaa + 3
// CHECK4-NEXT: if aaa == 3 { aaa = 4 }</Content>
// CHECK4-NEXT: <Type>Void</Type>
-// CHECK4-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK4-NEXT: <Context>swift_ide_test.(file).foo()</Context>
// CHECK4-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK4-NEXT: <ASTNodes>2</ASTNodes>
// CHECK4-NEXT: <end>
@@ -169,7 +169,7 @@
// CHECK5-NEXT: if aaa == 3 { aaa = 4 }
// CHECK5-NEXT: return aaa</Content>
// CHECK5-NEXT: <Type>Int</Type>
-// CHECK5-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK5-NEXT: <Context>swift_ide_test.(file).foo()</Context>
// CHECK5-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK5-NEXT: <ASTNodes>3</ASTNodes>
// CHECK5-NEXT: <end>
@@ -178,7 +178,7 @@
// CHECK6-NEXT: if aaa == 3 { aaa = 4 }
// CHECK6-NEXT: return aaa</Content>
// CHECK6-NEXT: <Type>Int</Type>
-// CHECK6-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK6-NEXT: <Context>swift_ide_test.(file).foo()</Context>
// CHECK6-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK6-NEXT: <ASTNodes>2</ASTNodes>
// CHECK6-NEXT: <end>
@@ -189,7 +189,7 @@
// CHECK7-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK7-NEXT: print(b + c)</Content>
// CHECK7-NEXT: <Type>()</Type>
-// CHECK7-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK7-NEXT: <Context>swift_ide_test.(file).foo2()</Context>
// CHECK7-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK7-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
// CHECK7-NEXT: <Referenced>a</Referenced><Type>Int</Type>
@@ -203,7 +203,7 @@
// CHECK8-NEXT: s = s.increment()
// CHECK8-NEXT: return c + b</Content>
// CHECK8-NEXT: <Type>Int</Type>
-// CHECK8-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK8-NEXT: <Context>swift_ide_test.(file).foo3(s:)</Context>
// CHECK8-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
// CHECK8-NEXT: <Referenced>s</Referenced><Type>@lvalue S1</Type>
// CHECK8-NEXT: <Referenced>b</Referenced><Type>Int</Type>
@@ -216,7 +216,7 @@
// CHECK9-NEXT: let c = s.foo() + b
// CHECK9-NEXT: return c + b</Content>
// CHECK9-NEXT: <Type>Int</Type>
-// CHECK9-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK9-NEXT: <Context>swift_ide_test.(file).foo4(s:)</Context>
// CHECK9-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK9-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
// CHECK9-NEXT: <Referenced>s</Referenced><Type>S1</Type>
@@ -228,7 +228,7 @@
// CHECK10: <Kind>MultiStatement</Kind>
// CHECK10-NEXT: <Content>let a = c.c.getC().c.getC().getC().getC()
// CHECK10-NEXT: let b = a.c.c.c.c.getC().getC()</Content>
-// CHECK10-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK10-NEXT: <Context>swift_ide_test.(file).foo5(c:)</Context>
// CHECK10-NEXT: <Declared>a</Declared><OutscopeReference>true</OutscopeReference>
// CHECK10-NEXT: <Declared>b</Declared><OutscopeReference>true</OutscopeReference>
// CHECK10-NEXT: <Referenced>c</Referenced><Type>C1</Type>
@@ -240,7 +240,7 @@
// CHECK11-NEXT: <Content>let a = c.c.getC().c.getC().getC().getC()
// CHECK11-NEXT: let b = a.c.c.c.c.getC().getC()
// CHECK11-NEXT: let d = a.c.getC().getC().c.c</Content>
-// CHECK11-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK11-NEXT: <Context>swift_ide_test.(file).foo5(c:)</Context>
// CHECK11-NEXT: <Declared>a</Declared><OutscopeReference>true</OutscopeReference>
// CHECK11-NEXT: <Declared>b</Declared><OutscopeReference>true</OutscopeReference>
// CHECK11-NEXT: <Declared>d</Declared><OutscopeReference>true</OutscopeReference>
@@ -255,7 +255,7 @@
// CHECK12-NEXT: let d = a.c.getC().getC().c.c
// CHECK12-NEXT: return a.take(another: b).take(another: d)</Content>
// CHECK12-NEXT: <Type>C1</Type>
-// CHECK12-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK12-NEXT: <Context>swift_ide_test.(file).foo5(c:)</Context>
// CHECK12-NEXT: <Declared>a</Declared><OutscopeReference>false</OutscopeReference>
// CHECK12-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK12-NEXT: <Declared>d</Declared><OutscopeReference>false</OutscopeReference>
@@ -273,7 +273,7 @@
// CHECK13-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK13-NEXT: print(b + c)</Content>
// CHECK13-NEXT: <Type>()</Type>
-// CHECK13-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0</Context>
+// CHECK13-NEXT: <Context>swift_ide_test.(file).foo6().explicit closure discriminator=0</Context>
// CHECK13-NEXT: <Declared>a</Declared><OutscopeReference>false</OutscopeReference>
// CHECK13-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK13-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
@@ -298,7 +298,7 @@
// CHECK14-NEXT: return 1
// CHECK14-NEXT: }()</Content>
// CHECK14-NEXT: <Type>Int</Type>
-// CHECK14-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0</Context>
+// CHECK14-NEXT: <Context>swift_ide_test.(file).foo6().explicit closure discriminator=0</Context>
// CHECK14-NEXT: <Declared>a</Declared><OutscopeReference>false</OutscopeReference>
// CHECK14-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK14-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
@@ -320,7 +320,7 @@
// CHECK15-NEXT: let c = a.byteSwapped
// CHECK15-NEXT: b = b.bigEndian.bigEndian.byteSwapped</Content>
// CHECK15-NEXT: <Type>()</Type>
-// CHECK15-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0.explicit closure discriminator=0</Context>
+// CHECK15-NEXT: <Context>swift_ide_test.(file).foo6().explicit closure discriminator=0.explicit closure discriminator=0</Context>
// CHECK15-NEXT: <Declared>a</Declared><OutscopeReference>false</OutscopeReference>
// CHECK15-NEXT: <Declared>b</Declared><OutscopeReference>true</OutscopeReference>
// CHECK15-NEXT: <Declared>c</Declared><OutscopeReference>true</OutscopeReference>
@@ -337,7 +337,7 @@
// CHECK16-NEXT: print(b + c)
// CHECK16-NEXT: return 1</Content>
// CHECK16-NEXT: <Type>Int</Type>
-// CHECK16-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0.explicit closure discriminator=0</Context>
+// CHECK16-NEXT: <Context>swift_ide_test.(file).foo6().explicit closure discriminator=0.explicit closure discriminator=0</Context>
// CHECK16-NEXT: <Declared>a</Declared><OutscopeReference>false</OutscopeReference>
// CHECK16-NEXT: <Declared>b</Declared><OutscopeReference>false</OutscopeReference>
// CHECK16-NEXT: <Declared>c</Declared><OutscopeReference>false</OutscopeReference>
@@ -350,7 +350,7 @@
// CHECK17: <Kind>SingleExpression</Kind>
// CHECK17-NEXT: <Content>print(b + c)</Content>
// CHECK17-NEXT: <Type>()</Type>
-// CHECK17-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0.explicit closure discriminator=0</Context>
+// CHECK17-NEXT: <Context>swift_ide_test.(file).foo6().explicit closure discriminator=0.explicit closure discriminator=0</Context>
// CHECK17-NEXT: <Referenced>b</Referenced><Type>@lvalue Int</Type>
// CHECK17-NEXT: <Referenced>c</Referenced><Type>Int</Type>
// CHECK17-NEXT: <ASTNodes>1</ASTNodes>
@@ -362,7 +362,7 @@
// CHECK18-NEXT: case 2:
// CHECK18-NEXT: return 1</Content>
// CHECK18-NEXT: <Type>Void</Type>
-// CHECK18-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK18-NEXT: <Context>swift_ide_test.(file).foo7(a:)</Context>
// CHECK18-NEXT: <Entry>Multi</Entry>
// CHECK18-NEXT: <ASTNodes>2</ASTNodes>
// CHECK18-NEXT: <end>
@@ -371,7 +371,7 @@
// CHECK19-NEXT: <Content>case 1:
// CHECK19-NEXT: return 0</Content>
// CHECK19-NEXT: <Type>Void</Type>
-// CHECK19-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK19-NEXT: <Context>swift_ide_test.(file).foo7(a:)</Context>
// CHECK19-NEXT: <ASTNodes>1</ASTNodes>
// CHECK19-NEXT: <end>
@@ -381,7 +381,7 @@
// CHECK20-NEXT: default:
// CHECK20-NEXT: return a</Content>
// CHECK20-NEXT: <Type>Void</Type>
-// CHECK20-NEXT: <Context>swift_ide_test.(file).func decl</Context>
+// CHECK20-NEXT: <Context>swift_ide_test.(file).foo7(a:)</Context>
// CHECK20-NEXT: <Entry>Multi</Entry>
// CHECK20-NEXT: <ASTNodes>2</ASTNodes>
// CHECK20-NEXT: <end>
diff --git a/test/IDE/reconstruct_type_from_mangled_name_invalid.swift b/test/IDE/reconstruct_type_from_mangled_name_invalid.swift
index f001da0..80deae5 100644
--- a/test/IDE/reconstruct_type_from_mangled_name_invalid.swift
+++ b/test/IDE/reconstruct_type_from_mangled_name_invalid.swift
@@ -1,5 +1,5 @@
// RUN: %target-swift-ide-test -reconstruct-type -source-filename %s | %FileCheck %s -implicit-check-not="FAILURE"
-// REQUIRES: rdar://problem/30680565
+// REQUIRES: rdar30680565
struct GS<T> {
// CHECK: decl: struct GS<T> for 'GS'
diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift
index a4adaea..65c8398 100644
--- a/test/IRGen/abitypes.swift
+++ b/test/IRGen/abitypes.swift
@@ -551,7 +551,7 @@
// arm64-ios: [[STRUCTPTR:%.*]] = bitcast i64* [[COERCED]] to %TSC14FiveByteStructV
// arm64-ios: [[PTR0:%.*]] = getelementptr inbounds %TSC14FiveByteStructV, %TSC14FiveByteStructV* [[STRUCTPTR]], {{i.*}} 0, {{i.*}} 0
// arm64-ios: [[PTR1:%.*]] = getelementptr inbounds %T10ObjectiveC8ObjCBoolV, %T10ObjectiveC8ObjCBoolV* [[PTR0]], {{i.*}} 0, {{i.*}} 0
-// arm64-ios: [[PTR2:%.*]] = getelementptr inbounds %Sb, %Sb* [[PTR1]], {{i.*}} 0, {{i.*}} 0
+// arm64-ios: [[PTR2:%.*]] = getelementptr inbounds %TSb, %TSb* [[PTR1]], {{i.*}} 0, {{i.*}} 0
// arm64-ios: store i1 false, i1* [[PTR2]], align 8
// arm64-ios: [[ARG:%.*]] = load i64, i64* [[COERCED]]
// arm64-ios: call void bitcast (void ()* @objc_msgSend to void (i8*, i8*, i64)*)(i8* {{.*}}, i8* {{.*}}, i64 [[ARG]])
diff --git a/test/IRGen/asmname.swift b/test/IRGen/asmname.swift
index 86b5589..f55275d 100644
--- a/test/IRGen/asmname.swift
+++ b/test/IRGen/asmname.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
@_silgen_name("atan2") func atan2test(_ a: Double, _ b: Double) -> Double
diff --git a/test/IRGen/associated_types.swift b/test/IRGen/associated_types.swift
index 6b1a4da..2260286 100644
--- a/test/IRGen/associated_types.swift
+++ b/test/IRGen/associated_types.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
protocol Runcer {
associatedtype Runcee
@@ -30,7 +30,7 @@
class Pussycat<T : Runcible, U> {
init() {}
- // CHECK: define hidden swiftcc void @_T016associated_types8PussycatC3eat{{[_0-9a-zA-Z]*}}F(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %C16associated_types8Pussycat* swiftself)
+ // CHECK: define hidden swiftcc void @_T016associated_types8PussycatC3eat{{[_0-9a-zA-Z]*}}F(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %T16associated_types8PussycatC* swiftself)
func eat(_ what: T.RuncerType.Runcee, and: T.RuncerType, with: T) { }
}
diff --git a/test/IRGen/bitcast.sil b/test/IRGen/bitcast.sil
index 02b8cc0..96c3c36 100644
--- a/test/IRGen/bitcast.sil
+++ b/test/IRGen/bitcast.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir| %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
@@ -16,20 +16,20 @@
protocol CP: class {}
-// CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @bitcast_trivial(%C7bitcast1C*) {{.*}} {
-// CHECK-i386: [[BUF:%.*]] = alloca %C7bitcast1C*, align 4
-// CHECK-i386: store %C7bitcast1C* %0, %C7bitcast1C** [[BUF]]
-// CHECK-i386: [[OUT_BUF:%.*]] = bitcast %C7bitcast1C** [[BUF]] to %Si*
-// CHECK-i386: [[VALUE_BUF:%.*]] = getelementptr inbounds %Si, %Si* [[OUT_BUF]], i32 0, i32 0
+// CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @bitcast_trivial(%T7bitcast1CC*) {{.*}} {
+// CHECK-i386: [[BUF:%.*]] = alloca %T7bitcast1CC*, align 4
+// CHECK-i386: store %T7bitcast1CC* %0, %T7bitcast1CC** [[BUF]]
+// CHECK-i386: [[OUT_BUF:%.*]] = bitcast %T7bitcast1CC** [[BUF]] to %TSi*
+// CHECK-i386: [[VALUE_BUF:%.*]] = getelementptr inbounds %TSi, %TSi* [[OUT_BUF]], i32 0, i32 0
// CHECK-i386: [[VALUE:%.*]] = load i32, i32* [[VALUE_BUF]], align 4
// CHECK-i386: ret i32 [[VALUE]]
// CHECK-i386: }
-// CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_trivial(%C7bitcast1C*) {{.*}} {
-// CHECK-x86_64: [[BUF:%.*]] = alloca %C7bitcast1C*, align 8
-// CHECK-x86_64: store %C7bitcast1C* %0, %C7bitcast1C** [[BUF]]
-// CHECK-x86_64: [[OUT_BUF:%.*]] = bitcast %C7bitcast1C** [[BUF]] to %Si*
-// CHECK-x86_64: [[VALUE_BUF:%.*]] = getelementptr inbounds %Si, %Si* [[OUT_BUF]], i32 0, i32 0
+// CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_trivial(%T7bitcast1CC*) {{.*}} {
+// CHECK-x86_64: [[BUF:%.*]] = alloca %T7bitcast1CC*, align 8
+// CHECK-x86_64: store %T7bitcast1CC* %0, %T7bitcast1CC** [[BUF]]
+// CHECK-x86_64: [[OUT_BUF:%.*]] = bitcast %T7bitcast1CC** [[BUF]] to %TSi*
+// CHECK-x86_64: [[VALUE_BUF:%.*]] = getelementptr inbounds %TSi, %TSi* [[OUT_BUF]], i32 0, i32 0
// CHECK-x86_64: [[VALUE:%.*]] = load i64, i64* [[VALUE_BUF]], align 8
// CHECK-x86_64: ret i64 [[VALUE]]
// CHECK-x86_64: }
@@ -54,15 +54,15 @@
return %i : $Optional<Int>
}
-// CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @bitcast_ref(%C7bitcast1C*) {{.*}} {
+// CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @bitcast_ref(%T7bitcast1CC*) {{.*}} {
// CHECK-i386-NEXT: entry:
-// CHECK-i386-NEXT: [[VALUE:%.*]] = ptrtoint %C7bitcast1C* %0 to i32
+// CHECK-i386-NEXT: [[VALUE:%.*]] = ptrtoint %T7bitcast1CC* %0 to i32
// CHECK-i386-NEXT: ret i32 [[VALUE]]
// CHECK-i386-NEXT: }
-// CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_ref(%C7bitcast1C*) {{.*}} {
+// CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_ref(%T7bitcast1CC*) {{.*}} {
// CHECK-x86_64-NEXT: entry:
-// CHECK-x86_64-NEXT: [[VALUE:%.*]] = ptrtoint %C7bitcast1C* %0 to i64
+// CHECK-x86_64-NEXT: [[VALUE:%.*]] = ptrtoint %T7bitcast1CC* %0 to i64
// CHECK-x86_64-NEXT: ret i64 [[VALUE]]
// CHECK-x86_64-NEXT: }
sil @bitcast_ref: $@convention(thin) (C) -> Optional<C> {
@@ -88,12 +88,12 @@
// CHECK-x86_64-LABEL: define hidden swiftcc i64 @unchecked_bitwise_cast(i64, i64) {{.*}} {
// CHECK-x86_64-NEXT: entry:
-// CHECK-x86_64-NEXT: alloca <{ %Si, %Si }>, align 8
+// CHECK-x86_64-NEXT: alloca <{ %TSi, %TSi }>, align 8
// A bunch of GEPs happen here to get from Int to int.
// CHECK-x86_64: store i64 %{{.*}}, i64* %bitcast.elt._value, align 8
// CHECK-x86_64: store i64 %{{.*}}, i64* %bitcast.elt1._value, align 8
-// CHECK-x86_64-NEXT: %{{.*}} = bitcast <{ %Si, %Si }>* %bitcast to %Si*
-// CHECK-x86_64-NEXT: [[VAL:%.*]] = getelementptr inbounds %Si, %Si* %{{.*}}, i32 0, i32 0
+// CHECK-x86_64-NEXT: %{{.*}} = bitcast <{ %TSi, %TSi }>* %bitcast to %TSi*
+// CHECK-x86_64-NEXT: [[VAL:%.*]] = getelementptr inbounds %TSi, %TSi* %{{.*}}, i32 0, i32 0
// CHECK-x86_64-NEXT: [[RESULT:%.*]] = load i64, i64* [[VAL]], align 8
// CHECK-x86_64: ret i64 [[RESULT]]
// CHECK-x86_64-NEXT: }
@@ -107,7 +107,7 @@
// CHECK-x86_64-LABEL: define hidden swiftcc i64 @trivial_bitwise_cast(i64, i64) {{.*}} {
// CHECK-x86_64-NOT: trap
// CHECK-x86_64-NOT: unreachable
-// CHECK-x86_64: bitcast <{ %Si, %Si }>* %bitcast to %Si*
+// CHECK-x86_64: bitcast <{ %TSi, %TSi }>* %bitcast to %TSi*
// CHECK-x86_64: ret
sil hidden [noinline] @trivial_bitwise_cast : $@convention(thin) (Int, Int) -> Int {
bb0(%0 : $Int, %1 : $Int):
@@ -131,11 +131,11 @@
}
// CHECK-i386-LABEL: define{{( protected)?}} swiftcc i32 @unchecked_ref_cast_class_optional
-// CHECK-i386: ptrtoint %C7bitcast1A* %0 to i32
+// CHECK-i386: ptrtoint %T7bitcast1AC* %0 to i32
// CHECK-i386-NEXT: ret i32
// CHECK-x86_64-LABEL: define{{( protected)?}} swiftcc i64 @unchecked_ref_cast_class_optional
-// CHECK-x86_64: ptrtoint %C7bitcast1A* %0 to i64
+// CHECK-x86_64: ptrtoint %T7bitcast1AC* %0 to i64
// CHECK-x86_64-NEXT: ret i64
sil @unchecked_ref_cast_class_optional : $@convention(thin) (@owned A) -> @owned Optional<AnyObject> {
bb0(%0 : $A):
diff --git a/test/IRGen/bitcast_different_size.sil b/test/IRGen/bitcast_different_size.sil
index 0ae508a..f4839af 100644
--- a/test/IRGen/bitcast_different_size.sil
+++ b/test/IRGen/bitcast_different_size.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s -verify | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
diff --git a/test/IRGen/casts.sil b/test/IRGen/casts.sil
index 1203b76..ef94f22 100644
--- a/test/IRGen/casts.sil
+++ b/test/IRGen/casts.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -Xllvm -sil-disable-pass="External Defs To Decls" %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// XFAIL: linux
sil_stage canonical
@@ -16,8 +16,8 @@
sil_vtable A {}
sil_vtable B {}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %C5casts1B* @unchecked_addr_cast(%C5casts1A** noalias nocapture dereferenceable({{.*}})) {{.*}} {
-// CHECK: bitcast %C5casts1A** %0 to %C5casts1B**
+// CHECK-LABEL: define{{( protected)?}} swiftcc %T5casts1BC* @unchecked_addr_cast(%T5casts1AC** noalias nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: bitcast %T5casts1AC** %0 to %T5casts1BC**
sil @unchecked_addr_cast : $(@in A) -> B {
entry(%a : $*A):
%b = unchecked_addr_cast %a : $*A to $*B
@@ -207,7 +207,7 @@
unreachable
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %objc_object* @checked_upcast(%C5casts1A*) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc %objc_object* @checked_upcast(%T5casts1AC*) {{.*}} {
// -- Don't need to check conformance of an object to AnyObject.
// CHECK-NOT: call %objc_object* @swift_dynamicCastObjCProtocolConditional
// CHECK: phi %objc_object*
@@ -220,14 +220,14 @@
unreachable
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %C5casts1A* @checked_downcast_optional({{(i32|i64)}}) {{.*}} {
-// CHECK: [[T0:%.*]] = inttoptr {{(i32|i64)}} %0 to %C5casts1A*
-// CHECK: [[OBJ_PTR:%.*]] = bitcast %C5casts1A* [[T0]] to i8*
+// CHECK-LABEL: define{{( protected)?}} swiftcc %T5casts1AC* @checked_downcast_optional({{(i32|i64)}}) {{.*}} {
+// CHECK: [[T0:%.*]] = inttoptr {{(i32|i64)}} %0 to %T5casts1AC*
+// CHECK: [[OBJ_PTR:%.*]] = bitcast %T5casts1AC* [[T0]] to i8*
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T05casts1ACMa()
// CHECK: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
// CHECK: [[RESULT_PTR:%.*]] = call i8* @swift_rt_swift_dynamicCastClass(i8* [[OBJ_PTR]], i8* [[METADATA_PTR]])
-// CHECK: [[RESULT:%.*]] = bitcast i8* [[RESULT_PTR]] to %C5casts1A*
-// CHECK: [[COND:%.*]] = icmp ne %C5casts1A* [[RESULT]], null
+// CHECK: [[RESULT:%.*]] = bitcast i8* [[RESULT_PTR]] to %T5casts1AC*
+// CHECK: [[COND:%.*]] = icmp ne %T5casts1AC* [[RESULT]], null
// CHECK: br i1 [[COND]]
sil @checked_downcast_optional : $@convention(thin) (Optional<A>) -> @owned A {
entry(%a : $Optional<A>):
@@ -317,7 +317,7 @@
return %x : $OB
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %C5casts1B* @checked_object_to_object_casts(%C5casts1A*)
+// CHECK-LABEL: define{{( protected)?}} swiftcc %T5casts1BC* @checked_object_to_object_casts(%T5casts1AC*)
// CHECK: @swift_dynamicCastClassUnconditional
sil @checked_object_to_object_casts : $@convention(thin) (A) -> B {
entry(%a : $A):
@@ -325,7 +325,7 @@
return %b : $B
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %C5casts2OB* @checked_objc_object_to_object_casts(%C5casts2OA*)
+// CHECK-LABEL: define{{( protected)?}} swiftcc %T5casts2OBC* @checked_objc_object_to_object_casts(%T5casts2OAC*)
// CHECK: @swift_dynamicCastClassUnconditional
sil @checked_objc_object_to_object_casts : $@convention(thin) (OA) -> OB {
entry(%a : $OA):
diff --git a/test/IRGen/cf.sil b/test/IRGen/cf.sil
index 29993a9..606b888 100644
--- a/test/IRGen/cf.sil
+++ b/test/IRGen/cf.sil
@@ -1,10 +1,10 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -sdk %S/Inputs %s -emit-ir -import-cf-types | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
// CHECK: [[TYPE:%swift.type]] = type
-// CHECK: [[REFRIGERATOR:%CSo14CCRefrigerator]] = type
+// CHECK: [[REFRIGERATOR:%TSo14CCRefrigeratorC]] = type
// CHECK: [[OBJC:%objc_object]] = type
// CHECK: [[REFRIGERATOR_NAME:@.*]] = private unnamed_addr constant [20 x i8] c"So14CCRefrigeratorC\00"
diff --git a/test/IRGen/clang_inline.swift b/test/IRGen/clang_inline.swift
index c59b912..58eec15 100644
--- a/test/IRGen/clang_inline.swift
+++ b/test/IRGen/clang_inline.swift
@@ -12,7 +12,7 @@
// RUN: %FileCheck %s < %t.ll
// RUN: %FileCheck -check-prefix=NEGATIVE %s < %t.ll
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// XFAIL: linux
#if IMPORT_EMPTY
@@ -21,7 +21,7 @@
import gizmo
-// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline16CallStaticInlineC10ReturnZeros5Int64VyF(%C12clang_inline16CallStaticInline* swiftself) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline16CallStaticInlineC10ReturnZeros5Int64VyF(%T12clang_inline16CallStaticInlineC* swiftself) {{.*}} {
class CallStaticInline {
func ReturnZero() -> Int64 { return Int64(zero()) }
}
@@ -29,7 +29,7 @@
// CHECK-LABEL: define internal i32 @zero()
// CHECK: [[INLINEHINT_SSP_UWTABLE:#[0-9]+]] {
-// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline17CallStaticInline2C10ReturnZeros5Int64VyF(%C12clang_inline17CallStaticInline2* swiftself) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline17CallStaticInline2C10ReturnZeros5Int64VyF(%T12clang_inline17CallStaticInline2C* swiftself) {{.*}} {
class CallStaticInline2 {
func ReturnZero() -> Int64 { return Int64(wrappedZero()) }
}
diff --git a/test/IRGen/clang_inline_reverse.swift b/test/IRGen/clang_inline_reverse.swift
index 2891dc8..f0d587b 100644
--- a/test/IRGen/clang_inline_reverse.swift
+++ b/test/IRGen/clang_inline_reverse.swift
@@ -2,19 +2,19 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -sdk %S/Inputs -primary-file %s -emit-ir -module-name clang_inline | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// XFAIL: linux
import gizmo
-// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline16CallStaticInlineC10ReturnZeros5Int64VyF(%C12clang_inline16CallStaticInline* swiftself) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline16CallStaticInlineC10ReturnZeros5Int64VyF(%T12clang_inline16CallStaticInlineC* swiftself) {{.*}} {
class CallStaticInline {
func ReturnZero() -> Int64 { return Int64(wrappedZero()) }
}
// CHECK-LABEL: define internal i32 @wrappedZero() {{#[0-9]+}} {
-// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline17CallStaticInline2C10ReturnZeros5Int64VyF(%C12clang_inline17CallStaticInline2* swiftself) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc i64 @_T012clang_inline17CallStaticInline2C10ReturnZeros5Int64VyF(%T12clang_inline17CallStaticInline2C* swiftself) {{.*}} {
class CallStaticInline2 {
func ReturnZero() -> Int64 { return Int64(zero()) }
}
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index a71fa83..242fe80 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -88,6 +88,9 @@
// CHECK: [[INHERITED:%.*]] = load i8*, i8** %T.ClassBoundBinary, align 8
// CHECK: [[INHERITED_WTBL:%.*]] = bitcast i8* [[INHERITED]] to i8**
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[INHERITED_WTBL]], align 8
+ // FIXME: Redundant load of inherited conformance
+ // CHECK: [[INHERITED:%.*]] = load i8*, i8** %T.ClassBoundBinary, align 8
+ // CHECK: [[INHERITED_WTBL:%.*]] = bitcast i8* [[INHERITED]] to i8**
// CHECK: [[WITNESS_FUNC:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %swift.type*, i8**)
// CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* swiftself %0, %swift.type* {{.*}}, i8** [[INHERITED_WTBL]])
x.classBoundBinaryMethod(y)
diff --git a/test/IRGen/dynamic_cast.sil b/test/IRGen/dynamic_cast.sil
index 95e89e6..0f00bdb 100644
--- a/test/IRGen/dynamic_cast.sil
+++ b/test/IRGen/dynamic_cast.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// We have to claim this is raw SIL because there are critical edges from non
// cond_br instructions.
@@ -17,7 +17,7 @@
var v: Int
}
-// CHECK: [[INT:%Si]] = type <{ [[LLVM_PTRSIZE_INT:i(32|64)]] }>
+// CHECK: [[INT:%TSi]] = type <{ [[LLVM_PTRSIZE_INT:i(32|64)]] }>
// CHECK-LABEL: define{{( protected)?}} swiftcc void @testUnconditional0(
sil @testUnconditional0 : $@convention(thin) (@in P) -> () {
diff --git a/test/IRGen/dynamic_lookup.sil b/test/IRGen/dynamic_lookup.sil
index 337bd98..af7a081 100644
--- a/test/IRGen/dynamic_lookup.sil
+++ b/test/IRGen/dynamic_lookup.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
import Swift
diff --git a/test/IRGen/dynamic_self.sil b/test/IRGen/dynamic_self.sil
index c8cae59..07b2c34 100644
--- a/test/IRGen/dynamic_self.sil
+++ b/test/IRGen/dynamic_self.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 3210f64..3daf1d2 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime-%target-ptrsize
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// We have to claim this is raw SIL because there are critical edges from non
// cond_br instructions.
@@ -10,42 +10,42 @@
import Swift
// -- Singleton enum. The representation is just the singleton payload.
-// CHECK: %O4enum9Singleton = type <{ <{ i64, i64 }> }>
+// CHECK: %T4enum9SingletonO = type <{ <{ i64, i64 }> }>
// -- Singleton enum with heap object ref payload. <rdar://problem/15679353>
-// CHECK: %O4enum12SingletonRef = type <{ %swift.refcounted* }>
+// CHECK: %T4enum12SingletonRefO = type <{ %swift.refcounted* }>
// -- No-payload enums. The representation is just an enum tag.
-// CHECK: %O4enum10NoPayloads = type <{ i8 }>
-// CHECK: %O4enum11NoPayloads2 = type <{ i8 }>
+// CHECK: %T4enum10NoPayloadsO = type <{ i8 }>
+// CHECK: %T4enum11NoPayloads2O = type <{ i8 }>
// -- Single-payload enum, no extra inhabitants in the payload type. The
// representation adds a tag bit to distinguish payload from enum tag:
// case x(i64): X0 X1 X2 ... X63 | 0, where X0...X63 are the payload bits
// case y: 0 0 0 ... 0 | 1
// case z: 1 0 0 ... 0 | 1
-// CHECK-64: %O4enum17SinglePayloadNoXI = type <{ [8 x i8], [1 x i8] }>
-// CHECK-64: %O4enum18SinglePayloadNoXI2 = type <{ [8 x i8], [1 x i8] }>
-// CHECK-32: %O4enum17SinglePayloadNoXI = type <{ [4 x i8], [1 x i8] }>
-// CHECK-32: %O4enum18SinglePayloadNoXI2 = type <{ [4 x i8], [1 x i8] }>
+// CHECK-64: %T4enum17SinglePayloadNoXIO = type <{ [8 x i8], [1 x i8] }>
+// CHECK-64: %T4enum18SinglePayloadNoXI2O = type <{ [8 x i8], [1 x i8] }>
+// CHECK-32: %T4enum17SinglePayloadNoXIO = type <{ [4 x i8], [1 x i8] }>
+// CHECK-32: %T4enum18SinglePayloadNoXI2O = type <{ [4 x i8], [1 x i8] }>
// -- Single-payload enum, spare bits. The representation uses a tag bit
// out of the payload to distinguish payload from enum tag:
// case x(i3): X0 X1 X2 0 0 0 0 0
// case y: 0 0 0 1 0 0 0 0
// case z: 1 0 0 1 0 0 0 0
-// CHECK: %O4enum21SinglePayloadSpareBit = type <{ [8 x i8] }>
+// CHECK: %T4enum21SinglePayloadSpareBitO = type <{ [8 x i8] }>
// -- Single-payload enum containing a no-payload enum as its payload.
// The representation takes extra inhabitants starting after the greatest
// discriminator value used by the nested no-payload enum.
-// CHECK: %O4enum19SinglePayloadNested = type <{ [1 x i8] }>
+// CHECK: %T4enum19SinglePayloadNestedO = type <{ [1 x i8] }>
// -- Single-payload enum containing another single-payload enum as its
// payload.
// The representation takes extra inhabitants from the nested enum's payload
// that were unused by the nested enum.
-// CHECK: %O4enum25SinglePayloadNestedNested = type <{ [1 x i8] }>
+// CHECK: %T4enum019SinglePayloadNestedD0O = type <{ [1 x i8] }>
// -- Multi-payload enum, no spare bits. The representation adds tag bits
// to discriminate payloads. No-payload cases all share a tag.
@@ -55,7 +55,7 @@
// case a: 0 0 0 ... 0 0 | 1 1
// case b: 1 0 0 ... 0 0 | 1 1
// case c: 0 1 0 ... 0 0 | 1 1
-// CHECK: %O4enum23MultiPayloadNoSpareBits = type <{ [8 x i8], [1 x i8] }>
+// CHECK: %T4enum23MultiPayloadNoSpareBitsO = type <{ [8 x i8], [1 x i8] }>
// -- Multi-payload enum, one spare bit. The representation uses spare bits
// common to all payloads to partially discriminate payloads, with added
@@ -66,7 +66,7 @@
// case a: 0 0 0 0 0 0 0 1 | 1
// case b: 1 0 0 0 0 0 0 1 | 1
// case c: 0 1 0 0 0 0 0 1 | 1
-// CHECK: %O4enum23MultiPayloadOneSpareBit = type <{ [8 x i8], [1 x i8] }>
+// CHECK: %T4enum23MultiPayloadOneSpareBitO = type <{ [8 x i8], [1 x i8] }>
// -- Multi-payload enum, two spare bits. Same as above, except we have enough
// spare bits not to require any added tag bits.
@@ -76,28 +76,28 @@
// case a: 0 0 0 0 0 0 1 1
// case b: 1 0 0 0 0 0 1 1
// case c: 0 1 0 0 0 0 1 1
-// CHECK: %O4enum24MultiPayloadTwoSpareBits = type <{ [8 x i8] }>
+// CHECK: %T4enum24MultiPayloadTwoSpareBitsO = type <{ [8 x i8] }>
-// CHECK-64: %O4enum30MultiPayloadSpareBitAggregates = type <{ [16 x i8] }>
+// CHECK-64: %T4enum30MultiPayloadSpareBitAggregatesO = type <{ [16 x i8] }>
-// CHECK-64: %O4enum18MultiPayloadNested = type <{ [9 x i8] }>
-// CHECK-32: %O4enum18MultiPayloadNested = type <{ [5 x i8] }>
+// CHECK-64: %T4enum18MultiPayloadNestedO = type <{ [9 x i8] }>
+// CHECK-32: %T4enum18MultiPayloadNestedO = type <{ [5 x i8] }>
// 32-bit object references don't have enough spare bits.
-// CHECK-64: %O4enum27MultiPayloadNestedSpareBits = type <{ [8 x i8] }>
+// CHECK-64: %T4enum27MultiPayloadNestedSpareBitsO = type <{ [8 x i8] }>
// -- Dynamic enums. The type layout is opaque; we dynamically bitcast to
// the element type.
-// CHECK: %O4enum20DynamicSinglePayload = type <{}>
-// CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%GO4enum20DynamicSinglePayloadT__]] = type <{ [1 x i8] }>
+// CHECK: %T4enum20DynamicSinglePayloadO = type <{}>
+// CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%T4enum20DynamicSinglePayloadOyytG]] = type <{ [1 x i8] }>
// -- Address-only multi-payload enums. We can't use spare bits.
-// CHECK-64: %O4enum32MultiPayloadAddressOnlySpareBits = type <{ [16 x i8], [1 x i8] }>
-// CHECK-32: %O4enum32MultiPayloadAddressOnlySpareBits = type <{ [8 x i8], [1 x i8] }>
+// CHECK-64: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [16 x i8], [1 x i8] }>
+// CHECK-32: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [8 x i8], [1 x i8] }>
-// CHECK: [[DYNAMIC_SINGLETON:%O4enum16DynamicSingleton.*]] = type <{}>
+// CHECK: [[DYNAMIC_SINGLETON:%T4enum16DynamicSingletonO.*]] = type <{}>
-// CHECK: %O4enum40MultiPayloadLessThan32BitsWithEmptyCases = type <{ [1 x i8], [1 x i8] }>
+// CHECK: %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO = type <{ [1 x i8], [1 x i8] }>
// -- Dynamic metadata template carries a value witness table pattern
// we fill in on instantiation.
@@ -196,7 +196,7 @@
}
// CHECK-64: define{{( protected)?}} swiftcc void @singleton_switch(i64, i64) {{.*}} {
-// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch(%O4enum9Singleton* noalias nocapture dereferenceable(16)) {{.*}} {
+// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch(%T4enum9SingletonO* noalias nocapture dereferenceable(16)) {{.*}} {
sil @singleton_switch : $(Singleton) -> () {
// CHECK-64: entry:
// CHECK-32: entry:
@@ -215,12 +215,12 @@
}
// CHECK-64: define{{( protected)?}} swiftcc void @singleton_switch_arg(i64, i64) {{.*}} {
-// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch_arg(%O4enum9Singleton* noalias nocapture dereferenceable(16)) {{.*}} {
+// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch_arg(%T4enum9SingletonO* noalias nocapture dereferenceable(16)) {{.*}} {
sil @singleton_switch_arg : $(Singleton) -> () {
// CHECK-64: entry:
// CHECK-32: entry:
entry(%u : $Singleton):
-// CHECK-32: [[CAST:%.*]] = bitcast %O4enum9Singleton* %0 to <{ i64, i64 }>*
+// CHECK-32: [[CAST:%.*]] = bitcast %T4enum9SingletonO* %0 to <{ i64, i64 }>*
// CHECK-32: [[GEP1:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 0
// CHECK-32: [[ELT1:%.*]] = load i64, i64* [[GEP1]]
// CHECK-32: [[GEP2:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 1
@@ -246,11 +246,11 @@
return %x : $()
}
-// CHECK: define{{( protected)?}} swiftcc void @singleton_switch_indirect(%O4enum9Singleton* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @singleton_switch_indirect(%T4enum9SingletonO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK: entry:
// CHECK: br label %[[DEST:[0-9]+]]
// CHECK: ; <label>:[[DEST]]
-// CHECK: [[ADDR:%.*]] = bitcast %O4enum9Singleton* %0 to <{ i64, i64 }>*
+// CHECK: [[ADDR:%.*]] = bitcast %T4enum9SingletonO* %0 to <{ i64, i64 }>*
// CHECK: ret void
// CHECK: }
sil @singleton_switch_indirect : $(@inout Singleton) -> () {
@@ -268,9 +268,9 @@
// CHECK-64: [[B:%.*]] = insertvalue { i64, i64 } [[A]], i64 %1, 1
// CHECK-64: ret { i64, i64 } [[B]]
// CHECK-64: }
-// CHECK-32: define{{( protected)?}} swiftcc void @singleton_inject(%O4enum9Singleton* noalias nocapture sret, i64, i64) {{.*}} {
+// CHECK-32: define{{( protected)?}} swiftcc void @singleton_inject(%T4enum9SingletonO* noalias nocapture sret, i64, i64) {{.*}} {
// CHECK-32: entry:
-// CHECK-32: [[CAST:%.*]] = bitcast %O4enum9Singleton* %0 to <{ i64, i64 }>*
+// CHECK-32: [[CAST:%.*]] = bitcast %T4enum9SingletonO* %0 to <{ i64, i64 }>*
// CHECK-32: [[GEP1:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 0
// CHECK-32: store i64 %1, i64* [[GEP1]]
// CHECK-32: [[GEP2:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 1
@@ -284,9 +284,9 @@
return %u : $Singleton
}
-// CHECK: define{{( protected)?}} swiftcc void @singleton_inject_indirect(i64, i64, %O4enum9Singleton* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @singleton_inject_indirect(i64, i64, %T4enum9SingletonO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK: entry:
-// CHECK: [[DATA_ADDR:%.*]] = bitcast %O4enum9Singleton* %2 to <{ i64, i64 }>*
+// CHECK: [[DATA_ADDR:%.*]] = bitcast %T4enum9SingletonO* %2 to <{ i64, i64 }>*
// CHECK: [[DATA_0_ADDR:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[DATA_ADDR]], i32 0, i32 0
// CHECK: store i64 %0, i64* [[DATA_0_ADDR]]
// CHECK: [[DATA_1_ADDR:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[DATA_ADDR]], i32 0, i32 1
@@ -360,10 +360,10 @@
return %x : $()
}
-// CHECK: define{{( protected)?}} swiftcc void @no_payload_switch_indirect(%O4enum10NoPayloads* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @no_payload_switch_indirect(%T4enum10NoPayloadsO* nocapture dereferenceable({{.*}})) {{.*}} {
sil @no_payload_switch_indirect : $@convention(thin) (@inout NoPayloads) -> () {
entry(%u : $*NoPayloads):
-// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %O4enum10NoPayloads, %O4enum10NoPayloads* %0, i32 0, i32 0
+// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %T4enum10NoPayloadsO, %T4enum10NoPayloadsO* %0, i32 0, i32 0
// CHECK: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]]
// CHECK: switch i8 [[TAG]]
switch_enum_addr %u : $*NoPayloads, case #NoPayloads.x!enumelt: x_dest, case #NoPayloads.y!enumelt: y_dest, case #NoPayloads.z!enumelt: z_dest
@@ -409,9 +409,9 @@
return %u : $NoPayloads
}
-// CHECK: define{{( protected)?}} swiftcc void @no_payload_inject_z_indirect(%O4enum10NoPayloads* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @no_payload_inject_z_indirect(%T4enum10NoPayloadsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK: entry:
-// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %O4enum10NoPayloads, %O4enum10NoPayloads* %0, i32 0, i32 0
+// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %T4enum10NoPayloadsO, %T4enum10NoPayloadsO* %0, i32 0, i32 0
// CHECK: store i8 2, i8* [[TAG_ADDR]]
// CHECK: ret void
// CHECK: }
@@ -619,11 +619,11 @@
return %u : $SinglePayloadNoXI2
}
-// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_inject_x_indirect([[WORD]], %O4enum18SinglePayloadNoXI2* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_inject_x_indirect([[WORD]], %T4enum18SinglePayloadNoXI2O* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK: entry:
-// CHECK: [[DATA_ADDR:%.*]] = bitcast %O4enum18SinglePayloadNoXI2* %1 to [[WORD]]*
+// CHECK: [[DATA_ADDR:%.*]] = bitcast %T4enum18SinglePayloadNoXI2O* %1 to [[WORD]]*
// CHECK: store [[WORD]] %0, [[WORD]]* [[DATA_ADDR]]
-// CHECK: [[T0:%.*]] = getelementptr inbounds %O4enum18SinglePayloadNoXI2, %O4enum18SinglePayloadNoXI2* %1, i32 0, i32 1
+// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, %T4enum18SinglePayloadNoXI2O* %1, i32 0, i32 1
// CHECK: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK: store i1 false, i1* [[TAG_ADDR]]
// CHECK: ret void
@@ -647,11 +647,11 @@
return %u : $SinglePayloadNoXI2
}
-// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_inject_y_indirect(%O4enum18SinglePayloadNoXI2* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_inject_y_indirect(%T4enum18SinglePayloadNoXI2O* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK: entry:
-// CHECK: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum18SinglePayloadNoXI2* %0 to [[WORD]]*
+// CHECK: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum18SinglePayloadNoXI2O* %0 to [[WORD]]*
// CHECK: store [[WORD]] 0, [[WORD]]* [[PAYLOAD_ADDR]]
-// CHECK: [[T0:%.*]] = getelementptr inbounds %O4enum18SinglePayloadNoXI2, %O4enum18SinglePayloadNoXI2* %0, i32 0, i32 1
+// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, %T4enum18SinglePayloadNoXI2O* %0, i32 0, i32 1
// CHECK: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK: store i1 true, i1* [[TAG_ADDR]]
// CHECK: ret void
@@ -743,10 +743,10 @@
}
// CHECK-64: define{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2([[WORD]], [[WORD]], [[WORD]], [[WORD]]) {{.*}} {
-// CHECK-32: define{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2(%O4enum23AggregateSinglePayload2* noalias nocapture dereferenceable(16)) {{.*}} {
+// CHECK-32: define{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2(%T4enum23AggregateSinglePayload2O* noalias nocapture dereferenceable(16)) {{.*}} {
sil @aggregate_single_payload_unpack_2 : $@convention(thin) (AggregateSinglePayload2) -> () {
entry(%u : $AggregateSinglePayload2):
-// CHECK-32: [[CAST:%.*]] = bitcast %O4enum23AggregateSinglePayload2* %0 to { i32, i32, i32, i32 }*
+// CHECK-32: [[CAST:%.*]] = bitcast %T4enum23AggregateSinglePayload2O* %0 to { i32, i32, i32, i32 }*
// CHECK-32: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST]], i32 0, i32 0
// CHECK-32: [[LOAD1:%.*]] = load i32, i32* [[GEP]]
// CHECK-32: [[LOAD2:%.*]] = load i32, i32* {{.*}}
@@ -783,10 +783,10 @@
// CHECK-64: %9 = insertvalue { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %8, [[WORD]] %3, 3
// CHECK-64: ret { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %9
-// CHECK-32: define{{( protected)?}} swiftcc void @aggregate_single_payload_2_inject(%O4enum23AggregateSinglePayload2* noalias nocapture sret, i32, i32, i32, i32) {{.*}} {
+// CHECK-32: define{{( protected)?}} swiftcc void @aggregate_single_payload_2_inject(%T4enum23AggregateSinglePayload2O* noalias nocapture sret, i32, i32, i32, i32) {{.*}} {
// CHECK-32: [[TRUNC:%.*]] = trunc i32 %1 to i21
// CHECK-32: [[ZEXT:%.*]] = zext i21 [[TRUNC]] to i32
-// CHECK-32: [[CAST:%.*]] = bitcast %O4enum23AggregateSinglePayload2* %0 to { i32, i32, i32, i32 }*
+// CHECK-32: [[CAST:%.*]] = bitcast %T4enum23AggregateSinglePayload2O* %0 to { i32, i32, i32, i32 }*
// CHECK-32: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST]], i32 0, i32 0
// CHECK-32: store i32 [[ZEXT]], i32* [[GEP]]
// CHECK-32: store i32 %2, i32*
@@ -967,13 +967,13 @@
sil @single_payload_spare_bit_switch_indirect : $@convention(thin) (@inout SinglePayloadSpareBit) -> () {
entry(%u : $*SinglePayloadSpareBit):
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum21SinglePayloadSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// CHECK-64: switch i64 [[PAYLOAD]]
switch_enum_addr %u : $*SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt.1: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
// CHECK-64: ; <label>:
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum21SinglePayloadSpareBit* %0 to i63*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i63*
x_dest:
%u2 = unchecked_take_enum_data_addr %u : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt.1
%a = function_ref @a : $@convention(thin) () -> ()
@@ -1003,10 +1003,10 @@
return %u : $SinglePayloadSpareBit
}
-// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_x_indirect(i64, %O4enum21SinglePayloadSpareBit* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_x_indirect(i64, %T4enum21SinglePayloadSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
// CHECK-64: [[T:%.*]] = trunc i64 %0 to i63
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum21SinglePayloadSpareBit* %1 to i63*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %1 to i63*
// CHECK-64: store i63 [[T]], i63* [[DATA_ADDR]]
// CHECK-64: ret void
// CHECK-64: }
@@ -1030,9 +1030,9 @@
return %u : $SinglePayloadSpareBit
}
-// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_y_indirect(%O4enum21SinglePayloadSpareBit* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_y_indirect(%T4enum21SinglePayloadSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum21SinglePayloadSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i64*
// -- 0x8000_0000_0000_0000
// CHECK-64: store i64 -9223372036854775808, i64* [[PAYLOAD_ADDR]]
// CHECK-64: ret void
@@ -1146,7 +1146,7 @@
// CHECK-64: i64 4, label {{%.*}}
// CHECK-64: ]
// CHECK-64: ; <label>
-// CHECK-64: inttoptr [[WORD]] %0 to %C4enum1C*
+// CHECK-64: inttoptr [[WORD]] %0 to %T4enum1CC*
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_class_switch(i32) {{.*}} {
// CHECK-32: entry:
@@ -1156,7 +1156,7 @@
// CHECK-32: i32 2, label {{%.*}}
// CHECK-32: ]
// CHECK-32: ; <label>
-// CHECK-32: inttoptr [[WORD]] %0 to %C4enum1C*
+// CHECK-32: inttoptr [[WORD]] %0 to %T4enum1CC*
sil @single_payload_class_switch : $(SinglePayloadClass) -> () {
entry(%c : $SinglePayloadClass):
@@ -1270,8 +1270,8 @@
case w
}
-// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_switch(%O4enum20DynamicSinglePayload* noalias nocapture, %swift.type* %T) {{.*}} {
-// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %O4enum20DynamicSinglePayload* %0 to %swift.opaque*
+// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_switch(%T4enum20DynamicSinglePayloadO* noalias nocapture, %swift.type* %T) {{.*}} {
+// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
// CHECK: [[CASE_INDEX:%.*]] = call i32 @swift_rt_swift_getEnumCaseSinglePayload(%swift.opaque* [[OPAQUE_ENUM]], %swift.type* %T, i32 3)
// CHECK: switch i32 [[CASE_INDEX]], label {{%.*}} [
// CHECK: i32 -1, label {{%.*}}
@@ -1295,8 +1295,8 @@
return %v : $()
}
-// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%O4enum20DynamicSinglePayload* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T) {{.*}} {
-// CHECK: [[ADDR:%.*]] = bitcast %O4enum20DynamicSinglePayload* %0 to %swift.opaque*
+// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%T4enum20DynamicSinglePayloadO* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T) {{.*}} {
+// CHECK: [[ADDR:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
// CHECK: call void @swift_rt_swift_storeEnumTagSinglePayload(%swift.opaque* [[ADDR]], %swift.type* %T, i32 -1, i32 3)
sil @dynamic_single_payload_inject_x : $<T> (@in T) -> @out DynamicSinglePayload<T> {
entry(%r : $*DynamicSinglePayload<T>, %t : $*T):
@@ -1305,8 +1305,8 @@
return %v : $()
}
-// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%O4enum20DynamicSinglePayload* noalias nocapture sret, %swift.type* %T) {{.*}} {
-// CHECK: [[ADDR:%.*]] = bitcast %O4enum20DynamicSinglePayload* %0 to %swift.opaque*
+// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%T4enum20DynamicSinglePayloadO* noalias nocapture sret, %swift.type* %T) {{.*}} {
+// CHECK: [[ADDR:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
// CHECK: call void @swift_rt_swift_storeEnumTagSinglePayload(%swift.opaque* [[ADDR]], %swift.type* %T, i32 0, i32 3)
sil @dynamic_single_payload_inject_y : $<T> () -> @out DynamicSinglePayload<T> {
entry(%r : $*DynamicSinglePayload<T>):
@@ -1486,12 +1486,12 @@
return %v : $()
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch_indirect(%O4enum23MultiPayloadNoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch_indirect(%T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
sil @multi_payload_no_spare_bits_switch_indirect : $(@inout MultiPayloadNoSpareBits) -> () {
entry(%u : $*MultiPayloadNoSpareBits):
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadNoSpareBits* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadNoSpareBits, %O4enum23MultiPayloadNoSpareBits* %0, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %0, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
// CHECK-64: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]]
// CHECK-64: switch i8 [[TAG]]
@@ -1501,11 +1501,11 @@
switch_enum_addr %u : $*MultiPayloadNoSpareBits, case #MultiPayloadNoSpareBits.x!enumelt.1: x_dest, case #MultiPayloadNoSpareBits.y!enumelt.1: y_dest, case #MultiPayloadNoSpareBits.z!enumelt.1: z_dest, case #MultiPayloadNoSpareBits.a!enumelt: a_dest, case #MultiPayloadNoSpareBits.b!enumelt: b_dest, case #MultiPayloadNoSpareBits.c!enumelt: c_dest
// CHECK-64: ; <label>:[[X_DEST:[0-9]+]]
-// CHECK-64: bitcast %O4enum23MultiPayloadNoSpareBits* %0 to i64*
+// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
// CHECK-64: ; <label>:[[Y_DEST:[0-9]+]]
-// CHECK-64: bitcast %O4enum23MultiPayloadNoSpareBits* %0 to i32*
+// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i32*
// CHECK-64: ; <label>:[[Z_DEST:[0-9]+]]
-// CHECK-64: bitcast %O4enum23MultiPayloadNoSpareBits* %0 to i63*
+// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i63*
x_dest:
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt.1
@@ -1545,11 +1545,11 @@
return %u : $MultiPayloadNoSpareBits
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_x_indirect(i64, %O4enum23MultiPayloadNoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_x_indirect(i64, %T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum23MultiPayloadNoSpareBits* %1 to i64*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %1 to i64*
// CHECK-64: store i64 %0, i64* [[DATA_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadNoSpareBits, %O4enum23MultiPayloadNoSpareBits* %1, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %1, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
// CHECK-64: store i8 0, i8* [[TAG_ADDR]]
// CHECK-64: ret void
@@ -1600,11 +1600,11 @@
return %u : $MultiPayloadNoSpareBits
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_a_indirect(%O4enum23MultiPayloadNoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_a_indirect(%T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadNoSpareBits* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
// CHECK-64: store i64 0, i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadNoSpareBits, %O4enum23MultiPayloadNoSpareBits* %0, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %0, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
// CHECK-64: store i8 3, i8* [[TAG_ADDR]]
// CHECK-64: ret void
@@ -1734,9 +1734,9 @@
sil @multi_payload_one_spare_bit_switch_indirect : $(@inout MultiPayloadOneSpareBit) -> () {
entry(%u : $*MultiPayloadOneSpareBit):
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadOneSpareBit, %O4enum23MultiPayloadOneSpareBit* %0, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %0, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK-64: [[TAG:%.*]] = load i1, i1* [[TAG_ADDR]]
// CHECK-64: switch i8 {{%.*}}
@@ -1746,19 +1746,19 @@
switch_enum_addr %u : $*MultiPayloadOneSpareBit, case #MultiPayloadOneSpareBit.x!enumelt.1: x_dest, case #MultiPayloadOneSpareBit.y!enumelt.1: y_dest, case #MultiPayloadOneSpareBit.z!enumelt.1: z_dest, case #MultiPayloadOneSpareBit.a!enumelt: a_dest, case #MultiPayloadOneSpareBit.b!enumelt: b_dest, case #MultiPayloadOneSpareBit.c!enumelt: c_dest
// CHECK-64: ; <label>:[[X_PREDEST:[0-9]+]]
-// CHECK-64: bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i62*
+// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i62*
// CHECK-64: ; <label>:[[Y_PREDEST:[0-9]+]]
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// -- 0x7FFF_FFFF_FFFF_FFFF
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
-// CHECK-64: bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i63*
+// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i63*
// CHECK-64: ; <label>:[[Z_PREDEST:[0-9]+]]
-// CHECK-64: bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i61*
+// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i61*
x_dest:
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt.1
@@ -1800,18 +1800,18 @@
return %u : $MultiPayloadOneSpareBit
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_x_indirect(i64, %O4enum23MultiPayloadOneSpareBit* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_x_indirect(i64, %T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i62*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i62*
// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]]
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// -- 0x7FFF_FFFF_FFFF_FFFF
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadOneSpareBit, %O4enum23MultiPayloadOneSpareBit* %1, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %1, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK-64: store i1 false, i1* [[TAG_ADDR]]
// CHECK-64: ret void
@@ -1841,20 +1841,20 @@
return %u : $MultiPayloadOneSpareBit
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_y_indirect(i64, %O4enum23MultiPayloadOneSpareBit* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_y_indirect(i64, %T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i63*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i63*
// CHECK-64: store i63 [[NATIVECC_TRUNC]], i63* [[DATA_ADDR]]
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// -- 0x7FFF_FFFF_FFFF_FFFF
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
// -- 0x8000_0000_0000_0000
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], -9223372036854775808
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadOneSpareBit, %O4enum23MultiPayloadOneSpareBit* %1, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %1, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK-64: store i1 false, i1* [[TAG_ADDR]]
// CHECK-64: ret void
@@ -1894,12 +1894,12 @@
return %u : $MultiPayloadOneSpareBit
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_a_indirect(%O4enum23MultiPayloadOneSpareBit* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_a_indirect(%T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum23MultiPayloadOneSpareBit* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
// -- 0x8000_0000_0000_0000
// CHECK-64: store i64 -9223372036854775808, i64* [[PAYLOAD_ADDR]]
-// CHECK-64: [[T0:%.*]] = getelementptr inbounds %O4enum23MultiPayloadOneSpareBit, %O4enum23MultiPayloadOneSpareBit* %0, i32 0, i32 1
+// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %0, i32 0, i32 1
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
// CHECK-64: store i1 true, i1* [[TAG_ADDR]]
// CHECK-64: ret void
@@ -2040,16 +2040,16 @@
return %u : $MultiPayloadTwoSpareBits
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_x_indirect(i64, %O4enum24MultiPayloadTwoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_x_indirect(i64, %T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i62*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i62*
// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]]
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// -- 0x3FFF_FFFF_FFFF_FFFF
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 4611686018427387903
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
// CHECK-64: ret void
// CHECK-64: }
@@ -2076,18 +2076,18 @@
return %u : $MultiPayloadTwoSpareBits
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_y_indirect(i64, %O4enum24MultiPayloadTwoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_y_indirect(i64, %T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60
-// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i60*
+// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i60*
// CHECK-64: store i60 [[NATIVECC_TRUNC]], i60* [[DATA_ADDR]]
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
// -- 0x3FFF_FFFF_FFFF_FFFF
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 4611686018427387903
// -- 0x4000_0000_0000_0000
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], 4611686018427387904
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %1 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], i64* [[PAYLOAD_ADDR]]
// CHECK-64: ret void
// CHECK-64: }
@@ -2125,9 +2125,9 @@
return %u : $MultiPayloadTwoSpareBits
}
-// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_a_indirect(%O4enum24MultiPayloadTwoSpareBits* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_a_indirect(%T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %O4enum24MultiPayloadTwoSpareBits* %0 to i64*
+// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %0 to i64*
// -- 0xC000_0000_0000_0000
// CHECK-64: store i64 -4611686018427387904, i64* [[PAYLOAD_ADDR]]
// CHECK-64: ret void
@@ -2189,11 +2189,11 @@
// CHECK-64: i64 -9223372036854775800, label {{%.*}}
// CHECK-64: ]
// -- Extract x(C)
-// CHECK-64: inttoptr i64 %0 to %C4enum1C*
+// CHECK-64: inttoptr i64 %0 to %T4enum1CC*
// -- Extract y(D)
// -- 0x3fffffffffffffff
// CHECK-64: [[MASKED:%.*]] = and i64 %0, 4611686018427387903
-// CHECK-64: inttoptr i64 [[MASKED]] to %C4enum1D*
+// CHECK-64: inttoptr i64 [[MASKED]] to %T4enum1DC*
// CHECK-32-LABEL: define{{( protected)?}} swiftcc void @multi_payload_classes_switch(i32) {{.*}} {
// CHECK-32: %1 = trunc i32 %0 to i8
@@ -2208,10 +2208,10 @@
// CHECK-32: i32 6, label {{%.*}}
// CHECK-32: ]
// -- Extract x(C)
-// CHECK-32: inttoptr i32 %0 to %C4enum1C*
+// CHECK-32: inttoptr i32 %0 to %T4enum1CC*
// -- Extract y(D)
// CHECK-32: [[MASKED:%.*]] = and i32 %0, -4
-// CHECK-32: inttoptr i32 [[MASKED]] to %C4enum1D*
+// CHECK-32: inttoptr i32 [[MASKED]] to %T4enum1DC*
sil @multi_payload_classes_switch : $(MultiPayloadClasses) -> () {
entry(%c : $MultiPayloadClasses):
@@ -2261,8 +2261,8 @@
// CHECK-64: ; <label>:[[Y_DEST]]
// -- 0x3fffffffffffffff
// CHECK-64: [[Y_MASKED:%.*]] = and i64 %0, 4611686018427387903
-// CHECK-64: [[Y_0:%.*]] = inttoptr i64 [[Y_MASKED]] to %C4enum1C*
-// CHECK-64: [[Y_1:%.*]] = inttoptr i64 %1 to %C4enum1C*
+// CHECK-64: [[Y_0:%.*]] = inttoptr i64 [[Y_MASKED]] to %T4enum1CC*
+// CHECK-64: [[Y_1:%.*]] = inttoptr i64 %1 to %T4enum1CC*
// CHECK-64: ; <label>:[[Z_DEST]]
// -- 0x3fffffffffffffff
// CHECK-64: [[Z_MASKED:%.*]] = and i64 %0, 4611686018427387903
@@ -2297,7 +2297,7 @@
}
// CHECK-LABEL: define{{( protected)?}} swiftcc void @multi_payload_nested_switch
-// CHECK: %1 = bitcast %O4enum18MultiPayloadNested* %0 to { [[WORD]], i8 }*
+// CHECK: %1 = bitcast %T4enum18MultiPayloadNestedO* %0 to { [[WORD]], i8 }*
// CHECK: %2 = getelementptr
// CHECK: %3 = load [[WORD]], [[WORD]]* %2
// CHECK: %4 = getelementptr
@@ -2331,9 +2331,9 @@
case B(MultiPayloadInnerSpareBits)
}
-// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @multi_payload_nested_spare_bits_switch(%O4enum27MultiPayloadNestedSpareBits* noalias nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @multi_payload_nested_spare_bits_switch(%T4enum27MultiPayloadNestedSpareBitsO* noalias nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-64: entry:
-// CHECK-64: %1 = bitcast %O4enum27MultiPayloadNestedSpareBits* %0 to [[WORD]]*
+// CHECK-64: %1 = bitcast %T4enum27MultiPayloadNestedSpareBitsO* %0 to [[WORD]]*
// CHECK-64: %2 = load [[WORD]], [[WORD]]* %1
// CHECK-64: %3 = lshr [[WORD]] %2, 61
// CHECK-64: %4 = trunc [[WORD]] %3 to i1
@@ -2402,7 +2402,7 @@
case Y(Builtin.Int32)
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc void @multi_payload_address_only_destroy(%O4enum28MultiPayloadAddressOnlyFixed* noalias nocapture dereferenceable({{.*}}))
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @multi_payload_address_only_destroy(%T4enum28MultiPayloadAddressOnlyFixedO* noalias nocapture dereferenceable({{.*}}))
sil @multi_payload_address_only_destroy : $@convention(thin) (@in MultiPayloadAddressOnlyFixed) -> () {
entry(%m : $*MultiPayloadAddressOnlyFixed):
destroy_addr %m : $*MultiPayloadAddressOnlyFixed
@@ -2422,7 +2422,7 @@
case Y(AddressOnlySpareBitsPayload)
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc void @multi_payload_address_only_spare_bits(%O4enum32MultiPayloadAddressOnlySpareBits* noalias nocapture dereferenceable({{.*}}))
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @multi_payload_address_only_spare_bits(%T4enum32MultiPayloadAddressOnlySpareBitsO* noalias nocapture dereferenceable({{.*}}))
sil @multi_payload_address_only_spare_bits : $@convention(thin) (@in MultiPayloadAddressOnlySpareBits) -> () {
entry(%m : $*MultiPayloadAddressOnlySpareBits):
destroy_addr %m : $*MultiPayloadAddressOnlySpareBits
@@ -2561,7 +2561,7 @@
weak var delegate: delegateProtocol?
}
-// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @weak_optional(%GSqV4enum17StructWithWeakVar_* noalias nocapture dereferenceable({{.*}}))
+// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @weak_optional(%T4enum17StructWithWeakVarVSg* noalias nocapture dereferenceable({{.*}}))
sil @weak_optional : $@convention(thin) (@in StructWithWeakVar?) -> () {
entry(%x : $*StructWithWeakVar?):
// CHECK-64: icmp eq [[WORD]] {{%.*}}, 0
@@ -2714,8 +2714,8 @@
// CHECK-64: %6 = or i128 %5, 18446744073709551616
// CHECK-LABEL: define linkonce_odr hidden i32 @_T04enum40MultiPayloadLessThan32BitsWithEmptyCasesOwug(%swift.opaque* %value
-// CHECK: [[VAL00:%.*]] = bitcast %swift.opaque* %value to %O4enum40MultiPayloadLessThan32BitsWithEmptyCases*
-// CHECK: [[VAL01:%.*]] = bitcast %O4enum40MultiPayloadLessThan32BitsWithEmptyCases* [[VAL00]] to i8*
+// CHECK: [[VAL00:%.*]] = bitcast %swift.opaque* %value to %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO*
+// CHECK: [[VAL01:%.*]] = bitcast %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO* [[VAL00]] to i8*
// CHECK: [[VAL02:%.*]] = load {{.*}} [[VAL01]]
// CHECK: [[VAL03:%.*]] = getelementptr inbounds {{.*}} [[VAL00]], i32 0, i32 1
// CHECK: [[VAL04:%.*]] = bitcast {{.*}} [[VAL03]] to i8*
@@ -2736,7 +2736,7 @@
// CHECK: <label>:[[TLABEL]]
// CHECK: [[VAL03:%.*]] = trunc i32 %tag to i8
-// CHECK: [[VAL04:%.*]] = bitcast %O4enum40MultiPayloadLessThan32BitsWithEmptyCases* [[VAL00]] to i8*
+// CHECK: [[VAL04:%.*]] = bitcast %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO* [[VAL00]] to i8*
// CHECK: store i8 [[VAL03]], i8* [[VAL04]]
// CHECK: [[VAL05:%.*]] = getelementptr inbounds {{.*}} [[VAL00]], i32 0, i32 1
// CHECK: [[VAL06:%.*]] = bitcast [1 x i8]* [[VAL05]] to i8*
diff --git a/test/IRGen/enum_spare_bits.sil b/test/IRGen/enum_spare_bits.sil
index f9d4cf9..faf16ed 100644
--- a/test/IRGen/enum_spare_bits.sil
+++ b/test/IRGen/enum_spare_bits.sil
@@ -2,7 +2,7 @@
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -new-mangling-for-tests %s -emit-ir | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
import Swift
@@ -17,15 +17,15 @@
case A(C), B(D)
}
// can use spare bits—both payloads are Swift-defined classes
-// CHECK-32: %O15enum_spare_bits10SwiftClass = type <{ [4 x i8] }>
-// CHECK-64: %O15enum_spare_bits10SwiftClass = type <{ [8 x i8] }>
+// CHECK-32: %T15enum_spare_bits10SwiftClassO = type <{ [4 x i8] }>
+// CHECK-64: %T15enum_spare_bits10SwiftClassO = type <{ [8 x i8] }>
enum ObjCClass {
case A(NSObject), B(C)
}
// can't use spare bits—NSObject is an ObjC-defined class
-// CHECK-32: %O15enum_spare_bits9ObjCClass = type <{ [4 x i8] }>
-// CHECK-64: %O15enum_spare_bits9ObjCClass = type <{ [8 x i8], [1 x i8] }>
+// CHECK-32: %T15enum_spare_bits9ObjCClassO = type <{ [4 x i8] }>
+// CHECK-64: %T15enum_spare_bits9ObjCClassO = type <{ [8 x i8], [1 x i8] }>
@objc @unsafe_no_objc_tagged_pointer
protocol NoTaggedPointers {}
@@ -34,24 +34,24 @@
case A(AnyObject), B(C)
}
// can't use spare bits—existential may be bound to tagged pointer type
-// CHECK-32: %O15enum_spare_bits11Existential = type <{ [4 x i8] }>
-// CHECK-64: %O15enum_spare_bits11Existential = type <{ [8 x i8], [1 x i8] }>
+// CHECK-32: %T15enum_spare_bits11ExistentialO = type <{ [4 x i8] }>
+// CHECK-64: %T15enum_spare_bits11ExistentialO = type <{ [8 x i8], [1 x i8] }>
enum ExistentialNoTaggedPointers {
case A(NoTaggedPointers), B(C)
}
// can use spare bits—@unsafe_no_objc_tagged_pointer says it's ok
-// CHECK-32: %O15enum_spare_bits27ExistentialNoTaggedPointers = type <{ [4 x i8] }>
-// CHECK-64: %O15enum_spare_bits27ExistentialNoTaggedPointers = type <{ [8 x i8] }>
+// CHECK-32: %T15enum_spare_bits27ExistentialNoTaggedPointersO = type <{ [4 x i8] }>
+// CHECK-64: %T15enum_spare_bits27ExistentialNoTaggedPointersO = type <{ [8 x i8] }>
enum Archetype<T: AnyObject> {
case A(T), B(C)
}
// can't use spare bits—archetype may be bound to tagged pointer type
-// CHECK-32: [[ARCHETYPE:%GO15enum_spare_bits9ArchetypeCS_1C_]] = type <{ [4 x i8], [1 x i8] }>
-// CHECK-32: [[ARCHETYPE_OBJC:%GO15enum_spare_bits9ArchetypeCSo8NSObject_]] = type <{ [4 x i8], [1 x i8] }>
-// CHECK-64: [[ARCHETYPE:%GO15enum_spare_bits9ArchetypeCS_1C_]] = type <{ [8 x i8], [1 x i8] }>
-// CHECK-64: [[ARCHETYPE_OBJC:%GO15enum_spare_bits9ArchetypeCSo8NSObject_]] = type <{ [8 x i8], [1 x i8] }>
+// CHECK-32: [[ARCHETYPE:%T15enum_spare_bits9ArchetypeOyAA1CCG]] = type <{ [4 x i8], [1 x i8] }>
+// CHECK-32: [[ARCHETYPE_OBJC:%T15enum_spare_bits9ArchetypeOySo8NSObjectCG]] = type <{ [4 x i8], [1 x i8] }>
+// CHECK-64: [[ARCHETYPE:%T15enum_spare_bits9ArchetypeOyAA1CCG]] = type <{ [8 x i8], [1 x i8] }>
+// CHECK-64: [[ARCHETYPE_OBJC:%T15enum_spare_bits9ArchetypeOySo8NSObjectCG]] = type <{ [8 x i8], [1 x i8] }>
sil_global @swiftClass: $SwiftClass
sil_global @objcClass: $ObjCClass
diff --git a/test/IRGen/fixlifetime.sil b/test/IRGen/fixlifetime.sil
index d00ad60..c6d0d6a 100644
--- a/test/IRGen/fixlifetime.sil
+++ b/test/IRGen/fixlifetime.sil
@@ -2,31 +2,31 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-sil -emit-ir -disable-llvm-optzns -Ounchecked %s | %FileCheck --check-prefix=CHECK-%target-runtime %s
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-sil -emit-ir -disable-llvm-optzns -Onone %s | %FileCheck --check-prefix=ONONE %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// At -Onone we don't run the LLVM ARC optimizer, so the fixLifetime call is
// unnecessary.
// ONONE-NOT: @__swift_fixLifetime
-// CHECK-objc-LABEL: define{{( protected)?}} swiftcc void @test(%C11fixlifetime1C*, %objc_object*, i8**, i8*, %swift.refcounted*, %V11fixlifetime3Agg* noalias nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-objc-LABEL: define{{( protected)?}} swiftcc void @test(%T11fixlifetime1CC*, %objc_object*, i8**, i8*, %swift.refcounted*, %T11fixlifetime3AggV* noalias nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-objc: entry:
-// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C*)*)(%C11fixlifetime1C*
+// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC*)*)(%T11fixlifetime1CC*
// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%objc_object*)*)(%objc_object*
// CHECK-objc: call void @__swift_fixLifetime(%swift.refcounted*
-// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C*)*)(%C11fixlifetime1C*
+// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC*)*)(%T11fixlifetime1CC*
// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%objc_object*)*)(%objc_object*
// CHECK-objc: call void @__swift_fixLifetime(%swift.refcounted*
-// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C**)*)(%C11fixlifetime1C**
+// CHECK-objc: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC**)*)(%T11fixlifetime1CC**
-// CHECK-native-LABEL: define{{( protected)?}} swiftcc void @test(%C11fixlifetime1C*, %swift.refcounted*, i8**, i8*, %swift.refcounted*, %V11fixlifetime3Agg* noalias nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-native-LABEL: define{{( protected)?}} swiftcc void @test(%T11fixlifetime1CC*, %swift.refcounted*, i8**, i8*, %swift.refcounted*, %T11fixlifetime3AggV* noalias nocapture dereferenceable({{.*}})) {{.*}} {
// CHECK-native: entry:
-// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C*)*)(%C11fixlifetime1C*
+// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC*)*)(%T11fixlifetime1CC*
// CHECK-native: call void @__swift_fixLifetime(%swift.refcounted*
// CHECK-native: call void @__swift_fixLifetime(%swift.refcounted*
-// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C*)*)(%C11fixlifetime1C*
+// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC*)*)(%T11fixlifetime1CC*
// CHECK-native: call void @__swift_fixLifetime(%swift.refcounted*
// CHECK-native: call void @__swift_fixLifetime(%swift.refcounted*
-// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%C11fixlifetime1C**)*)(%C11fixlifetime1C**
+// CHECK-native: call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC**)*)(%T11fixlifetime1CC**
sil_stage canonical
diff --git a/test/IRGen/function_types.sil b/test/IRGen/function_types.sil
index 876004f..9e36338 100644
--- a/test/IRGen/function_types.sil
+++ b/test/IRGen/function_types.sil
@@ -1,21 +1,18 @@
-// RUN: %swift -target x86_64-apple-macosx10.9 -module-name function_types %s -emit-ir -o - | %FileCheck %s
-// RUN: %swift -target i386-apple-ios7.1 %s -module-name function_types -emit-ir -o - | %FileCheck %s
-// RUN: %swift -target x86_64-apple-ios7.1 %s -module-name function_types -emit-ir -o - | %FileCheck %s
-// RUN: %swift -target armv7-apple-ios7.1 %s -module-name function_types -emit-ir -o - | %FileCheck %s
-// RUN: %swift -target arm64-apple-ios7.1 %s -module-name function_types -emit-ir -o - | %FileCheck %s
-// RUN: %swift -target x86_64-unknown-linux-gnu -disable-objc-interop %s -module-name function_types -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target x86_64-apple-macosx10.9 -module-name function_types -assume-parsing-unqualified-ownership-sil %s -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target i386-apple-ios7.1 %s -module-name function_types -assume-parsing-unqualified-ownership-sil -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target x86_64-apple-ios7.1 %s -module-name function_types -assume-parsing-unqualified-ownership-sil -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target armv7-apple-ios7.1 %s -module-name function_types -assume-parsing-unqualified-ownership-sil -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target arm64-apple-ios7.1 %s -module-name function_types -assume-parsing-unqualified-ownership-sil -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target x86_64-unknown-linux-gnu -disable-objc-interop %s -module-name function_types -assume-parsing-unqualified-ownership-sil -emit-ir -o - | %FileCheck %s
// REQUIRES: CODEGENERATOR=X86
// REQUIRES: CODEGENERATOR=ARM
-// FIXME: SR-3603 test is failing after being unintentionally disabled for a while
-// REQUIRES: SR3603
-
import Builtin
sil_stage canonical
-// CHECK-LABEL: define{{( protected)?}} i8* @thin_func_value(i8*) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc i8* @thin_func_value(i8*) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i8* %0
// CHECK-NEXT: }
@@ -24,7 +21,7 @@
return %x : $@convention(thin) () -> ()
}
-// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @thick_func_value(i8*, %swift.refcounted*) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @thick_func_value(i8*, %swift.refcounted*) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @swift_rt_swift_retain(%swift.refcounted* %1) {{#[0-9]+}}
// CHECK-NEXT: call void @swift_rt_swift_release(%swift.refcounted* %1) {{#[0-9]+}}
@@ -39,11 +36,9 @@
return %x : $() -> ()
}
-// CHECK-LABEL: define{{( protected)?}} { i8*, i8** } @thin_witness_value(i8*, i8**) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc i8* @thin_witness_value(i8*) {{.*}} {
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[T0:%.*]] = insertvalue { i8*, i8** } undef, i8* %0, 0
-// CHECK-NEXT: [[T1:%.*]] = insertvalue { i8*, i8** } [[T0]], i8** %1, 1
-// CHECK-NEXT: ret { i8*, i8** } [[T1]]
+// CHECK-NEXT: ret i8* %0
// CHECK-NEXT: }
sil @thin_witness_value : $@convention(thin) (@convention(witness_method) () -> ()) -> @convention(witness_method) () -> () {
entry(%x : $@convention(witness_method) () -> ()):
@@ -54,9 +49,9 @@
sil @out_void_return : $@convention(thin) () -> @out X
-// CHECK-LABEL: define{{( protected)?}} void @use_void_return_value(%V14function_types1X* noalias nocapture sret) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @use_void_return_value(%T14function_types1XV* noalias nocapture sret) {{.*}} {
// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @out_void_return(%V14function_types1X* noalias nocapture sret %0)
+// CHECK-NEXT: call swiftcc void @out_void_return(%T14function_types1XV* noalias nocapture sret %0)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
sil @use_void_return_value : $@convention(thin) () -> @out X {
@@ -66,7 +61,7 @@
return %z : $()
}
-// CHECK-LABEL: define{{( protected)?}} i1 @test_is_nonnull_function(i8*, %swift.refcounted*) {{.*}} {
+// CHECK-LABEL: define{{( protected)?}} swiftcc i1 @test_is_nonnull_function(i8*, %swift.refcounted*) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: %2 = icmp ne i8* %0, null
// CHECK-NEXT: ret i1 %2
@@ -78,7 +73,7 @@
return %3 : $Builtin.Int1 // id: %5
}
-// CHECK-LABEL: define{{( protected)?}} i8* @test_function_to_pointer(i8*)
+// CHECK-LABEL: define{{( protected)?}} swiftcc i8* @test_function_to_pointer(i8*)
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i8* %0
sil @test_function_to_pointer : $@convention(thin) (@convention(thin) () -> ()) -> Builtin.RawPointer {
@@ -87,7 +82,7 @@
return %1 : $Builtin.RawPointer
}
-// CHECK-LABEL: define{{( protected)?}} i8* @test_pointer_to_function(i8*)
+// CHECK-LABEL: define{{( protected)?}} swiftcc i8* @test_pointer_to_function(i8*)
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i8* %0
sil @test_pointer_to_function : $@convention(thin) (Builtin.RawPointer) -> @convention(thin) () -> () {
diff --git a/test/IRGen/generic_class_anyobject.swift b/test/IRGen/generic_class_anyobject.swift
index 3e47b8b..f5d9d4c 100644
--- a/test/IRGen/generic_class_anyobject.swift
+++ b/test/IRGen/generic_class_anyobject.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
func foo<T: AnyObject>(_ x: T) -> T { return x }
diff --git a/test/IRGen/generic_classes_objc.sil b/test/IRGen/generic_classes_objc.sil
index ba563fa..e476e6f 100644
--- a/test/IRGen/generic_classes_objc.sil
+++ b/test/IRGen/generic_classes_objc.sil
@@ -2,7 +2,7 @@
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -new-mangling-for-tests %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
import Builtin
diff --git a/test/IRGen/generic_ternary.swift b/test/IRGen/generic_ternary.swift
index 5a240cb..ed7c99d 100644
--- a/test/IRGen/generic_ternary.swift
+++ b/test/IRGen/generic_ternary.swift
@@ -1,10 +1,10 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// <rdar://problem/13793646>
struct OptionalStreamAdaptor<T : IteratorProtocol> {
- // CHECK: define hidden swiftcc void @_T015generic_ternary21OptionalStreamAdaptorV4next{{[_0-9a-zA-Z]*}}F(%Sq{{.*}}* noalias nocapture sret, %swift.type* %"OptionalStreamAdaptor<T>", %V15generic_ternary21OptionalStreamAdaptor* nocapture swiftself dereferenceable({{.*}}))
+ // CHECK: define hidden swiftcc void @_T015generic_ternary21OptionalStreamAdaptorV4next{{[_0-9a-zA-Z]*}}F(%TSq{{.*}}* noalias nocapture sret, %swift.type* %"OptionalStreamAdaptor<T>", %T15generic_ternary21OptionalStreamAdaptorV* nocapture swiftself dereferenceable({{.*}}))
mutating
func next() -> Optional<T.Element> {
return x[0].next()
diff --git a/test/IRGen/indirect_return.swift b/test/IRGen/indirect_return.swift
index 2cb0b95..8d0957fb 100644
--- a/test/IRGen/indirect_return.swift
+++ b/test/IRGen/indirect_return.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// CHECK: define hidden swiftcc void @_T015indirect_return11generic_get{{[_0-9a-zA-Z]*}}F
func generic_get<T>(p: UnsafeMutablePointer<T>) -> T {
diff --git a/test/IRGen/infinite_archetype.swift b/test/IRGen/infinite_archetype.swift
index 5a974f3..f6b503d 100644
--- a/test/IRGen/infinite_archetype.swift
+++ b/test/IRGen/infinite_archetype.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -primary-file %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
protocol Fooable {
associatedtype Foo
diff --git a/test/IRGen/lazy_multi_file.swift b/test/IRGen/lazy_multi_file.swift
index dc4274e..fd343b2 100644
--- a/test/IRGen/lazy_multi_file.swift
+++ b/test/IRGen/lazy_multi_file.swift
@@ -1,17 +1,17 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil -primary-file %s %S/Inputs/lazy_multi_file_helper.swift -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
-// CHECK: %C15lazy_multi_file8Subclass = type <{ %swift.refcounted, %[[OPTIONAL_INT_TY:GSqSi_]], [{{[0-9]+}} x i8], %SS }>
+// CHECK: %T15lazy_multi_file8SubclassC = type <{ %swift.refcounted, %[[OPTIONAL_INT_TY:TSiSg]], [{{[0-9]+}} x i8], %TSS }>
// CHECK: %[[OPTIONAL_INT_TY]] = type <{ [{{[0-9]+}} x i8], [1 x i8] }>
-// CHECK: %V15lazy_multi_file13LazyContainer = type <{ %[[OPTIONAL_INT_TY]] }>
+// CHECK: %T15lazy_multi_file13LazyContainerV = type <{ %[[OPTIONAL_INT_TY]] }>
class Subclass : LazyContainerClass {
final var str = "abc"
- // CHECK-LABEL: @_T015lazy_multi_file8SubclassC6getStrSSyF(%C15lazy_multi_file8Subclass* swiftself) {{.*}} {
+ // CHECK-LABEL: @_T015lazy_multi_file8SubclassC6getStrSSyF(%T15lazy_multi_file8SubclassC* swiftself) {{.*}} {
func getStr() -> String {
- // CHECK: = getelementptr inbounds %C15lazy_multi_file8Subclass, %C15lazy_multi_file8Subclass* %0, i32 0, i32 3
+ // CHECK: = getelementptr inbounds %T15lazy_multi_file8SubclassC, %T15lazy_multi_file8SubclassC* %0, i32 0, i32 3
return str
}
}
diff --git a/test/IRGen/metatype_casts.sil b/test/IRGen/metatype_casts.sil
index 2c2a2cc..598440a 100644
--- a/test/IRGen/metatype_casts.sil
+++ b/test/IRGen/metatype_casts.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// XFAIL: linux
import Swift
@@ -68,8 +68,8 @@
class OtherClass : SomeClass {}
sil_vtable OtherClass {}
-// CHECK-LABEL: define{{( protected)?}} swiftcc void @value_metatype_cast(%C14metatype_casts9SomeClass*)
-// CHECK: [[T0:%.*]] = bitcast %C14metatype_casts9SomeClass* %0 to %swift.type**
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @value_metatype_cast(%T14metatype_casts9SomeClassC*)
+// CHECK: [[T0:%.*]] = bitcast %T14metatype_casts9SomeClassC* %0 to %swift.type**
// CHECK: [[T1:%.*]] = load %swift.type*, %swift.type** [[T0]]
// CHECK: [[T2:%.*]] = icmp eq %swift.type* [[T1]], {{.*}} @_T014metatype_casts10OtherClassCMf
sil @value_metatype_cast : $@convention(thin) (SomeClass) -> () {
diff --git a/test/IRGen/nondominant.sil b/test/IRGen/nondominant.sil
index e4c58c5..11740b8 100644
--- a/test/IRGen/nondominant.sil
+++ b/test/IRGen/nondominant.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
import Builtin
diff --git a/test/IRGen/objc_alloc.sil b/test/IRGen/objc_alloc.sil
index 364ac71..2d95809 100644
--- a/test/IRGen/objc_alloc.sil
+++ b/test/IRGen/objc_alloc.sil
@@ -2,7 +2,7 @@
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
// REQUIRES: objc_interop
sil_stage canonical
diff --git a/test/IRGen/protocol_extensions.sil b/test/IRGen/protocol_extensions.sil
index aea3760..2bd52c1 100644
--- a/test/IRGen/protocol_extensions.sil
+++ b/test/IRGen/protocol_extensions.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
import Builtin
diff --git a/test/IRGen/select_enum_single_payload.sil b/test/IRGen/select_enum_single_payload.sil
index a187bb0..f3d0aae 100644
--- a/test/IRGen/select_enum_single_payload.sil
+++ b/test/IRGen/select_enum_single_payload.sil
@@ -1,5 +1,5 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
diff --git a/test/IRGen/sil_witness_methods.sil b/test/IRGen/sil_witness_methods.sil
index 3681428..4e0d3dc 100644
--- a/test/IRGen/sil_witness_methods.sil
+++ b/test/IRGen/sil_witness_methods.sil
@@ -85,7 +85,7 @@
return %m : $@thick Foo.Type
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %T19sil_witness_methods3BarC{{(.1)?}}** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable)
+// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %T19sil_witness_methods3BarC{{.*}}** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable)
sil @generic_type_generic_method_witness : $@convention(witness_method) <T, U, V, Z> (@in Z, @in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type {
entry(%z : $*Z, %x : $*Bar<T, U, V>):
%t = metatype $@thick T.Type
diff --git a/test/IRGen/witness_method.sil b/test/IRGen/witness_method.sil
index de663e7..9aff540 100644
--- a/test/IRGen/witness_method.sil
+++ b/test/IRGen/witness_method.sil
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
sil_stage canonical
@@ -60,14 +60,14 @@
}
}
-// CHECK-LABEL: define{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %V14witness_method6SyncUp* noalias nocapture, %swift.type* %T)
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
// CHECK: entry:
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T014witness_method6SyncUpVMa(%swift.type* %T)
// CHECK: [[WTABLE:%.*]] = call i8** @_T014witness_method6SyncUpVyxGAA7SynergyAAlWa(%swift.type* [[METADATA]])
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 1
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
-// CHECK: [[ARG:%.*]] = bitcast %V14witness_method6SyncUp* %1 to %swift.opaque*
+// CHECK: [[ARG:%.*]] = bitcast %T14witness_method6SyncUpV* %1 to %swift.opaque*
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself [[ARG]], %swift.type* [[METADATA]], i8** [[WTABLE]])
// CHECK: ret void
diff --git a/test/IRGen/witness_method_phi.sil b/test/IRGen/witness_method_phi.sil
index d00962e..4447936 100644
--- a/test/IRGen/witness_method_phi.sil
+++ b/test/IRGen/witness_method_phi.sil
@@ -10,7 +10,6 @@
br bb1(%1 : $@convention(witness_method) <T: P> (@in P) -> ())
// CHECK: phi i8* [ %0, %entry ]
-// CHECK-NEXT: phi i8** [ %T.P, %entry ]
bb1(%2 : $@convention(witness_method) <T: P> (@in P) -> ()):
unreachable
}
diff --git a/test/Index/kinds.swift b/test/Index/kinds.swift
index c550867..1ddd0bf 100644
--- a/test/Index/kinds.swift
+++ b/test/Index/kinds.swift
@@ -43,10 +43,16 @@
class AClass {
// CHECK: [[@LINE-1]]:7 | class/Swift | AClass | s:14swift_ide_test6AClassC | Def | rel: 0
- // InstanceMethod
- func instanceMethod() {}
- // CHECK: [[@LINE-1]]:8 | instance-method/Swift | instanceMethod() | s:14swift_ide_test6AClassC14instanceMethodyyF | Def,RelChild | rel: 1
- // CHECK-NEXT: RelChild | AClass | s:14swift_ide_test6AClassC
+ // InstanceMethod + Parameters
+ func instanceMethod(a: Int, b b: Int, _ c: Int, d _: Int, _: Int) {}
+ // CHECK: [[@LINE-1]]:8 | instance-method/Swift | instanceMethod(a:b:_:d:_:) | s:14swift_ide_test6AClassC14instanceMethodySi1a_Si1bSiSi1dSitF | Def,RelChild | rel: 1
+ // CHECK-NEXT: RelChild | AClass | s:14swift_ide_test6AClassC
+ // CHECK: [[@LINE-3]]:23 | param/Swift | a | s:14swift_ide_test6AClassC14instanceMethodySi1a_Si1bSiSi1dSitFAEL_Siv | Def,RelChild | rel: 1
+ // CHECK-NEXT: RelChild | instanceMethod(a:b:_:d:_:) | s:14swift_ide_test6AClassC14instanceMethodySi1a_Si1bSiSi1dSitF
+ // CHECK-NOT: [[@LINE-5]]:33 | param/Swift | b | s:{{.*}} | Def,RelChild | rel: 1
+ // CHECK-NOT: [[@LINE-6]]:43 | param/Swift | c | s:{{.*}} | Def,RelChild | rel: 1
+ // CHECK-NOT: [[@LINE-7]]:53 | param/Swift | d | s:{{.*}} | Def,RelChild | rel: 1
+ // CHECK-NOT: [[@LINE-8]]:61 | param/Swift | _ | s:{{.*}} | Def,RelChild | rel: 1
// ClassMethod
class func classMethod() {}
diff --git a/test/Index/roles.swift b/test/Index/roles.swift
index ba39b63..757a19a 100644
--- a/test/Index/roles.swift
+++ b/test/Index/roles.swift
@@ -37,13 +37,15 @@
// CHECK: [[@LINE-1]]:3 | function/acc-get/Swift | getter:z | s:14swift_ide_test1zSifg | Def,RelChild,RelAcc | rel: 1
return y
- // CHECK: [[@LINE-1]]:12 | variable/Swift | y | s:14swift_ide_test1ySiv | Ref,Read | rel: 0
+ // CHECK: [[@LINE-1]]:12 | variable/Swift | y | s:14swift_ide_test1ySiv | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | getter:z | s:14swift_ide_test1zSifg
}
set {
// CHECK: [[@LINE-1]]:3 | function/acc-set/Swift | setter:z | s:14swift_ide_test1zSifs | Def,RelChild,RelAcc | rel: 1
y = newValue
- // CHECK: [[@LINE-1]]:5 | variable/Swift | y | s:14swift_ide_test1ySiv | Ref,Writ | rel: 0
+ // CHECK: [[@LINE-1]]:5 | variable/Swift | y | s:14swift_ide_test1ySiv | Ref,Writ,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | setter:z | s:14swift_ide_test1zSifs
}
}
// Write + Read of z
@@ -54,22 +56,40 @@
// CHECK: [[@LINE-4]]:5 | function/acc-get/Swift | getter:z | s:14swift_ide_test1zSifg | Ref,Call,Impl | rel: 0
// Call
-func aCalledFunction() {}
-// CHECK: [[@LINE-1]]:6 | function/Swift | aCalledFunction() | s:14swift_ide_test15aCalledFunctionyyF | Def | rel: 0
+func aCalledFunction(a: Int, b: inout Int) {
+// CHECK: [[@LINE-1]]:6 | function/Swift | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF | Def | rel: 0
+// CHECK: [[@LINE-2]]:22 | param/Swift | a | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
+// CHECK: [[@LINE-4]]:30 | param/Swift | b | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
-aCalledFunction()
-// CHECK: [[@LINE-1]]:1 | function/Swift | aCalledFunction() | s:14swift_ide_test15aCalledFunctionyyF | Ref,Call | rel: 0
+ var _ = a + b
+ // CHECK: [[@LINE-1]]:11 | param/Swift | a | s:{{.*}} | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
+ // CHECK: [[@LINE-3]]:15 | param/Swift | b | s:{{.*}} | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
+
+ b = a + 1
+ // CHECK: [[@LINE-1]]:3 | param/Swift | b | s:{{.*}} | Ref,Writ,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
+ // CHECK: [[@LINE-3]]:7 | param/Swift | a | s:{{.*}} | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF
+}
+
+aCalledFunction(a: 1, b: &z)
+// CHECK: [[@LINE-1]]:1 | function/Swift | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF | Ref,Call | rel: 0
+// CHECK: [[@LINE-2]]:27 | variable/Swift | z | s:14swift_ide_test1zSiv | Ref,Read,Writ | rel: 0
func aCaller() {
// CHECK: [[@LINE-1]]:6 | function/Swift | aCaller() | s:14swift_ide_test7aCalleryyF | Def | rel: 0
- aCalledFunction()
- // CHECK: [[@LINE-1]]:3 | function/Swift | aCalledFunction() | s:14swift_ide_test15aCalledFunctionyyF | Ref,Call,RelCall | rel: 1
- // CHECK-NEXT: RelCall | aCaller() | s:14swift_ide_test7aCalleryyF
+ aCalledFunction(a: 1, b: &z)
+ // CHECK: [[@LINE-1]]:3 | function/Swift | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF | Ref,Call,RelCall,RelCont | rel: 1
+ // CHECK-NEXT: RelCall,RelCont | aCaller() | s:14swift_ide_test7aCalleryyF
}
-let _ = aCalledFunction
-// CHECK: [[@LINE-1]]:9 | function/Swift | aCalledFunction() | s:14swift_ide_test15aCalledFunctionyyF | Ref | rel: 0
+let aRef = aCalledFunction
+// CHECK: [[@LINE-1]]:12 | function/Swift | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF | Ref | rel: 0
// RelationChildOf, Implicit
struct AStruct {
@@ -82,15 +102,16 @@
// CHECK-NEXT: RelChild | AStruct | s:14swift_ide_test7AStructV
x += 1
- // CHECK: [[@LINE-1]]:5 | instance-property/Swift | x | s:14swift_ide_test7AStructV1xSiv | Ref,Read,Writ | rel: 0
- // CHECK: [[@LINE-2]]:5 | function/acc-get/Swift | getter:x | s:14swift_ide_test7AStructV1xSifg | Ref,Call,Impl,RelRec,RelCall | rel: 2
- // CHECK-NEXT: RelCall | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
+ // CHECK: [[@LINE-1]]:5 | instance-property/Swift | x | s:14swift_ide_test7AStructV1xSiv | Ref,Read,Writ,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
+ // CHECK: [[@LINE-3]]:5 | function/acc-get/Swift | getter:x | s:14swift_ide_test7AStructV1xSifg | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+ // CHECK-NEXT: RelCall,RelCont | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
// CHECK-NEXT: RelRec | AStruct | s:14swift_ide_test7AStructV
- // CHECK: [[@LINE-5]]:5 | function/acc-set/Swift | setter:x | s:14swift_ide_test7AStructV1xSifs | Ref,Call,Impl,RelRec,RelCall | rel: 2
- // CHECK-NEXT: RelCall | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
+ // CHECK: [[@LINE-6]]:5 | function/acc-set/Swift | setter:x | s:14swift_ide_test7AStructV1xSifs | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+ // CHECK-NEXT: RelCall,RelCont | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
// CHECK-NEXT: RelRec | AStruct | s:14swift_ide_test7AStructV
- // CHECK: [[@LINE-8]]:7 | function/infix-operator/Swift | +=(_:_:) | s:s2peoiySiz_SitF | Ref,Call,RelCall | rel: 1
- // CHECK-NEXT: RelCall | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
+ // CHECK: [[@LINE-9]]:7 | function/infix-operator/Swift | +=(_:_:) | s:s2peoiySiz_SitF | Ref,Call,RelCall,RelCont | rel: 1
+ // CHECK-NEXT: RelCall,RelCont | aMethod() | s:14swift_ide_test7AStructV7aMethodyyF
}
// RelationChildOf, RelationAccessorOf
@@ -243,3 +264,47 @@
// CHECK: [[@LINE-2]]:22 | instance-method/Swift | foo() | s:14swift_ide_test6AClassC3fooSiyF | Ref,Call,Dyn,RelRec | rel: 1
// CHECK-NEXT: RelRec | AClass | s:14swift_ide_test6AClassC
+// RelationContainedBy
+let contained = 2
+// CHECK: [[@LINE-1]]:5 | variable/Swift | contained | s:14swift_ide_test9containedSiv | Def | rel: 0
+
+func containing() {
+// CHECK: [[@LINE-1]]:6 | function/Swift | containing() | s:14swift_ide_test10containingyyF | Def | rel: 0
+ let _ = contained
+ // CHECK: [[@LINE-1]]:11 | variable/Swift | contained | s:14swift_ide_test9containedSiv | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ var x = contained
+ // CHECK: [[@LINE-1]]:11 | variable/Swift | contained | s:14swift_ide_test9containedSiv | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ struct LocalStruct {
+ var i: AClass = AClass(x: contained)
+ // CHECK: [[@LINE-1]]:12 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+ // CHECK: [[@LINE-3]]:21 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+ // CHECK: [[@LINE-5]]:31 | variable/Swift | contained | s:14swift_ide_test9containedSiv | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ init(i _: AClass) {}
+ // CHECK: [[@LINE-1]]:15 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ func inner() -> Int {
+ let _: AClass = AClass(x: contained)
+ // CHECK: [[@LINE-1]]:14 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+ // CHECK: [[@LINE-3]]:23 | class/Swift | AClass | s:14swift_ide_test6AClassC | Ref,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+ // CHECK: [[@LINE-5]]:33 | variable/Swift | contained | s:14swift_ide_test9containedSiv | Ref,Read,RelCont | rel: 1
+ // CHECK-NEXT: RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ aCalledFunction(a: 1, b: &z)
+ // CHECK: [[@LINE-1]]:7 | function/Swift | aCalledFunction(a:b:) | s:14swift_ide_test15aCalledFunctionySi1a_Siz1btF | Ref,Call,RelCall,RelCont | rel: 1
+ // CHECK-NEXT: RelCall,RelCont | containing() | s:14swift_ide_test10containingyyF
+
+ return contained
+ }
+ }
+}
diff --git a/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h b/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
index fe1cef5..439ee9f 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
@@ -67,6 +67,9 @@
@end
+@interface PettableOverextendedMetaphor: NSObject <Pettable>
+@end
+
@protocol Fungible
@end
diff --git a/test/Inputs/comment_to_something_conversion.swift b/test/Inputs/comment_to_something_conversion.swift
index 5f118e3..83cf5d1 100644
--- a/test/Inputs/comment_to_something_conversion.swift
+++ b/test/Inputs/comment_to_something_conversion.swift
@@ -11,7 +11,7 @@
/// Aaa. init().
public init() {}
-// CHECK: {{.*}}DocCommentAsXML=[<Function file="{{.*}}" line="{{.*}}" column="{{.*}}"><Name>init()</Name><USR>c:objc(cs)A010_AttachToEntities(cm)init</USR><Declaration>public init()</Declaration><Abstract><Para>Aaa. init().</Para></Abstract></Function>]
+// CHECK: {{.*}}DocCommentAsXML=[<Function file="{{.*}}" line="{{.*}}" column="{{.*}}"><Name>init()</Name><USR>c:objc(cs)A010_AttachToEntities(im)init</USR><Declaration>public init()</Declaration><Abstract><Para>Aaa. init().</Para></Abstract></Function>]
/// Aaa. subscript(i: Int).
public subscript(i: Int) -> Int {
diff --git a/test/Interpreter/generic_subscript.swift b/test/Interpreter/generic_subscript.swift
new file mode 100644
index 0000000..8e8a4d4
--- /dev/null
+++ b/test/Interpreter/generic_subscript.swift
@@ -0,0 +1,132 @@
+//===--- generic_subscript.swift ------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+//
+
+import StdlibUnittest
+
+
+var GenericSubscriptTestSuite = TestSuite("GenericSubscript")
+
+struct S<T> : P {
+ typealias Element = T
+ var t: T
+
+ subscript<U>(a: (T) -> U, b: (U) -> T) -> U {
+ get {
+ print(T.self)
+ print(U.self)
+
+ return a(t)
+ }
+ set {
+ print(T.self)
+ print(U.self)
+
+ t = b(newValue)
+ }
+ }
+}
+
+protocol P {
+ associatedtype Element
+ subscript<U>(a: (Element) -> U, b: (U) -> Element) -> U { get set }
+}
+
+func increment<T : P>(p: inout T) where T.Element == String {
+ p[{Int($0)!}, {String($0)}] += 1
+}
+
+GenericSubscriptTestSuite.test("Basic") {
+ var s = S<String>(t: "0")
+ increment(p: &s)
+ expectEqual(s.t, "1")
+}
+
+protocol AnySubscript {
+ subscript(k: AnyHashable) -> Any? { get set }
+}
+
+struct AnyDictionary : AnySubscript {
+ var dict: [AnyHashable : Any] = [:]
+
+ subscript(k: AnyHashable) -> Any? {
+ get {
+ return dict[k]
+ }
+ set {
+ dict[k] = newValue
+ }
+ }
+}
+
+extension AnySubscript {
+ subscript<K : Hashable, V>(k k: K) -> V? {
+ get {
+ return self[k] as! V?
+ }
+ set {
+ self[k] = newValue
+ }
+ }
+}
+
+GenericSubscriptTestSuite.test("ProtocolExtensionConcrete") {
+ var dict = AnyDictionary()
+
+ func doIt(dict: inout AnyDictionary) {
+ dict["a" ] = 0
+ dict[k: "a"]! += 1
+ }
+
+ doIt(dict: &dict)
+
+ expectEqual(dict["a"]! as! Int, 1)
+ expectEqual(dict[k: "a"]!, 1)
+}
+
+GenericSubscriptTestSuite.test("ProtocolExtensionAbstract") {
+ var dict = AnyDictionary()
+
+ func doIt<T : AnySubscript>(dict: inout T) {
+ dict["a" ] = 0
+ dict[k: "a"]! += 1
+ }
+
+ doIt(dict: &dict)
+
+ expectEqual(dict["a"]! as! Int, 1)
+ expectEqual(dict[k: "a"]!, 1)
+}
+
+protocol GenericSubscript : AnySubscript {
+ subscript<K : Hashable, V>(k k: K) -> V? { get set }
+}
+
+extension AnyDictionary : GenericSubscript { }
+
+GenericSubscriptTestSuite.test("ProtocolExtensionWitness") {
+ var dict = AnyDictionary()
+
+ func doIt<T : GenericSubscript>(dict: inout T) {
+ dict["a" ] = 0
+ dict[k: "a"]! += 1
+ }
+
+ doIt(dict: &dict)
+
+ expectEqual(dict["a"]! as! Int, 1)
+ expectEqual(dict[k: "a"]!, 1)
+}
+
+runAllTests()
diff --git a/test/NameBinding/scope_map.swift b/test/NameBinding/scope_map.swift
index ae85d46..4067a15 100644
--- a/test/NameBinding/scope_map.swift
+++ b/test/NameBinding/scope_map.swift
@@ -368,7 +368,7 @@
// CHECK-EXPANDED: {{^}} `-BraceStmt {{.*}} [142:41 - 155:1] expanded
// CHECK-EXPANDED-NEXT: {{^}} `-PatternBinding {{.*}} entry 0 [143:7 - 155:1] expanded
// CHECK-EXPANDED-NEXT: {{^}} `-AfterPatternBinding {{.*}} entry 0 [143:17 - 155:1] expanded
-// CHECK-EXPANDED-NEXT: {{^}} |-Accessors {{.*}} scope_map.(file).func decl.computed@{{.*}}scope_map.swift:143:7 [143:21 - 149:3] expanded
+// CHECK-EXPANDED-NEXT: {{^}} |-Accessors {{.*}} scope_map.(file).funcWithComputedProperties(i:).computed@{{.*}}scope_map.swift:143:7 [143:21 - 149:3] expanded
// CHECK-EXPANDED-NEXT: {{^}} |-AbstractFunctionDecl {{.*}} _ [144:5 - 145:5] expanded
// CHECK-EXPANDED-NEXT: {{^}} `-AbstractFunctionParams {{.*}} _ param 0:0 [144:5 - 145:5] expanded
// CHECK-EXPANDED: {{^}} `-BraceStmt {{.*}} [144:9 - 145:5] expanded
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index b7989a7..63296e1 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -3,7 +3,7 @@
// FIXME: this test only passes on platforms which have Float80.
// <rdar://problem/19508460> Floating point enum raw values are not portable
-// REQUIRES: CPU=i386 || CPU=x86_64
+// REQUIRES: CPU=i386_or_x86_64
enum Empty {}
diff --git a/test/Parse/matching_patterns.swift b/test/Parse/matching_patterns.swift
index d7766ec..57dd399 100644
--- a/test/Parse/matching_patterns.swift
+++ b/test/Parse/matching_patterns.swift
@@ -100,7 +100,7 @@
}
switch foo {
- case .Naught: // expected-error{{enum case 'Naught' not found in type 'Foo'}}
+ case .Naught: // expected-error{{pattern cannot match values of type 'Foo'}}
()
case .A, .B, .C:
()
@@ -137,7 +137,7 @@
var notAnEnum = 0
switch notAnEnum {
-case .Foo: // expected-error{{enum case 'Foo' not found in type 'Int'}}
+case .Foo: // expected-error{{pattern cannot match values of type 'Int'}}
()
}
@@ -264,10 +264,8 @@
// expected-error@-1{{'+++' is not a prefix unary operator}}
()
case (_, var e, 3) +++ (1, 2, 3):
-// expected-error@-1{{binary operator '+++' cannot be applied to operands of type '(_, <<error type>>, Int)' and '(Int, Int, Int)'}}
-// expected-note@-2{{expected an argument list of type '((Int, Int, Int), (Int, Int, Int))'}}
-// expected-error@-3{{'var' binding pattern cannot appear in an expression}}
-// expected-error@-4{{'var' binding pattern cannot appear in an expression}}
+// expected-error@-1{{'_' can only appear in a pattern}}
+// expected-error@-2{{'var' binding pattern cannot appear in an expression}}
()
}
diff --git a/test/Parse/switch.swift b/test/Parse/switch.swift
index 6741c3b..7e2b81ae 100644
--- a/test/Parse/switch.swift
+++ b/test/Parse/switch.swift
@@ -264,7 +264,7 @@
func enumElementSyntaxOnTuple() {
switch (1, 1) {
- case .Bar: // expected-error {{enum case 'Bar' not found in type '(Int, Int)'}}
+ case .Bar: // expected-error {{pattern cannot match values of type '(Int, Int)'}}
break
default:
break
diff --git a/test/PrintAsObjC/extensions.swift b/test/PrintAsObjC/extensions.swift
index 49fd2e1..6b6974a 100644
--- a/test/PrintAsObjC/extensions.swift
+++ b/test/PrintAsObjC/extensions.swift
@@ -84,7 +84,7 @@
func anyOldMethod() {}
}
-// CHECK-LABEL: @interface GenericClass (SWIFT_EXTENSION(extensions))
+// CHECK-LABEL: @interface GenericClass<T> (SWIFT_EXTENSION(extensions))
// CHECK-NEXT: - (void)bar;
// CHECK-NEXT: @end
extension GenericClass {
@@ -115,3 +115,17 @@
class func fromColor(_ color: NSColor) -> NSString? { return nil; }
}
+// CHECK-LABEL: @interface PettableContainer<T> (SWIFT_EXTENSION(extensions))
+// CHECK-NEXT: - (PettableContainer<T> * _Nonnull)duplicate SWIFT_WARN_UNUSED_RESULT;
+// CHECK-NEXT: - (PettableContainer<T> * _Nonnull)duplicate2 SWIFT_WARN_UNUSED_RESULT;
+// CHECK-NEXT: - (PettableContainer<PettableOverextendedMetaphor *> * _Nonnull)duplicate3 SWIFT_WARN_UNUSED_RESULT;
+// CHECK-NEXT: - (T _Nonnull)extract SWIFT_WARN_UNUSED_RESULT;
+// CHECK-NEXT: - (T _Nullable)extract2 SWIFT_WARN_UNUSED_RESULT;
+// CHECK-NEXT: @end
+extension PettableContainer {
+ func duplicate() -> PettableContainer { fatalError() }
+ func duplicate2() -> PettableContainer<T> { fatalError() }
+ func duplicate3() -> PettableContainer<PettableOverextendedMetaphor> { fatalError() }
+ func extract() -> T { fatalError() }
+ func extract2() -> T? { fatalError() }
+}
diff --git a/test/Runtime/weak-reference-racetests.swift b/test/Runtime/weak-reference-racetests.swift
index a3235f5..40a1a2c 100644
--- a/test/Runtime/weak-reference-racetests.swift
+++ b/test/Runtime/weak-reference-racetests.swift
@@ -1,5 +1,6 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
+// UNSUPPORTED: nonatomic_rc
import StdlibUnittest
diff --git a/test/SIL/Parser/opaque_values_parse.sil b/test/SIL/Parser/opaque_values_parse.sil
index cf286a1..1ae6709 100644
--- a/test/SIL/Parser/opaque_values_parse.sil
+++ b/test/SIL/Parser/opaque_values_parse.sil
@@ -1,9 +1,54 @@
// RUN: %target-sil-opt -enable-sil-opaque-values -enable-sil-verify-all -emit-sorted-sil %s | %FileCheck %s
import Builtin
+import Swift
sil_stage canonical
+protocol Foo {
+ func foo()
+}
+
+struct S : Foo {
+ func foo()
+ init()
+}
+
+// CHECK-LABEL: sil @castOpaque : $@convention(thin) (Int) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Int):
+// CHECK: unconditional_checked_cast_opaque [[ARG]] : $Int to $Foo
+// CHECK-LABEL: } // end sil function 'castOpaque'
+sil @castOpaque : $@convention(thin) (Int) -> () {
+bb0(%0 : $Int):
+ %c = unconditional_checked_cast_opaque %0 : $Int to $Foo
+ %t = tuple ()
+ return %t : $()
+}
+
+// CHECK-LABEL: sil @initDeinitExistentialOpaque : $@convention(thin) <T> (@in T) -> () {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[IE:%.*]] = init_existential_opaque [[ARG]] : $T, $T, $Any
+// CHECK: deinit_existential_opaque [[IE]] : $Any
+// CHECK-LABEL: } // end sil function 'initDeinitExistentialOpaque'
+sil @initDeinitExistentialOpaque : $@convention(thin) <T> (@in T) -> () {
+bb0(%0 : $T):
+ %i = init_existential_opaque %0 : $T, $T, $Any
+ %d = deinit_existential_opaque %i : $Any
+ %t = tuple ()
+ return %t : $()
+}
+
+// CHECK-LABEL: sil @openExistentialOpaque : $@convention(thin) (@in Foo) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Foo):
+// CHECK: open_existential_opaque [[ARG]] : $Foo to $@opened("2E9EACA6-FD59-11E6-B016-685B3593C496") Foo
+// CHECK-LABEL: } // end sil function 'openExistentialOpaque'
+sil @openExistentialOpaque : $@convention(thin) (@in Foo) -> () {
+bb0(%0 : $Foo):
+ %o = open_existential_opaque %0 : $Foo to $@opened("2E9EACA6-FD59-11E6-B016-685B3593C496") Foo
+ %t = tuple ()
+ return %t : $()
+}
+
// Test @callee_guaranteed parsing.
// ----
@@ -38,15 +83,6 @@
// Test @in_guaranteed parsing.
// ----
-protocol Foo {
- func foo()
-}
-
-struct S : Foo {
- func foo()
- init()
-}
-
sil @doWithS : $@convention(method) (S) -> ()
// CHECK-LABEL: sil hidden [transparent] [thunk] @parse_mutating : $@convention(witness_method) (@in_guaranteed S) -> () {
diff --git a/test/SIL/Parser/undef.sil b/test/SIL/Parser/undef.sil
index 68c83d6..fadb388 100644
--- a/test/SIL/Parser/undef.sil
+++ b/test/SIL/Parser/undef.sil
@@ -244,14 +244,6 @@
bridge_object_to_word undef : $Builtin.BridgeObject to $Builtin.Word
// CHECK: thin_to_thick_function undef : $@convention(thin) () -> () to $() -> ()
thin_to_thick_function undef : $@convention(thin) () -> () to $() -> ()
- // CHECK: thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
- thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
- // CHECK: objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
- objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
- // CHECK: objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
- objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
- // CHECK: objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
- objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
// CHECK: is_nonnull undef : $C
is_nonnull undef : $C
diff --git a/test/SIL/Parser/undef_objc.sil b/test/SIL/Parser/undef_objc.sil
new file mode 100644
index 0000000..b4119cd
--- /dev/null
+++ b/test/SIL/Parser/undef_objc.sil
@@ -0,0 +1,23 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil %s | %target-sil-opt -assume-parsing-unqualified-ownership-sil | %FileCheck %s
+// REQUIRES: objc_interop
+
+sil_stage raw
+
+import Builtin
+import Swift
+
+protocol P { }
+class C { }
+
+sil @general_test : $() -> () {
+bb0:
+ // CHECK: thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
+ thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
+ // CHECK: objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
+ objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
+ // CHECK: objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
+ objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
+ // CHECK: objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
+ objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
+ unreachable
+}
diff --git a/test/SIL/Serialization/opaque_values_serialize.sil b/test/SIL/Serialization/opaque_values_serialize.sil
index 680516d..945b17a 100644
--- a/test/SIL/Serialization/opaque_values_serialize.sil
+++ b/test/SIL/Serialization/opaque_values_serialize.sil
@@ -9,6 +9,51 @@
sil_stage canonical
import Builtin
+import Swift
+
+protocol Foo {
+ func foo()
+}
+
+struct S : Foo {
+ func foo()
+ init()
+}
+
+// CHECK-LABEL: sil @castOpaque : $@convention(thin) (Int) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Int):
+// CHECK: unconditional_checked_cast_opaque [[ARG]] : $Int to $Foo
+// CHECK-LABEL: } // end sil function 'castOpaque'
+sil @castOpaque : $@convention(thin) (Int) -> () {
+bb0(%0 : $Int):
+ %c = unconditional_checked_cast_opaque %0 : $Int to $Foo
+ %t = tuple ()
+ return %t : $()
+}
+
+// CHECK-LABEL: sil @initDeinitExistentialOpaque : $@convention(thin) <T> (@in T) -> () {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[IE:%.*]] = init_existential_opaque [[ARG]] : $T, $T, $Any
+// CHECK: deinit_existential_opaque [[IE]] : $Any
+// CHECK-LABEL: } // end sil function 'initDeinitExistentialOpaque'
+sil @initDeinitExistentialOpaque : $@convention(thin) <T> (@in T) -> () {
+bb0(%0 : $T):
+ %i = init_existential_opaque %0 : $T, $T, $Any
+ %d = deinit_existential_opaque %i : $Any
+ %t = tuple ()
+ return %t : $()
+}
+
+// CHECK-LABEL: sil @openExistentialOpaque : $@convention(thin) (@in Foo) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Foo):
+// CHECK: open_existential_opaque [[ARG]] : $Foo to $@opened({{.*}}) Foo
+// CHECK-LABEL: } // end sil function 'openExistentialOpaque'
+sil @openExistentialOpaque : $@convention(thin) (@in Foo) -> () {
+bb0(%0 : $Foo):
+ %o = open_existential_opaque %0 : $Foo to $@opened("2E9EACA6-FD59-11E6-B016-685B3593C496") Foo
+ %t = tuple ()
+ return %t : $()
+}
// Test @in/@out serialization.
// ----
@@ -25,15 +70,6 @@
// Test @in_guaranteed serialization.
// ----
-protocol Foo {
- func foo()
-}
-
-struct S : Foo {
- func foo()
- init()
-}
-
sil @doWithS : $@convention(method) (S) -> ()
// CHECK-LABEL: sil hidden [transparent] [thunk] @serialize_mutating : $@convention(witness_method) (@in_guaranteed S) -> () {
diff --git a/test/SIL/ownership-verifier/use_verifier.sil b/test/SIL/ownership-verifier/use_verifier.sil
index 7405276..782008b 100644
--- a/test/SIL/ownership-verifier/use_verifier.sil
+++ b/test/SIL/ownership-verifier/use_verifier.sil
@@ -528,17 +528,18 @@
destroy_value %1 : $SuperKlass
br bb3
-bb2:
+bb2(%2 : @owned $Builtin.NativeObject):
+ destroy_value %2 : $Builtin.NativeObject
br bb3
bb3:
- %2 = metatype $@thick SuperKlass.Type
- checked_cast_br %2 : $@thick SuperKlass.Type to $@thick SubKlass.Type, bb4, bb5
+ %3 = metatype $@thick SuperKlass.Type
+ checked_cast_br %3 : $@thick SuperKlass.Type to $@thick SubKlass.Type, bb4, bb5
-bb4(%3 : @trivial $@thick SubKlass.Type):
+bb4(%4 : @trivial $@thick SubKlass.Type):
br bb6
-bb5:
+bb5(%5 : @trivial $@thick SuperKlass.Type):
br bb6
bb6:
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index 1f74097..3f124b0 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -65,7 +65,7 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
// SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed.
// CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*A
@@ -128,7 +128,7 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store [[BORROWED_ARG_RHS]] to [init] [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
@@ -154,7 +154,7 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index ec23481..fe274de 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -331,6 +331,14 @@
// CHECK: store [[VALUE]] to [[T2]] : $*Int32
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// materializeForSet callback for G.value
+// CHECK-LABEL: sil hidden [transparent] @_T010addressors1GC5values5Int32VfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type):
+// CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[OWNER:%.*]] = load [[T0]]
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// CHECK: dealloc_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+
// materializeForSet for G.value
// CHECK-LABEL: sil hidden [transparent] @_T010addressors1GC5values5Int32Vfm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed G) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $G):
@@ -355,14 +363,6 @@
// CHECK: [[RESULT:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK: return [[RESULT]]
-// materializeForSet callback for G.value
-// CHECK-LABEL: sil hidden [transparent] @_T010addressors1GC5values5Int32VfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () {
-// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type):
-// CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
-// CHECK: [[OWNER:%.*]] = load [[T0]]
-// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
-// CHECK: dealloc_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
-
class H {
var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
@@ -451,6 +451,14 @@
// CHECK: store [[VALUE]] to [[T2]] : $*Int32
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// materializeForSet callback for I.value
+// CHECK-LABEL: sil hidden [transparent] @_T010addressors1IC5values5Int32VfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type):
+// CHECK: [[T0:%.*]] = project_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[OWNER:%.*]] = load [[T0]]
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: dealloc_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+
// CHECK-LABEL: sil hidden [transparent] @_T010addressors1IC5values5Int32Vfm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed I) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $I):
// Call the addressor.
@@ -474,14 +482,6 @@
// CHECK: [[RESULT:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK: return [[RESULT]]
-// materializeForSet callback for I.value
-// CHECK-LABEL: sil hidden [transparent] @_T010addressors1IC5values5Int32VfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () {
-// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type):
-// CHECK: [[T0:%.*]] = project_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
-// CHECK: [[OWNER:%.*]] = load [[T0]]
-// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
-// CHECK: dealloc_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
-
struct RecInner {
subscript(i: Int32) -> Int32 {
mutating get { return i }
diff --git a/test/SILGen/c_materializeForSet_linkage.swift b/test/SILGen/c_materializeForSet_linkage.swift
index 0825c55..3d9b221 100644
--- a/test/SILGen/c_materializeForSet_linkage.swift
+++ b/test/SILGen/c_materializeForSet_linkage.swift
@@ -19,8 +19,8 @@
// CHECK-LABEL: sil shared [transparent] [fragile] @_T0SC7NSPointV1xSffm
// CHECK-LABEL: sil shared [transparent] [fragile] @_T0SC7NSPointV1ySffm
-// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1xSffm
-// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1ySffm
-
// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1xSffmytfU_
+// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1xSffm
+
// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1ySffmytfU_
+// CHECK-LABEL: sil shared @_T0So16NSReferencePointC1ySffm
diff --git a/test/SILGen/casts.swift b/test/SILGen/casts.swift
index 3e9a92f..e493c45 100644
--- a/test/SILGen/casts.swift
+++ b/test/SILGen/casts.swift
@@ -16,11 +16,20 @@
// CHECK-LABEL: sil hidden @_T05casts3isa{{[_0-9a-zA-Z]*}}F
func isa(b: B) -> Bool {
- // CHECK: checked_cast_br {{%.*}}, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
- // CHECK: [[YES]]({{%.*}}):
+ // CHECK: bb0([[ARG:%.*]] : $B):
+ // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[COPIED_BORROWED_ARG:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK: checked_cast_br [[COPIED_BORROWED_ARG]] : $B to $D, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+ //
+ // CHECK: [[YES]]([[CASTED_VALUE:%.*]] : $D):
// CHECK: integer_literal {{.*}} -1
- // CHECK: [[NO]]:
+ // CHECK: destroy_value [[CASTED_VALUE]]
+ // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
+ //
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $B):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
// CHECK: integer_literal {{.*}} 0
+ // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
return b is D
}
@@ -42,15 +51,22 @@
return b as! T
}
+// This is making sure that we do not have the default propagating behavior in
+// the address case.
+//
// CHECK-LABEL: sil hidden @_T05casts12is_archetype{{[_0-9a-zA-Z]*}}F
func is_archetype<T : B>(b: B, _: T) -> Bool {
- // CHECK: checked_cast_br {{%.*}}, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
- // CHECK: [[YES]]({{%.*}}):
+ // CHECK: bb0([[ARG1:%.*]] : $B, [[ARG2:%.*]] : $T):
+ // CHECK: checked_cast_br {{%.*}}, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+ // CHECK: [[YES]]([[CASTED_ARG:%.*]] : $T):
// CHECK: integer_literal {{.*}} -1
- // CHECK: [[NO]]:
+ // CHECK: destroy_value [[CASTED_ARG]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $B):
+ // CHCEK: destroy_value [[CASTED_ARG]]
// CHECK: integer_literal {{.*}} 0
return b is T
}
+// CHECK: } // end sil function '_T05casts12is_archetype{{[_0-9a-zA-Z]*}}F'
// CHECK: sil hidden @_T05casts20downcast_conditional{{[_0-9a-zA-Z]*}}F
// CHECK: checked_cast_br {{%.*}} : $B to $D
diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift
index 61223b0..e6820ca 100644
--- a/test/SILGen/constrained_extensions.swift
+++ b/test/SILGen/constrained_extensions.swift
@@ -10,8 +10,9 @@
// CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifg : $@convention(method) (@guaranteed Array<Int>) -> Int
// CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifs : $@convention(method) (Int, @inout Array<Int>) -> ()
+ // CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>, @thick Array<Int>.Type) -> ()
// CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
- // CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>, @thick Array<Int>.Type) -> ()
+
public var instanceProperty: Element {
get {
return self[0]
@@ -70,8 +71,8 @@
// CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fg : $@convention(method) <Key, Value where Key == Int> (@guaranteed Dictionary<Int, Value>) -> @out Value
// CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fs : $@convention(method) <Key, Value where Key == Int> (@in Value, @inout Dictionary<Int, Value>) -> ()
+ // CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>, @thick Dictionary<Int, Value>.Type) -> ()
// CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fm : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
- // CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(thin) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>, @thick Dictionary<Int, Value>.Type) -> ()
public var instanceProperty: Value {
get {
return self[0]!
diff --git a/test/SILGen/generic_casts.swift b/test/SILGen/generic_casts.swift
index 959d179..6269058 100644
--- a/test/SILGen/generic_casts.swift
+++ b/test/SILGen/generic_casts.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-runtime %s
protocol ClassBound : class {}
protocol NotClassBound {}
@@ -57,16 +57,21 @@
func class_archetype_to_class_archetype
<T:ClassBound, U:ClassBound>(_ t:T) -> U {
return t as! U
- // CHECK: unconditional_checked_cast_addr {{.*}} T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
- // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
- // CHECK: return [[DOWNCAST]] : $U
+ // Error bridging can change the identity of class-constrained archetypes.
+ // CHECK-objc: unconditional_checked_cast_addr {{.*}} T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
+ // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
+ // CHECK-objc: return [[DOWNCAST]] : $U
+
+ // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $T to $U
}
// CHECK-LABEL: sil hidden @_TF13generic_casts34class_archetype_is_class_archetype{{.*}}
func class_archetype_is_class_archetype
<T:ClassBound, U:ClassBound>(_ t:T, u:U.Type) -> Bool {
return t is U
- // CHECK: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
+ // Error bridging can change the identity of class-constrained archetypes.
+ // CHECK-objc: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
+ // CHECK-native: checked_cast_br {{.*}} : $T to $U
}
// CHECK-LABEL: sil hidden @_TF13generic_casts38opaque_archetype_to_addr_only_concrete{{.*}}
@@ -156,16 +161,19 @@
func class_existential_to_class_archetype
<T:ClassBound>(_ p:ClassBound) -> T {
return p as! T
- // CHECK: unconditional_checked_cast_addr {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
- // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
- // CHECK: return [[DOWNCAST]] : $T
+ // CHECK-objc: unconditional_checked_cast_addr {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
+ // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
+ // CHECK-objc: return [[DOWNCAST]] : $T
+
+ // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $ClassBound to $T
}
// CHECK-LABEL: sil hidden @_TF13generic_casts36class_existential_is_class_archetype{{.*}}
func class_existential_is_class_archetype
<T:ClassBound>(_ p:ClassBound, _: T) -> Bool {
return p is T
- // CHECK: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
+ // CHECK-objc: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
+ // CHECK-native: checked_cast_br {{.*}} : $ClassBound to $T
}
// CHECK-LABEL: sil hidden @_TF13generic_casts40opaque_existential_to_addr_only_concrete{{.*}}
diff --git a/test/SILGen/if_while_binding.swift b/test/SILGen/if_while_binding.swift
index 2f0d3c1..93d8159 100644
--- a/test/SILGen/if_while_binding.swift
+++ b/test/SILGen/if_while_binding.swift
@@ -309,8 +309,8 @@
// CHECK: [[DERIVED_CLS_SOME:%.*]] = enum $Optional<DerivedClass>, #Optional.some!enumelt.1, [[DERIVED_CLS]] : $DerivedClass
// CHECK: br [[MERGE:bb[0-9]+]]([[DERIVED_CLS_SOME]] : $Optional<DerivedClass>)
- // CHECK: [[ISBASEBB]]:
- // CHECK: destroy_value [[CLS]] : $BaseClass
+ // CHECK: [[ISBASEBB]]([[BASECLASS:%.*]] : $BaseClass):
+ // CHECK: destroy_value [[BASECLASS]] : $BaseClass
// CHECK: = enum $Optional<DerivedClass>, #Optional.none!enumelt
// CHECK: br [[MERGE]](
diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift
index 39a4ab5..47cad67 100644
--- a/test/SILGen/lifetime.swift
+++ b/test/SILGen/lifetime.swift
@@ -380,7 +380,7 @@
// CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]]
// CHECK: [[MARKED_ADDR:%.*]] = mark_dependence [[ADDR]] : $*Aleph on [[R2]]
// CHECK: {{.*}}([[CALLBACK_ADDR:%.*]] :
- // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> ()
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> ()
// CHECK: [[TEMP:%.*]] = alloc_stack $RefWithProp
// CHECK: store [[R2]] to [init] [[TEMP]]
// CHECK: apply [[CALLBACK]]({{.*}}, [[STORAGE]], [[TEMP]], {{%.*}})
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index c92c9d6..7f3d867 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -6,6 +6,14 @@
// The ordering here is unfortunate: we generate the property
// getters and setters after we've processed the decl.
+ // CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Base, [[SELFTYPE:%.*]] : $@thick Base.Type):
+// CHECK: [[T0:%.*]] = load_borrow [[SELF]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T2:%.*]] = load [trivial] [[T1]] : $*Int
+// CHECK: [[SETTER:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifs
+// CHECK: apply [[SETTER]]([[T2]], [[T0]])
+
// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC8computedSifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed Base) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $Base):
// CHECK: [[ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
@@ -13,21 +21,13 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[ADDR]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[ADDR]]
-// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> ()
+// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> ()
// CHECK: [[T2:%.*]] = thin_function_to_pointer [[T0]]
// CHECK: [[T3:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T2]] : $Builtin.RawPointer
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[T3]] : $Optional<Builtin.RawPointer>)
// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: }
-// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () {
-// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Base, [[SELFTYPE:%.*]] : $@thick Base.Type):
-// CHECK: [[T0:%.*]] = load_borrow [[SELF]]
-// CHECK: [[T1:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK: [[T2:%.*]] = load [trivial] [[T1]] : $*Int
-// CHECK: [[SETTER:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifs
-// CHECK: apply [[SETTER]]([[T2]], [[T0]])
-
// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC6storedSifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed Base) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $Base):
// CHECK: [[T0:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.stored
@@ -68,6 +68,21 @@
// an abstraction pattern present.
extension Derived : Abstractable {}
+
+// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> ()
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
+// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_owned () -> @out Int
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]])
+// CHECK-NEXT: [[FN:%.*]] = class_method [[SELF]] : $Base, #Base.storedFunction!setter.1 : (Base) -> (@escaping () -> Int) -> ()
+// CHECK-NEXT: apply [[FN]]([[NEWVALUE]], [[SELF]])
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
// CHECK: sil hidden [transparent] [thunk] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction{{[_0-9a-zA-Z]*}}fmTW
// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived):
// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
@@ -92,17 +107,17 @@
// CHECK-NEXT: dealloc_stack [[TEMP]]
// CHECK-NEXT: return [[T0]]
-// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> ()
+// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP19finalStoredFunction6ResultQzycfmytfU_TW :
// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_owned () -> @out Int
-// CHECK-NEXT: function_ref
+// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]])
-// CHECK-NEXT: [[FN:%.*]] = class_method [[SELF]] : $Base, #Base.storedFunction!setter.1 : (Base) -> (@escaping () -> Int) -> ()
-// CHECK-NEXT: apply [[FN]]([[NEWVALUE]], [[SELF]])
+// CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
+// CHECK-NEXT: assign [[NEWVALUE]] to [[ADDR]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
@@ -125,19 +140,18 @@
// CHECK-NEXT: [[T0:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK-NEXT: return [[T0]]
-// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP19finalStoredFunction6ResultQzycfmytfU_TW :
-// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
-// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
-// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
-// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
-// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_owned () -> @out Int
-// CHECK-NEXT: // function_ref
-// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
-// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]])
-// CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
-// CHECK-NEXT: assign [[NEWVALUE]] to [[ADDR]]
-// CHECK-NEXT: tuple ()
-// CHECK-NEXT: return
+// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*@thick Derived.Type, %3 : $@thick Derived.Type.Type):
+// CHECK-NEXT: [[SELF:%.*]] = load_borrow %2 : $*@thick Derived.Type
+// CHECK-NEXT: [[BASE_SELF:%.*]] = upcast [[SELF]] : $@thick Derived.Type to $@thick Base.Type
+// CHECK-NEXT: [[BUFFER:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[BUFFER]] : $*@callee_owned () -> @out Int
+// CHECK: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]]) : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
+// CHECK: [[SETTER_FN:%.*]] = function_ref @_T017materializeForSet4BaseC14staticFunctionSiycfsZ : $@convention(method) (@owned @callee_owned () -> Int, @thick Base.Type) -> ()
+// CHECK-NEXT: apply [[SETTER_FN]]([[NEWVALUE]], [[BASE_SELF]]) : $@convention(method) (@owned @callee_owned () -> Int, @thick Base.Type) -> ()
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]] : $()
// CHECK-LABEL: sil hidden [transparent] [thunk] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZTW
// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $@thick Derived.Type):
@@ -153,26 +167,13 @@
// CHECK-NEXT: destroy_addr [[OUT]] : $*@callee_owned () -> Int
// CHECK-NEXT: store [[NEWVALUE]] to [init] [[RESULT_ADDR]] : $*@callee_owned () -> @out Int
// CHECK-NEXT: [[ADDR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_owned () -> @out Int to $Builtin.RawPointer
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> ()
-// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> ()
+// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer
// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] : $Builtin.RawPointer
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ADDR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK-NEXT: dealloc_stack [[OUT]] : $*@callee_owned () -> Int
// CHECK-NEXT: return [[RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
-// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW
-// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*@thick Derived.Type, %3 : $@thick Derived.Type.Type):
-// CHECK-NEXT: [[SELF:%.*]] = load_borrow %2 : $*@thick Derived.Type
-// CHECK-NEXT: [[BASE_SELF:%.*]] = upcast [[SELF]] : $@thick Derived.Type to $@thick Base.Type
-// CHECK-NEXT: [[BUFFER:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_owned () -> @out Int
-// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[BUFFER]] : $*@callee_owned () -> @out Int
-// CHECK: [[REABSTRACTOR:%.*]] = function_ref @_T0SiIxr_SiIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
-// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [[REABSTRACTOR]]([[VALUE]]) : $@convention(thin) (@owned @callee_owned () -> @out Int) -> Int
-// CHECK: [[SETTER_FN:%.*]] = function_ref @_T017materializeForSet4BaseC14staticFunctionSiycfsZ : $@convention(method) (@owned @callee_owned () -> Int, @thick Base.Type) -> ()
-// CHECK-NEXT: apply [[SETTER_FN]]([[NEWVALUE]], [[BASE_SELF]]) : $@convention(method) (@owned @callee_owned () -> Int, @thick Base.Type) -> ()
-// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
-// CHECK-NEXT: return [[RESULT]] : $()
-
protocol ClassAbstractable : class {
associatedtype Result
var storedFunction: () -> Result { get set }
@@ -212,7 +213,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
@@ -231,7 +232,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
@@ -244,22 +245,7 @@
didSet {}
}
-// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasStoredDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
-// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasStoredDidSet):
-// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
-// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifg
-// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
-// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
-// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
-// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
-// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
-// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
-// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
-// CHECK: }
-}
-
-// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () {
+// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*HasStoredDidSet, [[METATYPE:%.*]] : $@thick HasStoredDidSet.Type):
// CHECK: [[SELF_VALUE:%.*]] = load_borrow [[SELF]] : $*HasStoredDidSet
// CHECK: [[BUFFER_ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
@@ -269,6 +255,21 @@
// CHECK: return
// CHECK: }
+// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasStoredDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasStoredDidSet):
+// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifg
+// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+}
+
class HasWeak {
weak var weakvar: HasWeak?
}
@@ -279,7 +280,7 @@
// CHECK: [[T1:%.*]] = load_weak [[T0]] : $*@sil_weak Optional<HasWeak>
// CHECK: store [[T1]] to [init] [[T2]] : $*Optional<HasWeak>
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet7HasWeakC7weakvarACSgXwfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
+// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet7HasWeakC7weakvarACSgXwfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional<Builtin.RawPointer>)
// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: }
@@ -336,10 +337,13 @@
// CHECK: }
// CHECK-LABEL: sil hidden [transparent] [thunk] @_T017materializeForSet4BillVAA8TotalledAaaDP5totalSifmTW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Bill) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
-// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Bill):
-// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BillV5totalSifm
-// CHECK: [[T1:%.*]] = apply [[T0]]([[BUFFER]], [[STORAGE]], [[SELF]])
-// CHECK: return [[T1]] :
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Bill):
+// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BillV5totalSifm
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[BUFFER]], [[STORAGE]], [[SELF]])
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_extract [[T1]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_extract [[T1]]
+// CHECK-NEXT: [[T1:%.*]] = tuple ([[LEFT]] : $Builtin.RawPointer, [[RIGHT]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: return [[T1]] :
protocol AddressOnlySubscript {
associatedtype Index
@@ -355,6 +359,47 @@
func increment(_ x: inout Int) { x += 1 }
+// Generic subscripts.
+
+protocol GenericSubscriptProtocol {
+ subscript<T>(_: T) -> T { get set }
+}
+
+struct GenericSubscriptWitness : GenericSubscriptProtocol {
+ subscript<T>(_: T) -> T { get { } set { } }
+}
+
+// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufmytfU_ : $@convention(method) <T> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () {
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*GenericSubscriptWitness, %3 : $@thick GenericSubscriptWitness.Type):
+// CHECK: [[BUFFER:%.*]] = project_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[INDICES:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T
+// CHECK: [[SETTER:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufs : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> ()
+// CHECK-NEXT: apply [[SETTER]]<T>([[INDICES]], [[BUFFER]], %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> ()
+// CHECK-NEXT: dealloc_value_buffer $*T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]] : $()
+
+// CHECK-LABEL sil hidden [transparent] [thunk] @_T017materializeForSet23GenericSubscriptWitnessVAA0dE8ProtocolAaaDP9subscriptqd__qd__clufmTW : $@convention(witness_method) <τ_0_0> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in τ_0_0, @inout GenericSubscriptWitness) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*T, %3 : $*GenericSubscriptWitness):
+// CHECK-NEXT: [[BUFFER:%.*]] = alloc_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: copy_addr %2 to [initialization] [[BUFFER]] : $*T
+// CHECK-NEXT: [[VALUE:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T
+// CHECK-NEXT: [[SELF:%.*]] = load [trivial] %3 : $*GenericSubscriptWitness
+// CHECK: [[GETTER:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufg : $@convention(method) <τ_0_0> (@in τ_0_0, GenericSubscriptWitness) -> @out τ_0_0
+// CHECK-NEXT: apply [[GETTER]]<T>([[VALUE]], %2, [[SELF]]) : $@convention(method) <τ_0_0> (@in τ_0_0, GenericSubscriptWitness) -> @out τ_0_0
+// CHECK-NEXT: [[VALUE_PTR:%.*]] = address_to_pointer [[VALUE]] : $*T to $Builtin.RawPointer
+// CHECK: [[CALLBACK:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufmytfU_
+// CHECK-NEXT: [[CALLBACK_PTR:%.*]] = thin_function_to_pointer [[CALLBACK]] : $@convention(method) <τ_0_0> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () to $Builtin.RawPointer
+// CHECK-NEXT: [[CALLBACK_OPTIONAL:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_PTR]] : $Builtin.RawPointer
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[VALUE_PTR]] : $Builtin.RawPointer, [[CALLBACK_OPTIONAL]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: return [[RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+
+extension GenericSubscriptProtocol {
+ subscript<T>(t: T) -> T { get { } set { } }
+}
+
+struct GenericSubscriptDefaultWitness : GenericSubscriptProtocol { }
+
// Test for materializeForSet vs static properties of structs.
protocol Beverage {
@@ -435,6 +480,18 @@
struct TuxedoPanda : Panda { }
+// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
+
+ // FIXME: Useless re-abstractions
+
+ // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIxir_AcCIxyd_TR : $@convention(thin) (TuxedoPanda, @owned @callee_owned (@in TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
+
+ // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcfs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
+
+ // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIxyd_AcCIxir_TR : $@convention(thin) (@in TuxedoPanda, @owned @callee_owned (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
+
+// CHECK: }
+
// CHECK-LABEL: sil hidden [transparent] [thunk] @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmTW
// Call the getter:
@@ -454,19 +511,7 @@
// The callback:
- // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
-
-// CHECK: }
-
-// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
-
- // FIXME: Useless re-abstractions
-
- // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIxir_AcCIxyd_TR : $@convention(thin) (TuxedoPanda, @owned @callee_owned (@in TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
-
- // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcfs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
-
- // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIxyd_AcCIxir_TR : $@convention(thin) (@in TuxedoPanda, @owned @callee_owned (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
+ // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
// CHECK: }
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index a6e20bb..e8387d6 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -290,3 +290,93 @@
func s190___return_foo_var() -> Foo {
return foo_var
}
+
+// Tests deinit of opaque existentials
+// ---
+// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s200______use_foo_varyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[GLOBAL:%.*]] = global_addr {{.*}} : $*Foo
+// CHECK: [[LOAD_GLOBAL:%.*]] = load [copy] [[GLOBAL]] : $*Foo
+// CHECK: [[OPEN_VAR:%.*]] = open_existential_opaque [[LOAD_GLOBAL]] : $Foo
+// CHECK: [[WITNESS:%.*]] = witness_method $@opened
+// CHECK: apply [[WITNESS]]
+// CHECK: destroy_value [[OPEN_VAR]]
+// CHECK: deinit_existential_opaque [[LOAD_GLOBAL]] : $Foo
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s200______use_foo_varyyF'
+func s200______use_foo_var() {
+ foo_var.foo()
+}
+
+// Tests composition erasure of opaque existentials + copy into of opaques
+// ---
+// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s210______compErasures5Error_psAC_AA3FoopF : $@convention(thin) (@in Error & Foo) -> @owned Error {
+// CHECK: bb0([[ARG:%.*]] : $Error & Foo):
+// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_opaque [[BORROWED_ARG]] : $Error & Foo to $@opened({{.*}}) Error & Foo
+// CHECK: [[EXIST_BOX:%.*]] = alloc_existential_box $Error, $@opened({{.*}}) Error & Foo
+// CHECK: [[PROJ_BOX:%.*]] = project_existential_box $@opened({{.*}}) Error & Foo in [[EXIST_BOX]]
+// CHECK: [[COPY_OPAQUE:%.*]] = copy_value [[OPAQUE_ARG]] : $@opened({{.*}}) Error & Foo
+// CHECK: store [[COPY_OPAQUE]] to [init] [[PROJ_BOX]] : $*@opened({{.*}}) Error & Foo
+// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
+// CHECK: destroy_value [[ARG]] : $Error & Foo
+// CHECK: return [[EXIST_BOX]] : $Error
+// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s210______compErasures5Error_psAC_AA3FoopF'
+func s210______compErasure(_ x: Foo & Error) -> Error {
+ return x
+}
+
+// Tests that existential boxes can contain opaque types
+// ---
+// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s220_____openExistBoxSSs5Error_pF : $@convention(thin) (@owned Error) -> @owned String {
+// CHECK: bb0([[ARG:%.*]] : $Error):
+// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box [[BORROWED_ARG]] : $Error to $@opened({{.*}}) Error
+// CHECK: [[RET_STRING:%.*]] = apply{{.*}}<@opened({{.*}}) Error>([[OPAQUE_ARG]]) : $@convention(witness_method) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> @owned String
+// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
+// CHECK: destroy_value [[ARG]] : $Error
+// CHECK: return [[RET_STRING]] : $String
+// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s220_____openExistBoxSSs5Error_pF'
+func s220_____openExistBox(_ x: Error) -> String {
+ return x._domain
+}
+
+// Tests LogicalPathComponent's writeback for opaque value types
+// ---
+// CHECK-LABEL: sil @_T0s10DictionaryV20opaque_values_silgenE22inoutAccessOfSubscriptyq_3key_tF : $@convention(method) <Key, Value where Key : Hashable> (@in Value, @inout Dictionary<Key, Value>) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Value, [[ARG1:%.*]] : $*Dictionary<Key, Value>):
+// CHECK: [[OPTIONAL_ALLOC:%.*]] = alloc_stack $Optional<Value>
+// CHECK: switch_enum_addr [[OPTIONAL_ALLOC]] : $*Optional<Value>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb2:
+// CHECK: [[OPTIONAL_LOAD:%.*]] = load [take] [[OPTIONAL_ALLOC]] : $*Optional<Value>
+// CHECK: apply {{.*}}<Key, Value>([[OPTIONAL_LOAD]], {{.*}}, [[ARG1]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '_T0s10DictionaryV20opaque_values_silgenE22inoutAccessOfSubscriptyq_3key_tF'
+
+// Tests materializeForSet's createSetterCallback for opaque values
+// ---
+// CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV20opaque_values_silgenE9subscriptq_Sgq_cfmytfU_ : $@convention(method) <Key, Value where Key : Hashable> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Key, Value>, @thick Dictionary<Key, Value>.Type) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.RawPointer, [[ARG1:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : $*Dictionary<Key, Value>, [[ARG3:%.*]] : $@thick Dictionary<Key, Value>.Type):
+// CHECK: [[PROJ_VAL1:%.*]] = project_value_buffer $Value in [[ARG1]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[LOAD_VAL1:%.*]] = load [take] [[PROJ_VAL1]] : $*Value
+// CHECK: [[ADDR_VAL0:%.*]] = pointer_to_address [[ARG0]] : $Builtin.RawPointer to [strict] $*Optional<Value>
+// CHECK: [[LOAD_VAL0:%.*]] = load [take] [[ADDR_VAL0]] : $*Optional<Value>
+// CHECK: apply {{.*}}<Key, Value>([[LOAD_VAL0]], [[LOAD_VAL1]], [[ARG2]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '_T0s10DictionaryV20opaque_values_silgenE9subscriptq_Sgq_cfmytfU_'
+extension Dictionary {
+ public subscript(key: Value) -> Value? {
+ @inline(__always)
+ get {
+ return key
+ }
+ set(newValue) {
+ }
+ }
+
+ public mutating func inoutAccessOfSubscript(key: Value) {
+ func increment(x: inout Value) { }
+
+ increment(x: &self[key]!)
+ }
+}
diff --git a/test/SILGen/optional-cast.swift b/test/SILGen/optional-cast.swift
index 1ca7fa4..e2ed3eb 100644
--- a/test/SILGen/optional-cast.swift
+++ b/test/SILGen/optional-cast.swift
@@ -30,8 +30,8 @@
// CHECK-NEXT: br [[CONT:bb[0-9]+]]
//
// If not, destroy_value the A and inject nothing into x.
-// CHECK: [[NOT_B]]:
-// CHECK-NEXT: destroy_value [[VAL]]
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : $A):
+// CHECK-NEXT: destroy_value [[ORIGINAL_VALUE]]
// CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional<B>, #Optional.none
// CHECK-NEXT: br [[CONT]]
//
@@ -111,8 +111,8 @@
// CHECK-NEXT: br [[SWITCH_OB2:bb[0-9]+]](
//
// If not, inject nothing into an optional.
-// CHECK: [[NOT_B]]:
-// CHECK-NEXT: destroy_value [[VAL]]
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : $A):
+// CHECK-NEXT: destroy_value [[ORIGINAL_VALUE]]
// CHECK-NEXT: enum $Optional<B>, #Optional.none!enumelt
// CHECK-NEXT: br [[SWITCH_OB2]](
//
@@ -174,9 +174,10 @@
// CHECK: [[VAL:%.*]] = unchecked_enum_data [[ARG_COPY]]
// CHECK-NEXT: [[X_VALUE:%.*]] = init_enum_data_addr [[PB]] : $*Optional<B>, #Optional.some
// CHECK-NEXT: checked_cast_br [[VAL]] : $AnyObject to $B, [[IS_B:bb.*]], [[NOT_B:bb[0-9]+]]
-// CHECK: [[IS_B]](
-// CHECK: [[NOT_B]]:
-// CHECK: destroy_value [[VAL]]
+// CHECK: [[IS_B]]([[CASTED_VALUE:%.*]] : $B):
+// CHECK: store [[CASTED_VALUE]] to [init] [[X_VALUE]]
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : $AnyObject):
+// CHECK: destroy_value [[ORIGINAL_VALUE]]
// CHECK: } // end sil function '_T04main3bazys9AnyObject_pSgF'
func baz(_ y : AnyObject?) {
var x = (y as? B)
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index e54101b..3e66fde 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -227,7 +227,7 @@
// -- writeback to val.ref.val_prop
// CHECK: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
- // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> ()
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> ()
// CHECK: [[REF_MAT:%.*]] = alloc_stack $Ref
// CHECK: store [[VAL_REF]] to [init] [[REF_MAT]]
// CHECK: [[T0:%.*]] = metatype $@thick Ref.Type
diff --git a/test/SILGen/protocol_resilience.swift b/test/SILGen/protocol_resilience.swift
index 8b7b32c..35e64a5 100644
--- a/test/SILGen/protocol_resilience.swift
+++ b/test/SILGen/protocol_resilience.swift
@@ -120,8 +120,8 @@
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE26mutablePropertyWithDefaultSifg
// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSifs
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE26mutablePropertyWithDefaultSifs
-// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSifm
// CHECK-LABEL: sil [transparent] @_T019protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSifmytfU_
+// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSifm
public var mutablePropertyWithDefault: Int {
get { return 0 }
set { }
@@ -136,8 +136,8 @@
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE33mutableGenericPropertyWithDefault1TQzfg
// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzfs
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE33mutableGenericPropertyWithDefault1TQzfs
-// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzfm
// CHECK-LABEL: sil [transparent] @_T019protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzfmytfU_
+// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzfm
public var mutableGenericPropertyWithDefault: T {
get {
return T(default: ())
@@ -149,8 +149,8 @@
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE9subscript1TQzAFcfg
// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP9subscript1TQzAFcfs
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE9subscript1TQzAFcfs
-// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP9subscript1TQzAFcfm
// CHECK-LABEL: sil [transparent] @_T019protocol_resilience16ResilientStorageP9subscript1TQzAFcfmytfU_
+// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP9subscript1TQzAFcfm
public subscript(x: T) -> T {
get {
return x
@@ -162,8 +162,8 @@
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE36mutatingGetterWithNonMutatingDefaultSifg
// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSifs
// CHECK-LABEL: sil @_T019protocol_resilience16ResilientStoragePAAE36mutatingGetterWithNonMutatingDefaultSifs
-// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSifm
// CHECK-LABEL: sil [transparent] @_T019protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSifmytfU_
+// CHECK-LABEL: sil [transparent] [thunk] @_T019protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSifm
public var mutatingGetterWithNonMutatingDefault: Int {
get {
return 0
diff --git a/test/SILOptimizer/address_lowering.sil b/test/SILOptimizer/address_lowering.sil
index 1e937e8..db8221f 100644
--- a/test/SILOptimizer/address_lowering.sil
+++ b/test/SILOptimizer/address_lowering.sil
@@ -5,12 +5,12 @@
sil_stage canonical
// CHECK: sil_stage lowered
-// CHECK-LABEL: sil hidden @addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
+// CHECK-LABEL: sil hidden @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
// CHECK: bb0(%0 : $*T, %1 : $*T):
// CHECK: copy_addr [take] %1 to [initialization] %0 : $*T
// CHECK: return %{{.*}} : $()
-// CHECK-LABEL: } // end sil function 'addrlower_identity'
-sil hidden @addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
+// CHECK-LABEL: } // end sil function 'f010_addrlower_identity'
+sil hidden @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
bb0(%0 : $T):
return %0 : $T
}
@@ -29,7 +29,7 @@
// Test returning an opaque tuple of tuples as a concrete tuple.
// The multiResult call is specialized, but the SIL result convention does not change.
// ---
-// CHECK-LABEL: sil @f030_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
+// CHECK-LABEL: sil @f021_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
// CHECK: bb0(%0 : $Builtin.Int64):
// CHECK: %[[FN:.*]] = function_ref @f020_multiResult : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
// CHECK: %[[IN:.*]] = alloc_stack $Builtin.Int64
@@ -39,16 +39,16 @@
// CHECK: %[[OUT3:.*]] = alloc_stack $Builtin.Int64
// CHECK: %{{.*}} = apply %[[FN]]<Builtin.Int64>(%[[OUT1]], %[[OUT2]], %[[OUT3]], %[[IN]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
// CHECK: %[[R3:.*]] = load %[[OUT3]] : $*Builtin.Int64
-// CHECK: %[[R2:.*]] = load %[[OUT2]] : $*Builtin.Int64
-// CHECK: %[[R1:.*]] = load %[[OUT1]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT3]] : $*Builtin.Int64
+// CHECK: %[[R2:.*]] = load %[[OUT2]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT2]] : $*Builtin.Int64
+// CHECK: %[[R1:.*]] = load %[[OUT1]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT1]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[IN]] : $*Builtin.Int64
// CHECK: %[[R:.*]] = tuple (%[[R1]] : $Builtin.Int64, %[[R2]] : $Builtin.Int64, %[[R3]] : $Builtin.Int64)
// CHECK: return %[[R]] : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
-// CHECK-LABEL: } // end sil function 'f030_callMultiResult'
-sil @f030_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
+// CHECK-LABEL: } // end sil function 'f021_callMultiResult'
+sil @f021_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
bb0(%0 : $Builtin.Int64):
%1 = function_ref @f020_multiResult : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
%2 = apply %1<Builtin.Int64>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
@@ -58,3 +58,318 @@
%6 = tuple (%3 : $Builtin.Int64, %4 : $Builtin.Int64, %5 : $Builtin.Int64)
return %6 : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
}
+
+// CHECK-LABEL: sil @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
+// CHECK: %[[LOCAL:.*]] = alloc_stack $T
+// CHECK: copy_addr %2 to [initialization] %[[LOCAL]] : $*T
+// CHECK: copy_addr [take] %[[LOCAL]] to [initialization] %0 : $*T
+// CHECK: copy_addr [take] %2 to [initialization] %1 : $*T
+// CHECK: %[[R:.*]] = tuple ()
+// CHECK: dealloc_stack %[[LOCAL]] : $*T
+// CHECK: return %[[R]] : $()
+// CHECK-LABEL: } // end sil function 'f030_returnPair'
+sil @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
+bb0(%0 : $T):
+ %2 = copy_value %0 : $T
+ %3 = tuple (%2 : $T, %0 : $T)
+ return %3 : $(T, T)
+}
+
+// CHECK-LABEL: sil @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
+// CHECK: bb0(%0 : $*T, %1 : $*T):
+// CHECK: %[[LOC2:.*]] = alloc_stack $T
+// CHECK: %[[OUT2:.*]] = alloc_stack $T
+// CHECK: %[[LOC1:.*]] = alloc_stack $T
+// CHECK: %[[OUT1:.*]] = alloc_stack $T
+// CHECK: %[[LOC0:.*]] = alloc_stack $T
+// CHECK: // function_ref f030_returnPair
+// CHECK: %7 = function_ref @f030_returnPair : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
+// CHECK: copy_addr %1 to [initialization] %[[LOC0]] : $*T
+// CHECK: %[[IN:.*]] = alloc_stack $T
+// CHECK: copy_addr [take] %[[LOC0]] to [initialization] %[[IN]] : $*T
+// CHECK: %11 = apply %7<T>(%[[OUT1]], %[[OUT2]], %[[IN]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
+// CHECK: dealloc_stack %[[IN]] : $*T
+// CHECK: copy_addr %[[OUT1]] to [initialization] %[[LOC1]] : $*T
+// CHECK: copy_addr %[[OUT2]] to [initialization] %[[LOC2]] : $*T
+// CHECK: destroy_addr %[[OUT1]] : $*T
+// CHECK: destroy_addr %[[OUT2]] : $*T
+// CHECK: destroy_addr %[[LOC1]] : $*T
+// CHECK: destroy_addr %1 : $*T
+// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %0 : $*T
+// CHECK: %[[R:.*]] = tuple ()
+// CHECK: dealloc_stack %[[LOC0]] : $*T
+// CHECK: dealloc_stack %[[OUT1]] : $*T
+// CHECK: dealloc_stack %[[LOC1]] : $*T
+// CHECK: dealloc_stack %[[OUT2]] : $*T
+// CHECK: dealloc_stack %[[LOC2]] : $*T
+// CHECK: return %[[R]] : $()
+// CHECK-LABEL: } // end sil function 'f031_unusedIndirect'
+sil @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
+bb0(%0 : $T):
+ %2 = function_ref @f030_returnPair : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
+ %3 = copy_value %0 : $T
+ %4 = apply %2<T>(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
+ %5 = tuple_extract %4 : $(T, T), 0
+ %6 = copy_value %5 : $T
+ %7 = tuple_extract %4 : $(T, T), 1
+ %8 = copy_value %7 : $T
+ destroy_value %4 : $(T, T)
+ destroy_value %6 : $T
+ destroy_value %0 : $T
+ return %8 : $T
+}
+
+sil hidden @f040_consumeArg : $@convention(thin) <T> (@in T) -> () {
+bb0(%0 : $T):
+ destroy_value %0 : $T
+ %3 = tuple ()
+ return %3 : $()
+}
+
+// CHECK-LABEL: sil @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
+// CHECK: bb0(%0 : $*T):
+// CHECK: %[[LOC:.*]] = alloc_stack $T
+// CHECK: %[[FN:.*]] = function_ref @f040_consumeArg : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+// CHECK: copy_addr %0 to [initialization] %[[LOC]] : $*T
+// CHECK: %[[ARG:.*]] = alloc_stack $T
+// CHECK: copy_addr [take] %[[LOC]] to [initialization] %[[ARG]] : $*T
+// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+// CHECK: dealloc_stack %[[ARG]] : $*T
+// CHECK: destroy_addr %0 : $*T
+// CHECK: %[[R:.*]] = tuple ()
+// CHECK: dealloc_stack %[[LOC]] : $*T
+// CHECK: return %[[R]] : $()
+// CHECK-LABEL: } // end sil function 'f041_opaqueArg'
+sil @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
+bb0(%0 : $T):
+ %2 = function_ref @f040_consumeArg : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ %3 = copy_value %0 : $T
+ %4 = apply %2<T>(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ destroy_value %0 : $T
+ %6 = tuple ()
+ return %6 : $()
+}
+
+// CHECK-LABEL: sil @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
+// CHECK: %[[PREV2:.*]] = alloc_stack $T
+// CHECK: %[[ARG2:.*]] = alloc_stack $T
+// CHECK: %[[PREV1:.*]] = alloc_stack $T
+// CHECK: %[[ARG1:.*]] = alloc_stack $T
+// CHECK: debug_value_addr %0 : $*T, var, name "t", argno 1
+// CHECK: debug_value_addr %1 : $*T, var, name "u", argno 2
+// CHECK: debug_value_addr %2 : $*T
+// CHECK: copy_addr %2 to [initialization] %[[ARG1]] : $*T
+// CHECK: copy_addr [take] %0 to [initialization] %[[PREV1]] : $*T
+// CHECK: copy_addr [take] %[[ARG1]] to [initialization] %0 : $*T
+// CHECK: destroy_addr %[[PREV1]] : $*T
+// CHECK: copy_addr %2 to [initialization] %[[ARG2]] : $*T
+// CHECK: copy_addr [take] %1 to [initialization] %[[PREV2]] : $*T
+// CHECK: copy_addr [take] %[[ARG2]] to [initialization] %1 : $*T
+// CHECK: destroy_addr %[[PREV2]] : $*T
+// CHECK: destroy_addr %2 : $*T
+// CHECK: %19 = tuple ()
+// CHECK: dealloc_stack %[[ARG1]] : $*T
+// CHECK: dealloc_stack %[[PREV1]] : $*T
+// CHECK: dealloc_stack %[[ARG2]] : $*T
+// CHECK: dealloc_stack %[[PREV2]] : $*T
+// CHECK: return %19 : $()
+// CHECK-LABEL: } // end sil function 'f050_storeinout'
+sil @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
+bb0(%0 : $*T, %1 : $*T, %2 : $T):
+ debug_value_addr %0 : $*T, var, name "t", argno 1
+ debug_value_addr %1 : $*T, var, name "u", argno 2
+ debug_value %2 : $T, let, name "x", argno 3
+ %6 = copy_value %2 : $T
+ %7 = load %0 : $*T
+ store %6 to %0 : $*T
+ destroy_value %7 : $T
+ %10 = copy_value %2 : $T
+ %11 = load %1 : $*T
+ store %10 to %1 : $*T
+ destroy_value %11 : $T
+ destroy_value %2 : $T
+ %15 = tuple ()
+ return %15 : $()
+}
+
+sil hidden @f060_mutate : $@convention(thin) <T> (@inout T, @in T) -> () {
+bb0(%0 : $*T, %1 : $T):
+ %4 = copy_value %1 : $T
+ %5 = load %0 : $*T
+ store %4 to %0 : $*T
+ destroy_value %5 : $T
+ destroy_value %1 : $T
+ %9 = tuple ()
+ return %9 : $()
+}
+
+// CHECK-LABEL: sil @f061_callinout : $@convention(thin) <T> (@in T) -> () {
+// CHECK: bb0(%0 : $*T):
+// CHECK: %[[LOC2:.*]] = alloc_stack $T
+// CHECK: %[[LOC1:.*]] = alloc_stack $T
+// CHECK: %[[INOUT:.*]] = alloc_stack $T, var, name "u"
+// CHECK: copy_addr %0 to [initialization] %[[LOC1]] : $*T
+// CHECK: copy_addr [take] %[[LOC1]] to [initialization] %[[INOUT]] : $*T
+// CHECK: %[[FN:.*]] = function_ref @f060_mutate : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
+// CHECK: copy_addr %0 to [initialization] %[[LOC2]] : $*T
+// CHECK: %[[IN:.*]] = alloc_stack $T
+// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %[[IN]] : $*T
+// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[INOUT]], %[[IN]]) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
+// CHECK: dealloc_stack %[[IN]] : $*T
+// CHECK: destroy_addr %[[INOUT]] : $*T
+// CHECK: destroy_addr %0 : $*T
+// CHECK: %[[R:.*]] = tuple ()
+// CHECK: dealloc_stack %[[INOUT]] : $*T
+// CHECK: dealloc_stack %[[LOC1]] : $*T
+// CHECK: dealloc_stack %[[LOC2]] : $*T
+// CHECK: return %[[R]] : $()
+// CHECK-LABEL: } // end sil function 'f061_callinout'
+sil @f061_callinout : $@convention(thin) <T> (@in T) -> () {
+bb0(%0 : $T):
+ %1 = alloc_stack $T, var, name "u"
+ %3 = copy_value %0 : $T
+ store %3 to %1 : $*T
+ %5 = function_ref @f060_mutate : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
+ %6 = copy_value %0 : $T
+ %7 = apply %5<T>(%1, %6) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
+ destroy_addr %1 : $*T
+ destroy_value %0 : $T
+ %10 = tuple ()
+ dealloc_stack %1 : $*T
+ return %10 : $()
+}
+
+public protocol C : class {}
+
+// CHECK-LABEL: sil @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $C):
+// CHECK: copy_addr [take] %1 to [initialization] %0 : $*T
+// CHECK: return %2 : $C
+// CHECK-LABEL: } // end sil function 'f070_mixedResult1'
+sil @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
+bb0(%0 : $T, %1 : $C):
+ %4 = tuple (%0 : $T, %1 : $C)
+ return %4 : $(T, C)
+}
+
+// CHECK-LABEL: sil @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : $C):
+// CHECK: %[[L:.*]] = alloc_stack $T
+// CHECK: copy_addr %2 to [initialization] %[[L]] : $*T
+// CHECK: strong_retain %3 : $C
+// CHECK: copy_addr [take] %[[L]] to [initialization] %0 : $*T
+// CHECK: copy_addr [take] %2 to [initialization] %1 : $*T
+// CHECK: %[[T:.*]] = tuple (%3 : $C, %3 : $C)
+// CHECK: dealloc_stack %[[L]] : $*T
+// CHECK: return %[[T]] : $(C, C)
+// CHECK-LABEL: } // end sil function 'f071_mixedResult2'
+sil @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
+bb0(%0 : $T, %1 : $C):
+ %4 = copy_value %0 : $T
+ strong_retain %1 : $C
+ %6 = tuple (%4 : $T, %0 : $T, %1 : $C, %1 : $C)
+ return %6 : $(T, T, C, C)
+}
+
+// CHECK-LABEL: sil @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $C):
+// CHECK: %[[LOUT:.*]] = alloc_stack $T
+// CHECK: %[[OUT:.*]] = alloc_stack $T
+// CHECK: %[[LIN:.*]] = alloc_stack $T
+// CHECK: // function_ref f070_mixedResult1
+// CHECK: %[[F:.*]] = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
+// CHECK: copy_addr %1 to [initialization] %[[LIN]] : $*T
+// CHECK: strong_retain %2 : $C
+// CHECK: %[[IN:.*]] = alloc_stack $T
+// CHECK: copy_addr [take] %[[LIN]] to [initialization] %[[IN]] : $*T
+// CHECK: %11 = apply %[[F]]<T>(%[[OUT]], %[[IN]], %2) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
+// CHECK: dealloc_stack %[[IN]] : $*T
+// CHECK: copy_addr %[[OUT]] to [initialization] %[[LOUT]] : $*T
+// CHECK: strong_retain %11 : $C
+// CHECK: destroy_addr %[[OUT]] : $*T
+// CHECK: strong_release %11 : $C
+// CHECK: strong_release %2 : $C
+// CHECK: destroy_addr %1 : $*T
+// CHECK: copy_addr [take] %[[LOUT]] to [initialization] %0 : $*T
+// CHECK: dealloc_stack %[[LIN]] : $*T
+// CHECK: dealloc_stack %[[OUT]] : $*T
+// CHECK: dealloc_stack %[[LOUT]] : $*T
+// CHECK: return %11 : $C
+// CHECK-LABEL: } // end sil function 'f072_callMixedResult1'
+sil @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
+bb0(%0 : $T, %1 : $C):
+ %4 = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
+ %5 = copy_value %0 : $T
+ strong_retain %1 : $C
+ %7 = apply %4<T>(%5, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
+ %8 = tuple_extract %7 : $(T, C), 0
+ %9 = copy_value %8 : $T
+ %10 = tuple_extract %7 : $(T, C), 1
+ strong_retain %10 : $C
+ destroy_value %7 : $(T, C)
+ strong_release %1 : $C
+ destroy_value %0 : $T
+ %15 = tuple (%9 : $T, %10 : $C)
+ return %15 : $(T, C)
+}
+
+// CHECK-LABEL: sil @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
+// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : $C):
+// CHECK: %[[LOC2:.*]] = alloc_stack $T
+// CHECK: %[[OUT2:.*]] = alloc_stack $T
+// CHECK: %[[LOC1:.*]] = alloc_stack $T
+// CHECK: %[[OUT1:.*]] = alloc_stack $T
+// CHECK: %[[LOC0:.*]] = alloc_stack $T
+// CHECK: %[[F:.*]] = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
+// CHECK: copy_addr %2 to [initialization] %[[LOC0]] : $*T
+// CHECK: strong_retain %3 : $C
+// CHECK: %[[IN:.*]] = alloc_stack $T
+// CHECK: copy_addr [take] %[[LOC0]] to [initialization] %[[IN]] : $*T
+// CHECK: %[[R:.*]] = apply %[[F]]<T>(%[[OUT1]], %[[OUT2]], %[[IN]], %3) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
+// CHECK: %[[T2:.*]] = tuple_extract %[[R]] : $(C, C), 1
+// CHECK: %[[T1:.*]] = tuple_extract %[[R]] : $(C, C), 0
+// CHECK: dealloc_stack %[[IN]] : $*T
+// CHECK: copy_addr %[[OUT1]] to [initialization] %[[LOC1]] : $*T
+// CHECK: copy_addr %[[OUT2]] to [initialization] %[[LOC2]] : $*T
+// CHECK: strong_retain %[[T1]] : $C
+// CHECK: strong_retain %[[T2]] : $C
+// CHECK: destroy_addr %[[OUT1]] : $*T
+// CHECK: destroy_addr %[[OUT2]] : $*T
+// CHECK: strong_release %[[T1]] : $C
+// CHECK: strong_release %[[T2]] : $C
+// CHECK: strong_release %3 : $C
+// CHECK: destroy_addr %2 : $*T
+// CHECK: copy_addr [take] %[[LOC1]] to [initialization] %0 : $*T
+// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %1 : $*T
+// CHECK: %[[T:.*]] = tuple (%[[T1]] : $C, %[[T2]] : $C)
+// CHECK: dealloc_stack %[[LOC0]] : $*T
+// CHECK: dealloc_stack %[[OUT1]] : $*T
+// CHECK: dealloc_stack %[[LOC1]] : $*T
+// CHECK: dealloc_stack %[[OUT2]] : $*T
+// CHECK: dealloc_stack %[[LOC2]] : $*T
+// CHECK: return %[[T]] : $(C, C)
+// CHECK-LABEL: } // end sil function 'f073_callMixedResult2'
+sil @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
+bb0(%0 : $T, %1 : $C):
+ %4 = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
+ %5 = copy_value %0 : $T
+ strong_retain %1 : $C
+ %7 = apply %4<T>(%5, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
+ %8 = tuple_extract %7 : $(T, T, C, C), 0
+ %9 = copy_value %8 : $T
+ %10 = tuple_extract %7 : $(T, T, C, C), 1
+ %11 = copy_value %10 : $T
+ %12 = tuple_extract %7 : $(T, T, C, C), 2
+ strong_retain %12 : $C
+ %14 = tuple_extract %7 : $(T, T, C, C), 3
+ strong_retain %14 : $C
+ destroy_value %7 : $(T, T, C, C)
+ strong_release %1 : $C
+ destroy_value %0 : $T
+ %19 = tuple (%9 : $T, %11 : $T, %12 : $C, %14 : $C)
+ return %19 : $(T, T, C, C)
+}
+
+sil_default_witness_table C {}
diff --git a/test/SILOptimizer/capture_promotion_generic_context.sil b/test/SILOptimizer/capture_promotion_generic_context.sil
index 1eb5b86..b7b2812 100644
--- a/test/SILOptimizer/capture_promotion_generic_context.sil
+++ b/test/SILOptimizer/capture_promotion_generic_context.sil
@@ -35,16 +35,11 @@
return %k : $@callee_owned () -> Int
}
-// Applying the caller's substitutions to a generic closure callee would also
-// be disastrous, but it appears that capture promotion currently bails out
-// on generic closures. This test is included to ensure there aren't regressions
-// if capture promotion is ever generalized to generic closures.
-
protocol P {}
-// TODO: Ought to be promotable, but currently is not.
-// rdar://problem/28948735
-// CHECK-LABEL: sil @generic_promotable_box
+// CHECK-LABEL: sil @_TTSf2n_i__generic_promotable_box : $@convention(thin) <T> (@in T, Builtin.Int32) -> Builtin.Int32
+// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int32):
+// CHECK-NEXT: return %1 : $Builtin.Int32
sil @generic_promotable_box : $@convention(thin) <T> (@in T, <τ_0_0> { var τ_0_0 } <Int>) -> Int {
entry(%0 : $*T, %b : $<τ_0_0> { var τ_0_0 } <Int>):
@@ -54,8 +49,12 @@
}
// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic
-// CHECK: [[F:%.*]] = function_ref @generic_promotable_box
-// CHECK: partial_apply [[F]]<U>(
+// CHECK: bb0(%0 : $*T, %1 : $*U, %2 : $Builtin.Int32):
+// CHECK-NEXT: destroy_addr %0 : $*T
+// CHECK-NEXT: destroy_addr %1 : $*U
+// CHECK: [[F:%.*]] = function_ref @_TTSf2n_i__generic_promotable_box : $@convention(thin) <τ_0_0> (@in τ_0_0, Builtin.Int32) -> Builtin.Int32
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [[F]]<U>(%2)
+// CHECK-NEXT: return [[CLOSURE]]
sil @call_generic_promotable_box_from_different_generic : $@convention(thin) <T, U: P> (@in T, @in U, Int) -> @owned @callee_owned (@in U) -> Int {
entry(%0 : $*T, %1 : $*U, %2 : $Int):
diff --git a/test/SILOptimizer/cse.sil b/test/SILOptimizer/cse.sil
index 10e8c82..f101457 100644
--- a/test/SILOptimizer/cse.sil
+++ b/test/SILOptimizer/cse.sil
@@ -720,104 +720,6 @@
%33 = return %32 : $()
}
-// CHECK-LABEL: sil @cse_value_metatype
-// CHECK: value_metatype $@objc_metatype
-// CHECK: objc_metatype_to_object
-// CHECK-NOT: value_metatype $@objc_metatype
-// CHECK: strong_release
-// CHECK: return
-sil @cse_value_metatype : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
-bb0(%0 : $T):
- %2 = value_metatype $@objc_metatype T.Type, %0 : $T
- %4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
- %5 = value_metatype $@objc_metatype T.Type, %0 : $T
- %7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
- strong_release %0 : $T
- %9 = tuple (%4: $AnyObject, %7: $AnyObject)
- return %9 : $(AnyObject, AnyObject)
-}
-
-
-@objc(XX) protocol XX {
-}
-
-// CHECK-LABEL: sil @cse_existential_metatype
-// CHECK: existential_metatype $@objc_metatype
-// CHECK: objc_existential_metatype_to_object
-// CHECK-NOT: existential_metatype $@objc_metatype
-// CHECK: strong_release
-// CHECK: return
-sil @cse_existential_metatype : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
-bb0(%0 : $XX):
- %2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
- %4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
- %5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
- %6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
- strong_release %0 : $XX
- %7 = tuple (%4: $AnyObject, %6: $AnyObject)
- return %7 : $(AnyObject, AnyObject)
-}
-
-// CHECK-LABEL: sil @nocse_existential_metatype_addr
-// CHECK: store
-// CHECK: existential_metatype $@thick Any.Type
-// CHECK: store
-// CHECK: existential_metatype $@thick Any.Type
-// CHECK: return
-sil @nocse_existential_metatype_addr : $@convention(thin) (@owned B, @owned B) -> (@thick Any.Type, @thick Any.Type) {
-bb0(%0 : $B, %1 : $B):
- %2 = alloc_stack $Any
- %3 = init_existential_addr %2 : $*Any, $B
- store %0 to %3 : $*B
- %5 = existential_metatype $@thick Any.Type, %2 : $*Any
- store %1 to %3 : $*B
- %7 = existential_metatype $@thick Any.Type, %2 : $*Any
- strong_release %1 : $B
- strong_release %0 : $B
- %99 = tuple (%5 : $@thick Any.Type, %7 : $@thick Any.Type)
- dealloc_stack %2 : $*Any
- return %99 : $(@thick Any.Type, @thick Any.Type)
-}
-
-
-// CHECK-LABEL: sil @cse_objc_metatype_to_object
-// CHECK: value_metatype $@objc_metatype
-// CHECK: objc_metatype_to_object
-// CHECK-NOT: value_metatype $@objc_metatype
-// CHECK-NOT: objc_metatype_to_object
-// CHECK: strong_release
-// CHECK: return
-sil @cse_objc_metatype_to_object : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
-bb0(%0 : $T):
- %2 = value_metatype $@objc_metatype T.Type, %0 : $T
- %4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
- %5 = value_metatype $@objc_metatype T.Type, %0 : $T
- %7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
- strong_release %0 : $T
- %9 = tuple (%4: $AnyObject, %7: $AnyObject)
- return %9 : $(AnyObject, AnyObject)
-}
-
-
-// CHECK-LABEL: sil @cse_objc_existential_metatype_to_object
-// CHECK: existential_metatype $@objc_metatype
-// CHECK: objc_existential_metatype_to_object
-// CHECK-NOT: existential_metatype $@objc_metatype
-// CHECK-NOT: objc_existential_metatype_to_object
-// CHECK: strong_release
-// CHECK: return
-sil @cse_objc_existential_metatype_to_object : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
-bb0(%0 : $XX):
- %2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
- %4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
- %5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
- %6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
- strong_release %0 : $XX
- %7 = tuple (%4: $AnyObject, %6: $AnyObject)
- return %7 : $(AnyObject, AnyObject)
-}
-
-
// CHECK-LABEL: sil @cse_raw_pointer_to_ref
// CHECK: raw_pointer_to_ref
// CHECK-NOT: raw_pointer_to_ref
@@ -937,24 +839,6 @@
return %3: $(Builtin.Int1, Builtin.Int1)
}
-
-@objc
-class XXX {
-}
-
-// CHECK-LABEL: sil @cse_objc_to_thick_metatype
-// CHECK: objc_to_thick_metatype
-// CHECK-NOT: objc_to_thick_metatype
-// CHECK: tuple
-// CHECK: return
-sil @cse_objc_to_thick_metatype : $@convention(thin) (@objc_metatype XXX.Type) -> (@thick XXX.Type, @thick XXX.Type) {
-bb0(%0 : $@objc_metatype XXX.Type):
- %1 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
- %2 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
- %3 = tuple (%1: $@thick XXX.Type, %2: $@thick XXX.Type)
- return %3: $(@thick XXX.Type, @thick XXX.Type)
-}
-
// CHECK-LABEL: sil @cse_bridge_object_to_ref
// CHECK: bridge_object_to_ref
// CHECK-NOT: bridge_object_to_ref
diff --git a/test/SILOptimizer/cse_objc.sil b/test/SILOptimizer/cse_objc.sil
index 0d0a71c..40d3be1 100644
--- a/test/SILOptimizer/cse_objc.sil
+++ b/test/SILOptimizer/cse_objc.sil
@@ -154,6 +154,118 @@
return %13 : $()
}
+// CHECK-LABEL: sil @cse_value_metatype
+// CHECK: value_metatype $@objc_metatype
+// CHECK: objc_metatype_to_object
+// CHECK-NOT: value_metatype $@objc_metatype
+// CHECK: strong_release
+// CHECK: return
+sil @cse_value_metatype : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
+bb0(%0 : $T):
+ %2 = value_metatype $@objc_metatype T.Type, %0 : $T
+ %4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
+ %5 = value_metatype $@objc_metatype T.Type, %0 : $T
+ %7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
+ strong_release %0 : $T
+ %9 = tuple (%4: $AnyObject, %7: $AnyObject)
+ return %9 : $(AnyObject, AnyObject)
+}
+
+// CHECK-LABEL: sil @cse_existential_metatype
+// CHECK: existential_metatype $@objc_metatype
+// CHECK: objc_existential_metatype_to_object
+// CHECK-NOT: existential_metatype $@objc_metatype
+// CHECK: strong_release
+// CHECK: return
+sil @cse_existential_metatype : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
+bb0(%0 : $XX):
+ %2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
+ %4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
+ %5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
+ %6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
+ strong_release %0 : $XX
+ %7 = tuple (%4: $AnyObject, %6: $AnyObject)
+ return %7 : $(AnyObject, AnyObject)
+}
+
+class B {}
+
+// CHECK-LABEL: sil @nocse_existential_metatype_addr
+// CHECK: store
+// CHECK: existential_metatype $@thick Any.Type
+// CHECK: store
+// CHECK: existential_metatype $@thick Any.Type
+// CHECK: return
+sil @nocse_existential_metatype_addr : $@convention(thin) (@owned B, @owned B) -> (@thick Any.Type, @thick Any.Type) {
+bb0(%0 : $B, %1 : $B):
+ %2 = alloc_stack $Any
+ %3 = init_existential_addr %2 : $*Any, $B
+ store %0 to %3 : $*B
+ %5 = existential_metatype $@thick Any.Type, %2 : $*Any
+ store %1 to %3 : $*B
+ %7 = existential_metatype $@thick Any.Type, %2 : $*Any
+ strong_release %1 : $B
+ strong_release %0 : $B
+ %99 = tuple (%5 : $@thick Any.Type, %7 : $@thick Any.Type)
+ dealloc_stack %2 : $*Any
+ return %99 : $(@thick Any.Type, @thick Any.Type)
+}
+
+
+// CHECK-LABEL: sil @cse_objc_metatype_to_object
+// CHECK: value_metatype $@objc_metatype
+// CHECK: objc_metatype_to_object
+// CHECK-NOT: value_metatype $@objc_metatype
+// CHECK-NOT: objc_metatype_to_object
+// CHECK: strong_release
+// CHECK: return
+sil @cse_objc_metatype_to_object : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
+bb0(%0 : $T):
+ %2 = value_metatype $@objc_metatype T.Type, %0 : $T
+ %4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
+ %5 = value_metatype $@objc_metatype T.Type, %0 : $T
+ %7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
+ strong_release %0 : $T
+ %9 = tuple (%4: $AnyObject, %7: $AnyObject)
+ return %9 : $(AnyObject, AnyObject)
+}
+
+
+// CHECK-LABEL: sil @cse_objc_existential_metatype_to_object
+// CHECK: existential_metatype $@objc_metatype
+// CHECK: objc_existential_metatype_to_object
+// CHECK-NOT: existential_metatype $@objc_metatype
+// CHECK-NOT: objc_existential_metatype_to_object
+// CHECK: strong_release
+// CHECK: return
+sil @cse_objc_existential_metatype_to_object : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
+bb0(%0 : $XX):
+ %2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
+ %4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
+ %5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
+ %6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
+ strong_release %0 : $XX
+ %7 = tuple (%4: $AnyObject, %6: $AnyObject)
+ return %7 : $(AnyObject, AnyObject)
+}
+
+@objc
+class XXX {
+}
+
+// CHECK-LABEL: sil @cse_objc_to_thick_metatype
+// CHECK: objc_to_thick_metatype
+// CHECK-NOT: objc_to_thick_metatype
+// CHECK: tuple
+// CHECK: return
+sil @cse_objc_to_thick_metatype : $@convention(thin) (@objc_metatype XXX.Type) -> (@thick XXX.Type, @thick XXX.Type) {
+bb0(%0 : $@objc_metatype XXX.Type):
+ %1 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
+ %2 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
+ %3 = tuple (%1: $@thick XXX.Type, %2: $@thick XXX.Type)
+ return %3: $(@thick XXX.Type, @thick XXX.Type)
+}
+
sil_vtable Bar {
#Bar.init!initializer.1: _TFC4test3BarcfMS0_FT_S0_ // test.Bar.init (test.Bar.Type)() -> test.Bar
#Bar.walk!1: _TFC4test3Bar4walkfS0_FT_T_ // test.Bar.walk (test.Bar)() -> ()
diff --git a/test/SILOptimizer/devirt_materializeForSet.swift b/test/SILOptimizer/devirt_materializeForSet.swift
index e84bc40..77b805b 100644
--- a/test/SILOptimizer/devirt_materializeForSet.swift
+++ b/test/SILOptimizer/devirt_materializeForSet.swift
@@ -5,7 +5,7 @@
// CHECK-LABEL: sil [transparent] [fragile] [thunk] @_T024devirt_materializeForSet7BaseFooCAA0F0AaaDP3barSSfmTW
// CHECK: checked_cast_br [exact] %{{.*}} : $BaseFoo to $ChildFoo
-// CHECK: thin_function_to_pointer %{{.*}} : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer
+// CHECK: thin_function_to_pointer %{{.*}} : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer
// CHECK: enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, %{{.*}} : $Builtin.RawPointer
// CHECK: tuple (%{{.*}} : $Builtin.RawPointer, %{{.*}} : $Optional<Builtin.RawPointer>)
diff --git a/test/SILOptimizer/existential_type_propagation.sil b/test/SILOptimizer/existential_type_propagation.sil
index 814ae81..d43dec7 100644
--- a/test/SILOptimizer/existential_type_propagation.sil
+++ b/test/SILOptimizer/existential_type_propagation.sil
@@ -253,18 +253,17 @@
// Check that sil-combine does not crash on this example and does not generate a wrong
// upcast.
// CHECK-LABEL: sil @silcombine_dont_generate_wrong_upcasts_during_devirt
-// CHECK-NOT: upcast
-// CHECK: witness_method $XXX, #PPP.foo!1 : {{.*}} : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
-// CHECK-NOT: upcast
+// CHECK: [[SELF:%.*]] = unchecked_ref_cast %0 : $BBB to $XXX
+// CHECK: [[WITNESS_THUNK:%.*]] = function_ref @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_ : $@convention(witness_method) (@guaranteed XXX) -> ()
+// CHECK: apply [[WITNESS_THUNK]]([[SELF]])
// CHECK: return
sil @silcombine_dont_generate_wrong_upcasts_during_devirt: $@convention(thin) (@owned BBB) -> () {
bb0(%0 : $BBB):
strong_retain %0 : $BBB
%3 = init_existential_ref %0 : $BBB : $BBB, $PPP
%5 = open_existential_ref %3 : $PPP to $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP
- %6 = witness_method $XXX, #PPP.foo!1, %5 : $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
+ %6 = witness_method $BBB, #PPP.foo!1, %5 : $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
%7 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
- %8 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
strong_release %3 : $PPP
%9 = tuple ()
strong_release %0 : $BBB
@@ -279,8 +278,6 @@
// CHECK-NOT: witness_method
// CHECK: [[FR1:%.*]] = function_ref @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_
// CHECK: apply [[FR1]](%0)
-// CHECK: [[FR2:%.*]] = function_ref @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_
-// CHECK: apply [[FR2]](%0)
// CHECK: return
sil @silcombine_devirt_both_applies_of_witness_method : $@convention(thin) (@owned XXX) -> () {
bb0(%0 : $XXX):
@@ -289,7 +286,6 @@
%5 = open_existential_ref %3 : $PPP to $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP
%6 = witness_method $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP, #PPP.foo!1, %5 : $@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
%7 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
- %8 = apply %6<@opened("0AC9A62E-926E-11E6-8BF5-685B35C48C83") PPP>(%5) : $@convention(witness_method) <τ_0_0 where τ_0_0 : PPP> (@guaranteed τ_0_0) -> ()
strong_release %3 : $PPP
%9 = tuple ()
strong_release %0 : $XXX
diff --git a/test/SILOptimizer/ownership_model_eliminator.sil b/test/SILOptimizer/ownership_model_eliminator.sil
index bedfe79..70288dd 100644
--- a/test/SILOptimizer/ownership_model_eliminator.sil
+++ b/test/SILOptimizer/ownership_model_eliminator.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -ownership-model-eliminator %s | %FileCheck %s
+// RUN: %target-sil-opt -enable-sil-ownership -ownership-model-eliminator %s | %FileCheck %s
sil_stage canonical
@@ -10,7 +10,7 @@
class C {}
// CHECK-LABEL: sil @load : $@convention(thin) (@in Builtin.NativeObject, @in Builtin.Int32) -> () {
-// CHECK: bb0([[ARG1:%[0-9]+]] : $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : $*Builtin.Int32):
+// CHECK: bb0([[ARG1:%[0-9]+]] : @trivial $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : @trivial $*Builtin.Int32):
// CHECK: [[LOAD2:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
// CHECK: apply {{%[0-9]+}}([[LOAD2]])
// CHECK: [[LOAD3:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
@@ -19,7 +19,7 @@
// CHECK: [[LOAD4:%[0-9]+]] = load [[ARG2]] : $*Builtin.Int32
// CHECK: apply {{%[0-9]+}}([[LOAD4]])
sil @load : $@convention(thin) (@in Builtin.NativeObject, @in Builtin.Int32) -> () {
-bb0(%0 : $*Builtin.NativeObject, %1 : $*Builtin.Int32):
+bb0(%0 : @trivial $*Builtin.NativeObject, %1 : @trivial $*Builtin.Int32):
%use_native_object_func = function_ref @use_native_object : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%use_int32_func = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> ()
@@ -37,28 +37,32 @@
}
// CHECK-LABEL: sil @store : $@convention(thin) (@in Builtin.NativeObject, Builtin.NativeObject, @in Builtin.Int32, Builtin.Int32) -> ()
-// CHECK: bb0([[ARG1:%[0-9]+]] : $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : $Builtin.NativeObject, [[ARG3:%[0-9]+]] : $*Builtin.Int32, [[ARG4:%[0-9]+]] : $Builtin.Int32):
+// CHECK: bb0([[ARG1:%[0-9]+]] : @trivial $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : @unowned $Builtin.NativeObject, [[ARG3:%[0-9]+]] : @trivial $*Builtin.Int32, [[ARG4:%[0-9]+]] : @trivial $Builtin.Int32):
+// CHECK: strong_retain [[ARG2]]
+// CHECK: strong_retain [[ARG2]]
// CHECK: store [[ARG2]] to [[ARG1]] : $*Builtin.NativeObject
// CHECK: [[OLDVAL:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
// CHECK: store [[ARG2]] to [[ARG1]] : $*Builtin.NativeObject
// CHECK: strong_release [[OLDVAL]]
// CHECK: store [[ARG4]] to [[ARG3]] : $*Builtin.Int32
sil @store : $@convention(thin) (@in Builtin.NativeObject, Builtin.NativeObject, @in Builtin.Int32, Builtin.Int32) -> () {
-bb0(%0 : $*Builtin.NativeObject, %1 : $Builtin.NativeObject, %2 : $*Builtin.Int32, %3 : $Builtin.Int32):
- store %1 to [init] %0 : $*Builtin.NativeObject
- store %1 to [assign] %0 : $*Builtin.NativeObject
+bb0(%0 : @trivial $*Builtin.NativeObject, %1 : @unowned $Builtin.NativeObject, %2 : @trivial $*Builtin.Int32, %3 : @trivial $Builtin.Int32):
+ %4 = copy_value %1 : $Builtin.NativeObject
+ %5 = copy_value %1 : $Builtin.NativeObject
+ store %4 to [init] %0 : $*Builtin.NativeObject
+ store %5 to [assign] %0 : $*Builtin.NativeObject
store %3 to [trivial] %2 : $*Builtin.Int32
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @borrow : $@convention(thin) (@in Builtin.NativeObject) -> () {
-// CHECK: bb0([[ARG:%[0-9]+]] : $*Builtin.NativeObject):
+// CHECK: bb0([[ARG:%[0-9]+]] : @trivial $*Builtin.NativeObject):
// CHECK: [[BORROWED_VALUE:%[0-9]+]] = load [[ARG]] : $*Builtin.NativeObject
// CHECK: unchecked_ref_cast [[BORROWED_VALUE]]
// CHECK-NOT: end_borrow
sil @borrow : $@convention(thin) (@in Builtin.NativeObject) -> () {
-bb0(%0 : $*Builtin.NativeObject):
+bb0(%0 : @trivial $*Builtin.NativeObject):
%1 = load_borrow %0 : $*Builtin.NativeObject
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $Builtin.NativeObject
end_borrow %1 from %0 : $Builtin.NativeObject, $*Builtin.NativeObject
@@ -69,12 +73,12 @@
sil @opaque_function : $@convention(thin) () -> ()
// CHECK-LABEL: sil @copy_value_destroy_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
-// CHECK: bb0([[ARG1:%.*]] : $Builtin.NativeObject):
+// CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject):
// CHECK: strong_retain [[ARG1]]
// CHECK: strong_release [[ARG1]]
// CHECK: return [[ARG1]]
sil @copy_value_destroy_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
-bb0(%0 : $Builtin.NativeObject):
+bb0(%0 : @owned $Builtin.NativeObject):
%1 = function_ref @opaque_function : $@convention(thin) () -> ()
%2 = copy_value %0 : $Builtin.NativeObject
apply %1() : $@convention(thin) () -> ()
@@ -83,28 +87,30 @@
}
// CHECK-LABEL: sil @begin_borrow_store_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
-// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
+// CHECK: bb0([[ARG:%.*]] : @owned $Builtin.NativeObject):
// CHECK-NEXT: [[MEM:%.*]] = alloc_stack $Builtin.NativeObject
// CHECK-NEXT: store [[ARG]] to [[MEM]] : $*Builtin.NativeObject
// CHECK-NEXT: dealloc_stack [[MEM]] : $*Builtin.NativeObject
+// CHECK-NEXT: strong_release [[ARG]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'begin_borrow_store_borrow'
sil @begin_borrow_store_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
-bb0(%0 : $Builtin.NativeObject):
+bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
%2 = alloc_stack $Builtin.NativeObject
- store_borrow %0 to %2 : $*Builtin.NativeObject
- end_borrow %2 from %0 : $*Builtin.NativeObject, $Builtin.NativeObject
+ %3 = begin_borrow %0 : $Builtin.NativeObject
+ store_borrow %3 to %2 : $*Builtin.NativeObject
+ end_borrow %3 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
dealloc_stack %2 : $*Builtin.NativeObject
-
+ destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @copy_unowned_value_test : $@convention(thin) (@owned @sil_unowned Builtin.NativeObject) -> () {
-// CHECK: bb0([[ARG:%.*]] : $@sil_unowned Builtin.NativeObject):
+// CHECK: bb0([[ARG:%.*]] : @owned $@sil_unowned Builtin.NativeObject):
// CHECK-NEXT: strong_retain_unowned [[ARG]] : $@sil_unowned Builtin.NativeObject
// CHECK-NEXT: [[OWNED_ARG:%.*]] = unowned_to_ref [[ARG]] : $@sil_unowned Builtin.NativeObject to $Builtin.NativeObject
// CHECK-NEXT: strong_release [[OWNED_ARG]] : $Builtin.NativeObject
@@ -112,7 +118,7 @@
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
sil @copy_unowned_value_test : $@convention(thin) (@owned @sil_unowned Builtin.NativeObject) -> () {
-bb0(%0 : $@sil_unowned Builtin.NativeObject):
+bb0(%0 : @owned $@sil_unowned Builtin.NativeObject):
%1 = copy_unowned_value %0 : $@sil_unowned Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
destroy_value %0 : $@sil_unowned Builtin.NativeObject
@@ -121,14 +127,14 @@
}
// CHECK-LABEL: sil @unmanaged_retain_release_test : $@convention(thin) (@owned Builtin.NativeObject, @owned C) -> () {
-// CHECK: bb0([[ARG1:%.*]] : $Builtin.NativeObject, [[ARG2:%.*]] : $C):
+// CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $C):
// CHECK: strong_retain [[ARG1]] : $Builtin.NativeObject
// CHECK: autorelease_value [[ARG2]] : $C
// CHECK: strong_release [[ARG1]] : $Builtin.NativeObject
// CHECK: strong_release [[ARG1]] : $Builtin.NativeObject
// CHECK: } // end sil function 'unmanaged_retain_release_test'
sil @unmanaged_retain_release_test : $@convention(thin) (@owned Builtin.NativeObject, @owned C) -> () {
-bb0(%0 : $Builtin.NativeObject, %1 : $C):
+bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $C):
unmanaged_retain_value %0 : $Builtin.NativeObject
unmanaged_autorelease_value %1 : $C
br bb1
@@ -136,6 +142,35 @@
bb1:
unmanaged_release_value %0 : $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
+ destroy_value %1 : $C
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @checked_cast_br_lowered : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] : @owned $Builtin.NativeObject):
+// CHECK: checked_cast_br [[ARG]] : $Builtin.NativeObject to $C, [[SUCCBB:bb[0-9]+]], [[FAILBB:bb[0-9]+]]
+//
+// CHECK: [[SUCCBB]]([[CASTED_VALUE:%.*]] : @owned $C):
+// CHECK-NEXT: strong_release [[CASTED_VALUE]]
+// CHECK-NEXT: br bb3
+//
+// CHECK: [[FAILBB]]:
+// CHECK-NEXT: strong_release [[ARG]]
+// CHECK-NEXT: br bb3
+sil @checked_cast_br_lowered : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+ checked_cast_br %0 : $Builtin.NativeObject to $C, bb1, bb2
+
+bb1(%1 : @owned $C):
+ destroy_value %1 : $C
+ br bb3
+
+bb2(%2 : @owned $Builtin.NativeObject):
+ destroy_value %2 : $Builtin.NativeObject
+ br bb3
+
+bb3:
%9999 = tuple()
return %9999 : $()
}
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 47ac926..2b31c1a 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -1969,34 +1969,6 @@
init()
}
-// CHECK-LABEL: sil @remove_release_objc_metatype_to_object
-// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
-sil @remove_release_objc_metatype_to_object : $@convention(thin) () -> () {
-bb0:
- %0 = metatype $@thick XXImpl.Type // user: %1
- %1 = thick_to_objc_metatype %0 : $@thick XXImpl.Type to $@objc_metatype XXImpl.Type // user: %2
- %2 = objc_metatype_to_object %1 : $@objc_metatype XXImpl.Type to $AnyObject // users: %3, %4
- debug_value %2 : $AnyObject // id: %3
- strong_release %2 : $AnyObject // id: %4
- %5 = tuple () // user: %6
- return %5 : $() // id: %6
-}
-
-// CHECK-LABEL: sil @remove_release_objc_existential_metatype_to_object
-// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
-sil @remove_release_objc_existential_metatype_to_object: $@convention(thin) (@owned XX) -> () {
-bb0(%0 : $XX):
- debug_value %0 : $XX // id: %1
- %2 = existential_metatype $@thick XX.Type, %0 : $XX // user: %3
- %3 = thick_to_objc_metatype %2 : $@thick XX.Type to $@objc_metatype XX.Type // user: %4
- %4 = objc_existential_metatype_to_object %3 : $@objc_metatype XX.Type to $AnyObject // users: %5, %6
- debug_value %4 : $AnyObject, let, name "obj1" // id: %5
- strong_release %4 : $AnyObject // id: %6
- strong_release %0 : $XX // id: %7
- %8 = tuple () // user: %9
- return %8 : $() // id: %9
-}
-
// CHECK-LABEL: sil @unowned_round_trips : $@convention(thin) (B, @sil_unowned B, AnyObject, @sil_unmanaged AnyObject) -> (B, @sil_unowned B, AnyObject, @sil_unmanaged AnyObject) {
// CHECK: bb0(
// CHECK-NEXT: tuple
diff --git a/test/SILOptimizer/sil_combine_objc.sil b/test/SILOptimizer/sil_combine_objc.sil
index e631e6d..ed1e877 100644
--- a/test/SILOptimizer/sil_combine_objc.sil
+++ b/test/SILOptimizer/sil_combine_objc.sil
@@ -151,3 +151,39 @@
return %4 : $Int
}
+@objc(XX) protocol XX {
+}
+
+class XXImpl : XX {
+ @objc deinit
+ init()
+}
+
+// CHECK-LABEL: sil @remove_release_objc_metatype_to_object
+// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
+sil @remove_release_objc_metatype_to_object : $@convention(thin) () -> () {
+bb0:
+ %0 = metatype $@thick XXImpl.Type // user: %1
+ %1 = thick_to_objc_metatype %0 : $@thick XXImpl.Type to $@objc_metatype XXImpl.Type // user: %2
+ %2 = objc_metatype_to_object %1 : $@objc_metatype XXImpl.Type to $AnyObject // users: %3, %4
+ debug_value %2 : $AnyObject // id: %3
+ strong_release %2 : $AnyObject // id: %4
+ %5 = tuple () // user: %6
+ return %5 : $() // id: %6
+}
+
+// CHECK-LABEL: sil @remove_release_objc_existential_metatype_to_object
+// CHECK-NOT: strong_release {{%[0-9]+}} : $AnyObject
+sil @remove_release_objc_existential_metatype_to_object: $@convention(thin) (@owned XX) -> () {
+bb0(%0 : $XX):
+ debug_value %0 : $XX // id: %1
+ %2 = existential_metatype $@thick XX.Type, %0 : $XX // user: %3
+ %3 = thick_to_objc_metatype %2 : $@thick XX.Type to $@objc_metatype XX.Type // user: %4
+ %4 = objc_existential_metatype_to_object %3 : $@objc_metatype XX.Type to $AnyObject // users: %5, %6
+ debug_value %4 : $AnyObject, let, name "obj1" // id: %5
+ strong_release %4 : $AnyObject // id: %6
+ strong_release %0 : $XX // id: %7
+ %8 = tuple () // user: %9
+ return %8 : $() // id: %9
+}
+
diff --git a/test/Sema/circular_decl_checking.swift b/test/Sema/circular_decl_checking.swift
index 28998c9..1e556fb 100644
--- a/test/Sema/circular_decl_checking.swift
+++ b/test/Sema/circular_decl_checking.swift
@@ -44,9 +44,8 @@
protocol AProtocol {
+ // FIXME: Should produce an error here, but it's currently causing problems.
associatedtype e : e
- // expected-error@-1 {{type 'e' references itself}}
- // expected-note@-2 {{type declared here}}
}
diff --git a/test/Serialization/Inputs/alias.swift b/test/Serialization/Inputs/alias.swift
index eff05c2..6786981 100644
--- a/test/Serialization/Inputs/alias.swift
+++ b/test/Serialization/Inputs/alias.swift
@@ -26,3 +26,8 @@
}
}
public typealias BaseAlias = Base
+
+public protocol ProtoWrapper {}
+extension ProtoWrapper {
+ public typealias Boolean = Bool
+}
diff --git a/test/Serialization/Inputs/has_xref.swift b/test/Serialization/Inputs/has_xref.swift
index 46d3759..48aa625 100644
--- a/test/Serialization/Inputs/has_xref.swift
+++ b/test/Serialization/Inputs/has_xref.swift
@@ -3,6 +3,7 @@
public func numeric(_ x: MyInt64) {}
public func conditional(_ x: AliasWrapper.Boolean) {}
+public func conditional2(_ x: ProtoWrapper.Boolean) {}
public func longInt(_ x: Int.EspeciallyMagicalInt) {}
public func numericArray(_ x: IntSlice) {}
diff --git a/test/Serialization/xref.swift b/test/Serialization/xref.swift
index db2c249..547976d 100644
--- a/test/Serialization/xref.swift
+++ b/test/Serialization/xref.swift
@@ -14,6 +14,7 @@
numeric(42)
conditional(true)
+conditional2(true)
longInt(42)
numericArray([42])
diff --git a/test/attr/attr_specialize.swift b/test/attr/attr_specialize.swift
index 32b2fd9..83438fc 100644
--- a/test/attr/attr_specialize.swift
+++ b/test/attr/attr_specialize.swift
@@ -50,6 +50,7 @@
@_specialize(where T == Int)
@_specialize(where T == T) // expected-error{{Only concrete type same-type requirements are supported by '_specialize' attribute}}
@_specialize(where T == S<T>) // expected-error{{Only concrete type same-type requirements are supported by '_specialize' attribute}}
+ // expected-error@-1{{same-type constraint 'T' == 'S<T>' is recursive}}
@_specialize(where T == Int, U == Int) // expected-error{{use of undeclared type 'U'}}
func noGenericParams() {}
@@ -115,6 +116,8 @@
@_specialize(where X:_Trivial(8), Y == Int)
@_specialize(where X == Int, Y == Int)
@_specialize(where X == Int, X == Int) // expected-error{{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'Y' in '_specialize' attribute}}
+// expected-warning@-1{{redundant same-type constraint 'X' == 'Int'}}
+// expected-note@-2{{same-type constraint 'X' == 'Int' written here}}
@_specialize(where Y:_Trivial(32), X == Float)
@_specialize(where X1 == Int, Y1 == Int) // expected-error{{use of undeclared type 'X1'}} expected-error{{use of undeclared type 'Y1'}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 0, but expected 2)}} expected-error{{Missing constraint for 'X' in '_specialize' attribute}} expected-error{{Missing constraint for 'Y' in '_specialize' attribute}}
public func funcWithTwoGenericParameters<X, Y>(x: X, y: Y) {
diff --git a/test/decl/inherit/inherit.swift b/test/decl/inherit/inherit.swift
index 05e9069..5c45988 100644
--- a/test/decl/inherit/inherit.swift
+++ b/test/decl/inherit/inherit.swift
@@ -30,11 +30,15 @@
// Protocol composition in inheritance clauses
struct S3 : P, P & Q { } // expected-error {{duplicate inheritance from 'P'}}
// expected-error @-1 {{protocol composition is neither allowed nor needed here}}
+ // expected-error @-2 {{'Q' requires that 'S3' inherit from 'A'}}
+ // expected-note @-3 {{requirement specified as 'Self' : 'A' [with Self = S3]}}
struct S4 : P, P { } // expected-error {{duplicate inheritance from 'P'}}
struct S6 : P & { } // expected-error {{expected identifier for type name}}
// expected-error @-1 {{protocol composition is neither allowed nor needed here}}
struct S7 : protocol<P, Q> { } // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
// expected-error @-1 {{protocol composition is neither allowed nor needed here}}{{13-22=}} {{26-27=}}
+ // expected-error @-2 {{'Q' requires that 'S7' inherit from 'A'}}
+ // expected-note @-3 {{requirement specified as 'Self' : 'A' [with Self = S7]}}
class GenericBase<T> {}
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index a57bba5..f82826b 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -36,7 +36,7 @@
v1.creator = "Me" // expected-error {{cannot assign to property: 'creator' is a get-only property}}
}
-protocol Bogus : Int {} // expected-error{{inheritance from non-protocol type 'Int'}}
+protocol Bogus : Int {} // expected-error{{inheritance from non-protocol, non-class type 'Int'}}
// Explicit conformance checks (successful).
diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift
index d559d82..5b61cb1 100644
--- a/test/decl/protocol/req/recursion.swift
+++ b/test/decl/protocol/req/recursion.swift
@@ -20,17 +20,18 @@
// expected-note@-1{{type declared here}}
// expected-note@-2{{protocol requires nested type 'Z'; do you want to add it?}}
- associatedtype Z2 = Z3 // expected-note{{type declared here}}
+ associatedtype Z2 = Z3
// expected-note@-1{{protocol requires nested type 'Z2'; do you want to add it?}}
- associatedtype Z3 = Z2 // expected-error{{associated type 'Z2' references itself}}
+ associatedtype Z3 = Z2
// expected-note@-1{{protocol requires nested type 'Z3'; do you want to add it?}}
- associatedtype Z4 = Self.Z4 // expected-error{{associated type 'Z4' is not a member type of 'Self'}}
- // expected-note@-1{{protocol requires nested type 'Z4'; do you want to add it?}}
+ associatedtype Z4 = Self.Z4 // expected-error{{associated type 'Z4' references itself}}
+ // expected-note@-1{{type declared here}}
+ // expected-note@-2{{protocol requires nested type 'Z4'; do you want to add it?}}
associatedtype Z5 = Self.Z6
// expected-note@-1{{protocol requires nested type 'Z5'; do you want to add it?}}
- associatedtype Z6 = Self.Z5 // expected-error{{associated type 'Z5' is not a member type of 'Self'}}
+ associatedtype Z6 = Self.Z5
// expected-note@-1{{protocol requires nested type 'Z6'; do you want to add it?}}
}
diff --git a/test/expr/capture/noescape-error.swift b/test/expr/capture/noescape-error.swift
new file mode 100644
index 0000000..448d20a
--- /dev/null
+++ b/test/expr/capture/noescape-error.swift
@@ -0,0 +1,11 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+class C {}
+class D {}
+
+func f1(f : (inout Int) -> ()) {}
+
+func f2(f : (inout Any) -> ()) {
+ // TODO: Error here is still pretty bad...
+ f1 { f(&$0) } // expected-error{{conversion from 'Int' to 'Any'}}
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index a7f618b..dd05346 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -465,6 +465,9 @@
config.available_features.add("OS=" + run_os)
config.available_features.add("PTRSIZE=" + run_ptrsize)
+if run_cpu == "i386" or run_cpu == "x86_64":
+ config.available_features.add("CPU=i386_or_x86_64")
+
config.available_features.add("SWIFT_VERSION=" + swift_version)
if "optimized_stdlib" in config.available_features:
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index dc33f68..0184045 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -68,6 +68,9 @@
if "@SWIFT_STDLIB_ENABLE_RESILIENCE@" == "TRUE":
config.available_features.add("resilient_stdlib")
+if "@SWIFT_STDLIB_USE_NONATOMIC_RC@" == "TRUE":
+ config.available_features.add("nonatomic_rc")
+
if "@SWIFT_HAVE_WORKING_STD_REGEX@" == "FALSE":
config.available_features.add('broken_std_regex')
diff --git a/test/stdlib/CommandLine.swift b/test/stdlib/CommandLine.swift
index cfbfa55..6b0e851 100644
--- a/test/stdlib/CommandLine.swift
+++ b/test/stdlib/CommandLine.swift
@@ -7,6 +7,7 @@
// RUN: %target-build-swift %t/CommandLineStressTest.o %t/CommandLineStressTestSwift.o -o %t/CommandLineStressTest
// RUN: %target-run %t/CommandLineStressTest foo bar baz qux quux corge grault garply waldo fred plugh xyzzy and thud
// REQUIRES: executable_test
+// UNSUPPORTED: nonatomic_rc
// This file is an empty stub to call into the command line stress test which
// houses `main`.
diff --git a/test/stdlib/DispatchDeprecationWatchOS.swift b/test/stdlib/DispatchDeprecationWatchOS.swift
index 3341bb3..bbc5fc6 100644
--- a/test/stdlib/DispatchDeprecationWatchOS.swift
+++ b/test/stdlib/DispatchDeprecationWatchOS.swift
@@ -1,5 +1,5 @@
// RUN: %swift -typecheck -target i386-apple-watchos2.0 -verify -sdk %sdk %s
-// REQUIRES: OS=watchos
+// REQUIRES: CPU=i386, OS=watchos
// REQUIRES: objc_interop
import Foundation
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 97954b7..4d106bb 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -991,9 +991,7 @@
DataTests.test("test_repeatingValueInitialization") { TestData().test_repeatingValueInitialization() }
// XCTest does not have a crash detection, whereas lit does
-DataTests.test("bounding failure subdata")
- .skip(.always("fails with resilient stdlib (rdar://problem/30560514)"))
- .code {
+DataTests.test("bounding failure subdata") {
let data = "Hello World".data(using: .utf8)!
expectCrashLater()
let c = data.subdata(in: 5..<200)
@@ -1051,7 +1049,9 @@
data.append("hello", count: Int.min)
}
-DataTests.test("bounding failure subscript") {
+DataTests.test("bounding failure subscript")
+ .skip(.always("fails with resilient stdlib (rdar://problem/30560514)"))
+ .code {
var data = "Hello World".data(using: .utf8)!
expectCrashLater()
data[100] = 4
diff --git a/test/stmt/Inputs/Foundation-with-NSError.swift b/test/stmt/Inputs/Foundation-with-NSError.swift
new file mode 100644
index 0000000..0005b24
--- /dev/null
+++ b/test/stmt/Inputs/Foundation-with-NSError.swift
@@ -0,0 +1 @@
+public class NSError: Error {}
diff --git a/test/stmt/errors_nonobjc.swift b/test/stmt/errors_nonobjc.swift
new file mode 100644
index 0000000..2c3369d
--- /dev/null
+++ b/test/stmt/errors_nonobjc.swift
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: %target-swift-frontend -emit-module -module-name Foundation -o %t/Foundation.swiftmodule %S/Inputs/Foundation-with-NSError.swift
+// RUN: %target-swift-frontend -I %t -typecheck -verify %s
+// UNSUPPORTED: objc_interop
+
+import Foundation
+
+// Catching `as NSError` ought *not* to be exhaustive when ObjC interop is
+// disabled. It's just another error type.
+
+func bar() throws {}
+
+func foo() {
+ do {
+ try bar() // expected-error{{enclosing catch is not exhaustive}}
+ } catch _ as NSError {
+ }
+}
diff --git a/test/stmt/errors_objc.swift b/test/stmt/errors_objc.swift
new file mode 100644
index 0000000..42caa10
--- /dev/null
+++ b/test/stmt/errors_objc.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
+// REQUIRES: objc_interop
+
+import Foundation
+
+// Catching `as NSError` ought to be exhaustive when ObjC interop is enabled.
+func bar() throws {}
+
+func foo() {
+ do {
+ try bar()
+ } catch _ as NSError {
+ }
+}
diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift
index b33944c..f927ee7 100644
--- a/test/stmt/statements.swift
+++ b/test/stmt/statements.swift
@@ -247,7 +247,7 @@
func brokenSwitch(_ x: Int) -> Int {
switch x {
- case .Blah(var rep): // expected-error{{enum case 'Blah' not found in type 'Int'}}
+ case .Blah(var rep): // expected-error{{pattern cannot match values of type 'Int'}}
return rep
}
}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
index 8e3d9aa..f9256f0 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
@@ -65,6 +65,8 @@
}
Action startSourceEntity(const IndexSymbol &symbol) override {
+ if (symbol.symInfo.Kind == SymbolKind::Parameter)
+ return Skip;
// report any parent relations to this reference
if (symbol.roles & (SymbolRoleSet)SymbolRole::RelationBaseOf) {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 31e8986..765dd8e 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -724,8 +724,6 @@
DelayedStringRetriever OverUSRsStream(SS);
- SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs;
-
ide::walkOverriddenDecls(VD,
[&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) {
OverUSRsStream.startPiece();
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index 03ac94c..12a4da6 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -240,6 +240,8 @@
Invocation.getLangOptions().DisableAvailabilityChecking = true;
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
+ Invocation.getLangOptions().EnableObjCInterop =
+ llvm::Triple(Target).isOSDarwin();
Invocation.getLangOptions().ASTVerifierProcessCount =
ASTVerifierProcessCount;
diff --git a/tools/swift-syntax-format/swift-syntax-format.cpp b/tools/swift-syntax-format/swift-syntax-format.cpp
index 5ceed50..4d41650 100644
--- a/tools/swift-syntax-format/swift-syntax-format.cpp
+++ b/tools/swift-syntax-format/swift-syntax-format.cpp
@@ -1,4 +1,4 @@
-//===--- swift-syntax-test.cpp - Reflection Syntax testing application ----===//
+//===--- swift-syntax-format.cpp - Reflection Syntax testing application --===//
//
// This source file is part of the Swift.org open source project
//
diff --git a/unittests/Syntax/CMakeLists.txt b/unittests/Syntax/CMakeLists.txt
index bdb109f..d812d93 100644
--- a/unittests/Syntax/CMakeLists.txt
+++ b/unittests/Syntax/CMakeLists.txt
@@ -6,7 +6,9 @@
StmtSyntaxTests.cpp
ThreadSafeCachingTests.cpp
TriviaTests.cpp
- TypeSyntaxTests.cpp)
+ TypeSyntaxTests.cpp
+ UnknownSyntaxTests.cpp
+ )
target_link_libraries(SwiftSyntaxTests
swiftSyntax)
diff --git a/unittests/Syntax/ExprSyntaxTests.cpp b/unittests/Syntax/ExprSyntaxTests.cpp
index 4be2a07..ae95b65 100644
--- a/unittests/Syntax/ExprSyntaxTests.cpp
+++ b/unittests/Syntax/ExprSyntaxTests.cpp
@@ -9,3 +9,480 @@
#pragma mark - integer-literal-expression
// TODO
+
+#pragma mark - symbolic-reference
+
+TEST(ExprSyntaxTests, SymbolicReferenceExprGetAPIs) {
+ {
+ auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
+ auto IntType = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+ GenericArgumentClauseBuilder ArgBuilder;
+ ArgBuilder
+ .useLeftAngleBracket(SyntaxFactory::makeLeftAngleToken({}, {}))
+ .useRightAngleBracket(SyntaxFactory::makeRightAngleToken({}, {}))
+ .addGenericArgument(llvm::None, IntType);
+
+ auto GenericArgs = ArgBuilder.build();
+
+ auto Ref = SyntaxFactory::makeSymbolicReferenceExpr(Array, GenericArgs);
+
+ ASSERT_EQ(Ref.getIdentifier(), Array);
+
+ auto GottenArgs = Ref.getGenericArgumentClause().getValue();
+ auto GottenArgs2 = Ref.getGenericArgumentClause().getValue();
+ ASSERT_TRUE(GottenArgs.hasSameIdentityAs(GottenArgs2));
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ GottenArgs.print(OS);
+ ASSERT_EQ(OS.str().str(), "<Int>");
+ }
+ }
+}
+
+TEST(ExprSyntaxTests, SymbolicReferenceExprMakeAPIs) {
+ auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
+ auto IntType = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+ GenericArgumentClauseBuilder ArgBuilder;
+ ArgBuilder
+ .useLeftAngleBracket(SyntaxFactory::makeLeftAngleToken({}, {}))
+ .useRightAngleBracket(SyntaxFactory::makeRightAngleToken({}, {}))
+ .addGenericArgument(llvm::None, IntType);
+ auto GenericArgs = ArgBuilder.build();
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankSymbolicReferenceExpr().print(OS);
+ EXPECT_EQ(OS.str().str(), "");
+ }
+
+ {
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto BlankArgs = SyntaxFactory::makeBlankGenericArgumentClause();
+
+ SyntaxFactory::makeSymbolicReferenceExpr(Foo, BlankArgs).print(OS);
+ EXPECT_EQ(OS.str().str(), "foo");
+ }
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeSymbolicReferenceExpr(Array, GenericArgs).print(OS);
+ ASSERT_EQ(OS.str().str(), "Array<Int>");
+ }
+}
+
+TEST(ExprSyntaxTests, SymbolicReferenceExprWithAPIs) {
+ auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
+ auto IntType = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+ GenericArgumentClauseBuilder ArgBuilder;
+ ArgBuilder
+ .useLeftAngleBracket(SyntaxFactory::makeLeftAngleToken({}, {}))
+ .useRightAngleBracket(SyntaxFactory::makeRightAngleToken({}, {}))
+ .addGenericArgument(llvm::None, IntType);
+ auto GenericArgs = ArgBuilder.build();
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankSymbolicReferenceExpr()
+ .withIdentifier(Array)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "Array");
+ }
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankSymbolicReferenceExpr()
+ .withGenericArgumentClause(GenericArgs)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "<Int>");
+ }
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankSymbolicReferenceExpr()
+ .withIdentifier(Array)
+ .withGenericArgumentClause(GenericArgs)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "Array<Int>");
+ }
+}
+
+#pragma mark - function-call-argument
+
+TEST(ExprSyntaxTests, FunctionCallArgumentGetAPIs) {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+
+ {
+ auto Arg = SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef,
+ Comma);
+
+ ASSERT_EQ(X, Arg.getLabel());
+ ASSERT_EQ(Colon, Arg.getColonToken());
+
+ auto GottenExpr = Arg.getExpression().getValue();
+ auto GottenExpr2 = Arg.getExpression().getValue();
+ ASSERT_TRUE(GottenExpr.hasSameIdentityAs(GottenExpr2));
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ GottenExpr.print(OS);
+ ASSERT_EQ("foo", OS.str().str());
+
+ ASSERT_EQ(Comma, Arg.getTrailingComma());
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallArgumentMakeAPIs) {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallArgument().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallArgument()
+ .withExpression(SymbolicRef).print(OS);
+ ASSERT_EQ(OS.str().str(), "foo");
+ }
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef, Comma)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, ");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallArgumentWithAPIs) {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+
+ {
+ llvm::SmallString<48> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallArgument()
+ .withLabel(X)
+ .withColonToken(Colon)
+ .withExpression(SymbolicRef)
+ .withTrailingComma(Comma)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, ");
+ }
+}
+
+#pragma mark - function-call-argument-list
+
+namespace {
+FunctionCallArgumentListSyntax getFullArgumentList() {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Y = SyntaxFactory::makeIdentifier("y", {}, {});
+ auto Z = SyntaxFactory::makeIdentifier("z", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+
+ auto Arg = SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef,
+ Comma);
+
+ return SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .withAdditionalArgument(Arg)
+ .withAdditionalArgument(Arg.withLabel(Y))
+ .withAdditionalArgument(Arg.withLabel(Z).withTrailingComma(NoComma));
+}
+
+FunctionCallArgumentListSyntax getLabellessArgumentList() {
+ auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto TwoDigits = SyntaxFactory::makeIntegerLiteralToken("2", {}, {});
+ auto ThreeDigits = SyntaxFactory::makeIntegerLiteralToken("3", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+ auto NoLabel = TokenSyntax::missingToken(tok::identifier, "");
+ auto NoColon = TokenSyntax::missingToken(tok::colon, ":");
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto Two = SyntaxFactory::makeIntegerLiteralExpr(NoSign, TwoDigits);
+ auto Three = SyntaxFactory::makeIntegerLiteralExpr(NoSign, ThreeDigits);
+
+ auto OneArg = SyntaxFactory::makeFunctionCallArgument(NoLabel, NoColon, One,
+ Comma);
+ auto TwoArg = SyntaxFactory::makeFunctionCallArgument(NoLabel, NoColon, Two,
+ Comma);
+ auto ThreeArg = SyntaxFactory::makeFunctionCallArgument(NoLabel, NoColon,
+ Three, NoComma);
+
+ return SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .withAdditionalArgument(OneArg)
+ .withAdditionalArgument(TwoArg)
+ .withAdditionalArgument(ThreeArg);
+}
+}
+
+TEST(ExprSyntaxTests, FunctionCallArgumentListGetAPIs) {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Y = SyntaxFactory::makeIdentifier("y", {}, {});
+ auto Z = SyntaxFactory::makeIdentifier("z", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+
+ auto Arg = SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef,
+ Comma);
+
+ auto ArgList = SyntaxFactory::makeBlankFunctionCallArgumentList()
+ .withAdditionalArgument(Arg)
+ .withAdditionalArgument(Arg.withLabel(Y))
+ .withAdditionalArgument(Arg.withLabel(Z).withTrailingComma(NoComma));
+
+ ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+
+ {
+ llvm::SmallString<16> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenArg1 = ArgList.getArgument(0);
+ auto GottenArg1_2 = ArgList.getArgument(0);
+ ASSERT_TRUE(GottenArg1.hasSameIdentityAs(GottenArg1_2));
+ GottenArg1.print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, ");
+ }
+
+ {
+ llvm::SmallString<16> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenArg2 = ArgList.getArgument(1);
+ auto GottenArg2_2 = ArgList.getArgument(1);
+ ASSERT_TRUE(GottenArg2.hasSameIdentityAs(GottenArg2_2));
+ GottenArg2.print(OS);
+ ASSERT_EQ(OS.str().str(), "y: foo, ");
+ }
+
+ {
+ llvm::SmallString<16> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto GottenArg3 = ArgList.getArgument(2);
+ auto GottenArg3_2 = ArgList.getArgument(2);
+ ASSERT_TRUE(GottenArg3.hasSameIdentityAs(GottenArg3_2));
+ GottenArg3.print(OS);
+ ASSERT_EQ(OS.str().str(), "z: foo");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallArgumentListMakeAPIs) {
+ {
+ llvm::SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallArgumentList().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+ {
+ auto X = SyntaxFactory::makeIdentifier("x", {}, {});
+ auto Y = SyntaxFactory::makeIdentifier("y", {}, {});
+ auto Z = SyntaxFactory::makeIdentifier("z", {}, {});
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo,
+ llvm::None);
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+
+ auto Arg = SyntaxFactory::makeFunctionCallArgument(X, Colon, SymbolicRef,
+ Comma);
+
+ std::vector<FunctionCallArgumentSyntax> Args {
+ Arg, Arg.withLabel(Y), Arg.withLabel(Z).withTrailingComma(NoComma)
+ };
+
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ auto ArgList = SyntaxFactory::makeFunctionCallArgumentList(Args);
+ ArgList.print(OS);
+ ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(OS.str().str(), "x: foo, y: foo, z: foo");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallArgumentListWithAPIs) {
+ auto ArgList = getFullArgumentList();
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ArgList.print(OS);
+ ASSERT_EQ(ArgList.getNumArguments(), size_t(3));
+ ASSERT_EQ(OS.str().str(), "x: foo, y: foo, z: foo");
+}
+
+#pragma mark - function-call-expression
+
+TEST(ExprSyntaxTests, FunctionCallExprGetAPIs) {
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto ArgList = getFullArgumentList();
+ auto RightParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ auto Call = SyntaxFactory::makeFunctionCallExpr(SymbolicRef, LeftParen,
+ ArgList, RightParen);
+
+ {
+ auto GottenExpression1 = Call.getCalledExpression();
+ auto GottenExpression2 = Call.getCalledExpression();
+ ASSERT_TRUE(GottenExpression1.hasSameIdentityAs(GottenExpression2));
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ GottenExpression1.print(OS);
+ ASSERT_EQ(OS.str().str(), "foo");
+ }
+
+ ASSERT_EQ(LeftParen, Call.getLeftParen());
+ ASSERT_EQ(RightParen, Call.getRightParen());
+
+ {
+ auto GottenArgs1 = Call.getArgumentList();
+ auto GottenArgs2 = Call.getArgumentList();
+ ASSERT_TRUE(GottenArgs1.hasSameIdentityAs(GottenArgs2));
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ GottenArgs1.print(OS);
+ ASSERT_EQ(OS.str().str(), "x: foo, y: foo, z: foo");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallExprMakeAPIs) {
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto ArgList = getFullArgumentList();
+ auto RightParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ {
+ auto Call = SyntaxFactory::makeFunctionCallExpr(SymbolicRef, LeftParen,
+ ArgList, RightParen);
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ Call.print(OS);
+ ASSERT_EQ(OS.str().str(), "foo(x: foo, y: foo, z: foo)");
+ }
+
+ {
+ llvm::SmallString<1> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallExpr().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallExprWithAPIs) {
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+ auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto ArgList = getFullArgumentList();
+ auto RightParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallExpr()
+ .withCalledExpression(SymbolicRef)
+ .withLeftParen(LeftParen)
+ .withRightParen(RightParen)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "foo()");
+ }
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ SyntaxFactory::makeBlankFunctionCallExpr()
+ .withCalledExpression(SymbolicRef)
+ .withLeftParen(LeftParen)
+ .withArgumentList(getLabellessArgumentList())
+ .withRightParen(RightParen)
+ .print(OS);
+ ASSERT_EQ(OS.str().str(), "foo(1, 2, 3)");
+ }
+}
+
+TEST(ExprSyntaxTests, FunctionCallExprBuilderAPIs) {
+ FunctionCallExprSyntaxBuilder CallBuilder;
+
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ CallBuilder.build().print(OS);
+ ASSERT_EQ(OS.str().str(), "");
+ }
+
+ auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto RightParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ CallBuilder.useLeftParen(LeftParen);
+ CallBuilder.useRightParen(RightParen);
+ CallBuilder.build().print(OS);
+ ASSERT_EQ(OS.str().str(), "()");
+ }
+
+ auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto TwoDigits = SyntaxFactory::makeIntegerLiteralToken("2", {}, {});
+ auto ThreeDigits = SyntaxFactory::makeIntegerLiteralToken("3", {}, {});
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+ auto NoLabel = TokenSyntax::missingToken(tok::identifier, "");
+ auto NoColon = TokenSyntax::missingToken(tok::colon, ":");
+ auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+ auto Foo = SyntaxFactory::makeIdentifier("foo", {}, {});
+ auto SymbolicRef = SyntaxFactory::makeSymbolicReferenceExpr(Foo, llvm::None);
+
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ CallBuilder.useCalledExpression(SymbolicRef);
+ CallBuilder.build().print(OS);
+ ASSERT_EQ(OS.str().str(), "foo()");
+ }
+
+ auto OneArg = SyntaxFactory::makeFunctionCallArgument(NoLabel, NoColon, One,
+ Comma);
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ CallBuilder.appendArgument(OneArg);
+ CallBuilder.build().print(OS);
+ ASSERT_EQ(OS.str().str(), "foo(1, )");
+ }
+
+ {
+ llvm::SmallString<64> Scratch;
+ llvm::raw_svector_ostream OS(Scratch);
+ CallBuilder.appendArgument(OneArg.withTrailingComma(NoComma));
+ CallBuilder.build().print(OS);
+ ASSERT_EQ(OS.str().str(), "foo(1, 1)");
+ }
+}
diff --git a/unittests/Syntax/ThreadSafeCachingTests.cpp b/unittests/Syntax/ThreadSafeCachingTests.cpp
index 9718330..d4e55b1 100644
--- a/unittests/Syntax/ThreadSafeCachingTests.cpp
+++ b/unittests/Syntax/ThreadSafeCachingTests.cpp
@@ -4,18 +4,78 @@
#include "llvm/ADT/SmallString.h"
#include "gtest/gtest.h"
+#include <future>
#include <thread>
+#include <queue>
using namespace swift;
using namespace swift::syntax;
-static void getExpressionFrom(ReturnStmtSyntax Return,
- uintptr_t *DataPointer) {
+static uintptr_t getExpressionFrom(ReturnStmtSyntax Return) {
auto Expression = Return.getExpression().getValue();
- auto Data = Expression.getDataPointer();
- *DataPointer = reinterpret_cast<uintptr_t>(Data);
+ return reinterpret_cast<uintptr_t>(Expression.getDataPointer());
}
+class Pool {
+ static constexpr size_t NumThreads = 2;
+ using FuncTy = std::function<uintptr_t(ReturnStmtSyntax)>;
+ std::vector<std::thread> Workers;
+ std::queue<std::function<void()>> Tasks;
+ std::mutex QueueLock;
+ std::condition_variable Condition;
+ bool Stop;
+
+public:
+ Pool() : Stop(false) {
+ for(size_t i = 0; i < NumThreads; ++i)
+ Workers.emplace_back([this] {
+ while (true) {
+ std::function<void()> Task;
+ {
+ std::unique_lock<std::mutex> L(QueueLock);
+
+ Condition.wait(L, [this]{
+ return Stop || !Tasks.empty();
+ });
+
+ if(Stop && Tasks.empty()) {
+ return;
+ }
+
+ Task = std::move(Tasks.front());
+ Tasks.pop();
+ }
+
+ Task();
+ }
+ });
+ }
+
+ std::future<uintptr_t> run(FuncTy Func, ReturnStmtSyntax Return) {
+ auto Task = std::make_shared<std::packaged_task<uintptr_t()>>(
+ std::bind(Func, Return));
+
+ auto Future = Task->get_future();
+ {
+ std::unique_lock<std::mutex> L(QueueLock);
+ Tasks.emplace([Task](){ (*Task)(); });
+ }
+ Condition.notify_one();
+ return Future;
+ }
+
+ ~Pool() {
+ {
+ std::lock_guard<std::mutex> L(QueueLock);
+ Stop = true;
+ }
+ Condition.notify_all();
+ for(auto &Worker : Workers) {
+ Worker.join();
+ }
+ }
+};
+
// Tests that, when multiple threads ask for a child node of the same syntax
// node:
// - Only one thread inserts the realized child into the parent
@@ -26,29 +86,22 @@
auto One = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, One);
+ Pool P;
+
for (unsigned i = 0; i < 10000; ++i) {
- llvm::SmallString<48> Scratch;
- llvm::raw_svector_ostream OS(Scratch);
auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne);
- uintptr_t FirstDataPointer;
- uintptr_t SecondDataPointer;
+ auto Future1 = P.run(getExpressionFrom, Return);
+ auto Future2 = P.run(getExpressionFrom, Return);
- std::thread first(getExpressionFrom, Return, &FirstDataPointer);
- std::thread second(getExpressionFrom, Return, &SecondDataPointer);
- first.join();
- second.join();
+ auto FirstDataPointer = Future1.get();
+ auto SecondDataPointer = Future2.get();
auto DataPointer = reinterpret_cast<uintptr_t>(
Return.getExpression().getValue().getDataPointer());
ASSERT_EQ(FirstDataPointer, SecondDataPointer);
ASSERT_EQ(FirstDataPointer, DataPointer);
-
- if (FirstDataPointer != SecondDataPointer ||
- FirstDataPointer != DataPointer) {
- break;
- }
}
}
diff --git a/unittests/Syntax/TriviaTests.cpp b/unittests/Syntax/TriviaTests.cpp
index beca54f..3890cdc 100644
--- a/unittests/Syntax/TriviaTests.cpp
+++ b/unittests/Syntax/TriviaTests.cpp
@@ -255,9 +255,9 @@
}
TEST(TriviaTests, size) {
- ASSERT_EQ(Trivia().size(), 0);
- ASSERT_EQ(Trivia::spaces(1).size(), 1);
+ ASSERT_EQ(Trivia().size(), size_t(0));
+ ASSERT_EQ(Trivia::spaces(1).size(), size_t(1));
// Trivia doesn't currently coalesce on its own.
- ASSERT_EQ((Trivia::spaces(1) + Trivia::spaces(1)).size(), 2);
+ ASSERT_EQ((Trivia::spaces(1) + Trivia::spaces(1)).size(), size_t(2));
}
diff --git a/unittests/Syntax/UnknownSyntaxTests.cpp b/unittests/Syntax/UnknownSyntaxTests.cpp
new file mode 100644
index 0000000..9173e51
--- /dev/null
+++ b/unittests/Syntax/UnknownSyntaxTests.cpp
@@ -0,0 +1,191 @@
+#include "swift/Syntax/ExprSyntax.h"
+#include "swift/Syntax/GenericSyntax.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/UnknownSyntax.h"
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+
+using llvm::None;
+using llvm::SmallString;
+
+using namespace swift;
+using namespace swift::syntax;
+
+SymbolicReferenceExprSyntax getCannedSymbolicRef() {
+ // First, make a symbolic reference to an 'Array<Int>'
+ auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
+ auto IntType = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
+ GenericArgumentClauseBuilder ArgBuilder;
+ ArgBuilder
+ .useLeftAngleBracket(SyntaxFactory::makeLeftAngleToken({}, {}))
+ .useRightAngleBracket(SyntaxFactory::makeRightAngleToken({}, {}))
+ .addGenericArgument(llvm::None, IntType);
+
+ return SyntaxFactory::makeSymbolicReferenceExpr(Array, ArgBuilder.build());
+}
+
+FunctionCallExprSyntax getCannedFunctionCall() {
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto RParen = SyntaxFactory::makeRightParenToken({}, {});
+
+ auto Label = SyntaxFactory::makeIdentifier("elements", {}, {});
+ auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
+ auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
+ auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
+ auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+ auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
+
+ auto Arg = SyntaxFactory::makeFunctionCallArgument(Label, Colon, One,
+ NoComma);
+ auto Args = SyntaxFactory::makeFunctionCallArgumentList({ Arg });
+
+ return SyntaxFactory::makeFunctionCallExpr(getCannedSymbolicRef(), LParen,
+ Args, RParen);
+}
+
+TEST(UnknownSyntaxTests, UnknownSyntaxMakeAPIs) {
+ {
+ auto SymbolicRef = getCannedSymbolicRef();
+
+ // Print the known symbolic reference. It should print as "Array<Int>".
+ SmallString<48> KnownScratch;
+ llvm::raw_svector_ostream KnownOS(KnownScratch);
+ SymbolicRef.print(KnownOS);
+ ASSERT_EQ(KnownOS.str().str(), "Array<Int>");
+
+ // Wrap that symbolic reference as an UnknownSyntax. This has the same
+ // RawSyntax layout but with the Unknown Kind.
+ auto UnknownSymbolicRefData = UnknownSyntaxData::make(SymbolicRef.getRaw());
+
+ auto Unknown = UnknownSyntax {
+ UnknownSymbolicRefData,
+ UnknownSymbolicRefData.get()
+ };
+
+ // Print the unknown syntax. It should also print as "Array<Int>".
+ SmallString<48> UnknownScratch;
+ llvm::raw_svector_ostream UnknownOS(UnknownScratch);
+ Unknown.print(UnknownOS);
+
+ ASSERT_EQ(KnownOS.str().str(), UnknownOS.str().str());
+ }
+}
+
+TEST(UnknownSyntaxTests, UnknownSyntaxGetAPIs) {
+ auto Call = getCannedFunctionCall();
+
+ // Function call child 0 -> layout child 0 -> called expression
+ {
+ // Pull the called expression from the function call, which should print
+ // as "Array<Int>"
+ SmallString<48> KnownScratch;
+ llvm::raw_svector_ostream KnownOS(KnownScratch);
+ auto GottenExpr = Call.getCalledExpression();
+ GottenExpr.print(KnownOS);
+
+ // Wrap that call as an UnknownExprSyntax. This has the same
+ // RawSyntax layout but with the UnknownExpr Kind.
+ auto UnknownCallData = UnknownExprSyntaxData::make(Call.getRaw());
+
+ auto Unknown = UnknownExprSyntax {
+ UnknownCallData,
+ UnknownCallData.get()
+ };
+
+ ASSERT_EQ(Unknown.getNumChildren(), size_t(2));
+
+ // Get the second child from the unknown call, which is the argument list.
+ // This should print the same as the known one: "elements: 1"
+ SmallString<48> UnknownScratch;
+ llvm::raw_svector_ostream UnknownOS(UnknownScratch);
+ auto ExprGottenFromUnknown = Unknown.getChild(0)
+ .castTo<SymbolicReferenceExprSyntax>();
+ ExprGottenFromUnknown.print(UnknownOS);
+
+ ASSERT_EQ(KnownOS.str().str(), UnknownOS.str().str());
+
+ auto ExprGottenFromUnknown2 = Unknown.getChild(0);
+ ASSERT_TRUE(ExprGottenFromUnknown
+ .hasSameIdentityAs(ExprGottenFromUnknown2));
+ }
+
+ // Function call child 1 -> layout child 2 -> function call argument list
+ {
+ // Pull the argument list from the function call, which should print
+ // as "elements: 1"
+ SmallString<48> KnownScratch;
+ llvm::raw_svector_ostream KnownOS(KnownScratch);
+ auto GottenArgs = Call.getArgumentList();
+ GottenArgs.print(KnownOS);
+
+ // Wrap that symbolic reference as an UnknownSyntax. This has the same
+ // RawSyntax layout but with the Unknown Kind.
+ auto UnknownCallData = UnknownSyntaxData::make(Call.getRaw());
+
+ auto Unknown = UnknownSyntax {
+ UnknownCallData,
+ UnknownCallData.get()
+ };
+
+ ASSERT_EQ(Unknown.getNumChildren(), size_t(2));
+
+ // Get the second child from the unknown call, which is the argument list.
+ // This should print the same as the known one: "elements: 1"
+ SmallString<48> UnknownScratch;
+ llvm::raw_svector_ostream UnknownOS(UnknownScratch);
+ auto ArgsGottenFromUnknown = Unknown.getChild(1)
+ .castTo<FunctionCallArgumentListSyntax>();
+ ArgsGottenFromUnknown.print(UnknownOS);
+
+ ASSERT_EQ(KnownOS.str().str(), UnknownOS.str().str());
+
+ auto ArgsGottenFromUnknown2 = Unknown.getChild(1);
+ ASSERT_TRUE(ArgsGottenFromUnknown
+ .hasSameIdentityAs(ArgsGottenFromUnknown2));
+ }
+}
+
+TEST(UnknownSyntaxTests, EmbedUnknownExpr) {
+ auto SymbolicRef = getCannedSymbolicRef();
+ auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
+ auto RParen = SyntaxFactory::makeRightParenToken({}, {});
+ auto EmptyArgs = SyntaxFactory::makeBlankFunctionCallArgumentList();
+
+ SmallString<48> KnownScratch;
+ llvm::raw_svector_ostream KnownOS(KnownScratch);
+ auto CallWithKnownExpr = SyntaxFactory::makeFunctionCallExpr(SymbolicRef,
+ LParen,
+ EmptyArgs,
+ RParen);
+ CallWithKnownExpr.print(KnownOS);
+
+ // Let's make a function call expression where the called expression is
+ // actually unknown. It should print the same and have the same structure
+ // as one with a known called expression.
+ auto UnknownSymbolicRefData =
+ UnknownExprSyntaxData::make(SymbolicRef.getRaw());
+
+ auto UnknownSymbolicRef = UnknownExprSyntax {
+ UnknownSymbolicRefData,
+ UnknownSymbolicRefData.get()
+ }.castTo<ExprSyntax>();
+
+ SmallString<48> UnknownScratch;
+ llvm::raw_svector_ostream UnknownOS(UnknownScratch);
+
+ auto CallWithUnknownExpr = CallWithKnownExpr
+ .withCalledExpression(UnknownSymbolicRef);
+
+ CallWithUnknownExpr.print(UnknownOS);
+
+ ASSERT_EQ(KnownOS.str().str(), UnknownOS.str().str());
+}
+
+TEST(UnknownSyntaxTests, EmbedUnknownDecl) {
+ // TODO
+}
+
+TEST(UnknownSyntaxTests, EmbedUnknownStmt) {
+ // TODO
+}
+
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 7ee57ad..2d5b62e 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -188,6 +188,21 @@
skip-test-tvos-host
skip-test-watchos-host
+[preset: buildbot,tools=RA,stdlib=RD,single-thread]
+mixin-preset=
+ mixin_buildbot_tools_RA_stdlib_RD
+
+dash-dash
+
+# Enable non-atomic build of the stdlib
+swift-stdlib-use-nonatomic-rc=true
+
+# Don't run host tests for iOS, tvOS and watchOS platforms to make the build
+# faster.
+skip-test-ios-host
+skip-test-tvos-host
+skip-test-watchos-host
+
[preset: buildbot,tools=R,stdlib=RD]
mixin-preset=
mixin_buildbot_tools_R_stdlib_RD
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 9f832ab..c1e12b2 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -71,6 +71,7 @@
swift-stdlib-build-type "Debug" "the CMake build variant for Swift"
swift-stdlib-enable-assertions "1" "enable assertions in Swift"
swift-stdlib-enable-resilience "0" "build the Swift stdlib and overlays with resilience enabled"
+ swift-stdlib-use-nonatomic-rc "0" "build the Swift stdlib and overlays with nonatomic reference count operations enabled"
swift-stdlib-sil-serialize-all "1" "build the Swift stdlib and overlays with all method bodies serialized"
lldb-build-type "Debug" "the CMake build variant for LLDB"
llbuild-build-type "Debug" "the CMake build variant for llbuild"
@@ -1654,6 +1655,9 @@
if [[ $(is_cmake_release_build_type "${SWIFT_BUILD_TYPE}") ]] ; then
echo -n " -fno-stack-protector"
fi
+ if [[ "$(true_false "${SWIFT_STDLIB_USE_NONATOMIC_RC}")" == "TRUE" ]]; then
+ echo -n " -DSWIFT_STDLIB_USE_NONATOMIC_RC"
+ fi
}
function cmake_config_opt() {
@@ -2113,6 +2117,7 @@
-DSWIFT_STDLIB_BUILD_TYPE:STRING="${SWIFT_STDLIB_BUILD_TYPE}"
-DSWIFT_STDLIB_ASSERTIONS:BOOL=$(true_false "${SWIFT_STDLIB_ENABLE_ASSERTIONS}")
-DSWIFT_STDLIB_ENABLE_RESILIENCE:BOOL=$(true_false "${SWIFT_STDLIB_ENABLE_RESILIENCE}")
+ -DSWIFT_STDLIB_USE_NONATOMIC_RC:BOOL=$(true_false "${SWIFT_STDLIB_USE_NONATOMIC_RC}")
-DSWIFT_STDLIB_SIL_SERIALIZE_ALL:BOOL=$(true_false "${SWIFT_STDLIB_SIL_SERIALIZE_ALL}")
-DSWIFT_NATIVE_LLVM_TOOLS_PATH:STRING="${native_llvm_tools_path}"
-DSWIFT_NATIVE_CLANG_TOOLS_PATH:STRING="${native_clang_tools_path}"
diff --git a/utils/rusage.py b/utils/rusage.py
index b2354f2..e37e359 100755
--- a/utils/rusage.py
+++ b/utils/rusage.py
@@ -91,7 +91,7 @@
args = parser.parse_args()
if len(args.remainder) == 0:
parser.print_help()
- exit(1)
+ sys.exit(1)
if args.enforce:
if args.time is not None:
diff --git a/utils/sil-mode.el b/utils/sil-mode.el
index 371d66a..6d390d0 100644
--- a/utils/sil-mode.el
+++ b/utils/sil-mode.el
@@ -51,7 +51,7 @@
font-lock-keyword-face)
;; Highlight attributes written in [...].
- '("\\[\\(.+\\)\\]" 1 font-lock-keyword-face)
+ '("\\[\\(.+?\\)\\]" 1 font-lock-keyword-face)
;; SIL Instructions - Allocation/Deallocation.
`(,(regexp-opt '("alloc_stack" "alloc_ref" "alloc_ref_dynamic" "alloc_box"
@@ -121,7 +121,8 @@
;; Protocol and Protocol Composition Types
`(,(regexp-opt '("init_existential_addr" "deinit_existential_addr"
"open_existential_addr"
- "init_existential_opaque" "open_existential_opaque"
+ "init_existential_opaque" "deinit_existential_opaque"
+ "open_existential_opaque"
"alloc_existential_box" "project_existential_box"
"open_existential_box" "dealloc_existential_box"
"init_existential_ref" "open_existential_ref"
diff --git a/utils/swift_build_support/swift_build_support/products/product.py b/utils/swift_build_support/swift_build_support/products/product.py
index f9df4a5..f3f841a 100644
--- a/utils/swift_build_support/swift_build_support/products/product.py
+++ b/utils/swift_build_support/swift_build_support/products/product.py
@@ -26,7 +26,7 @@
The name of the source code directory of this product.
It provides a customization point for Product subclasses. It is set to
- the value of product_name() by default for this reason.
+ the value of product_name() by default for this reason.
"""
return cls.product_name()
diff --git a/utils/vim/syntax/sil.vim b/utils/vim/syntax/sil.vim
index c2bad45..1aea5ad 100644
--- a/utils/vim/syntax/sil.vim
+++ b/utils/vim/syntax/sil.vim
@@ -36,7 +36,7 @@
syn keyword swiftKeyword metatype value_metatype existential_metatype skipwhite
syn keyword swiftKeyword retain_value release_value tuple tuple_extract tuple_element_addr struct struct_extract struct_element_addr ref_element_addr skipwhite
syn keyword swiftKeyword init_enum_data_addr unchecked_enum_data unchecked_take_enum_data_addr inject_enum_addr skipwhite
-syn keyword swiftKeyword init_existential_addr init_existential_opaque init_existential_metatype deinit_existential_addr open_existential_addr open_existential_box open_existential_metatype init_existential_ref open_existential_ref open_existential_opaque skipwhite
+syn keyword swiftKeyword init_existential_addr init_existential_opaque init_existential_metatype deinit_existential_addr deinit_existential_opaque open_existential_addr open_existential_box open_existential_metatype init_existential_ref open_existential_ref open_existential_opaque skipwhite
syn keyword swiftKeyword upcast address_to_pointer pointer_to_address pointer_to_thin_function unchecked_addr_cast unchecked_ref_cast unchecked_ref_cast_addr ref_to_raw_pointer ref_to_bridge_object ref_to_unmanaged unmanaged_to_ref raw_pointer_to_ref skipwhite
syn keyword swiftKeyword convert_function thick_to_objc_metatype thin_function_to_pointer objc_to_thick_metatype thin_to_thick_function is_nonnull unchecked_ref_bit_cast unchecked_trivial_bit_cast bridge_object_to_ref bridge_object_to_word unchecked_bitwise_cast skipwhite
syn keyword swiftKeyword objc_existential_metatype_to_object objc_metatype_to_object objc_protocol skipwhite
diff --git a/validation-test/BuildSystem/LTO/object-files-do-have-bitcode.test-sh b/validation-test/BuildSystem/LTO/object-files-do-have-bitcode.test-sh
index 5d76bf4..67f0c59 100755
--- a/validation-test/BuildSystem/LTO/object-files-do-have-bitcode.test-sh
+++ b/validation-test/BuildSystem/LTO/object-files-do-have-bitcode.test-sh
@@ -13,14 +13,14 @@
# REQUIRES: OS=macosx
# RUN: %s %swift_obj_root
-if [[ -n "$(find $1/lib -iname '*.cpp.o' -type f -exec file {} \; | grep -v -e bitcode -e bit-code)" ]]; then
+if find $1/lib -iname '*.cpp.o' -type f -exec file {} \; | grep -q -v -e bitcode -e bit-code; then
echo "Found a ./lib non-bitcode object file!"
exit 1
else
echo "All ./lib object files are bit-code files!"
fi
-if [[ -n "$(find $1/unittests -iname '*.cpp.o' -type f -exec file {} \; | grep -v -e bitcode -e bit-code)" ]]; then
+if find $1/unittests -iname '*.cpp.o' -type f -exec file {} \; | grep -q -v -e bitcode -e bit-code; then
echo "Found a ./unittests non-bitcode object file!"
exit 1
else
diff --git a/validation-test/BuildSystem/LTO/target-libraries-do-not-have-bitcode.test-sh b/validation-test/BuildSystem/LTO/target-libraries-do-not-have-bitcode.test-sh
index 6ce1fd8..5404295 100755
--- a/validation-test/BuildSystem/LTO/target-libraries-do-not-have-bitcode.test-sh
+++ b/validation-test/BuildSystem/LTO/target-libraries-do-not-have-bitcode.test-sh
@@ -34,7 +34,7 @@
mkdir -p "${LIB_TEMP_DIR}"
cd "${LIB_TEMP_DIR}"
ar -x ${ARCHIVE}
- if [[ -n "$(find ./ -iname '*.o' -exec file {} \; | grep -e bitcode -e bit-code)" ]]; then
+ if find ./ -iname '*.o' -exec file {} \; | grep -q -e bitcode -e bit-code; then
echo "Found bitcode file in thin archive: ${ARCHIVE}"
exit 1
else
@@ -78,7 +78,7 @@
cd ${arch}
ar -x "${LIB_ARCHIVE_DIR}/${THIN_ARCHIVE}"
- if [[ -n "$(find ./ -iname '*.o' -exec file {} \; | grep -e bitcode -e bit-code)" ]]; then
+ if find ./ -iname '*.o' -exec file {} \; | grep -q -e bitcode -e bit-code; then
echo "Found bitcode file in thin archive: ${THIN_ARCHIVE}. Taken from thick archive: ${ARCHIVE}"
exit 1
else
diff --git a/validation-test/StdlibUnittest/RaceTest.swift b/validation-test/StdlibUnittest/RaceTest.swift
index a63fd18..53c0e2c 100644
--- a/validation-test/StdlibUnittest/RaceTest.swift
+++ b/validation-test/StdlibUnittest/RaceTest.swift
@@ -1,5 +1,6 @@
// RUN: %target-build-swift -Xfrontend -disable-access-control -module-name a %s -o %t.out
// RUN: %target-run %t.out | %FileCheck %s
+// UNSUPPORTED: nonatomic_rc
import StdlibUnittest
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
diff --git a/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift b/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift
new file mode 100644
index 0000000..479b7b8
--- /dev/null
+++ b/validation-test/compiler_crashers/28702-swift-typebase-getcanonicaltype.swift
@@ -0,0 +1,9 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+{extension{func 丏(UInt=1 + 1 + 1 as?Int){a
diff --git a/validation-test/compiler_crashers/28703-swift-typebase-getdesugaredtype.swift b/validation-test/compiler_crashers/28703-swift-typebase-getdesugaredtype.swift
new file mode 100644
index 0000000..e4d7ab4
--- /dev/null
+++ b/validation-test/compiler_crashers/28703-swift-typebase-getdesugaredtype.swift
@@ -0,0 +1,9 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+func b(UInt=1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 as?Int){a
diff --git a/validation-test/compiler_crashers/28704-swift-newmangling-astmangler-appendcontext-swift-declcontext-const.swift b/validation-test/compiler_crashers/28704-swift-newmangling-astmangler-appendcontext-swift-declcontext-const.swift
new file mode 100644
index 0000000..56a136a
--- /dev/null
+++ b/validation-test/compiler_crashers/28704-swift-newmangling-astmangler-appendcontext-swift-declcontext-const.swift
@@ -0,0 +1,9 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+protocol A{var f={struct ManagedBuffer{var f=(t:f
diff --git a/validation-test/compiler_crashers/28705-swift-typebase-getcanonicaltype.swift b/validation-test/compiler_crashers/28705-swift-typebase-getcanonicaltype.swift
new file mode 100644
index 0000000..2483570
--- /dev/null
+++ b/validation-test/compiler_crashers/28705-swift-typebase-getcanonicaltype.swift
@@ -0,0 +1,13 @@
+// This source file is part of the Swift.org open source project
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+{
+struct c{}func t(UInt= 1 + 1 + 1 + 1 as?Int){
+{{
+protocol P{extension{class C:P{
+protocol defaulImplementation unon
diff --git a/validation-test/compiler_crashers_2/0074-rdar28544316.swift b/validation-test/compiler_crashers_2/0074-rdar28544316.swift
new file mode 100644
index 0000000..f967f8d
--- /dev/null
+++ b/validation-test/compiler_crashers_2/0074-rdar28544316.swift
@@ -0,0 +1,38 @@
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+// REQUIRES: asserts
+
+class PropertyDataSource<O: PropertyHosting> {
+}
+
+protocol TableViewCellFactoryType {
+ associatedtype Item
+}
+
+public protocol PropertyHosting {
+ associatedtype PType: Hashable, EntityOwned
+}
+
+public protocol EntityOwned: class {
+ associatedtype Owner
+}
+
+public protocol PropertyType: class {
+}
+
+func useType<T>(cellType: T.Type) {
+}
+
+final class PropertyTableViewAdapter<Factory: TableViewCellFactoryType>
+ where
+ Factory.Item: PropertyType,
+ Factory.Item.Owner: PropertyHosting,
+ Factory.Item.Owner.PType == Factory.Item
+{
+ typealias Item = Factory.Item
+
+ let dataManager: PropertyDataSource<Factory.Item.Owner>
+ init(dataManager: PropertyDataSource<Factory.Item.Owner>) {
+ useType(cellType: Factory.Item.Owner.self)
+ self.dataManager = dataManager
+ }
+}
diff --git a/validation-test/compiler_crashers_2/0076-sr3500.swift b/validation-test/compiler_crashers_2/0076-sr3500.swift
new file mode 100644
index 0000000..2a514fe
--- /dev/null
+++ b/validation-test/compiler_crashers_2/0076-sr3500.swift
@@ -0,0 +1,12 @@
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+
+protocol A {
+ associatedtype Coordinate: Strideable
+ func doSomething(_: Range<Coordinate>) -> Coordinate.Stride
+}
+
+extension A where Coordinate == Int {
+ func extensionFunc(_ range: Range<Coordinate>) {
+ _ = doSomething(range)
+ }
+}
diff --git a/validation-test/compiler_crashers_2/0079-rdar30354669.swift b/validation-test/compiler_crashers_2/0079-rdar30354669.swift
new file mode 100644
index 0000000..6dacf98
--- /dev/null
+++ b/validation-test/compiler_crashers_2/0079-rdar30354669.swift
@@ -0,0 +1,30 @@
+// RUN: not --crash %target-swift-frontend -primary-file %s -emit-ir
+
+public func ==<T: EquatableMetaType>(lhs: T, rhs: T) -> Bool {
+ return type(of: lhs) == type(of: lhs)
+}
+
+
+public protocol EquatableMetaType {
+}
+
+
+class Block : Equatable, EquatableMetaType {
+}
+
+extension Array where Element : Block {
+ func indexByType(of: Element) -> Array.Index? {
+ let count = self.count
+ var result: Array.Index = 0
+
+ for i in self {
+ if i == of {
+ return result
+ }
+ if result < count {
+ result += 1
+ }
+ }
+ return nil
+ }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0077-sr3884.swift b/validation-test/compiler_crashers_2_fixed/0077-sr3884.swift
new file mode 100644
index 0000000..d50643c
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0077-sr3884.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend %s -emit-ir
+
+protocol DataSourceItem { }
+
+protocol TableDataSourceItem : DataSourceItem { }
+
+
+class DataSource<T : DataSourceItem> { }
+
+class TableDataSource<T : TableDataSourceItem>: DataSource<T> { }
+
+
+class DataSourceBuilder<T : TableDataSourceItem, U : TableDataSource<T>> { }
+
+class TableDataSourceBuilder<T : TableDataSourceItem, U : TableDataSource<T>> : DataSourceBuilder<T, U> { }
+
+
+enum MyItem: TableDataSourceItem { }
+
+class MyBuilder : TableDataSourceBuilder<MyItem, TableDataSource<MyItem>> { }
+
+let builder = MyBuilder()
diff --git a/validation-test/compiler_crashers_2_fixed/0078-sr4059.swift b/validation-test/compiler_crashers_2_fixed/0078-sr4059.swift
new file mode 100644
index 0000000..a073b13
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0078-sr4059.swift
@@ -0,0 +1,9 @@
+// RUN: %target-swift-frontend %s -emit-ir
+
+class Base {
+ init<S: Sequence>(_ s: S) where S.Iterator.Element == UInt8 { }
+}
+
+class Sub: Base {
+ init(_ b: [UInt8]) { super.init(b) }
+}
\ No newline at end of file
diff --git a/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift b/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
index 240c285..18fddac 100644
--- a/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
+++ b/validation-test/compiler_crashers_fixed/28445-gp-getouterparameters-proto-getdeclcontext-getgenericparamsofcontext-failed.swift
@@ -6,6 +6,9 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
+// FIXME(huonw): where clauses on associatedtypes broke this
+// XFAIL: *
+// REQUIRES: asserts
class A{let f= <c
protocol A{
typealias e:A{}
diff --git a/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift b/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
index 5d170bb..d8533f9 100644
--- a/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
+++ b/validation-test/compiler_crashers_fixed/28547-env-dependent-type-in-non-generic-context.swift
@@ -6,5 +6,8 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
+// FIXME(huonw): where clauses on associatedtypes broke this
+// XFAIL: *
+// REQUIRES: asserts
class A:a
protocol a{typealias B:A.B
diff --git a/validation-test/lit.site.cfg.in b/validation-test/lit.site.cfg.in
index 7c6b75f..9c4fce1 100644
--- a/validation-test/lit.site.cfg.in
+++ b/validation-test/lit.site.cfg.in
@@ -68,6 +68,9 @@
if "@SWIFT_STDLIB_ENABLE_RESILIENCE@" == "TRUE":
config.available_features.add("resilient_stdlib")
+if "@SWIFT_STDLIB_USE_NONATOMIC_RC@" == "TRUE":
+ config.available_features.add("nonatomic_rc")
+
if "@CMAKE_GENERATOR@" == "Xcode":
xcode_bin_dir = os.path.join(config.llvm_obj_root, "@LLVM_BUILD_TYPE@",
'bin')
diff --git a/validation-test/stdlib/ArrayBridging.swift b/validation-test/stdlib/ArrayBridging.swift
index 626fe4c..a6bea01 100644
--- a/validation-test/stdlib/ArrayBridging.swift
+++ b/validation-test/stdlib/ArrayBridging.swift
@@ -9,6 +9,7 @@
// REQUIRES: objc_interop
// REQUIRES: executable_test
+// UNSUPPORTED: nonatomic_rc
import StdlibUnittest
import Foundation
diff --git a/validation-test/stdlib/AtomicInt.swift b/validation-test/stdlib/AtomicInt.swift
index 52701c0..b076bce 100644
--- a/validation-test/stdlib/AtomicInt.swift
+++ b/validation-test/stdlib/AtomicInt.swift
@@ -4,6 +4,7 @@
// RUN: %target-build-swift -module-name a %s -o %t.out -O
// RUN: %target-run %t.out
// REQUIRES: executable_test
+// UNSUPPORTED: nonatomic_rc
import SwiftPrivate
import StdlibUnittest
diff --git a/validation-test/stdlib/DictionaryBridging.swift b/validation-test/stdlib/DictionaryBridging.swift
index 5ca3e25..2dc33e4 100644
--- a/validation-test/stdlib/DictionaryBridging.swift
+++ b/validation-test/stdlib/DictionaryBridging.swift
@@ -8,6 +8,7 @@
// REQUIRES: executable_test
// REQUIRES: objc_interop
+// UNSUPPORTED: nonatomic_rc
import StdlibUnittest
import Foundation
diff --git a/validation-test/stdlib/ErrorProtocol.swift b/validation-test/stdlib/ErrorProtocol.swift
index 5c2b557..a62bdf1 100644
--- a/validation-test/stdlib/ErrorProtocol.swift
+++ b/validation-test/stdlib/ErrorProtocol.swift
@@ -1,6 +1,7 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
+// UNSUPPORTED: nonatomic_rc
import SwiftPrivate
import StdlibUnittest