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"
             }
         },