Merge pull request #42 from DougGregor/api-notes-change-types-3_1

[API Notes] Add support for overriding the types of declarations via API notes.
diff --git a/include/clang/APINotes/Types.h b/include/clang/APINotes/Types.h
index 09fbc8d..6fbd5d8 100644
--- a/include/clang/APINotes/Types.h
+++ b/include/clang/APINotes/Types.h
@@ -297,6 +297,9 @@
   /// has been audited.
   unsigned Nullable : 2;
 
+  /// The C type of the variable, as a string.
+  std::string Type;
+
 public:
   VariableInfo()
     : CommonEntityInfo(),
@@ -315,10 +318,14 @@
     Nullable = static_cast<unsigned>(kind);
   }
 
+  const std::string &getType() const { return Type; }
+  void setType(const std::string &type) { Type = type; }
+
   friend bool operator==(const VariableInfo &lhs, const VariableInfo &rhs) {
     return static_cast<const CommonEntityInfo &>(lhs) == rhs &&
            lhs.NullabilityAudited == rhs.NullabilityAudited &&
-           lhs.Nullable == rhs.Nullable;
+           lhs.Nullable == rhs.Nullable &&
+           lhs.Type == rhs.Type;
   }
 
   friend bool operator!=(const VariableInfo &lhs, const VariableInfo &rhs) {
@@ -330,6 +337,8 @@
     static_cast<CommonEntityInfo &>(lhs) |= rhs;
     if (!lhs.NullabilityAudited && rhs.NullabilityAudited)
       lhs.setNullabilityAudited(*rhs.getNullability());
+    if (lhs.Type.empty() && !rhs.Type.empty())
+      lhs.Type = rhs.Type;
     return lhs;
   }
 };
