sammccall created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, ilya-biryukov.
Herald added a project: clang.

In many places, Sema refuses to create an Expr if it encounters an error.
This means that broken code has no representation in the AST. As well as
the broken node itself, child Exprs and parent Exprs are usually dropped.

This is terrible for tools that rely on the AST and see a lot of broken
code (e.g. libclang-based IDEs and clangd).
In the expression `foo(a, takes2args(b))`, "go to definition" doesn't
work on any of the subexpressions. And after `takes2args(x).`, member
completion doesn't work, although in practice we almost always know the type.

This patch introduces RecoveryExpr. This AST node represents broken
code, and has very weak semantics. It's part of the final AST (unlike TypoExpr)
but can't produce code, as it's always accompanied by an error.
It captures valid subexpressions without checking or assigning them meaning.
Some RecoveryExprs have a known type (e.g. a broken non-overloaded call).
Where the type is unknown, it is modeled as a new type ErrorTy.

In this patch, ErrorTy is not dependent. See D61722 
<https://reviews.llvm.org/D61722> for that approach.
Here ErrorTy must be explicitly handled on many paths, similar to dependent
types (though also for C). I've certainly missed some that tests didn't flag.

Initiallly, RecoveryExpr is emitted in two common cases:

- a function call where overload resolution failed (most typically: wrong args) 
Callee is captured as an UnresolvedLookupExpr, and args are captured. Type is 
available if the "best" candidates have the same return type.
- access of a nonexistent member Base expression is captured, type is never 
available.

Test changes:

- SemaCXX/enable_if.cpp: we now emit more detailed diagnostics (the 
non-constexpr subexpression is inside a function call), which breaks the 
heuristic that tries to move the whole diagnostic to the subexpression 
location. This case (IMO) doesn't matter much: the subexpression is invalid, 
flagging it as non-constexpr isn't very useful to start with.
- SemaTemplate/instantiate-function-params.cpp: it looks like the testcase was 
minimized in an unrealistic way: the only version of if_ doesn't have `type` 
and the only version of `requirement_` doesn't have `failed`, and it seems 
reasonable to diagnose this. If the precise invalid form is required, I can add 
another 17 expect-*s to the test, or remove -verify so we only fail on 
crashing. Original patch adding this test is very terse: 
https://github.com/llvm/llvm-project/commit/5112157958438005095aff805853f9b14ba974eb
 Testcase subsequently modified to test for a crash: 
https://github.com/llvm/llvm-project/commit/a02bb341552b2b91c93e708645c32d11cc4133d2
- CodeGen/builtins-systemz-zvector[2]-error.c: these tests now generate extra 
noisy (but correct) diagnostics: vecintrin.h uses a cast to an invalid type to 
suppress them, and the cast now succeeds. The right fix is probably to rewrite 
the builtin header somehow, I haven't investigated fully yet.


Repository:
  rC Clang

https://reviews.llvm.org/D62184

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/AST/Expr.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/AST/Stmt.h
  include/clang/AST/TextNodeDumper.h
  include/clang/AST/Type.h
  include/clang/Basic/StmtNodes.td
  include/clang/Sema/Initialization.h
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/ASTContext.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprClassification.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/MicrosoftMangle.cpp
  lib/AST/NSAPI.cpp
  lib/AST/Stmt.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/AST/TextNodeDumper.cpp
  lib/AST/Type.cpp
  lib/AST/TypeLoc.cpp
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CodeGenTypes.cpp
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Index/USRGeneration.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaCast.cpp
  lib/Sema/SemaCoroutine.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaExceptionSpec.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/SemaExprMember.cpp
  lib/Sema/SemaInit.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaPseudoObject.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
  test/CodeCompletion/member-access.cpp
  test/Index/getcursor-recovery.cpp
  test/Parser/recovery.c
  test/SemaCXX/constructor-initializer.cpp
  test/SemaCXX/enable_if.cpp
  test/SemaTemplate/dependent-names.cpp
  test/SemaTemplate/instantiate-function-params.cpp
  test/SemaTemplate/instantiate-init.cpp
  tools/libclang/CIndex.cpp
  tools/libclang/CXCursor.cpp

Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -289,6 +289,7 @@
   case Stmt::ObjCDictionaryLiteralClass:
   case Stmt::ObjCBoxedExprClass:
   case Stmt::ObjCSubscriptRefExprClass:
+  case Stmt::RecoveryExprClass:
     K = CXCursor_UnexposedExpr;
     break;
 
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1516,6 +1516,7 @@
   case BuiltinType::Void:
   case BuiltinType::NullPtr:
   case BuiltinType::Dependent:
+  case BuiltinType::Error:
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
   case BuiltinType::Id:
 #include "clang/Basic/OpenCLImageTypes.def"
Index: test/SemaTemplate/instantiate-init.cpp
===================================================================
--- test/SemaTemplate/instantiate-init.cpp
+++ test/SemaTemplate/instantiate-init.cpp
@@ -100,9 +100,9 @@
     integral_c<1> ic1 = array_lengthof(Description<int>::data);
     (void)sizeof(array_lengthof(Description<float>::data));
 
-    sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}}
-                          Description<int*>::data // expected-note{{in instantiation of static data member 'PR7985::Description<int *>::data' requested here}}
-                          ));
+    (void)sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}}
+        Description<int *>::data // expected-note{{in instantiation of static data member 'PR7985::Description<int *>::data' requested here}}
+        ));
 
     array_lengthof(Description<float*>::data); // expected-error{{no matching function for call to 'array_lengthof'}}
   }
Index: test/SemaTemplate/instantiate-function-params.cpp
===================================================================
--- test/SemaTemplate/instantiate-function-params.cpp
+++ test/SemaTemplate/instantiate-function-params.cpp
@@ -3,7 +3,7 @@
 // PR6619
 template<bool C> struct if_c { };
 template<typename T1> struct if_ {
-  typedef if_c< static_cast<bool>(T1::value)> almost_type_; // expected-note 5{{in instantiation}}
+  typedef if_c< static_cast<bool>(T1::value)> type; // expected-note 5{{in instantiation}}
 };
 template <class Model, void (Model::*)()> struct wrap_constraints { };
 template <class Model> 
@@ -17,7 +17,9 @@
 template <class ModelFn> struct requirement_;
 template <void(*)()> struct instantiate {
 };
-template <class Model> struct requirement_<void(*)(Model)>                           : if_<       not_satisfied<Model>         >::type { // expected-note 5{{in instantiation}}
+template <class Model>
+struct requirement_<void (*)(Model)> : if_<not_satisfied<Model>>::type { // expected-note 5{{in instantiation}}
+  static void failed();
 };
 template <class Model> struct usage_requirements {
 };
Index: test/SemaTemplate/dependent-names.cpp
===================================================================
--- test/SemaTemplate/dependent-names.cpp
+++ test/SemaTemplate/dependent-names.cpp
@@ -176,7 +176,7 @@
     void f(char&); // expected-note {{candidate function not viable}}
 
     template<typename T> struct C {
-      static const int n = f(T()); // expected-error {{no matching function}}
+      static const int n = f(T()); // expected-error {{no matching function}} expected-error {{variable of type 'const int' with an lvalue of type 'void'}}
     };
   }
 
