From 58676616eafd0d4a9b6a167ca5d99e2f1214503a Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 30 Jul 2016 11:04:38 +0900 Subject: [PATCH 1/2] [Dispatch] .size to .stride --- stdlib/public/SDK/Dispatch/Data.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/SDK/Dispatch/Data.swift b/stdlib/public/SDK/Dispatch/Data.swift index ca43f824c813..f0ca01084ae2 100644 --- a/stdlib/public/SDK/Dispatch/Data.swift +++ b/stdlib/public/SDK/Dispatch/Data.swift @@ -149,7 +149,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable { /// Copy the contents of the data into a buffer. /// - /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout.size * buffer.count` then the first N bytes will be copied into the buffer. + /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout.stride * buffer.count` then the first N bytes will be copied into the buffer. /// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called. /// - parameter buffer: A buffer to copy the data into. /// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied. From fd4ddd63221459d7e6b021e97f299f88db95af87 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 29 Jul 2016 13:53:59 +0900 Subject: [PATCH 2/2] [SE-0101] Migration support for sizeof(T) family to MemoryLayout --- lib/Sema/MiscDiagnostics.cpp | 83 +++++++++++++++++++++++++++++++++++- test/1_stdlib/Renames.swift | 9 ++++ test/expr/expressions.swift | 27 ++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 0b6b550693fb..bb1db601c350 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -25,6 +25,7 @@ #include "swift/Parse/Lexer.h" #include "swift/Parse/Parser.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/SaveAndRestore.h" using namespace swift; @@ -1810,6 +1811,9 @@ class AvailabilityWalker : public ASTWalker { const ApplyExpr *call = nullptr); bool diagnoseIncDecRemoval(const ValueDecl *D, SourceRange R, const AvailableAttr *Attr); + bool diagnoseMemoryLayoutMigration(const ValueDecl *D, SourceRange R, + const AvailableAttr *Attr, + const ApplyExpr *call); /// Walks up from a potential callee to the enclosing ApplyExpr. const ApplyExpr *getEnclosingApplyExpr() const { @@ -1948,9 +1952,12 @@ bool AvailabilityWalker::diagAvailability(const ValueDecl *D, SourceRange R, if (!D) return false; - if (auto *attr = AvailableAttr::isUnavailable(D)) + if (auto *attr = AvailableAttr::isUnavailable(D)) { if (diagnoseIncDecRemoval(D, R, attr)) return true; + if (call && diagnoseMemoryLayoutMigration(D, R, attr, call)) + return true; + } if (TC.diagnoseExplicitUnavailability(D, R, DC, call)) return true; @@ -2050,7 +2057,81 @@ bool AvailabilityWalker::diagnoseIncDecRemoval(const ValueDecl *D, return false; } +/// If this is a call to an unavailable sizeof family functions, diagnose it +/// with a fixit hint and return true. If not, or if we fail, return false. +bool AvailabilityWalker::diagnoseMemoryLayoutMigration(const ValueDecl *D, + SourceRange R, + const AvailableAttr *Attr, + const ApplyExpr *call) { + + if (!D->getModuleContext()->isStdlibModule()) + return false; + + std::pair KindValue + = llvm::StringSwitch>(D->getNameStr()) + .Case("sizeof", {"size", false}) + .Case("alignof", {"alignment", false}) + .Case("strideof", {"stride", false}) + .Case("sizeofValue", {"size", true}) + .Case("alignofValue", {"alignment", true}) + .Case("strideofValue", {"stride", true}) + .Default({}); + + if (KindValue.first.empty()) + return false; + + auto Kind = KindValue.first; + auto isValue = KindValue.second; + auto args = dyn_cast(call->getArg()); + if (!args) + return false; + + auto subject = args->getSubExpr(); + if (!isValue) { + // sizeof(x.dynamicType) is equivalent to sizeofValue(x) + if (auto DTE = dyn_cast(subject)) { + subject = DTE->getBase(); + isValue = true; + } + } + + EncodedDiagnosticMessage EncodedMessage(Attr->Message); + auto diag = TC.diagnose(R.Start, diag::availability_decl_unavailable_msg, + D->getFullName(), EncodedMessage.Message); + diag.highlight(R); + + StringRef Prefix = "MemoryLayout<"; + StringRef Suffix = ">."; + if (isValue) { + auto valueType = subject->getType()->getRValueType(); + if (!valueType || valueType->is()) { + // If we dont have good argument, We cannot emit fix-it. + return true; + } + + // NOTE: We are destructively replacing the source text here. + // For instance, `sizeof(x.doSomethig())` => `MemoryLayout.size` where + // T is return type of `doSomething()`. If that function have any + // side effects, it will break the source. + diag.fixItReplace(call->getSourceRange(), + (Prefix + valueType->getString() + Suffix + Kind).str()); + } else { + SourceRange PrefixRange(call->getStartLoc(), args->getLParenLoc()); + SourceRange SuffixRange(args->getRParenLoc()); + + // We must truncate `.self`. + // E.g. sizeof(T.self) => MemoryLayout.size + if (auto *DSE = dyn_cast(subject)) + SuffixRange.Start = DSE->getDotLoc(); + + diag + .fixItReplace(PrefixRange, Prefix) + .fixItReplace(SuffixRange, (Suffix + Kind).str()); + } + + return true; +} /// Diagnose uses of unavailable declarations. static void diagAvailability(TypeChecker &TC, const Expr *E, diff --git a/test/1_stdlib/Renames.swift b/test/1_stdlib/Renames.swift index c4a9206c8ea3..4b8271f9d0f3 100644 --- a/test/1_stdlib/Renames.swift +++ b/test/1_stdlib/Renames.swift @@ -280,6 +280,15 @@ func _Map(c: C) { _ = LazyMapCollection(c) { _ in true } // expected-error {{'init(_:transform:)' is unavailable: use '.lazy.map' on the collection}} {{none}} } +func _MemoryLayout(t: T) { + _ = sizeof(T.self) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-14=MemoryLayout<}} {{15-21=>.size}} {{none}} + _ = alignof(T.self) // expected-error {{'alignof' is unavailable: use MemoryLayout.alignment instead.}} {{7-15=MemoryLayout<}} {{16-22=>.alignment}} {{none}} + _ = strideof(T.self) // expected-error {{'strideof' is unavailable: use MemoryLayout.stride instead.}} {{7-16=MemoryLayout<}} {{17-23=>.stride}} {{none}} + _ = sizeofValue(t) // expected-error {{'sizeofValue' is unavailable: use MemoryLayout.size instead.}} {{7-21=MemoryLayout.size}} {{none}} + _ = alignofValue(t) // expected-error {{'alignofValue' is unavailable: use MemoryLayout.alignment instead.}} {{7-22=MemoryLayout.alignment}} {{none}} + _ = strideofValue(t) // expected-error {{'strideofValue' is unavailable: use MemoryLayout.stride instead.}} {{7-23=MemoryLayout.stride}} {{none}} +} + func _Mirror() { func fn(_: M) {} // expected-error {{'MirrorPathType' has been renamed to 'MirrorPath'}} {{15-29=MirrorPath}} {{none}} } diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 98828cb0da6a..218ec33084aa 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -872,3 +872,30 @@ let _ = (x, 3).1 (x,y).1 = 7 // expected-error {{cannot assign to immutable expression of type 'Int'}} x = (x,(3,y)).1.1 + +// SE-0101 sizeof family functions are reconfigured into MemoryLayout +protocol Pse0101 { + associatedtype Value + func getIt() -> Value +} +class Cse0101 { + typealias T = U + var val: U { fatalError() } +} +func se0101(x: Cse0101

) { + // Note: The first case is actually not allowed, but it is very common and can be compiled currently. + _ = sizeof(P) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-14=MemoryLayout<}} {{15-16=>.size}} {{none}} + // expected-warning@-1 {{missing '.self' for reference to metatype of type 'P'}} + _ = sizeof(P.self) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-14=MemoryLayout<}} {{15-21=>.size}} {{none}} + _ = sizeof(P.Value.self) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-14=MemoryLayout<}} {{21-27=>.size}} {{none}} + _ = sizeof(Cse0101

.self) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-14=MemoryLayout<}} {{24-30=>.size}} {{none}} + _ = alignof(Cse0101

.T.self) // expected-error {{'alignof' is unavailable: use MemoryLayout.alignment instead.}} {{7-15=MemoryLayout<}} {{27-33=>.alignment}} {{none}} + _ = strideof(P.Type.self) // expected-error {{'strideof' is unavailable: use MemoryLayout.stride instead.}} {{7-16=MemoryLayout<}} {{22-28=>.stride}} {{none}} + _ = sizeof(type(of: x)) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-26=MemoryLayout>.size}} {{none}}/ + _ = sizeof(x.dynamicType) // expected-error {{'sizeof' is unavailable: use MemoryLayout.size instead.}} {{7-28=MemoryLayout>.size}} {{none}} + // expected-warning@-1 {{'.dynamicType' is deprecated. Use 'type(of: ...)' instead}} + + _ = sizeofValue(x) // expected-error {{'sizeofValue' is unavailable: use MemoryLayout.size instead.}} {{7-21=MemoryLayout>.size}} {{none}} + _ = alignofValue(x.val) // expected-error {{'alignofValue' is unavailable: use MemoryLayout.alignment instead.}} {{7-26=MemoryLayout

.alignment}} {{none}} + _ = strideofValue(x.val.getIt()) // expected-error {{'strideofValue' is unavailable: use MemoryLayout.stride instead.}} {{7-35=MemoryLayout.stride}} {{none}} +}