@@ -347,6 +356,8 @@
   /// Merge class-wide information into the given property.
   friend ObjCPropertyInfo &operator|=(ObjCPropertyInfo &lhs,
                                       const ObjCContextInfo &rhs) {
+    static_cast<VariableInfo &>(lhs) |= rhs;
+
     // Merge nullability.
     if (!lhs.getNullability()) {
       if (auto nullable = rhs.getDefaultNullability()) {
@@ -462,6 +473,9 @@
   //  of the parameters.
   uint64_t NullabilityPayload = 0;
 
+  /// The result type of this function, as a C type.
+  std::string ResultType;
+
   /// The function parameters.
   std::vector<ParamInfo> Params;
 
@@ -525,7 +539,9 @@
     return static_cast<const CommonEntityInfo &>(lhs) == rhs &&
            lhs.NullabilityAudited == rhs.NullabilityAudited &&
            lhs.NumAdjustedNullable == rhs.NumAdjustedNullable &&
-           lhs.NullabilityPayload == rhs.NullabilityPayload;
+           lhs.NullabilityPayload == rhs.NullabilityPayload &&
+           lhs.ResultType == rhs.ResultType &&
+           lhs.Params == rhs.Params;
   }
 
   friend bool operator!=(const FunctionInfo &lhs, const FunctionInfo &rhs) {
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index fb3db57..6f55fec 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -1014,6 +1014,9 @@
 def err_pragma_invalid_keyword : Error<
   "invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;
 
+// API notes.
+def err_type_unparsed : Error<"unparsed tokens following type">;
+
 // Pragma unroll support.
 def warn_pragma_unroll_cuda_value_in_parens : Warning<
   "argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index f9efa41..cc5e9fb 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8157,6 +8157,13 @@
   "blocks in this form of device side enqueue call are expected to have have no parameters">;
 } // end of sema category
 
+let CategoryName = "API Notes Issue" in {
+
+def err_incompatible_replacement_type : Error<
+  "API notes replacement type %0 has a different size from original type %1">;
+
+}
+
 let CategoryName = "OpenMP Issue" in {
 // OpenMP support.
 def err_omp_expected_var_arg : Error<
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 830c25a..6f1f7c6 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -133,15 +133,17 @@
   /// from.  Currently this is only used by _Pragma handling.
   SourceLocation getFileLoc() const { return FileLoc; }
 
-private:
   /// Lex - Return the next token in the file.  If this is the end of file, it
   /// return the tok::eof token.  This implicitly involves the preprocessor.
   bool Lex(Token &Result);
 
-public:
   /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
   bool isPragmaLexer() const { return Is_PragmaLexer; }
 
+  /// Note that this Lexer is being used to lex a pragma, or something like it
+  /// that has simple end-of-file behavior.
+  void setIsPragmaLexer(bool value) { Is_PragmaLexer = value; }
+
 private:
   /// IndirectLex - An indirect call to 'Lex' that can be invoked via
   ///  the PreprocessorLexer interface.
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 8117741..f1157c3 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2681,7 +2681,19 @@
   //===--------------------------------------------------------------------===//
   // C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
   ExprResult ParseTypeTrait();
-  
+
+  /// Parse the given string as a type.
+  ///
+  /// This is a dangerous utility function currently employed only by API notes.
+  /// It is not a general entry-point for safely parsing types from strings.
+  ///
+  /// \param typeStr The string to be parsed as a type.
+  /// \param context The name of the context in which this string is being
+  /// parsed, which will be used in diagnostics.
+  /// \param includeLoc The location at which this parse was triggered.
+  TypeResult parseTypeFromString(StringRef typeStr, StringRef context,
+                                 SourceLocation includeLoc);
+
   //===--------------------------------------------------------------------===//
   // Embarcadero: Arary and Expression Traits
   ExprResult ParseArrayTypeTrait();
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4080a54..87dffa6 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -54,6 +54,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include <deque>
+#include <functional>
 #include <memory>
 #include <string>
 #include <vector>
@@ -572,6 +573,10 @@
     OpaqueParser = P;
   }
 
+  /// \brief Callback to the parser to parse a type expressed as a string.
+  std::function<TypeResult(StringRef, StringRef, SourceLocation)>
+    ParseTypeFromStringCallback;
+
   class DelayedDiagnostics;
 
   class DelayedDiagnosticsState {
@@ -1778,6 +1783,8 @@
   ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
                                           SourceLocation Loc,
                                           QualType T);
+  QualType adjustParameterTypeForObjCAutoRefCount(QualType T,
+                                                  SourceLocation Loc);
   ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc,
                               SourceLocation NameLoc, IdentifierInfo *Name,
                               QualType T, TypeSourceInfo *TSInfo,
diff --git a/lib/APINotes/APINotesFormat.h b/lib/APINotes/APINotesFormat.h
index b3d2d36..ef3ef73 100644
--- a/lib/APINotes/APINotesFormat.h
+++ b/lib/APINotes/APINotesFormat.h
@@ -36,7 +36,7 @@
 /// API notes file minor version number.
 ///
 /// When the format changes IN ANY WAY, this number should be incremented.
-const uint16_t VERSION_MINOR = 20;  // ImportPropertyAsAccessors
+const uint16_t VERSION_MINOR = 21;  // Override types
 
 using IdentifierID = PointerEmbeddedInt<unsigned, 31>;
 using IdentifierIDField = BCVBR<16>;
diff --git a/lib/APINotes/APINotesReader.cpp b/lib/APINotes/APINotesReader.cpp
index 1daf27b..e889ac4 100644
--- a/lib/APINotes/APINotesReader.cpp
+++ b/lib/APINotes/APINotesReader.cpp
@@ -265,6 +265,11 @@
       info.setNullabilityAudited(static_cast<NullabilityKind>(*data));
     }
     ++data;
+
+    auto typeLen
+      = endian::readNext<uint16_t, little, unaligned>(data);
+    info.setType(std::string(data, data + typeLen));
+    data += typeLen;
   }
 
   /// Used to deserialize the on-disk Objective-C property table.
@@ -292,6 +297,17 @@
     }
   };
 
+  /// Read serialized ParamInfo.
+  void readParamInfo(const uint8_t *&data, ParamInfo &info) {
+    readVariableInfo(data, info);
+
+    uint8_t payload = endian::readNext<uint8_t, little, unaligned>(data);
+    if (payload & 0x01) {
+      info.setNoEscape(payload & 0x02);
+    }
+    payload >>= 2; assert(payload == 0 && "Bad API notes");
+  }
+
   /// Read serialized FunctionInfo.
   void readFunctionInfo(const uint8_t *&data, FunctionInfo &info) {
     readCommonEntityInfo(data, info);
@@ -304,21 +320,16 @@
 
     unsigned numParams = endian::readNext<uint16_t, little, unaligned>(data);
     while (numParams > 0) {
-      uint8_t payload = endian::readNext<uint8_t, little, unaligned>(data);
-
       ParamInfo pi;
-      uint8_t nullabilityValue = payload & 0x3; payload >>= 2;
-      if (payload & 0x01)
-        pi.setNullabilityAudited(static_cast<NullabilityKind>(nullabilityValue));
-      payload >>= 1;
-      if (payload & 0x01) {
-        pi.setNoEscape(payload & 0x02);
-      }
-      payload >>= 2; assert(payload == 0 && "Bad API notes");
-
+      readParamInfo(data, pi);
       info.Params.push_back(pi);
       --numParams;
     }
+
+    unsigned resultTypeLen
+      = endian::readNext<uint16_t, little, unaligned>(data);
+    info.ResultType = std::string(data, data + resultTypeLen);
+    data += resultTypeLen;
   }
 
   /// Used to deserialize the on-disk Objective-C method table.