Index: test/SemaCXX/enable_if.cpp
===================================================================
--- test/SemaCXX/enable_if.cpp
+++ test/SemaCXX/enable_if.cpp
@@ -406,16 +406,16 @@
 static_assert(callNoError<1>() == 0, "");
 
 template <int N> constexpr int templated() __attribute__((enable_if(N, ""))) {
-  return 1;
+  return 1; //expected-note@-1 2 {{candidate disabled}}
 }
 
-constexpr int A = templated<0>(); // expected-error{{no matching function for call to 'templated'}} expected-note@-4{{candidate disabled}}
+constexpr int A = templated<0>(); // expected-error{{no matching function for call to 'templated'}}
 static_assert(templated<1>() == 1, "");
 
-template <int N> constexpr int callTemplated() { return templated<N>(); }
+template <int N> constexpr int callTemplated() { return templated<N>(); } // expected-error{{no matching function for call to 'templated'}} expected-note{{subexpression not valid}}
 
-constexpr int B = 10 + // the carat for the error should be pointing to the problematic call (on the next line), not here.
-    callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-3{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-10{{candidate disabled}}
+constexpr int B = 10 +                // expected-error{{initialized by a constant expression}}
+                  callTemplated<0>(); // expected-note{{in instantiation of function template}} expected-note{{in call to 'callTemplated()'}}
 static_assert(callTemplated<1>() == 1, "");
 }
 
Index: test/SemaCXX/constructor-initializer.cpp
===================================================================
--- test/SemaCXX/constructor-initializer.cpp
+++ test/SemaCXX/constructor-initializer.cpp
@@ -250,7 +250,7 @@
     B(const String& s, int e=0) // expected-error {{unknown type name}} 
       : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}}
     B(const B& e)
-      : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{does not name}} \
+      : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error 2 {{does not name}} \
       // expected-error {{no member named 'm_String' in 'test3::B'}}
     }
   };
Index: test/Parser/recovery.c
===================================================================
--- test/Parser/recovery.c
+++ test/Parser/recovery.c
@@ -33,8 +33,8 @@
   else
     ;
   
-  if ((x.hello == 0))   // expected-error {{no member named 'hello'}}
-    test(0);
+  if ((x.hello == 0))   // expected-error {{no member named 'hello'}} expected-warning {{extraneous parentheses}}
+    test(0); // expected-note@-1 {{remove extraneous parentheses}} expected-note@-1 {{turn this equality comparison into an assignment}}
   else
     ;
 
Index: test/Index/getcursor-recovery.cpp
===================================================================
--- /dev/null
+++ test/Index/getcursor-recovery.cpp
@@ -0,0 +1,50 @@
+int foo(int, int);
+int foo(int, double);
+int x;
+
+void testTypedRecoveryExpr() {
+  // Inner foo() is a recoveryexpr of type int. Outer foo() is a regular call.
+  foo(x, foo(x));
+}
+// RUN: c-index-test -cursor-at=%s:7:3 %s | FileCheck -check-prefix=OUTER-FOO %s
+// OUTER-FOO: DeclRefExpr=foo:1:5
+// RUN: c-index-test -cursor-at=%s:7:7 %s | FileCheck -check-prefix=OUTER-X %s
+// OUTER-X: DeclRefExpr=x:3:5
+// RUN: c-index-test -cursor-at=%s:7:10 %s | FileCheck -check-prefix=INNER-FOO %s
+// INNER-FOO: OverloadedDeclRef=foo[2:5, 1:5]
+// RUN: c-index-test -cursor-at=%s:7:14 %s | FileCheck -check-prefix=INNER-X %s
+// INNER-X: DeclRefExpr=x:3:5
+
+
+
+
+int bar(int, int);
+int bar(int, double);
+int y;
+
+void testUntypedRecoveryExpr() {
+  // Inner bar() is a recoveryexpr of RecoveryTy. Outer is a dependent CallExpr.
+  bar(y, bar(y));
+}
+// RUN: c-index-test -cursor-at=%s:27:3 %s | FileCheck -check-prefix=OUTER-BAR %s
+// OUTER-BAR: DeclRefExpr=bar:21:5
+// RUN: c-index-test -cursor-at=%s:27:7 %s | FileCheck -check-prefix=OUTER-Y %s
+// OUTER-Y: DeclRefExpr=y:23:5
+// RUN: c-index-test -cursor-at=%s:27:10 %s | FileCheck -check-prefix=INNER-BAR %s
+// INNER-BAR: OverloadedDeclRef=bar[22:5, 21:5]
+// RUN: c-index-test -cursor-at=%s:27:14 %s | FileCheck -check-prefix=INNER-Y %s
+// INNER-Y: DeclRefExpr=y:23:5
+
+
+
+
+struct S{} s;
+int z;
+
+void testInvalidMember() {
+  s.mem(z);
+}
+// RUN: c-index-test -cursor-at=%s:45:3 %s | FileCheck -check-prefix=S %s
+// S: DeclRefExpr=s:41:12
+// RUN: c-index-test -cursor-at=%s:45:9 %s | FileCheck -check-prefix=Z %s
+// Z: DeclRefExpr=z:42:5
Index: test/CodeCompletion/member-access.cpp
===================================================================
--- test/CodeCompletion/member-access.cpp
+++ test/CodeCompletion/member-access.cpp
@@ -210,3 +210,14 @@
 // CHECK-CC9: memfun2 (InBase) : [#void#][#Base3::#]memfun2(<#int#>) (requires fix-it: {181:4-181:5} to "->")
 // CHECK-CC9: memfun3 : [#int#]memfun3(<#int#>) (requires fix-it: {181:4-181:5} to "->")
 // CHECK-CC9: operator-> : [#Derived *#]operator->()[# const#]
+
+struct S { int MysteryMember; };
+S overloaded(int);
+S overloaded(double);
+void foo() {
+  // No overload matches, but we recover with the correct type.
+  overloaded().
+}
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:219:16 %s -o - | FileCheck -check-prefix=CHECK-CC10 %s
+// CHECK-CC10: [#int#]MysteryMember
+
Index: test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
===================================================================
--- test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
+++ test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
@@ -124,6 +124,7 @@
   template<typename T, typename U> using U = S<T, int, U>; // expected-note 2{{template parameter is declared here}}
   template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}}
   S<int, int, double> &s1 = f({}, 0, 0.0); // expected-error {{no matching function}}
