Merge pull request #16727 from jckarter/decodeMangledType-node-checks-4.2
[4.2] TypeDecoder: Be more forgiving of extra child nodes in demangled nominal types.
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 3e6a8d8..fd9a78a 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1320,6 +1320,8 @@
"'@%0' has been renamed to '@%1'", (StringRef, StringRef))
WARNING(attr_renamed_warning, none,
"'@%0' has been renamed to '@%1'", (StringRef, StringRef))
+ERROR(attr_name_close_match, none,
+ "no attribute named '@%0'; did you mean '@%1'?", (StringRef, StringRef))
// availability
ERROR(attr_availability_platform,none,
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 957ee92..b23b46d 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -260,6 +260,21 @@
SF->getASTContext().SourceMgr, Range).str() == "nil";
}
+ bool isDotMember(CharSourceRange Range) {
+ auto S = Range.str();
+ return S.startswith(".") && S.substr(1).find(".") == StringRef::npos;
+ }
+
+ bool isDotMember(SourceRange Range) {
+ return isDotMember(Lexer::getCharSourceRangeFromSourceRange(
+ SF->getASTContext().SourceMgr, Range));
+ }
+
+ bool isDotMember(Expr *E) {
+ auto Range = E->getSourceRange();
+ return Range.isValid() && isDotMember(Range);
+ }
+
std::vector<APIDiffItem*> getRelatedDiffItems(ValueDecl *VD) {
std::vector<APIDiffItem*> results;
auto addDiffItems = [&](ValueDecl *VD) {
@@ -308,11 +323,11 @@
}
- bool isSimpleReplacement(APIDiffItem *Item, std::string &Text) {
+ bool isSimpleReplacement(APIDiffItem *Item, bool isDotMember, std::string &Text) {
if (auto *MD = dyn_cast<TypeMemberDiffItem>(Item)) {
if (MD->Subkind == TypeMemberDiffItemSubKind::SimpleReplacement) {
- Text = (llvm::Twine(MD->newTypeName) + "." + MD->getNewName().base()).
- str();
+ Text = (llvm::Twine(isDotMember ? "" : MD->newTypeName) + "." +
+ MD->getNewName().base()).str();
return true;
}
}
@@ -375,7 +390,7 @@
Type T, ReferenceMetaData Data) override {
for (auto *Item: getRelatedDiffItems(CtorTyRef ? CtorTyRef: D)) {
std::string RepText;
- if (isSimpleReplacement(Item, RepText)) {
+ if (isSimpleReplacement(Item, isDotMember(Range), RepText)) {
Editor.replace(Range, RepText);
return true;
}
@@ -450,8 +465,9 @@
for (auto *I: getRelatedDiffItems(VD)) {
if (auto *Item = dyn_cast<TypeMemberDiffItem>(I)) {
if (Item->Subkind == TypeMemberDiffItemSubKind::QualifiedReplacement) {
- Editor.replace(ToReplace, (llvm::Twine(Item->newTypeName) + "." +
- Item->getNewName().base()).str());
+ Editor.replace(ToReplace,
+ (llvm::Twine(isDotMember(ToReplace) ? "" : Item->newTypeName) + "." +
+ Item->getNewName().base()).str());
return true;
}
}
@@ -725,7 +741,7 @@
StringRef LeftComment;
StringRef RightComment;
for (auto *Item: getRelatedDiffItems(RD)) {
- if (isSimpleReplacement(Item, Rename)) {
+ if (isSimpleReplacement(Item, isDotMember(Reference), Rename)) {
} else if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
if (CI->isStringRepresentableChange() &&
CI->NodeKind == SDKNodeKind::DeclVar) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index f7cb302..c451968 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1465,35 +1465,34 @@
// If the attribute follows the new representation, switch
// over to the alternate parsing path.
DeclAttrKind DK = DeclAttribute::getAttrKindFromString(Tok.getText());
-
- auto checkRenamedAttr = [&](StringRef oldName, StringRef newName,
- DeclAttrKind kind, bool warning) {
- if (DK == DAK_Count && Tok.getText() == oldName) {
+
+ auto checkInvalidAttrName = [&](StringRef invalidName, StringRef correctName,
+ DeclAttrKind kind, Diag<StringRef, StringRef> diag) {
+ if (DK == DAK_Count && Tok.getText() == invalidName) {
// We renamed @availability to @available, so if we see the former,
// treat it as the latter and emit a Fix-It.
DK = kind;
- if (warning) {
- diagnose(Tok, diag::attr_renamed_warning, oldName, newName)
- .fixItReplace(Tok.getLoc(), newName);
- } else {
- diagnose(Tok, diag::attr_renamed, oldName, newName)
- .fixItReplace(Tok.getLoc(), newName);
- }
+
+ diagnose(Tok, diag, invalidName, correctName)
+ .fixItReplace(Tok.getLoc(), correctName);
}
};
// FIXME: This renaming happened before Swift 3, we can probably remove
// the specific fallback path at some point.
- checkRenamedAttr("availability", "available", DAK_Available, false);
+ checkInvalidAttrName("availability", "available", DAK_Available, diag::attr_renamed);
+
+ // Check if attr is inlineable, and suggest inlinable instead
+ checkInvalidAttrName("inlineable", "inlinable", DAK_Inlinable, diag::attr_name_close_match);
// In Swift 5 and above, these become hard errors. Otherwise, emit a
// warning for compatibility.
if (!Context.isSwiftVersionAtLeast(5)) {
- checkRenamedAttr("_versioned", "usableFromInline", DAK_UsableFromInline, true);
- checkRenamedAttr("_inlineable", "inlinable", DAK_Inlinable, true);
+ checkInvalidAttrName("_versioned", "usableFromInline", DAK_UsableFromInline, diag::attr_renamed_warning);
+ checkInvalidAttrName("_inlineable", "inlinable", DAK_Inlinable, diag::attr_renamed_warning);
} else {
- checkRenamedAttr("_versioned", "usableFromInline", DAK_UsableFromInline, false);
- checkRenamedAttr("_inlineable", "inlinable", DAK_Inlinable, false);
+ checkInvalidAttrName("_versioned", "usableFromInline", DAK_UsableFromInline, diag::attr_renamed);
+ checkInvalidAttrName("_inlineable", "inlinable", DAK_Inlinable, diag::attr_renamed);
}
if (DK == DAK_Count && Tok.getText() == "warn_unused_result") {
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 69e4bcd..243c89e 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -23,7 +23,6 @@
#include "swift/AST/ForeignInfo.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ProtocolConformance.h"
-#include "swift/Basic/StringExtras.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILType.h"
#include "clang/AST/Attr.h"
@@ -1736,12 +1735,23 @@
StringRef text = name.get();
while (!text.empty() && text[0] == '_') text = text.substr(1);
- StringRef firstWord = camel_case::getFirstWord(text);
+ // Does the given selector start with the given string as a prefix, in the
+ // sense of the selector naming conventions?
+ // This implementation matches the one used by
+ // clang::Selector::getMethodFamily, to make sure we behave the same as Clang
+ // ARC. We're not just calling that method here because it means allocating a
+ // clang::IdentifierInfo, which requires a Clang ASTContext.
+ auto hasPrefix = [](StringRef text, StringRef prefix) {
+ if (!text.startswith(prefix)) return false;
+ if (text.size() == prefix.size()) return true;
+ assert(text.size() > prefix.size());
+ return !clang::isLowercase(text[prefix.size()]);
+ };
auto result = SelectorFamily::None;
if (false) /*for #define purposes*/;
#define CHECK_PREFIX(LABEL, PREFIX) \
- else if (firstWord == PREFIX) result = SelectorFamily::LABEL;
+ else if (hasPrefix(text, PREFIX)) result = SelectorFamily::LABEL;
FOREACH_FAMILY(CHECK_PREFIX)
#undef CHECK_PREFIX
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 85a6b42..7efbc04 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -1150,8 +1150,10 @@
}
}
+ auto typeName = field.getMangledTypeName(0);
+
auto typeInfo = _getTypeByMangledName(
- field.getMangledTypeName(0),
+ typeName,
[&](unsigned depth, unsigned index) -> const Metadata * {
if (depth >= descriptorPath.size())
return nullptr;
@@ -1175,6 +1177,16 @@
return base->getGenericArgs()[flatIndex];
});
+ // If demangling the type failed, pretend it's an empty type instead with
+ // a log message.
+ if (typeInfo == nullptr) {
+ typeInfo = TypeInfo(&METADATA_SYM(EMPTY_TUPLE_MANGLING), {});
+ warning(0, "SWIFT RUNTIME BUG: unable to demangle type of field '%*s'. "
+ "mangled type name is '%*s'",
+ (int)name.size(), name.data(),
+ (int)typeName.size(), typeName.data());
+ }
+
callback(name, FieldType()
.withType(typeInfo)
.withIndirect(field.isIndirectCase())
diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h
index 43b39d8..3bcfcaa 100644
--- a/stdlib/public/runtime/Private.h
+++ b/stdlib/public/runtime/Private.h
@@ -60,7 +60,7 @@
/// itself related info has to be bundled with it.
class TypeInfo {
const Metadata *Type;
- const TypeReferenceOwnership ReferenceOwnership;
+ TypeReferenceOwnership ReferenceOwnership;
public:
TypeInfo() : Type(nullptr), ReferenceOwnership() {}
diff --git a/test/Migrator/qualified-replacement.swift b/test/Migrator/qualified-replacement.swift
index 47bb412..a8e68b3 100644
--- a/test/Migrator/qualified-replacement.swift
+++ b/test/Migrator/qualified-replacement.swift
@@ -14,6 +14,8 @@
_ = Cities.CityKind.Town
_ = ToplevelType()
_ = ToplevelType(recordName: "")
+ bar(.orderedSame)
}
func foo(_: ToplevelType) {}
+func bar(_ : FooComparisonResult) {}
diff --git a/test/Migrator/qualified-replacement.swift.expected b/test/Migrator/qualified-replacement.swift.expected
index b3ec305..7b1344c 100644
--- a/test/Migrator/qualified-replacement.swift.expected
+++ b/test/Migrator/qualified-replacement.swift.expected
@@ -10,10 +10,12 @@
_ = NewPropertyUserInterface.newFieldPlus
NewPropertyUserInterface.newMethodPlus(1)
_ = NewFooComparisonResult.NewFooOrderedSame
- let _ : FooComparisonResult = NewFooComparisonResult.NewFooOrderedSame
+ let _ : FooComparisonResult = .NewFooOrderedSame
_ = NewCityKind.NewTown
_ = ToplevelWrapper.internalType()
_ = ToplevelWrapper.internalType(recordName: "")
+ bar(.NewFooOrderedSame)
}
func foo(_: ToplevelWrapper.internalType) {}
+func bar(_ : FooComparisonResult) {}
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index 15d55d8..a96f955 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -64,6 +64,36 @@
// CHECK-NEXT: return [[RES]]
// CHECK-NEXT: }
+ // NS_RETURNS_RETAINED by family (-mutableCopy)
+ @objc func mutableCopyFoo() -> Gizmo { return self }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC14mutableCopyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC14mutableCopyFooSo5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // NS_RETURNS_RETAINED by family (-copy). This is different from Swift's
+ // normal notion of CamelCase, but it's what Clang does, so we should match
+ // it.
+ @objc func copy8() -> Gizmo { return self }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC5copy8So5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC5copy8So5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
// NS_RETURNS_RETAINED by family (-copy)
@objc(copyDuplicate) func makeDuplicate() -> Gizmo { return self }
// CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
diff --git a/test/attr/attr_inlinable_close_match.swift b/test/attr/attr_inlinable_close_match.swift
new file mode 100644
index 0000000..e414185
--- /dev/null
+++ b/test/attr/attr_inlinable_close_match.swift
@@ -0,0 +1,4 @@
+// RUN: %target-typecheck-verify-swift
+
+@inlineable public func misspelledInlinable() {}
+// expected-error@-1 {{no attribute named '@inlineable'; did you mean '@inlinable'?}}{{2-12=inlinable}}
\ No newline at end of file
diff --git a/utils/update-checkout-config.json b/utils/update-checkout-config.json
index 56d52ba..2a7a033 100644
--- a/utils/update-checkout-config.json
+++ b/utils/update-checkout-config.json
@@ -195,9 +195,9 @@
"clang": "swift-4.2-branch",
"swift": "swift-4.2-branch",
"lldb": "swift-4.2-branch",
- "cmark": "master",
- "llbuild": "master",
- "swiftpm": "master",
+ "cmark": "swift-4.2-branch",
+ "llbuild": "swift-4.2-branch",
+ "swiftpm": "swift-4.2-branch",
"compiler-rt": "swift-4.2-branch",
"swift-corelibs-xctest": "swift-4.2-branch",
"swift-corelibs-foundation": "swift-4.2-branch",
@@ -248,19 +248,19 @@
"swift-4.2-branch-04-30-2018" : {
"aliases": ["swift-4.2-branch-04-30-2018"],
"repos": {
- "llvm": "swift-4.2-branch-04-30-2018",
- "clang": "swift-4.2-branch-04-30-2018",
+ "llvm": "swift-4.2-branch",
+ "clang": "swift-4.2-branch",
"swift": "swift-4.2-branch-04-30-2018",
- "lldb": "swift-4.2-branch-04-30-2018",
- "cmark": "master",
- "llbuild": "master",
- "swiftpm": "master",
- "compiler-rt": "swift-4.2-branch-04-30-2018",
- "swift-corelibs-xctest": "swift-4.2-branch-04-30-2018",
- "swift-corelibs-foundation": "swift-4.2-branch-04-30-2018",
- "swift-corelibs-libdispatch": "swift-4.2-branch-04-30-2018",
- "swift-integration-tests": "swift-4.2-branch-04-30-2018",
- "swift-xcode-playground-support": "swift-4.2-branch-04-30-2018",
+ "lldb": "swift-4.2-branch",
+ "cmark": "swift-4.2-branch",
+ "llbuild": "swift-4.2-branch",
+ "swiftpm": "swift-4.2-branch",
+ "compiler-rt": "swift-4.2-branch",
+ "swift-corelibs-xctest": "swift-4.2-branch",
+ "swift-corelibs-foundation": "swift-4.2-branch",
+ "swift-corelibs-libdispatch": "swift-4.2-branch",
+ "swift-integration-tests": "swift-4.2-branch",
+ "swift-xcode-playground-support": "swift-4.2-branch",
"ninja": "release"
}
},