diff --git a/lib/APINotes/APINotesWriter.cpp b/lib/APINotes/APINotesWriter.cpp
index d696aa6..86b6abd 100644
--- a/lib/APINotes/APINotesWriter.cpp
+++ b/lib/APINotes/APINotesWriter.cpp
@@ -490,7 +490,7 @@
   /// Retrieve the serialized size of the given VariableInfo, for use in
   /// on-disk hash tables.
   unsigned getVariableInfoSize(const VariableInfo &info) {
-    return 2 + getCommonEntityInfoSize(info);
+    return 2 + getCommonEntityInfoSize(info) + 2 + info.getType().size();
   }
 
   /// Emit a serialized representation of the variable information.
@@ -506,6 +506,10 @@
     }
 
     out.write(reinterpret_cast<const char *>(bytes), 2);
+
+    endian::Writer<little> writer(out);
+    writer.write<uint16_t>(info.getType().size());
+    out.write(info.getType().data(), info.getType().size());
   }
 
   /// On-dish hash table info key base for handling versioned data.
@@ -691,11 +695,34 @@
 }
 
 namespace {
+  static unsigned getParamInfoSize(const ParamInfo &info) {
+    return getVariableInfoSize(info) + 1;
+  }
+
+  static void emitParamInfo(raw_ostream &out, const ParamInfo &info) {
+    emitVariableInfo(out, info);
+
+    endian::Writer<little> writer(out);
+
+    uint8_t payload = 0;
+    if (auto noescape = info.isNoEscape()) {
+      payload |= 0x01;
+      if (*noescape)
+        payload |= 0x02;
+    }
+    writer.write<uint8_t>(payload);
+  }
+
   /// Retrieve the serialized size of the given FunctionInfo, for use in
   /// on-disk hash tables.
   static unsigned getFunctionInfoSize(const FunctionInfo &info) {
-    return 2 + sizeof(uint64_t) + getCommonEntityInfoSize(info) + 
-           2 + info.Params.size() * 1;
+    unsigned size = 2 + sizeof(uint64_t) + getCommonEntityInfoSize(info) + 2;
+
+    for (const auto &param : info.Params)
+      size += getParamInfoSize(param);
+
+    size += 2 + info.ResultType.size();
+    return size;
   }
 
   /// Emit a serialized representation of the function information.
@@ -709,22 +736,12 @@
 
     // Parameters.
     writer.write<uint16_t>(info.Params.size());
-    for (const auto &pi : info.Params) {
-      uint8_t payload = 0;
-      if (auto noescape = pi.isNoEscape()) {
-        payload |= 0x01;
-        if (*noescape)
-          payload |= 0x02;
-      }
+    for (const auto &pi : info.Params)
+      emitParamInfo(out, pi);
 
-      auto nullability = pi.getNullability();
-      payload = (payload << 1) | nullability.hasValue();
-
-      payload = payload << 2;
-      if (nullability)
-        payload |= static_cast<uint8_t>(*nullability);
-      writer.write<uint8_t>(payload);
-    }
+    // Result type.
+    writer.write<uint16_t>(info.ResultType.size());
+    out.write(info.ResultType.data(), info.ResultType.size());
   }
 
   /// Used to serialize the on-disk Objective-C method table.
diff --git a/lib/APINotes/APINotesYAMLCompiler.cpp b/lib/APINotes/APINotesYAMLCompiler.cpp
index 1f3783c..0ac0b6d 100644
--- a/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -173,6 +173,7 @@
     unsigned Position;
     Optional<bool> NoEscape = false;
     llvm::Optional<NullabilityKind> Nullability;
+    StringRef Type;
   };
   typedef std::vector<Param> ParamsSeq;
 
@@ -189,6 +190,7 @@
       = api_notes::FactoryAsInitKind::Infer;
     bool DesignatedInit = false;
     bool Required = false;
+    StringRef ResultType;
   };
   typedef std::vector<Method> MethodsSeq;
 
@@ -200,6 +202,7 @@
     Optional<bool> SwiftPrivate;
     StringRef SwiftName;
     Optional<bool> SwiftImportAsAccessors;
+    StringRef Type;
   };
   typedef std::vector<Property> PropertiesSeq;
 
@@ -224,6 +227,8 @@
     AvailabilityItem Availability;
     Optional<bool> SwiftPrivate;
     StringRef SwiftName;
+    StringRef Type;
+    StringRef ResultType;
   };
   typedef std::vector<Function> FunctionsSeq;
 