+  // f() is invalid, so: expected-error@-1 {{cannot bind to a value of unrelated type 'int'}}
 }
 
 namespace PR18401 {
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1174,6 +1174,7 @@
     case Stmt::UnresolvedLookupExprClass:
     case Stmt::UnresolvedMemberExprClass:
     case Stmt::TypoExprClass:
+    case Stmt::RecoveryExprClass:
     case Stmt::CXXNoexceptExprClass:
     case Stmt::PackExpansionExprClass:
     case Stmt::SubstNonTypeTemplateParmPackExprClass:
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -11,6 +11,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
@@ -655,6 +656,17 @@
   Code = serialization::EXPR_CALL;
 }
 
+void ASTStmtWriter::VisitRecoveryExpr(RecoveryExpr *E) {
+  VisitExpr(E);
+  Record.push_back(std::distance(E->children().begin(), E->children().end()));
+  Record.AddSourceLocation(E->getBeginLoc());
+  Record.AddSourceLocation(E->getEndLoc());
+  Record.push_back(E->attemptedStmtClass());
+  for (Stmt* Child : E->children())
+    Record.AddStmt(Child);
+  Code = serialization::EXPR_RECOVERY;
+}
+
 void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
   // Don't call VisitExpr, we'll write everything here.
 
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -1838,6 +1838,20 @@
   llvm_unreachable("Cannot read TypoExpr nodes");
 }
 
+void ASTStmtReader::VisitRecoveryExpr(RecoveryExpr *E) {
+  VisitExpr(E);
+  unsigned NumArgs = Record.readInt();
+  E->BeginLoc = ReadSourceLocation();
+  E->EndLoc = ReadSourceLocation();
+  E->Attempted = (Stmt::StmtClass)Record.readInt();
+  assert(
+      (NumArgs == std::distance(E->children().begin(), E->children().end())) &&
+      "Wrong NumArgs!");
+  (void)NumArgs;
+  for (Stmt*& Child : E->children())
+    Child = Record.readSubStmt();
+}
+
 //===----------------------------------------------------------------------===//
 // Microsoft Expressions and Statements
 //===----------------------------------------------------------------------===//
@@ -2544,6 +2558,11 @@
           Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
       break;
 
