From 427bf752a4d96ecde187447e3fe0449bc998e6f0 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 4 Apr 2016 17:53:58 -0700 Subject: [PATCH 1/6] [Import as member] Perform checks on get-only property inference Fixes a bug where we weren't performing enough checks on inferred computed properties that did not have a pair-ed up setter. --- lib/ClangImporter/IAMInference.cpp | 76 ++++++++++++++++++--------- test/IDE/infer_import_as_member.swift | 1 + 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/lib/ClangImporter/IAMInference.cpp b/lib/ClangImporter/IAMInference.cpp index 0468c18abde38..21ebded58e111 100644 --- a/lib/ClangImporter/IAMInference.cpp +++ b/lib/ClangImporter/IAMInference.cpp @@ -536,40 +536,42 @@ static bool roughlyEqual(clang::QualType left, clang::QualType right) { right->getUnqualifiedDesugaredType(); } -bool IAMInference::validToImportAsProperty( - const clang::FunctionDecl *originalDecl, StringRef propSpec, - Optional selfIndex, const clang::FunctionDecl *&pairedAccessor) { - bool isGet = propSpec == "Get"; - pairedAccessor = findPairedAccessor(originalDecl->getName(), propSpec); - if (!pairedAccessor) - return isGet; +static bool +isValidAsStaticProperty(const clang::FunctionDecl *getterDecl, + const clang::FunctionDecl *setterDecl = nullptr) { + // Getter has none, setter has one arg + if (getterDecl->getNumParams() != 0 || + (setterDecl && setterDecl->getNumParams() != 1)) { + ++InvalidPropertyStaticNumParams; + return false; + } - auto getterDecl = isGet ? originalDecl : pairedAccessor; - auto setterDecl = isGet ? pairedAccessor : originalDecl; + // Setter's arg type should be same as getter's return type auto getterTy = getterDecl->getReturnType(); - - // See if this is a static property - if (!selfIndex) { - // Getter has none, setter has one arg - if (getterDecl->getNumParams() != 0 || setterDecl->getNumParams() != 1) { - ++InvalidPropertyStaticNumParams; - return false; - } - - // Setter's arg type should be same as getter's return type - if (!roughlyEqual(getterTy, setterDecl->getParamDecl(0)->getType())) { - ++InvalidPropertyStaticGetterSetterType; - return false; - } - - return true; + if (setterDecl && + !roughlyEqual(getterTy, setterDecl->getParamDecl(0)->getType())) { + ++InvalidPropertyStaticGetterSetterType; + return false; } + return true; +} + +static bool +isValidAsInstanceProperty(const clang::FunctionDecl *getterDecl, + const clang::FunctionDecl *setterDecl = nullptr) { // Instance property, look beyond self - if (getterDecl->getNumParams() != 1 || setterDecl->getNumParams() != 2) { + if (getterDecl->getNumParams() != 1 || + (setterDecl && setterDecl->getNumParams() != 2)) { ++InvalidPropertyInstanceNumParams; return false; } + + if (!setterDecl) + return true; + + // Make sure they pair up + auto getterTy = getterDecl->getReturnType(); auto selfTy = getterDecl->getParamDecl(0)->getType(); clang::QualType setterTy = {}; @@ -593,6 +595,28 @@ bool IAMInference::validToImportAsProperty( return true; } +bool IAMInference::validToImportAsProperty( + const clang::FunctionDecl *originalDecl, StringRef propSpec, + Optional selfIndex, const clang::FunctionDecl *&pairedAccessor) { + bool isGet = propSpec == "Get"; + pairedAccessor = findPairedAccessor(originalDecl->getName(), propSpec); + if (!pairedAccessor) { + if (!isGet) + return false; + if (!selfIndex) + return isValidAsStaticProperty(originalDecl); + return isValidAsInstanceProperty(originalDecl); + } + + auto getterDecl = isGet ? originalDecl : pairedAccessor; + auto setterDecl = isGet ? pairedAccessor : originalDecl; + + if (!selfIndex) + return isValidAsStaticProperty(getterDecl, setterDecl); + + return isValidAsInstanceProperty(getterDecl, setterDecl); +} + IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { if (clangDecl->getName().startswith("_")) { ++SkipLeadingUnderscore; diff --git a/test/IDE/infer_import_as_member.swift b/test/IDE/infer_import_as_member.swift index f5f2000051160..675dc8b5e7829 100644 --- a/test/IDE/infer_import_as_member.swift +++ b/test/IDE/infer_import_as_member.swift @@ -48,6 +48,7 @@ import InferImportAsMember // PRINT-LABEL: /// Various static functions that can't quite be imported as properties. // PRINT-NEXT: static func staticGetNonPropertyNumParams() -> Float // PRINT-NEXT: static func staticSetNonPropertyNumParams(a a: Float, b b: Float) +// PRINT-NEXT: static func staticGetNonPropertyNumParamsGetter(d d: Double) // PRINT-NEXT: static func staticGetNonPropertyType() -> Float // PRINT-NEXT: static func staticSetNonPropertyType(x x: Double) // PRINT-NEXT: static func staticGetNonPropertyNoSelf() -> Float From 74ba9ede7fc400a7015251d43ea18fffa052db62 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 5 Apr 2016 13:12:07 -0700 Subject: [PATCH 2/6] [Import as member] Check the module attribute to kick of inference --- lib/ClangImporter/ClangImporter.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 926f03f47dfdf..97ce6cdc38164 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -2004,6 +2004,31 @@ hasOrInheritsSwiftBridgeAttr(const clang::ObjCInterfaceDecl *objcClass) { return false; } +/// Whether the decl is from a module who requested import-as-member inference +static bool moduleIsInferImportAsMember(const clang::NamedDecl *decl, + clang::Sema &clangSema) { + clang::Module *submodule; + if (auto m = decl->getImportedOwningModule()) { + submodule = m; + } else if (auto m = decl->getLocalOwningModule()) { + submodule = m; + } else if (auto m = clangSema.getPreprocessor().getCurrentModule()) { + submodule = m; + } else if (auto m = clangSema.getPreprocessor().getCurrentSubmodule()) { + submodule = m; + } else { + return false; + } + + while (submodule) { + if (submodule->IsSwiftInferImportAsMember) + return true; + submodule = submodule->Parent; + } + + return false; +} + auto ClangImporter::Implementation::importFullName( const clang::NamedDecl *D, ImportNameOptions options, @@ -2186,7 +2211,8 @@ auto ClangImporter::Implementation::importFullName( return result; } - } else if (InferImportAsMember && + } else if ((InferImportAsMember || + moduleIsInferImportAsMember(D, clangSema)) && (isa(D) || isa(D)) && dc->isTranslationUnit()) { auto inference = IAMResult::infer(SwiftContext, clangSema, D); From 2b5b839686583823ed3b901df511c69af47a99b2 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 5 Apr 2016 14:08:46 -0700 Subject: [PATCH 3/6] [Import as member] Turn on CoreGraphics. Introduces CoreGraphics.apinotes, in which we enable the import-as-member inference system. Additionally, include some explicit SwiftNames, for when inference doesn't produce the right result, and to aid compatibility with the overlays. Refactors many of the trivial overlays out, shrinking the CoreGraphics.swift overlay by over half. Updates in-tree test cases. The names we currently have will be highly in flux for a while, and are likely to change frequently over the near term. There are a few remaining known bugs that are worked around by apinotes entries. --- CMakeLists.txt | 6 +- apinotes/CoreGraphics.apinotes | 65 +++++++++ lib/ClangImporter/SwiftLookupTable.h | 2 +- .../SDK/CoreGraphics/CoreGraphics.swift | 135 ++---------------- test/Interpreter/SDK/CALayer.swift | 4 +- test/Interpreter/SDK/c_pointers.swift | 2 +- test/Interpreter/SDK/cf_extensions.swift | 8 +- test/Interpreter/SDK/cf_type_bridging.swift | 3 +- 8 files changed, 88 insertions(+), 137 deletions(-) create mode 100644 apinotes/CoreGraphics.apinotes diff --git a/CMakeLists.txt b/CMakeLists.txt index 484f1899e48a0..7fc20e9133d33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -683,7 +683,11 @@ endif() # # Set up global CMake variables for API notes. # - +# API notes version 1.0.0 +# +# Change the above comment to 'touch' this file and keep incremental builds +# working when adding a new apinotes file. +# set(SWIFT_API_NOTES_PATH "${SWIFT_SOURCE_DIR}/apinotes") if(NOT EXISTS "${SWIFT_API_NOTES_PATH}/Foundation.apinotes") message(FATAL_ERROR "API notes are not available in ${SWIFT_API_NOTES_PATH}") diff --git a/apinotes/CoreGraphics.apinotes b/apinotes/CoreGraphics.apinotes new file mode 100644 index 0000000000000..02a6df19c9ebf --- /dev/null +++ b/apinotes/CoreGraphics.apinotes @@ -0,0 +1,65 @@ +--- +Name: CoreGraphics +SwiftInferImportAsMember: true +# The below are inline functions that are irrelevant due to memberwise inits +Functions: +- Name: CGPointMake + Availability: nonswift +- Name: CGSizeMake + Availability: nonswift +- Name: CGVectorMake + Availability: nonswift +- Name: CGRectMake + Availability: nonswift +- Name: CGAffineTransformMake + Availability: nonswift +# The below are fixups that inference didn't quite do what we wanted, and are +# pulled over from what used to be in the overlays +- Name: CGRectIsNull + SwiftName: "getter:CGRect.isNull(self:)" +- Name: CGRectIsEmpty + SwiftName: "getter:CGRect.isEmpty(self:)" +- Name: CGRectIsInfinite + SwiftName: "getter:CGRect.isInfinite(self:)" +- Name: CGRectStandardize + SwiftName: "getter:CGRect.standardized(self:)" +- Name: CGRectIntegral + SwiftName: "getter:CGRect.integral(self:)" +- Name: CGRectInset + SwiftName: "CGRect.insetBy(self:dx:dy:)" +- Name: CGRectOffset + SwiftName: "CGRect.offsetBy(self:dx:dy:)" +- Name: CGRectUnion + SwiftName: "CGRect.union(self:_:)" +- Name: CGRectIntersection + SwiftName: "CGRect.intersect(self:_:)" +- Name: CGRectContainsRect + SwiftName: "CGRect.contains(self:_:)" +- Name: CGRectContainsPoint + SwiftName: "CGRect.contains(self:_:)" +- Name: CGRectIntersectsRect + SwiftName: "CGRect.intersects(self:_:)" +# The below are left alone, due to an unknown bug +# FIXME: fix me +- Name: CGColorSpaceCreateDeviceRGB + SwiftName: "CGColorSpaceCreateDeviceRGB()" + +# The below are globals that are defined as opaque C constants for no good +# reason. +Globals: +- Name: CGPointZero + Availability: nonswift +- Name: CGSizeZero + Availability: nonswift +- Name: CGVectorZero + Availability: nonswift +- Name: CGRectZero + Availability: nonswift +- Name: CGAffineTransformIdentity + Availability: nonswift +# The below are left alone, due to an unknown bug +# FIXME: fix me +- Name: kCGColorBlack + SwiftName: "kCGColorBlack" +- Name: kCGColorWhite + SwiftName: "kCGColorWhite" diff --git a/lib/ClangImporter/SwiftLookupTable.h b/lib/ClangImporter/SwiftLookupTable.h index 3f30d96580614..b320b0ed49edc 100644 --- a/lib/ClangImporter/SwiftLookupTable.h +++ b/lib/ClangImporter/SwiftLookupTable.h @@ -146,7 +146,7 @@ const uint16_t SWIFT_LOOKUP_TABLE_VERSION_MAJOR = 1; /// Lookup table minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t SWIFT_LOOKUP_TABLE_VERSION_MINOR = 11; // globals-as-members +const uint16_t SWIFT_LOOKUP_TABLE_VERSION_MINOR = 12; // CG import-as-member /// A lookup table that maps Swift names to the set of Clang /// declarations with that particular name. diff --git a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift index 44400793c55d2..229f4894006ad 100644 --- a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift +++ b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift @@ -130,14 +130,6 @@ public extension CGRect { @_transparent // @fragile get { return CGRect(x: 0, y: 0, width: 0, height: 0) } } - static var null: CGRect { - @_transparent // @fragile - get { return CGRectNull } - } - static var infinite: CGRect { - @_transparent // @fragile - get { return CGRectInfinite } - } @_transparent // @fragile init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) { @@ -157,61 +149,6 @@ public extension CGRect { size: CGSize(width: width, height: height)) } - var width: CGFloat { - @_transparent // @fragile - get { return CGRectGetWidth(self) } - } - var height: CGFloat { - @_transparent // @fragile - get { return CGRectGetHeight(self) } - } - - var minX: CGFloat { - @_transparent // @fragile - get { return CGRectGetMinX(self) } - } - var midX: CGFloat { - @_transparent // @fragile - get { return CGRectGetMidX(self) } - } - var maxX: CGFloat { - @_transparent // @fragile - get { return CGRectGetMaxX(self) } - } - var minY: CGFloat { - @_transparent // @fragile - get { return CGRectGetMinY(self) } - } - var midY: CGFloat { - @_transparent // @fragile - get { return CGRectGetMidY(self) } - } - var maxY: CGFloat { - @_transparent // @fragile - get { return CGRectGetMaxY(self) } - } - var isNull: Bool { - @_transparent // @fragile - get { return CGRectIsNull(self) } - } - var isEmpty: Bool { - @_transparent // @fragile - get { return CGRectIsEmpty(self) } - } - var isInfinite: Bool { - @_transparent // @fragile - get { return CGRectIsInfinite(self) } - } - var standardized: CGRect { - @_transparent // @fragile - get { return CGRectStandardize(self) } - } - - var integral: CGRect { - @_transparent // @fragile - get { return CGRectIntegral(self) } - } - @_transparent // @fragile mutating func standardizeInPlace() { self = standardized @@ -222,45 +159,21 @@ public extension CGRect { self = integral } - @_transparent // @fragile - @warn_unused_result(mutable_variant: "insetInPlace") - func insetBy(dx dx: CGFloat, dy: CGFloat) -> CGRect { - return CGRectInset(self, dx, dy) - } - @_transparent // @fragile mutating func insetInPlace(dx dx: CGFloat, dy: CGFloat) { self = insetBy(dx: dx, dy: dy) } - @_transparent // @fragile - @warn_unused_result(mutable_variant: "offsetInPlace") - func offsetBy(dx dx: CGFloat, dy: CGFloat) -> CGRect { - return CGRectOffset(self, dx, dy) - } - @_transparent // @fragile mutating func offsetInPlace(dx dx: CGFloat, dy: CGFloat) { self = offsetBy(dx: dx, dy: dy) } - @_transparent // @fragile - @warn_unused_result(mutable_variant: "unionInPlace") - func union(rect: CGRect) -> CGRect { - return CGRectUnion(self, rect) - } - @_transparent // @fragile mutating func unionInPlace(rect: CGRect) { self = union(rect) } - @_transparent // @fragile - @warn_unused_result(mutable_variant: "intersectInPlace") - func intersect(rect: CGRect) -> CGRect { - return CGRectIntersection(self, rect) - } - @_transparent // @fragile mutating func intersectInPlace(rect: CGRect) { self = intersect(rect) @@ -273,27 +186,10 @@ public extension CGRect { { var slice = CGRect.zero var remainder = CGRect.zero - CGRectDivide(self, &slice, &remainder, atDistance, fromEdge) + divide(slice: &slice, remainder: &remainder, amount: atDistance, + edge: fromEdge) return (slice, remainder) } - - @_transparent // @fragile - @warn_unused_result - func contains(rect: CGRect) -> Bool { - return CGRectContainsRect(self, rect) - } - - @_transparent // @fragile - @warn_unused_result - func contains(point: CGPoint) -> Bool { - return CGRectContainsPoint(self, point) - } - - @_transparent // @fragile - @warn_unused_result - func intersects(rect: CGRect) -> Bool { - return CGRectIntersectsRect(self, rect) - } } extension CGRect : CustomReflectable, CustomPlaygroundQuickLookable { @@ -321,28 +217,13 @@ extension CGRect : Equatable {} @_transparent // @fragile @warn_unused_result public func == (lhs: CGRect, rhs: CGRect) -> Bool { - return CGRectEqualToRect(lhs, rhs) -} - -// Overlay the C names of these constants with transparent definitions. The -// C constants are opaque extern globals for no good reason. - -public var CGPointZero: CGPoint { - @_transparent // @fragile - get { return CGPoint.zero } -} - -public var CGRectZero: CGRect { - @_transparent // @fragile - get { return CGRect.zero } + return lhs.equalToRect(rect2: rhs) } -public var CGSizeZero: CGSize { - @_transparent // @fragile - get { return CGSize.zero } +extension CGAffineTransform { + public static var identity: CGAffineTransform { + @_transparent // @fragile + get { return CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) } + } } -public var CGAffineTransformIdentity: CGAffineTransform { - @_transparent // @fragile - get { return CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) } -} diff --git a/test/Interpreter/SDK/CALayer.swift b/test/Interpreter/SDK/CALayer.swift index 8dd183ba49447..f91a52e231c80 100644 --- a/test/Interpreter/SDK/CALayer.swift +++ b/test/Interpreter/SDK/CALayer.swift @@ -22,10 +22,10 @@ func hangCanary(o: AnyObject) { class FooLayer: CALayer { var black: CGColor - var white: CGColor = CGColorGetConstantColor(kCGColorWhite)! + var white: CGColor = CGColor.getConstantColor(colorName: kCGColorWhite)! override init() { - black = CGColorGetConstantColor(kCGColorBlack)! + black = CGColor.getConstantColor(colorName: kCGColorBlack)! super.init() hangCanary(self) } diff --git a/test/Interpreter/SDK/c_pointers.swift b/test/Interpreter/SDK/c_pointers.swift index 0fb4824d6277f..b12f550b4ec8c 100644 --- a/test/Interpreter/SDK/c_pointers.swift +++ b/test/Interpreter/SDK/c_pointers.swift @@ -23,7 +23,7 @@ typealias XXColor = UIColor // let rgb = CGColorSpaceCreateDeviceRGB() -let cgRed = CGColorCreate(rgb, [1.0, 0.0, 0.0, 1.0])! +let cgRed = CGColor(space: rgb, components: [1.0, 0.0, 0.0, 1.0])! let nsRed = XXColor(cgColor: cgRed) diff --git a/test/Interpreter/SDK/cf_extensions.swift b/test/Interpreter/SDK/cf_extensions.swift index e20b921657829..03f50b06d971e 100644 --- a/test/Interpreter/SDK/cf_extensions.swift +++ b/test/Interpreter/SDK/cf_extensions.swift @@ -22,12 +22,12 @@ extension CGColorSpace { extension CGColor { class func create(colorSpace colorSpace: CGColorSpace, components: [CGFloat]) -> CGColor { - return CGColorCreate(colorSpace, components)! + return CGColor(space: colorSpace, components: components)! } - var r: CGFloat { return CGColorGetComponents(self)[0] } - var g: CGFloat { return CGColorGetComponents(self)[1] } - var b: CGFloat { return CGColorGetComponents(self)[2] } + var r: CGFloat { return components[0] } + var g: CGFloat { return components[1] } + var b: CGFloat { return components[2] } } let pink = CGColor.create(colorSpace: .deviceRGB(), diff --git a/test/Interpreter/SDK/cf_type_bridging.swift b/test/Interpreter/SDK/cf_type_bridging.swift index 655439a7281e7..e0f32168478e6 100644 --- a/test/Interpreter/SDK/cf_type_bridging.swift +++ b/test/Interpreter/SDK/cf_type_bridging.swift @@ -10,7 +10,8 @@ import AppKit import UIKit #endif -let foo: [CGColor] = [CGColorCreate(CGColorSpaceCreateDeviceRGB(), [1.0, 0.0, 0.0, 1.0])!] +let foo: [CGColor] = [CGColor(space: CGColorSpaceCreateDeviceRGB(), + components: [1.0, 0.0, 0.0, 1.0])!] let bar = foo as NSArray From c5dc3469de87918d47fcba0c61f9768a53dbf9d1 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 5 Apr 2016 16:50:11 -0700 Subject: [PATCH 4/6] [Import as member] Fix UIKit overlay for Playground quicklook --- stdlib/public/SDK/UIKit/UIKit.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/SDK/UIKit/UIKit.swift b/stdlib/public/SDK/UIKit/UIKit.swift index 47a0c2032968c..d71bd4fc5cc6d 100644 --- a/stdlib/public/SDK/UIKit/UIKit.swift +++ b/stdlib/public/SDK/UIKit/UIKit.swift @@ -204,7 +204,7 @@ extension UIView : CustomPlaygroundQuickLookable { // be present.) let ctx: CGContext! = UIGraphicsGetCurrentContext() UIColor(white:1.0, alpha:0.0).set() - CGContextFillRect(ctx, bounds) + ctx.fillRect(bounds) layer.render(in: ctx) let image: UIImage! = UIGraphicsGetImageFromCurrentImageContext() From a51d4330d4f762cbcae17409356046947f1c3597 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Wed, 6 Apr 2016 10:31:18 -0700 Subject: [PATCH 5/6] [Import as member] Don't infer special CF memory management names --- lib/ClangImporter/IAMInference.cpp | 72 +++++++++++++++++++----------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/lib/ClangImporter/IAMInference.cpp b/lib/ClangImporter/IAMInference.cpp index 21ebded58e111..d80c36c7d1832 100644 --- a/lib/ClangImporter/IAMInference.cpp +++ b/lib/ClangImporter/IAMInference.cpp @@ -39,6 +39,8 @@ STATISTIC(FailInferFunction, "# of functions unable to infer"); // Specifically skipped/avoided STATISTIC(SkipLeadingUnderscore, "# of globals skipped due to leading underscore"); +STATISTIC(SkipCFMemoryManagement, + "# of CF memory management globals skipped"); // Success statistics STATISTIC(SuccessImportAsTypeID, "# imported as 'typeID'"); @@ -176,6 +178,7 @@ class IAMInference { } IAMResult infer(const clang::NamedDecl *); + IAMResult inferVar(const clang::VarDecl *); private: // typeID @@ -617,39 +620,43 @@ bool IAMInference::validToImportAsProperty( return isValidAsInstanceProperty(getterDecl, setterDecl); } -IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { - if (clangDecl->getName().startswith("_")) { - ++SkipLeadingUnderscore; +IAMResult IAMInference::inferVar(const clang::VarDecl *varDecl) { + auto fail = [varDecl]() -> IAMResult { + DEBUG(llvm::dbgs() << "failed to infer variable: "); + DEBUG(varDecl->print(llvm::dbgs())); + DEBUG(llvm::dbgs() << "\n"); + ++FailInferVar; return {}; - } + }; - if (auto varDecl = dyn_cast(clangDecl)) { - auto fail = [varDecl]() -> IAMResult { - DEBUG(llvm::dbgs() << "failed to infer variable: "); - DEBUG(varDecl->print(llvm::dbgs())); - DEBUG(llvm::dbgs() << "\n"); - ++FailInferVar; - return {}; - }; + // Try to find a type to add this as a static property to + StringRef workingName = varDecl->getName(); + if (workingName.empty()) + return fail(); - // Try to find a type to add this as a static property to - StringRef workingName = varDecl->getName(); - if (workingName.empty()) - return fail(); + // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with + // property "Baz" + if (*camel_case::getWords(workingName).begin() == "k") + workingName = workingName.drop_front(1); - // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with - // property "Baz" - if (*camel_case::getWords(workingName).begin() == "k") - workingName = workingName.drop_front(1); + NameBuffer remainingName; + if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) - NameBuffer remainingName; - if (auto effectiveDC = findTypeAndMatch(workingName, remainingName)) + return importAsStaticProperty(remainingName, effectiveDC); - return importAsStaticProperty(remainingName, effectiveDC); + return fail(); +} - return fail(); +IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { + if (clangDecl->getName().startswith("_")) { + ++SkipLeadingUnderscore; + return {}; } + // Try to infer a member variable + if (auto varDecl = dyn_cast(clangDecl)) + return inferVar(varDecl); + // Try to infer a member function auto funcDecl = dyn_cast(clangDecl); if (!funcDecl) { @@ -675,9 +682,11 @@ IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { auto retTy = funcDecl->getReturnType(); unsigned numParams = funcDecl->getNumParams(); - // 0) Special cases are specially handled: *GetTypeID() + // 0) Special cases are specially handled // StringRef getTypeID = "GetTypeID"; + StringRef cfSpecials[] = {"Release", "Retain", "Autorelease"}; + // *GetTypeID if (numParams == 0 && workingName.endswith(getTypeID)) { NameBuffer remainingName; if (auto effectiveDC = findTypeAndMatch( @@ -688,6 +697,19 @@ IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) { return importAsTypeID(retTy, effectiveDC); } } + // *Release/*Retain/*Autorelease + } else if (numParams == 1 && + std::any_of(std::begin(cfSpecials), std::end(cfSpecials), + [workingName](StringRef suffix) { + return workingName.endswith(suffix); + })) { + if (auto type = + funcDecl->getParamDecl(0)->getType()->getAs()) { + if (CFPointeeInfo::classifyTypedef(type->getDecl())) { + ++SkipCFMemoryManagement; + return {}; + } + } } // 1) If we find an init specifier and our name matches the return type, we From 13c2a3427ad22d417b744e10510c3e15dd432bc9 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Wed, 6 Apr 2016 12:55:07 -0700 Subject: [PATCH 6/6] [Import as member] Temporary hack to work around a clang module cache issue --- lib/ClangImporter/ClangImporter.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 97ce6cdc38164..1dae9e38623d8 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -2021,8 +2021,13 @@ static bool moduleIsInferImportAsMember(const clang::NamedDecl *decl, } while (submodule) { - if (submodule->IsSwiftInferImportAsMember) + if (submodule->IsSwiftInferImportAsMember) { + // HACK HACK HACK: This is a workaround for some module invalidation issue + // and inconsistency. This will go away soon. + if (submodule->Name != "CoreGraphics") + return false; return true; + } submodule = submodule->Parent; }