@@ -233,6 +238,7 @@
     AvailabilityItem Availability;
     Optional<bool> SwiftPrivate;
     StringRef SwiftName;
+    StringRef Type;
   };
   typedef std::vector<GlobalVariable> GlobalVariablesSeq;
 
@@ -385,6 +391,7 @@
         io.mapOptional("Nullability",     p.Nullability, 
                                           AbsentNullability);
         io.mapOptional("NoEscape",        p.NoEscape);
+        io.mapOptional("Type",            p.Type, StringRef(""));
       }
     };
 
@@ -400,6 +407,7 @@
         io.mapOptional("SwiftPrivate",    p.SwiftPrivate);
         io.mapOptional("SwiftName",       p.SwiftName);
         io.mapOptional("SwiftImportAsAccessors", p.SwiftImportAsAccessors);
+        io.mapOptional("Type",            p.Type, StringRef(""));
       }
     };
 
@@ -420,6 +428,7 @@
                                           api_notes::FactoryAsInitKind::Infer);
         io.mapOptional("DesignatedInit",  m.DesignatedInit, false);
         io.mapOptional("Required",        m.Required, false);
+        io.mapOptional("ResultType",      m.ResultType, StringRef(""));
       }
     };
 
@@ -451,6 +460,7 @@
         io.mapOptional("AvailabilityMsg",  f.Availability.Msg);
         io.mapOptional("SwiftPrivate",     f.SwiftPrivate);
         io.mapOptional("SwiftName",        f.SwiftName);
+        io.mapOptional("ResultType",       f.ResultType, StringRef(""));
       }
     };
 
@@ -464,6 +474,7 @@
         io.mapOptional("AvailabilityMsg", v.Availability.Msg);
         io.mapOptional("SwiftPrivate",    v.SwiftPrivate);
         io.mapOptional("SwiftName",       v.SwiftName);
+        io.mapOptional("Type",            v.Type, StringRef(""));
       }
     };
 
@@ -621,7 +632,7 @@
         if (p.Nullability)
           pi.setNullabilityAudited(*p.Nullability);
         pi.setNoEscape(p.NoEscape);
-
+        pi.setType(p.Type);
         while (outInfo.Params.size() <= p.Position) {
           outInfo.Params.push_back(ParamInfo());
         }
@@ -712,6 +723,7 @@
       mInfo.Required = meth.Required;
       if (meth.FactoryAsInit != FactoryAsInitKind::Infer)
         mInfo.setFactoryAsInitKind(meth.FactoryAsInit);
+      mInfo.ResultType = meth.ResultType;
 
       // Translate parameter information.
       convertParams(meth.Params, mInfo);
@@ -788,6 +800,7 @@
           pInfo.setNullabilityAudited(*prop.Nullability);
         if (prop.SwiftImportAsAccessors)
           pInfo.setSwiftImportAsAccessors(*prop.SwiftImportAsAccessors);
+        pInfo.setType(prop.Type);
         if (prop.Kind) {
           Writer->addObjCProperty(clID, prop.Name,
                                   *prop.Kind == MethodKind::Instance, pInfo,
@@ -844,6 +857,7 @@
         info.SwiftName = global.SwiftName;
         if (global.Nullability)
           info.setNullabilityAudited(*global.Nullability);
+        info.setType(global.Type);
         Writer->addGlobalVariable(global.Name, info, swiftVersion);
       }
 
@@ -867,7 +881,7 @@
         convertNullability(function.Nullability,
                            function.NullabilityOfRet,
                            info, function.Name);
-
+        info.ResultType = function.ResultType;
         Writer->addGlobalFunction(function.Name, info, swiftVersion);
       }
 
@@ -1112,6 +1126,7 @@
         p.Position = position++;
         p.Nullability = pi.getNullability();
         p.NoEscape = pi.isNoEscape();
+        p.Type = copyString(pi.getType());
         params.push_back(p);
       }
     }
@@ -1181,7 +1196,7 @@
       method.FactoryAsInit = info.getFactoryAsInitKind();
       method.DesignatedInit = info.DesignatedInit;
       method.Required = info.Required;
-
+      method.ResultType = copyString(info.ResultType);
       auto &items = getTopLevelItems(swiftVersion);
       knownContexts[contextID.Value].getContext(swiftVersion, items)
         .Methods.push_back(method);
@@ -1203,6 +1218,8 @@
 
       property.SwiftImportAsAccessors = info.getSwiftImportAsAccessors();
 
+      property.Type = copyString(info.getType());
+
       auto &items = getTopLevelItems(swiftVersion);
       knownContexts[contextID.Value].getContext(swiftVersion, items)
         .Properties.push_back(property);