+    case EXPR_RECOVERY:
+      S = RecoveryExpr::CreateEmpty(
+          Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields]);
+      break;
+
     case EXPR_MEMBER: {
       // We load everything here and fully initialize it at creation.
       // That way we can use MemberExpr::Create and don't have to duplicate its
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -6959,6 +6959,9 @@
     case PREDEF_TYPE_OVERLOAD_ID:
       T = Context.OverloadTy;
       break;
+    case PREDEF_TYPE_ERROR_ID:
+      T = Context.ErrorTy;
+      break;
     case PREDEF_TYPE_BOUND_MEMBER:
       T = Context.BoundMemberTy;
       break;
Index: lib/Serialization/ASTCommon.cpp
===================================================================
--- lib/Serialization/ASTCommon.cpp
+++ lib/Serialization/ASTCommon.cpp
@@ -183,6 +183,9 @@
   case BuiltinType::Overload:
     ID = PREDEF_TYPE_OVERLOAD_ID;
     break;
+  case BuiltinType::Error:
+    ID = PREDEF_TYPE_ERROR_ID;
+    break;
   case BuiltinType::BoundMember:
     ID = PREDEF_TYPE_BOUND_MEMBER;
     break;
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -9391,6 +9391,12 @@
   return E;
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformRecoveryExpr(RecoveryExpr *E) {
+  return E;
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) {
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -3291,7 +3291,8 @@
   // pickier with blocks than for normal functions because we don't have GCC
   // compatibility to worry about here.
   const VarDecl *NRVOCandidate = nullptr;
-  if (FnRetType->isDependentType()) {
+  if (FnRetType->isDependentType() || FnRetType->isErrorType() ||
+      (RetValExp && RetValExp->hasErrorType())) {
     // Delay processing for now.  TODO: there are lots of dependent
     // types we can conclusively prove aren't void.
   } else if (FnRetType->isVoidType()) {
@@ -3619,7 +3620,7 @@
 
         // Drop the expression.
         RetValExp = nullptr;
-      } else if (!RetValExp->isTypeDependent()) {
+      } else if (!RetValExp->isTypeDependent() && !RetValExp->hasErrorType()) {
         // C99 6.8.6.4p1 (ext_ since GCC warns)
         unsigned D = diag::ext_return_has_expr;
         if (RetValExp->getType()->isVoidType()) {
Index: lib/Sema/SemaPseudoObject.cpp
===================================================================
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -1484,7 +1484,7 @@
       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
                               SourceLocation(), GetterName, nullptr);
-  if (GetterExpr.isInvalid()) {
+  if (GetterExpr.isInvalid() || isa<RecoveryExpr>(GetterExpr.get())) {
     S.Diag(RefExpr->getMemberLoc(),
            diag::err_cannot_find_suitable_accessor) << 0 /* getter */
       << RefExpr->getPropertyDecl();
@@ -1513,7 +1513,7 @@
       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
                               SourceLocation(), SetterName, nullptr);
-  if (SetterExpr.isInvalid()) {
+  if (SetterExpr.isInvalid() || isa<RecoveryExpr>(SetterExpr.get())) {
     S.Diag(RefExpr->getMemberLoc(),
            diag::err_cannot_find_suitable_accessor) << 1 /* setter */
       << RefExpr->getPropertyDecl();
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/Type.h"
 #include "clang/Sema/Overload.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
@@ -12114,6 +12115,42 @@
   return false;
 }
 
+// Guess at what the return type for an unresolvable overload should be.
+static QualType chooseRecoveryType(OverloadCandidateSet &CS,
+                                   OverloadCandidateSet::iterator *Best) {
+  llvm::Optional<QualType> Result;
+  // Adjust Type after seeing a candidate.
+  auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) {
+    if (!Candidate.Function)
+      return;
+    QualType T = Candidate.Function->getCallResultType();
+    if (T.isNull())
+      return;
+    if (!Result)
+      Result = T;
+    else if (Result != T)
+      Result = QualType();
+  };
+
+  // Look for an unambiguous type from a progressively larger subset.
+  // e.g. if types disagree, but all *viable* overloads return int, choose int.
+  //
+  // First, consider only the best candidate.
+  if (Best && *Best != CS.end())
+    ConsiderCandidate(**Best);
+  // Next, consider only viable candidates.
+  if (!Result)
+    for (const auto& C : CS)
+      if (C.Viable)
+        ConsiderCandidate(C);
+  // Finally, consider all candidates.
+  if (!Result)
+    for (const auto& C : CS)
+      ConsiderCandidate(C);
+
+  return Result.getValueOr(QualType());
+}
+
 /// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns
 /// the completed call expression. If overload resolution fails, emits
 /// diagnostics and returns ExprError()
@@ -12204,7 +12241,16 @@
   }
 
   // Overload resolution failed.
-  return ExprError();
+  if (!AllowTypoCorrection)
+    return ExprError();
+
+  // Build a RecoveryExpr so that arguments aren't orphaned in the AST.
+  // Also record the unresolved OverloadExpr, and the type (if unambiguous).
+  SmallVector<Stmt*, 8> SubExprs = {Fn};
+  SubExprs.append(Args.begin(), Args.end());
+  return RecoveryExpr::Create(
+      SemaRef.Context, chooseRecoveryType(*CandidateSet, Best),
+      Stmt::CallExprClass, Fn->getBeginLoc(), RParenLoc, SubExprs);
 }
 
 static void markUnaddressableCandidatesUnviable(Sema &S,
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -5464,6 +5464,10 @@
   //   parenthesized list of expressions.
   QualType DestType = Entity.getType();
 
+  if (DestType->isErrorType() || Expr::hasAnyErrorArguments(Args)) {
+    SequenceKind = ErrorSequence;
+    return;
+  }
   if (DestType->isDependentType() ||
       Expr::hasAnyTypeDependentArguments(Args)) {
     SequenceKind = DependentSequence;
@@ -7384,45 +7388,42 @@
                                       ZeroInitializationFixit);
   }
 
-  if (getKind() == DependentSequence) {
     // If the declaration is a non-dependent, incomplete array type
     // that has an initializer, then its type will be completed once
     // the initializer is instantiated.
-    if (ResultType && !Entity.getType()->isDependentType() &&
-        Args.size() == 1) {
-      QualType DeclType = Entity.getType();
-      if (const IncompleteArrayType *ArrayT
-                           = S.Context.getAsIncompleteArrayType(DeclType)) {
-        // FIXME: We don't currently have the ability to accurately
-        // compute the length of an initializer list without
-        // performing full type-checking of the initializer list
-        // (since we have to determine where braces are implicitly
-        // introduced and such).  So, we fall back to making the array
-        // type a dependently-sized array type with no specified
-        // bound.
-        if (isa<InitListExpr>((Expr *)Args[0])) {
-          SourceRange Brackets;
-
-          // Scavange the location of the brackets from the entity, if we can.
-          if (auto *DD = dyn_cast_or_null<DeclaratorDecl>(Entity.getDecl())) {
-            if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
-              TypeLoc TL = TInfo->getTypeLoc();
-              if (IncompleteArrayTypeLoc ArrayLoc =
-                      TL.getAs<IncompleteArrayTypeLoc>())
-                Brackets = ArrayLoc.getBracketsRange();
-            }
+  if (getKind() == DependentSequence && ResultType &&
+      !Entity.getType()->isDependentType() && Args.size() == 1) {
+    QualType DeclType = Entity.getType();
+    if (const IncompleteArrayType *ArrayT =
+            S.Context.getAsIncompleteArrayType(DeclType)) {
+      // FIXME: We don't currently have the ability to accurately
+      // compute the length of an initializer list without
+      // performing full type-checking of the initializer list
+      // (since we have to determine where braces are implicitly
+      // introduced and such).  So, we fall back to making the array
+      // type a dependently-sized array type with no specified
+      // bound.
+      if (isa<InitListExpr>((Expr *)Args[0])) {
+        SourceRange Brackets;
+
+        // Scavange the location of the brackets from the entity, if we can.
+        if (auto *DD = dyn_cast_or_null<DeclaratorDecl>(Entity.getDecl())) {
+          if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
+            TypeLoc TL = TInfo->getTypeLoc();
+            if (IncompleteArrayTypeLoc ArrayLoc =
+                    TL.getAs<IncompleteArrayTypeLoc>())
+              Brackets = ArrayLoc.getBracketsRange();
           }
-
-          *ResultType
-            = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
-                                                   /*NumElts=*/nullptr,
-                                                   ArrayT->getSizeModifier(),
-                                       ArrayT->getIndexTypeCVRQualifiers(),
-                                                   Brackets);
         }
 
+        *ResultType = S.Context.getDependentSizedArrayType(
+            ArrayT->getElementType(),
+            /*NumElts=*/nullptr, ArrayT->getSizeModifier(),
+            ArrayT->getIndexTypeCVRQualifiers(), Brackets);
       }
     }
+  }
+  if (getKind() == DependentSequence || getKind() == ErrorSequence) {
     if (Kind.getKind() == InitializationKind::IK_Direct &&
         !Kind.isExplicitCast()) {
       // Rebuild the ParenListExpr.
@@ -8923,6 +8924,10 @@
     OS << "Dependent sequence\n";
     return;
 
+  case ErrorSequence:
+    OS << "Error sequence\n";
+    return;
+
   case NormalSequence:
     OS << "Normal sequence: ";
     break;
Index: lib/Sema/SemaExprMember.cpp
===================================================================
--- lib/Sema/SemaExprMember.cpp
+++ lib/Sema/SemaExprMember.cpp
@@ -1022,7 +1022,21 @@
     Diag(R.getNameLoc(), diag::err_no_member)
       << MemberName << DC
       << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
-    return ExprError();
+
+    SourceLocation BeginLoc;
+    if (BaseExpr)
+      BeginLoc = BaseExpr->getBeginLoc();
+    if (BeginLoc.isInvalid())
+      BeginLoc = TemplateKWLoc;
+    if (BeginLoc.isInvalid())
+      BeginLoc = SS.getBeginLoc();
+    if (BeginLoc.isInvalid())
+      BeginLoc = MemberNameInfo.getBeginLoc();
+    llvm::SmallVector<Stmt*, 1> SubExprs;
+    if (BaseExpr)
+      SubExprs.push_back(BaseExpr);
+    return RecoveryExpr::Create(Context, QualType(), Stmt::MemberExprClass,
+                                BeginLoc, MemberNameInfo.getEndLoc(), SubExprs);
   }
 
   // Diagnose lookups that find only declarations from a non-base
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -5420,6 +5420,8 @@
   assert(!LHS.get()->getType()->isPlaceholderType() &&
          !RHS.get()->getType()->isPlaceholderType() &&
          "placeholders should have been weeded out by now");
+  if (LHS.get()->hasErrorType() || RHS.get()->hasErrorType())
+    return Context.ErrorTy;
 
   // The LHS undergoes lvalue conversions if this is ->*, and undergoes the
   // temporary materialization conversion otherwise.
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -5562,6 +5562,10 @@
       Fn = result.get();
     }
 
+    // If the callee is so broken we don't know its type, don't check it.
+    if (Fn->hasErrorType())
+      return CallExpr::Create(Context, Fn, ArgExprs, Context.ErrorTy, VK_RValue,
+                              RParenLoc);
     // Determine whether this is a dependent call inside a C++ template,
     // in which case we won't do any semantic analysis now.
     if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) {
@@ -6382,6 +6386,8 @@
                            CastKind &Kind) {
   assert(VectorTy->isVectorType() && "Not a vector type!");
 
+  if (VectorTy->isErrorType() || Ty->isErrorType())
+    return false;
   if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
     if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
       return Diag(R.getBegin(),
@@ -8825,6 +8831,9 @@
   QualType LHSType = LHS.get()->getType().getUnqualifiedType();
   QualType RHSType = RHS.get()->getType().getUnqualifiedType();
 
+  if (LHSType->isErrorType() || RHSType->isErrorType())
+    return Context.ErrorTy;
+
   const VectorType *LHSVecType = LHSType->getAs<VectorType>();
   const VectorType *RHSVecType = RHSType->getAs<VectorType>();
   assert(LHSVecType || RHSVecType);
@@ -9068,8 +9077,8 @@
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
 
-
-  if (compType.isNull() || !compType->isArithmeticType())
+  if (compType.isNull() ||
+      (!compType->isArithmeticType() && !compType->isErrorType()))
     return InvalidOperands(Loc, LHS, RHS);
   if (IsDiv) {
     DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
@@ -9096,7 +9105,8 @@
   if (LHS.isInvalid() || RHS.isInvalid())
     return QualType();
 
-  if (compType.isNull() || !compType->isIntegerType())
+  if (compType.isNull() ||
+      (!compType->isIntegerType() && !compType->isErrorType()))
     return InvalidOperands(Loc, LHS, RHS);
   DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
   return compType;
@@ -9392,7 +9402,8 @@
   }
 
   // handle the common case first (both operands are arithmetic).
-  if (!compType.isNull() && compType->isArithmeticType()) {
+  if (!compType.isNull() &&
+      (compType->isArithmeticType() || compType->isErrorType())) {
     if (CompLHSTy) *CompLHSTy = compType;
     return compType;
   }
@@ -9482,7 +9493,8 @@
   // Enforce type constraints: C99 6.5.6p3.
 
   // Handle the common case first (both operands are arithmetic).
-  if (!compType.isNull() && compType->isArithmeticType()) {
+  if (!compType.isNull() &&
+      (compType->isArithmeticType() || compType->isErrorType())) {
     if (CompLHSTy) *CompLHSTy = compType;
     return compType;
   }
@@ -9786,8 +9798,8 @@
   QualType RHSType = RHS.get()->getType();
 
   // C99 6.5.7p2: Each of the operands shall have integer type.
-  if (!LHSType->hasIntegerRepresentation() ||
-      !RHSType->hasIntegerRepresentation())
+  if (!(LHSType->hasIntegerRepresentation() || LHSType->isErrorType()) ||
+      !(RHSType->hasIntegerRepresentation() || RHSType->isErrorType()))
     return InvalidOperands(Loc, LHS, RHS);
 
   // C++0x: Don't allow scoped enums. FIXME: Use something better than
@@ -10438,6 +10450,9 @@
 
   QualType LHSType = LHS.get()->getType();
   QualType RHSType = RHS.get()->getType();
+  if (LHSType->isErrorType() || RHSType->isErrorType())
+    return IsThreeWay ? Context.ErrorTy : Context.getLogicalOperationType();
+
   if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) &&
       (RHSType->isArithmeticType() || RHSType->isEnumeralType()))
     return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc);
@@ -10962,7 +10977,8 @@
   LHS = LHSResult.get();
   RHS = RHSResult.get();
 
-  if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
+  if (!compType.isNull() && (compType->isIntegralOrUnscopedEnumerationType() ||
+                             compType->isErrorType()))
     return compType;
   return InvalidOperands(Loc, LHS, RHS);
 }
@@ -11030,8 +11046,8 @@
     if (RHS.isInvalid())
       return QualType();
 
-    if (!LHS.get()->getType()->isScalarType() ||
-        !RHS.get()->getType()->isScalarType())
+    if (!(LHS.get()->getType()->isScalarType() || LHS.get()->hasErrorType()) ||
+        !(RHS.get()->getType()->isScalarType() || RHS.get()->hasErrorType()))
       return InvalidOperands(Loc, LHS, RHS);
 
     return Context.IntTy;
@@ -11498,6 +11514,9 @@
                                        QualType CompoundType) {
   assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
 
+  if (LHSExpr->hasErrorType() || (RHS.isUsable() && RHS.get()->hasErrorType()))
+    return LHSExpr->getType();
+
   // Verify that LHS is a modifiable lvalue, and emit error if not.
   if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
     return QualType();
@@ -11722,6 +11741,8 @@
                                                ExprObjectKind &OK,
                                                SourceLocation OpLoc,
                                                bool IsInc, bool IsPrefix) {
+  if (Op->hasErrorType())
+    return Op->getType();
   if (Op->isTypeDependent())
     return S.Context.DependentTy;
 
@@ -11917,6 +11938,8 @@
     if (OrigOp.isInvalid()) return QualType();
   }
 
+  if (OrigOp.get()->hasErrorType())
+    return Context.ErrorTy;
   if (OrigOp.get()->isTypeDependent())
     return Context.DependentTy;
 
@@ -12119,6 +12142,8 @@
 /// CheckIndirectionOperand - Type check unary indirection (prefix '*').
 static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
                                         SourceLocation OpLoc) {
+  if (Op->hasErrorType())
+    return S.Context.ErrorTy;
   if (Op->isTypeDependent())
     return S.Context.DependentTy;
 
@@ -16313,7 +16338,7 @@
   if (result.isInvalid()) return ExprError();
   E = result.get();
 
-  if (!E->isTypeDependent()) {
+  if (!(E->isTypeDependent() || E->hasErrorType())) {
     if (getLangOpts().CPlusPlus)
       return CheckCXXBooleanCondition(E, IsConstexpr); // C++ 6.4p4
 
@@ -17002,7 +17027,7 @@
 }
 
 bool Sema::CheckCaseExpression(Expr *E) {
-  if (E->isTypeDependent())
+  if (E->isTypeDependent() || E->hasErrorType())
     return true;
   if (E->isValueDependent() || E->isIntegerConstantExpr(Context))
     return E->getType()->isIntegralOrEnumerationType();
Index: lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -1258,6 +1258,7 @@
   case Expr::UnresolvedLookupExprClass:
   case Expr::UnresolvedMemberExprClass:
   case Expr::TypoExprClass:
+  case Expr::RecoveryExprClass:
     // FIXME: Can any of the above throw?  If so, when?
     return CT_Cannot;
 
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -1169,7 +1169,8 @@
       Expr *Arg = E.get();
       E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc);
     }
-    if (E.isInvalid())
+    // Don't allow recovery of get() calls for now, this is a can of worms.
+    if (E.isInvalid() || isa<RecoveryExpr>(E.get()))
       return true;
     Expr *Init = E.get();
 
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -373,6 +373,8 @@
         << Base->getSourceRange();
     return ExprError();
   }
+  if (isa<RecoveryExpr>(Result.get()))
+    return ExprError();
 
   return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
 }
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp
+++ lib/Sema/SemaCast.cpp
@@ -13,6 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/OperationKinds.h"
+#include "clang/Sema/Ownership.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
@@ -261,8 +263,9 @@
   QualType DestType = DestTInfo->getType();
 
   // If the type is dependent, we won't do the semantic analysis now.
-  bool TypeDependent =
-      DestType->isDependentType() || Ex.get()->isTypeDependent();
+  bool TypeUnknown = DestType->isDependentType() ||
+                     Ex.get()->isTypeDependent() || DestType->isErrorType() ||
+                     Ex.get()->hasErrorType();
 
   CastOperation Op(*this, DestType, E);
   Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
@@ -272,7 +275,7 @@
   default: llvm_unreachable("Unknown C++ cast!");
 
   case tok::kw_const_cast:
-    if (!TypeDependent) {
+    if (!TypeUnknown) {
       Op.CheckConstCast();
       if (Op.SrcExpr.isInvalid())
         return ExprError();
@@ -290,7 +293,7 @@
                        << "dynamic_cast");
     }
 
-    if (!TypeDependent) {
+    if (!TypeUnknown) {
       Op.CheckDynamicCast();
       if (Op.SrcExpr.isInvalid())
         return ExprError();
@@ -302,7 +305,7 @@
                                                   AngleBrackets));
   }
   case tok::kw_reinterpret_cast: {
-    if (!TypeDependent) {
+    if (!TypeUnknown) {
       Op.CheckReinterpretCast();
       if (Op.SrcExpr.isInvalid())
         return ExprError();
@@ -315,7 +318,7 @@
                                                       AngleBrackets));
   }
   case tok::kw_static_cast: {
-    if (!TypeDependent) {
+    if (!TypeUnknown) {
       Op.CheckStaticCast();
       if (Op.SrcExpr.isInvalid())
         return ExprError();
@@ -2400,6 +2403,9 @@
     return;
   }
 
+  if (DestType->isErrorType() || SrcExpr.get()->hasErrorType())
+    return;
+
   // If the type is dependent, we won't do any other semantic analysis now.
   if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
       SrcExpr.get()->isValueDependent()) {
@@ -2563,6 +2569,9 @@
     return;
   }
 
+  if (DestType->isErrorType() || SrcExpr.get()->hasErrorType())
+    return;
+
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
     DeclAccessPair DAP;
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -510,7 +510,7 @@
   QualType ExprTy = Context.getCanonicalType(E->getType());
   QualType TypeTy = Context.getCanonicalType(Ty);
 
-  if (ExprTy == TypeTy)
+  if (ExprTy == TypeTy || ExprTy->isErrorType() || TypeTy->isErrorType())
     return E;
 
   // C++1z [conv.array]: The temporary materialization conversion is applied.
Index: lib/Index/USRGeneration.cpp
===================================================================
--- lib/Index/USRGeneration.cpp
+++ lib/Index/USRGeneration.cpp
@@ -713,6 +713,7 @@
 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
         case BuiltinType::Dependent:
+        case BuiltinType::Error:
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
         case BuiltinType::Id:
 #include "clang/Basic/OpenCLImageTypes.def"
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -2869,6 +2869,7 @@
       return false;
 
     case BuiltinType::Dependent:
+    case BuiltinType::Error:
 #define BUILTIN_TYPE(Id, SingletonId)
 #define PLACEHOLDER_TYPE(Id, SingletonId) \
     case BuiltinType::Id:
Index: lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- lib/CodeGen/CodeGenTypes.cpp
+++ lib/CodeGen/CodeGenTypes.cpp
@@ -513,6 +513,7 @@
       break;
 
     case BuiltinType::Dependent:
+    case BuiltinType::Error:
 #define BUILTIN_TYPE(Id, SingletonId)
 #define PLACEHOLDER_TYPE(Id, SingletonId) \
     case BuiltinType::Id:
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -630,6 +630,7 @@
 #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
   case BuiltinType::Dependent:
+  case BuiltinType::Error:
     llvm_unreachable("Unexpected builtin type");
   case BuiltinType::NullPtr:
     return DBuilder.createNullPtrType();
Index: lib/AST/TypeLoc.cpp
===================================================================
--- lib/AST/TypeLoc.cpp
+++ lib/AST/TypeLoc.cpp
@@ -372,6 +372,7 @@
 
   case BuiltinType::NullPtr:
   case BuiltinType::Overload:
+  case BuiltinType::Error:
   case BuiltinType::Dependent:
   case BuiltinType::BoundMember:
   case BuiltinType::UnknownAny:
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -2843,6 +2843,8 @@
     return "nullptr_t";
   case Overload:
     return "<overloaded function type>";
+  case Error:
+    return "<error type>";
   case BoundMember:
     return "<bound member function type>";
   case PseudoObject:
@@ -3860,6 +3862,7 @@
     // Dependent types that could instantiate to a pointer type.
     case BuiltinType::Dependent:
     case BuiltinType::Overload:
+    case BuiltinType::Error:
     case BuiltinType::BoundMember:
     case BuiltinType::PseudoObject:
     case BuiltinType::UnknownAny:
Index: lib/AST/TextNodeDumper.cpp
===================================================================
--- lib/AST/TextNodeDumper.cpp
+++ lib/AST/TextNodeDumper.cpp
@@ -717,6 +717,10 @@
   }
 }
 
+void TextNodeDumper::VisitRecoveryExpr(const RecoveryExpr *Node) {
+  OS << " " << Stmt::getStmtClassName(Node->attemptedStmtClass());
+}
+
 void TextNodeDumper::VisitUnresolvedLookupExpr(
     const UnresolvedLookupExpr *Node) {
   OS << " (";
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -1886,6 +1886,10 @@
   VisitExpr(E);
 }
 
+void StmtProfiler::VisitRecoveryExpr(const RecoveryExpr *E) {
+  VisitExpr(E);
+}
+
 void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) {
   VisitExpr(S);
 }
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -2376,6 +2376,20 @@
   llvm_unreachable("Cannot print TypoExpr nodes");
 }
 
+void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
+  OS << "<bad " << Stmt::getStmtClassName(Node->attemptedStmtClass()) << ">(";
+  const char *Sep = "";
+  for (Stmt *S : Node->children()) {
+    OS << Sep;
+    if (Expr *E = dyn_cast<Expr>(S))
+      PrintExpr(E);
+    else
+      PrintStmt(S);
+    Sep = ", ";
+  }
+  OS << ')';
+}
+
 void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) {
   OS << "__builtin_astype(";
   PrintExpr(Node->getSrcExpr());
Index: lib/AST/Stmt.cpp
===================================================================
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -71,8 +71,8 @@
   return ::operator new(bytes, C, alignment);
 }
 