@@ -1218,7 +1235,7 @@
       if (info.NumAdjustedNullable > 0)
         handleNullability(function.Nullability, function.NullabilityOfRet,
                           info, info.NumAdjustedNullable-1);
-
+      function.ResultType = copyString(info.ResultType);
       auto &items = getTopLevelItems(swiftVersion);
       items.Functions.push_back(function);
     }
@@ -1234,6 +1251,7 @@
       if (auto nullability = info.getNullability()) {
         global.Nullability = *nullability;
       }
+      global.Type = copyString(info.getType());
 
       auto &items = getTopLevelItems(swiftVersion);
       items.Globals.push_back(global);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ebf30a7..82195de 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -6558,3 +6558,68 @@
   }
   return false;
 }
+
+TypeResult Parser::parseTypeFromString(StringRef typeStr, StringRef context,
+                                       SourceLocation includeLoc) {
+  // Consume (unexpanded) tokens up to the end-of-directive.
+  SmallVector<Token, 4> tokens;
+  {
+    // Create a new buffer from which we will parse the type.
+    auto &sourceMgr = PP.getSourceManager();
+    FileID fileID = sourceMgr.createFileID(
+                      llvm::MemoryBuffer::getMemBufferCopy(typeStr, context),
+                      SrcMgr::C_User, 0, 0, includeLoc);
+
+    // Form a new lexer that references the buffer.
+    Lexer lexer(fileID, sourceMgr.getBuffer(fileID), PP);
+    lexer.setParsingPreprocessorDirective(true);
+    lexer.setIsPragmaLexer(true);
+
+    // Lex the tokens from that buffer.
+    Token tok;
+    do {
+      lexer.Lex(tok);
+      tokens.push_back(tok);
+    } while (tok.isNot(tok::eod));
+  }
+
+  // Replace the "eod" token with an "eof" token identifying the end of
+  // the provided string.
+  Token &endToken = tokens.back();
+  endToken.startToken();
+  endToken.setKind(tok::eof);
+  endToken.setLocation(Tok.getLocation());
+  endToken.setEofData(typeStr.data());
+
+  // Add the current token back.
+  tokens.push_back(Tok);
+
+  // Enter the tokens into the token stream.
+  PP.EnterTokenStream(tokens, /*DisableMacroExpansion=*/false);
+
+  // Consume the current token so that we'll start parsing the tokens we
+  // added to the stream.
+  ConsumeAnyToken();
+
+  // Enter a new scope.
+  ParseScope localScope(this, 0);
+
+  // Parse the type.
+  TypeResult result = ParseTypeName(nullptr);
+
+  // Check if we parsed the whole thing.
+  if (result.isUsable() &&
+      (Tok.isNot(tok::eof) || Tok.getEofData() != typeStr.data())) {
+    Diag(Tok.getLocation(), diag::err_type_unparsed);
+  }
+
+  // There could be leftover tokens (e.g. because of an error).
+  // Skip through until we reach the 'end of directive' token.
+  while (Tok.isNot(tok::eof))
+    ConsumeAnyToken();
+
+  // Consume the end token.
+  if (Tok.is(tok::eof) && Tok.getEofData() == typeStr.data())
+    ConsumeAnyToken();
+  return result;
+}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 2d35ad6..8be75c2 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -88,6 +88,11 @@
   PP.addCommentHandler(CommentSemaHandler.get());
 
   PP.setCodeCompletionHandler(*this);
+
+  Actions.ParseTypeFromStringCallback =
+    [this](StringRef typeStr, StringRef context, SourceLocation includeLoc) {
+      return this->parseTypeFromString(typeStr, context, includeLoc);
+    };
 }
 
 DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
@@ -420,6 +425,9 @@
 //===----------------------------------------------------------------------===//
 
 Parser::~Parser() {
+  // Clear out the parse-type-from-string callback.
+  Actions.ParseTypeFromStringCallback = nullptr;
+
   // If we still have scopes active, delete the scope tree.
   delete getCurScope();
   Actions.CurScope = nullptr;
diff --git a/lib/Sema/SemaAPINotes.cpp b/lib/Sema/SemaAPINotes.cpp
index 8f09313..064bbe8 100644
--- a/lib/Sema/SemaAPINotes.cpp
+++ b/lib/Sema/SemaAPINotes.cpp
@@ -264,10 +264,62 @@
                   role);
 }
 