-const char *Stmt::getStmtClassName() const {
-  return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
+const char *Stmt::getStmtClassName(StmtClass C) {
+  return getStmtInfoTableEntry(C).Name;
 }
 
 // Check that no statement / expression class is polymorphic. LLVM style RTTI
Index: lib/AST/NSAPI.cpp
===================================================================
--- lib/AST/NSAPI.cpp
+++ lib/AST/NSAPI.cpp
@@ -485,6 +485,7 @@
   case BuiltinType::BoundMember:
   case BuiltinType::Dependent:
   case BuiltinType::Overload:
+  case BuiltinType::Error:
   case BuiltinType::UnknownAny:
   case BuiltinType::ARCUnbridgedCast:
   case BuiltinType::Half:
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -2013,6 +2013,7 @@
   case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
   case BuiltinType::Dependent:
+  case BuiltinType::Error:
     llvm_unreachable("placeholder types shouldn't get to name mangling");
 
   case BuiltinType::ObjCId:
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -2626,6 +2626,7 @@
   case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
   case BuiltinType::Dependent:
+  case BuiltinType::Error:
     if (!NullOut)
       llvm_unreachable("mangling a placeholder type");
     break;
@@ -3591,6 +3592,7 @@
   case Expr::AtomicExprClass:
   case Expr::SourceLocExprClass:
   case Expr::FixedPointLiteralClass:
+  case Expr::RecoveryExprClass:
   {
     if (!NullOut) {
       // As bad as this diagnostic is, it's better than crashing.
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -8296,6 +8296,8 @@
 
     case BuiltinType::Dependent:
       llvm_unreachable("unexpected dependent type");
+    case BuiltinType::Error:
+      llvm_unreachable("unexpected error type");
     };
     llvm_unreachable("unexpected placeholder type");
 
@@ -11950,6 +11952,7 @@
   case Expr::CXXPseudoDestructorExprClass:
   case Expr::UnresolvedLookupExprClass:
   case Expr::TypoExprClass:
+  case Expr::RecoveryExprClass:
   case Expr::DependentScopeDeclRefExprClass:
   case Expr::CXXConstructExprClass:
   case Expr::CXXInheritedCtorInitExprClass:
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp
+++ lib/AST/ExprClassification.cpp
@@ -132,6 +132,7 @@
   case Expr::DependentCoawaitExprClass:
   case Expr::CXXDependentScopeMemberExprClass:
   case Expr::DependentScopeDeclRefExprClass:
+  case Expr::RecoveryExprClass:
     // ObjC instance variables are lvalues
     // FIXME: ObjC++0x might have different rules
   case Expr::ObjCIvarRefExprClass:
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -2247,7 +2247,7 @@
                                   ASTContext &Ctx) const {
   // Don't warn if the expr is type dependent. The type could end up
   // instantiating to void.
-  if (isTypeDependent())
+  if (isTypeDependent() || hasErrorType())
     return false;
 
   switch (getStmtClass()) {
@@ -2425,6 +2425,7 @@
   // If we don't know precisely what we're looking at, let's not warn.
   case UnresolvedLookupExprClass:
   case CXXUnresolvedConstructExprClass:
+  case RecoveryExprClass:
     return false;
 
   case CXXTemporaryObjectExprClass:
@@ -2972,6 +2973,11 @@
   return false;
 }
 
+bool Expr::hasAnyErrorArguments(ArrayRef<Expr *> Exprs) {
+  return llvm::any_of(Exprs,
+                      [](Expr *E) { return E->getType()->isErrorType(); });
+}
+
 bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
                                  const Expr **Culprit) const {
   assert(!isValueDependent() &&
@@ -3213,6 +3219,8 @@
   case TypoExprClass:
   case CXXFoldExprClass:
     llvm_unreachable("shouldn't see dependent / unresolved nodes here");
+  case RecoveryExprClass:
+    return IncludePossibleEffects;
 
   case DeclRefExprClass:
   case ObjCIvarRefExprClass:
@@ -4407,3 +4415,36 @@
   }
   return OriginalTy;
 }
+
+RecoveryExpr::RecoveryExpr(QualType T, StmtClass Attempted,
+                           SourceLocation BeginLoc, SourceLocation EndLoc,
+                           ArrayRef<Stmt *> Stmts)
+    : Expr(RecoveryExprClass, T, VK_LValue, OK_Ordinary, T->isDependentType(),
+           /*isValueDependent=*/true,
+           /*isInstantiationDependent=*/true,
+           /*containsUnexpandedParameterPack*/ false),
+      BeginLoc(BeginLoc), EndLoc(EndLoc), Attempted(Attempted),
+      NumStmts(Stmts.size()) {
+  std::copy(Stmts.begin(), Stmts.end(), getTrailingObjects<Stmt *>());
+}
+
+RecoveryExpr *RecoveryExpr::Create(ASTContext &Ctx, QualType T,
+                                   StmtClass Attempted, SourceLocation BeginLoc,
+                                   SourceLocation EndLoc,
+                                   ArrayRef<Stmt *> Stmts) {
+  // FIXME: In some contexts recovery is not desired (e.g. synthesized member
+  // accesses for coroutines). Currently the caller checks for RecoveryExpr and
+  // discards it, it would be cleaner/safer to have a flag on Sema and never
+  // call Create().
+  if (T.isNull())
+    T = Ctx.ErrorTy;
+  void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()),
+                           alignof(CallExpr));
+  return new (Mem) RecoveryExpr(T, Attempted, BeginLoc, EndLoc, Stmts);
+}
+
+RecoveryExpr *RecoveryExpr::CreateEmpty(ASTContext &Ctx, unsigned NumStmts) {
+  void *Mem =
+      Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CallExpr));
+  return new (Mem) RecoveryExpr(EmptyShell());
+}
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1247,6 +1247,9 @@
   // expressions.
   InitBuiltinType(DependentTy,         BuiltinType::Dependent);
 
+  // Placeholder type for broken/invalid expressions of unknown type.
+  InitBuiltinType(ErrorTy,             BuiltinType::Error);
+
   // Placeholder type for functions.
   InitBuiltinType(OverloadTy,          BuiltinType::Overload);
 
@@ -6610,6 +6613,7 @@
     case BuiltinType::OCLReserveID:
     case BuiltinType::OCLSampler:
     case BuiltinType::Dependent:
+    case BuiltinType::Error:
 #define BUILTIN_TYPE(KIND, ID)
 #define PLACEHOLDER_TYPE(KIND, ID) \
     case BuiltinType::KIND:
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -1010,6 +1010,9 @@
       /// \brief The '_Sat unsigned long _Fract' type
       PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69,
 
+      /// The type for broken/invalid expressions of unknown type.
+      PREDEF_TYPE_ERROR_ID = 70,
+
       /// OpenCL image types with auto numeration
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
       PREDEF_TYPE_##Id##_ID,
@@ -1753,6 +1756,9 @@
       /// An AtomicExpr record.
       EXPR_ATOMIC,
 
+      /// A RecoveryExpr record.
+      EXPR_RECOVERY,
+
       // Objective-C
 
       /// An ObjCStringLiteral record.
Index: include/clang/Sema/Initialization.h
===================================================================
--- include/clang/Sema/Initialization.h
+++ include/clang/Sema/Initialization.h
@@ -768,6 +768,8 @@
     /// dependently-typed expressions.
     DependentSequence,
 