+/// Check that the replacement type provided by API notes is reasonable.
+///
+/// This is a very weak form of ABI check.
+static bool checkAPINotesReplacementType(Sema &S, SourceLocation loc,
+                                         QualType origType,
+                                         QualType replacementType) {
+  if (S.Context.getTypeSize(origType) !=
+        S.Context.getTypeSize(replacementType)) {
+    S.Diag(loc, diag::err_incompatible_replacement_type)
+      << replacementType << origType;
+    return true;
+  }
+
+  return false;
+}
+
 /// Process API notes for a variable or property.
 static void ProcessAPINotes(Sema &S, Decl *D,
                             const api_notes::VariableInfo &info,
                             VersionedInfoRole role) {
+  // Type override.
+  if (role != VersionedInfoRole::Versioned &&
+      !info.getType().empty() && S.ParseTypeFromStringCallback) {
+    auto parsedType = S.ParseTypeFromStringCallback(info.getType(),
+                                                    "<API Notes>",
+                                                    D->getLocation());
+    if (parsedType.isUsable()) {
+      QualType type = Sema::GetTypeFromParser(parsedType.get());
+      auto typeInfo =
+        S.Context.getTrivialTypeSourceInfo(type, D->getLocation());
+
+      if (auto var = dyn_cast<VarDecl>(D)) {
+        // Make adjustments to parameter types.
+        if (isa<ParmVarDecl>(var)) {
+          type = S.adjustParameterTypeForObjCAutoRefCount(type,
+                                                          D->getLocation());
+          type = S.Context.getAdjustedParameterType(type);
+        }
+
+        if (!checkAPINotesReplacementType(S, var->getLocation(), var->getType(),
+                                          type)) {
+          var->setType(type);
+          var->setTypeSourceInfo(typeInfo);
+        }
+      } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
+        if (!checkAPINotesReplacementType(S, property->getLocation(),
+                                          property->getType(),
+                                          type)) {
+          property->setType(type, typeInfo);
+        }
+      } else {
+        llvm_unreachable("API notes allowed a type on an unknown declaration");
+      }
+    }
+  }
+
   // Nullability.
   if (auto Nullability = info.getNullability()) {
     applyNullability(S, D, *Nullability, role);
@@ -347,20 +399,75 @@
     NumParams = FD->getNumParams();
   else
     NumParams = MD->param_size();
-  
+
+  bool anyTypeChanged = false;
   for (unsigned I = 0; I != NumParams; ++I) {
     ParmVarDecl *Param;
     if (FD)
       Param = FD->getParamDecl(I);
     else
       Param = MD->param_begin()[I];
-    
+
+    QualType paramTypeBefore = Param->getType();
+
+    if (I < info.Params.size()) {
+      ProcessAPINotes(S, Param, info.Params[I], role);
+    }
+
     // Nullability.
     if (info.NullabilityAudited)
       applyNullability(S, Param, info.getParamTypeInfo(I), role);
 
-    if (I < info.Params.size()) {
-      ProcessAPINotes(S, Param, info.Params[I], role);
+    if (paramTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
+      anyTypeChanged = true;
+  }
+
+  // Result type override.
+  QualType overriddenResultType;
+  if (role != VersionedInfoRole::Versioned && !info.ResultType.empty() &&
+      S.ParseTypeFromStringCallback) {
+    auto parsedType = S.ParseTypeFromStringCallback(info.ResultType,
+                                                    "<API Notes>",
+                                                    D->getLocation());
+    if (parsedType.isUsable()) {
+      QualType resultType = Sema::GetTypeFromParser(parsedType.get());
+
+      if (MD) {
+        if (!checkAPINotesReplacementType(S, D->getLocation(),
+                                          MD->getReturnType(), resultType)) {
+          auto resultTypeInfo =
+            S.Context.getTrivialTypeSourceInfo(resultType, D->getLocation());
+          MD->setReturnType(resultType);
+          MD->setReturnTypeSourceInfo(resultTypeInfo);
+        }
+      } else if (!checkAPINotesReplacementType(S, FD->getLocation(),
+                                               FD->getReturnType(),
+                                               resultType)) {
+        overriddenResultType = resultType;
+        anyTypeChanged = true;
+      }
+    }
+  }
+
+  // If the result type or any of the parameter types changed for a function
+  // declaration, we have to rebuild the type.
+  if (FD && anyTypeChanged) {
+    if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
+      if (overriddenResultType.isNull())
+        overriddenResultType = fnProtoType->getReturnType();
+
+      SmallVector<QualType, 4> paramTypes;
+      for (auto param : FD->parameters()) {
+        paramTypes.push_back(param->getType());
+      }
+      FD->setType(S.Context.getFunctionType(overriddenResultType,
+                                            paramTypes,
+                                            fnProtoType->getExtProtoInfo()));
+    } else if (!overriddenResultType.isNull()) {
+      const auto *fnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
+      FD->setType(
+              S.Context.getFunctionNoProtoType(overriddenResultType,
+                                               fnNoProtoType->getExtInfo()));
     }
   }
 
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e10c545..94a455a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -11121,10 +11121,8 @@
   }
 }
 
-ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
-                                  SourceLocation NameLoc, IdentifierInfo *Name,
-                                  QualType T, TypeSourceInfo *TSInfo,
-                                  StorageClass SC) {
+QualType Sema::adjustParameterTypeForObjCAutoRefCount(QualType T,
+                                                      SourceLocation Loc) {
   // In ARC, infer a lifetime qualifier for appropriate parameter types.
   if (getLangOpts().ObjCAutoRefCount &&
       T.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -11139,7 +11137,7 @@
       if (!T.isConstQualified()) {
         DelayedDiagnostics.add(
             sema::DelayedDiagnostic::makeForbiddenType(
-            NameLoc, diag::err_arc_array_param_no_ownership, T, false));
+            Loc, diag::err_arc_array_param_no_ownership, T, false));
       }
       lifetime = Qualifiers::OCL_ExplicitNone;
     } else {
@@ -11148,6 +11146,16 @@
     T = Context.getLifetimeQualifiedType(T, lifetime);
   }
 
+  return T;
+}
+
+ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
+                                  SourceLocation NameLoc, IdentifierInfo *Name,
+                                  QualType T, TypeSourceInfo *TSInfo,
+                                  StorageClass SC) {
+  // Perform Objective-C ARC adjustments.
+  T = adjustParameterTypeForObjCAutoRefCount(T, NameLoc);
+
   ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
                                          Context.getAdjustedParameterType(T),
                                          TSInfo, SC, nullptr);
diff --git a/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes b/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes
index aa43d84..817af12 100644
--- a/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes
+++ b/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes
@@ -31,6 +31,31 @@
       - Selector: "initWithA:"
         MethodKind: Instance
         DesignatedInit: true
+  - Name: OverriddenTypes
+    Methods:
+      - Selector: "methodToMangle:second:"
+        MethodKind: Instance
+        ResultType: 'char *'
+        Parameters:
+          - Position: 0
+            Type: 'SOMEKIT_DOUBLE *'
+          - Position: 1
+            Type: 'float *'
+    Properties:
+      - Name: intPropertyToMangle
+        PropertyKind: Instance
+        Type: 'double *'
+Functions:
+  - Name: global_int_fun
+    ResultType: 'char *'
+    Parameters:
+      - Position: 0
+        Type: 'double *'
+      - Position: 1
+        Type: 'float *'
+Globals:
+  - Name: global_int_ptr
+    Type: 'double *'
 SwiftVersions:
   - Version: 3.0
     Classes:
diff --git a/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes b/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes
index aa43d84..d2d1003 100644
--- a/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes
+++ b/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes
@@ -31,6 +31,31 @@
       - Selector: "initWithA:"
         MethodKind: Instance
         DesignatedInit: true
+  - Name: OverriddenTypes
+    Methods:
+      - Selector: "methodToMangle:second:"
+        MethodKind: Instance
+        ResultType: 'char *'
+        Parameters:
+          - Position: 0
+            Type: 'SOMEKIT_DOUBLE *'
+          - Position: 1
+            Type: 'float *'
+    Properties:
+      - Name: intPropertyToMangle
+        PropertyKind: Instance
+        Type: 'double *'
+Functions:
+  - Name: global_int_fun
+    ResultType: 'char *'
+    Parameters:
+      - Position: 0
+        Type: 'double *'
+      - Position: 1
+        Type: 'float *'
+Globals:
+  - Name: global_int_ptr
+    Type: 'double (*)(int, int)'
 SwiftVersions:
   - Version: 3.0
     Classes:
diff --git a/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.h b/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.h
index 60d9afa..42a9fbc 100644
--- a/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.h
+++ b/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.h
@@ -37,4 +37,16 @@
 
 #import <SomeKit/SomeKitExplicitNullability.h>
 
+extern int *global_int_ptr;
+
+int *global_int_fun(int *ptr, int *ptr2);
+
+#define SOMEKIT_DOUBLE double
+
+__attribute__((objc_root_class))
+@interface OverriddenTypes
+-(int *)methodToMangle:(int *)ptr1 second:(int *)ptr2;
+@property int *intPropertyToMangle;
+@end
+
 #endif