+    ErrorSequence,
+
     /// A normal sequence.
     NormalSequence
   };
Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td
+++ include/clang/Basic/StmtNodes.td
@@ -192,6 +192,7 @@
 def BlockExpr : DStmt<Expr>;
 def OpaqueValueExpr : DStmt<Expr>;
 def TypoExpr : DStmt<Expr>;
+def RecoveryExpr : DStmt<Expr>;
 
 // Microsoft Extensions.
 def MSPropertyRefExpr : DStmt<Expr>;
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -2087,6 +2087,8 @@
   /// somehow depends on a template parameter (C++ [temp.dep.type]).
   bool isDependentType() const { return TypeBits.Dependent; }
 
+  bool isErrorType() const;
+
   /// Determine whether this type is an instantiation-dependent type,
   /// meaning that the type involves a template parameter (even if the
   /// definition does not actually depend on the type substituted for that
@@ -2419,8 +2421,9 @@
   friend class ASTContext; // ASTContext creates these.
 
   BuiltinType(Kind K)
-      : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
-             /*InstantiationDependent=*/(K == Dependent),
+      : Type(Builtin, QualType(),
+             /*Dependent=*/K == Dependent,
+             /*InstantiationDependent=*/K == Dependent,
              /*VariablyModified=*/false,
              /*Unexpanded parameter pack=*/false) {
     BuiltinTypeBits.Kind = K;
@@ -2484,6 +2487,10 @@
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
 };
 
+inline bool Type::isErrorType() const {
+  return isSpecificBuiltinType(BuiltinType::Error);
+}
+
 /// Complex values, per C99 6.2.5p11.  This supports the C99 complex
 /// types (_Complex float etc) as well as the GCC integer complex extensions.
 class ComplexType : public Type, public llvm::FoldingSetNode {
Index: include/clang/AST/TextNodeDumper.h
===================================================================
--- include/clang/AST/TextNodeDumper.h
+++ include/clang/AST/TextNodeDumper.h
@@ -259,6 +259,7 @@
   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
   void VisitExprWithCleanups(const ExprWithCleanups *Node);
   void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
+  void VisitRecoveryExpr(const RecoveryExpr *Node);
   void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
   void
   VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -1059,7 +1059,10 @@
   Stmt &operator=(const Stmt &) = delete;
   Stmt &operator=(Stmt &&) = delete;
 
-  const char *getStmtClassName() const;
+  static const char *getStmtClassName(StmtClass);
+  const char *getStmtClassName() const {
+    return getStmtClassName(getStmtClass());
+  }
 
   bool isOMPStructuredBlock() const { return StmtBits.IsOMPStructuredBlock; }
   void setIsOMPStructuredBlock(bool IsOMPStructuredBlock) {
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -2577,6 +2577,7 @@
 DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
 DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
 DEF_TRAVERSE_STMT(TypoExpr, {})
+DEF_TRAVERSE_STMT(RecoveryExpr, {})
 DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
 
 // These operators (all of them) do not need any action except
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -173,6 +173,9 @@
     ExprBits.TypeDependent = TD;
   }
 
+  /// Does this expression have an unknown type due to an error in the code?
+  bool hasErrorType() const { return getType()->isErrorType(); }
+
   /// Whether this expression is instantiation-dependent, meaning that
   /// it depends in some way on a template parameter, even if neither its type
   /// nor (constant) value can change due to the template instantiation.
@@ -869,6 +872,7 @@
   bool isImplicitCXXThis() const;
 
   static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);
+  static bool hasAnyErrorArguments(ArrayRef<Expr *> Exprs);
 
   /// For an expression of class type or pointer to class type,
   /// return the most derived class decl the expression is known to refer to.
@@ -5862,6 +5866,60 @@
   }
 
 };
+
+/// RecoveryExpr - a broken expression that we couldn't construct an AST for,
+/// e.g. because overload resolution failed.
+/// We capture:
+///  - the kind of expression that would have been produced
+///  - the valid subexpressions
+///  - the type, if known. If unknown, it is the built-in ErrorTy, which
+///    is dependent (and so generally suppresses further diagnostics etc).
+class RecoveryExpr final : public Expr,
+                           private llvm::TrailingObjects<RecoveryExpr, Stmt *> {
+public:
+  // T may be null, in which case ErrorTy is used.
+  static RecoveryExpr *Create(ASTContext &Ctx, QualType T, StmtClass Attempted,
+                              SourceLocation BeginLoc, SourceLocation EndLoc,
+                              ArrayRef<Stmt *> Stmts);
+  static RecoveryExpr *CreateEmpty(ASTContext &Ctx, unsigned NumStmts);
+
+  /// The expression type that would have been produced, if not for errors
+  /// in the code.
+  StmtClass attemptedStmtClass() const { return Attempted; }
+
+  child_range children() {
+    const_child_range CCR = const_cast<const RecoveryExpr *>(this)->children();
+    return child_range(cast_away_const(CCR.begin()),
+                       cast_away_const(CCR.end()));
+  }
+  const_child_range children() const {
+    Stmt *const *cs = const_cast<Stmt *const *>(
+        reinterpret_cast<const Stmt *const *>(getTrailingObjects<Stmt *>()));
+    return const_child_range(cs, cs + NumStmts);
+  }
+
+  SourceLocation getBeginLoc() const { return BeginLoc; }
+  SourceLocation getEndLoc() const { return EndLoc; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == RecoveryExprClass;
+  }
+
+private:
+  RecoveryExpr(QualType T, StmtClass Attempted, SourceLocation BeginLoc,
+               SourceLocation EndLoc, ArrayRef<Stmt *> Stmts);
+  RecoveryExpr(EmptyShell Empty) : Expr(RecoveryExprClass, Empty) {}
+
+  size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumStmts; }
+
+  SourceLocation BeginLoc, EndLoc;
+  StmtClass Attempted;
+  unsigned NumStmts;
+  friend TrailingObjects;
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+};
+
 } // end namespace clang
 
 #endif // LLVM_CLANG_AST_EXPR_H
Index: include/clang/AST/BuiltinTypes.def
===================================================================
--- include/clang/AST/BuiltinTypes.def
+++ include/clang/AST/BuiltinTypes.def
@@ -257,6 +257,13 @@
 // theoretically deducible.
 BUILTIN_TYPE(Dependent, DependentTy)
 
+// The type of a broken expression whose type isn't clear. e.g. 'foo()', where
+// foo's overloads require arguments and have different return types.
+// This type is considered dependent, even though it will never be deduced: the
+// concrete type is determined by correcting the source code, not instantiating
+// a template.
+BUILTIN_TYPE(Error, ErrorTy)
+
 // The type of an unresolved overload set.  A placeholder type.
 // Expressions with this type have one of the following basic
 // forms, with parentheses generally permitted:
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1037,7 +1037,7 @@
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   CanQualType Float128ComplexTy;
   CanQualType VoidPtrTy, NullPtrTy;
-  CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
+  CanQualType DependentTy, ErrorTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
   CanQualType BuiltinFnTy;
   CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to