diff --git a/test/APINotes/Inputs/Headers/BrokenTypes.apinotes b/test/APINotes/Inputs/Headers/BrokenTypes.apinotes
new file mode 100644
index 0000000..00f7b50
--- /dev/null
+++ b/test/APINotes/Inputs/Headers/BrokenTypes.apinotes
@@ -0,0 +1,10 @@
+Name: BrokenTypes
+Functions:
+  - Name: break_me_function
+    ResultType: 'int * with extra junk'
+    Parameters:
+      - Position: 0
+        Type: 'not_a_type'
+Globals:
+  - Name: break_me_variable
+    Type: 'double'
diff --git a/test/APINotes/Inputs/Headers/BrokenTypes.h b/test/APINotes/Inputs/Headers/BrokenTypes.h
new file mode 100644
index 0000000..fee054b
--- /dev/null
+++ b/test/APINotes/Inputs/Headers/BrokenTypes.h
@@ -0,0 +1,8 @@
+#ifndef BROKEN_TYPES_H
+#define BROKEN_TYPES_H
+
+char break_me_function(void *ptr);
+
+extern char break_me_variable;
+
+#endif // BROKEN_TYPES_H
diff --git a/test/APINotes/Inputs/Headers/module.modulemap b/test/APINotes/Inputs/Headers/module.modulemap
index 3e59efc..54af0f5 100644
--- a/test/APINotes/Inputs/Headers/module.modulemap
+++ b/test/APINotes/Inputs/Headers/module.modulemap
@@ -1,3 +1,7 @@
 module HeaderLib {
   header "HeaderLib.h"
 }
+
+module BrokenTypes {
+  header "BrokenTypes.h"
+}
diff --git a/test/APINotes/Inputs/roundtrip.apinotes b/test/APINotes/Inputs/roundtrip.apinotes
index 68169c4..05599a7 100644
--- a/test/APINotes/Inputs/roundtrip.apinotes
+++ b/test/APINotes/Inputs/roundtrip.apinotes
@@ -17,6 +17,7 @@
         SwiftPrivate:    false
         SwiftName:       ''
         FactoryAsInit:   C
+        ResultType:      id
       - Selector:        init
         MethodKind:      Instance
         NullabilityOfRet: U
@@ -77,6 +78,7 @@
           - Position:        1
           - Position:        2
             NoEscape:        true
+            Type:            id
         Nullability:     [ N, N, O ]
         NullabilityOfRet: N
         Availability:    available
@@ -97,6 +99,7 @@
         Availability:    available
         AvailabilityMsg: ''
         SwiftName:       enclosing
+        Type:            id
       - Name:            makeBackingLayer
         PropertyKind:    Class
         Nullability:     N
@@ -111,6 +114,7 @@
     Availability:    available
     AvailabilityMsg: ''
     SwiftName:       'availableWindowDepths()'
+    ResultType:      NSInteger
 Globals:         
   - Name:            NSCalibratedWhiteColorSpace
     Nullability:     N
@@ -118,6 +122,7 @@
     AvailabilityMsg: ''
     SwiftPrivate:    false
     SwiftName:       calibratedWhite
+    Type:            id
 Enumerators:     
   - Name:            NSColorRed
     Availability:    available
diff --git a/test/APINotes/broken_types.m b/test/APINotes/broken_types.m
new file mode 100644
index 0000000..164ae79
--- /dev/null
+++ b/test/APINotes/broken_types.m
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s 2> %t.err
+// RUN: FileCheck %s < %t.err
+
+#include "BrokenTypes.h"
+
+// CHECK: <API Notes>:1:1: error: unknown type name 'not_a_type'
+// CHECK-NEXT: not_a_type
+// CHECK-NEXT: ^
+
+// CHECK: <API Notes>:1:7: error: unparsed tokens following type
+// CHECK-NEXT: int * with extra junk
+// CHECK-NEXT:       ^
+
+// CHECK: BrokenTypes.h:4:6: error: API notes replacement type 'int *' has a different size from original type 'char'
+
+// CHECK: BrokenTypes.h:6:13: error: API notes replacement type 'double' has a different size from original type 'char'
+
+// CHECK: 5 errors generated.
diff --git a/test/APINotes/types.m b/test/APINotes/types.m
new file mode 100644
index 0000000..fccff80
--- /dev/null
+++ b/test/APINotes/types.m
@@ -0,0 +1,23 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify
+
+#import <SomeKit/SomeKit.h>
+
+void test(OverriddenTypes *overridden) {
+  int *ip1 = global_int_ptr; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double (*)(int, int)'}}
+
+  int *ip2 = global_int_fun( // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}}
+               ip2, // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'double *'}}
+               ip2); // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'float *'}}
+
+  int *ip3 = [overridden // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}}
+                methodToMangle: ip3 // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'double *'}}
+                        second: ip3]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'float *'}}
+
+  int *ip4 = overridden.intPropertyToMangle; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double *'}}
+}
+
+// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr' here}}
+// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr2' here}}
+// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr1' here}}
+// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr2' here}}