Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -1031,7 +1031,7 @@ CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; - CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; + CanQualType DependentTy, RecoveryTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; CanQualType PseudoObjectTy, ARCUnbridgedCastTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; 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(Recovery, RecoveryTy) + // 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/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -5797,6 +5797,64 @@ } }; + +/// 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 RecoveryTy, which +/// is dependent (and so generally suppresses further diagnostics etc). +class RecoveryExpr final : public Expr, + private llvm::TrailingObjects { +public: + // T may be null, in which case RecoveryTy is used. + // Returns None if recovery is not valid here, e.g. because dependent types + // are required but not supported. + static Optional Create(ASTContext &Ctx, QualType T, + StmtClass Attempted, + SourceLocation BeginLoc, + SourceLocation EndLoc, + ArrayRef 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(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( + reinterpret_cast(getTrailingObjects())); + 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 Stmts); + RecoveryExpr(EmptyShell Empty) : Expr(RecoveryExprClass, Empty) {} + + size_t numTrailingObjects(OverloadToken) 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/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2575,6 +2575,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/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -1047,7 +1047,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/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/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2419,8 +2419,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 || K == Recovery), + /*InstantiationDependent=*/(K == Dependent || K == Recovery), /*VariablyModified=*/false, /*Unexpanded parameter pack=*/false) { BuiltinTypeBits.Kind = K; Index: include/clang/Basic/StmtNodes.td =================================================================== --- include/clang/Basic/StmtNodes.td +++ include/clang/Basic/StmtNodes.td @@ -191,6 +191,7 @@ def BlockExpr : DStmt; def OpaqueValueExpr : DStmt; def TypoExpr : DStmt; +def RecoveryExpr : DStmt; // Microsoft Extensions. def MSPropertyRefExpr : DStmt; 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_RECOVERY_ID = 70, + /// OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, @@ -1750,6 +1753,9 @@ /// An AtomicExpr record. EXPR_ATOMIC, + /// A RecoveryExpr record. + EXPR_RECOVERY, + // Objective-C /// An ObjCStringLiteral record. 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(RecoveryTy, BuiltinType::Recovery); + // Placeholder type for functions. InitBuiltinType(OverloadTy, BuiltinType::Overload); @@ -6610,6 +6613,7 @@ case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: case BuiltinType::Dependent: + case BuiltinType::Recovery: #define BUILTIN_TYPE(KIND, ID) #define PLACEHOLDER_TYPE(KIND, ID) \ case BuiltinType::KIND: Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2339,6 +2339,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: @@ -3124,6 +3125,8 @@ case TypoExprClass: case CXXFoldExprClass: llvm_unreachable("shouldn't see dependent / unresolved nodes here"); + case RecoveryExprClass: + return IncludePossibleEffects; case DeclRefExprClass: case ObjCIvarRefExprClass: @@ -4317,3 +4320,41 @@ } return OriginalTy; } + +RecoveryExpr::RecoveryExpr(QualType T, StmtClass Attempted, + SourceLocation BeginLoc, SourceLocation EndLoc, + ArrayRef 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()); +} + +Optional RecoveryExpr::Create(ASTContext &Ctx, QualType T, + StmtClass Attempted, + SourceLocation BeginLoc, + SourceLocation EndLoc, + ArrayRef 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(). The current cases where we return None could be moved there. + + if (T.isNull()) { + if (!Ctx.getLangOpts().CPlusPlus) + return None; // We have no type, and can't use a dependent type. + T = Ctx.RecoveryTy; + } + void *Mem = Ctx.Allocate(totalSizeToAlloc(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(NumStmts), alignof(CallExpr)); + return new (Mem) RecoveryExpr(EmptyShell()); +} 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/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -8081,6 +8081,7 @@ return GCCTypeClass::None; case BuiltinType::Dependent: + case BuiltinType::Recovery: llvm_unreachable("unexpected dependent type"); }; llvm_unreachable("unexpected placeholder type"); @@ -11698,6 +11699,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/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::Recovery: if (!NullOut) llvm_unreachable("mangling a placeholder type"); break; @@ -3590,6 +3591,7 @@ case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: case Expr::FixedPointLiteralClass: + case Expr::RecoveryExprClass: { if (!NullOut) { // As bad as this diagnostic is, it's better than crashing. 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::Recovery: llvm_unreachable("placeholder types shouldn't get to name mangling"); case BuiltinType::ObjCId: 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::Recovery: case BuiltinType::UnknownAny: case BuiltinType::ARCUnbridgedCast: case BuiltinType::Half: 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/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -2372,6 +2372,20 @@ llvm_unreachable("Cannot print TypoExpr nodes"); } +void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) { + OS << "attemptedStmtClass()) << ">("; + const char *Sep = ""; + for (Stmt *S : Node->children()) { + OS << Sep; + if (Expr *E = dyn_cast(S)) + PrintExpr(E); + else + PrintStmt(S); + Sep = ", "; + } + OS << ')'; +} + void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { OS << "__builtin_astype("; PrintExpr(Node->getSrcExpr()); Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1882,6 +1882,10 @@ VisitExpr(E); } +void StmtProfiler::VisitRecoveryExpr(const RecoveryExpr *E) { + VisitExpr(E); +} + void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) { VisitExpr(S); } 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/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -2843,6 +2843,8 @@ return "nullptr_t"; case Overload: return ""; + case Recovery: + return ""; case BoundMember: return ""; case PseudoObject: @@ -3860,6 +3862,7 @@ // Dependent types that could instantiate to a pointer type. case BuiltinType::Dependent: case BuiltinType::Overload: + case BuiltinType::Recovery: case BuiltinType::BoundMember: case BuiltinType::PseudoObject: case BuiltinType::UnknownAny: 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::Recovery: case BuiltinType::Dependent: case BuiltinType::BoundMember: case BuiltinType::UnknownAny: 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::Recovery: llvm_unreachable("Unexpected builtin type"); case BuiltinType::NullPtr: return DBuilder.createNullPtrType(); Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -513,6 +513,7 @@ break; case BuiltinType::Dependent: + case BuiltinType::Recovery: #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ case BuiltinType::Id: Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2869,6 +2869,7 @@ return false; case BuiltinType::Dependent: + case BuiltinType::Recovery: #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ case BuiltinType::Id: 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::Recovery: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" 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" Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -373,6 +373,8 @@ << Base->getSourceRange(); return ExprError(); } + if (isa(Result.get())) + return ExprError(); return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr); } 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(E.get())) return true; Expr *Init = E.get(); 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/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -1022,6 +1022,23 @@ Diag(R.getNameLoc(), diag::err_no_member) << MemberName << DC << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + + 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 SubExprs; + if (BaseExpr) + SubExprs.push_back(BaseExpr); + if (auto RE = RecoveryExpr::Create(Context, QualType(), + Stmt::MemberExprClass, BeginLoc, + MemberNameInfo.getEndLoc(), SubExprs)) + return *RE; return ExprError(); } 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" @@ -12111,6 +12112,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 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() @@ -12201,6 +12238,17 @@ } // Overload resolution failed. + 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 SubExprs = {Fn}; + SubExprs.append(Args.begin(), Args.end()); + if (auto RE = RecoveryExpr::Create( + SemaRef.Context, chooseRecoveryType(*CandidateSet, Best), + Stmt::CallExprClass, Fn->getBeginLoc(), RParenLoc, SubExprs)) + return *RE; return ExprError(); } 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(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(SetterExpr.get())) { S.Diag(RefExpr->getMemberLoc(), diag::err_cannot_find_suitable_accessor) << 1 /* setter */ << RefExpr->getPropertyDecl(); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9378,6 +9378,12 @@ return E; } +template +ExprResult +TreeTransform::TransformRecoveryExpr(RecoveryExpr *E) { + return E; +} + template ExprResult TreeTransform::TransformPseudoObjectExpr(PseudoObjectExpr *E) { 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::Recovery: + ID = PREDEF_TYPE_RECOVERY_ID; + break; case BuiltinType::BoundMember: ID = PREDEF_TYPE_BOUND_MEMBER; break; 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_RECOVERY_ID: + T = Context.RecoveryTy; + break; case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break; Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1827,6 +1827,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 //===----------------------------------------------------------------------===// @@ -2533,6 +2547,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/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/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: 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 using U = S; // expected-note 2{{template parameter is declared here}} template U &f(U, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}} S &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: 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/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/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/SemaCXX/enable_if.cpp =================================================================== --- test/SemaCXX/enable_if.cpp +++ test/SemaCXX/enable_if.cpp @@ -406,16 +406,16 @@ static_assert(callNoError<1>() == 0, ""); template 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 constexpr int callTemplated() { return templated(); } +template constexpr int callTemplated() { return templated(); } // 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/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 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/SemaTemplate/instantiate-function-params.cpp =================================================================== --- test/SemaTemplate/instantiate-function-params.cpp +++ test/SemaTemplate/instantiate-function-params.cpp @@ -3,7 +3,7 @@ // PR6619 template struct if_c { }; template struct if_ { - typedef if_c< static_cast(T1::value)> almost_type_; // expected-note 5{{in instantiation}} + typedef if_c< static_cast(T1::value)> type; // expected-note 5{{in instantiation}} }; template struct wrap_constraints { }; template @@ -17,7 +17,9 @@ template struct requirement_; template struct instantiate { }; -template struct requirement_ : if_< not_satisfied >::type { // expected-note 5{{in instantiation}} +template +struct requirement_ : if_>::type { // expected-note 5{{in instantiation}} + static void failed(); }; template struct usage_requirements { }; 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::data); (void)sizeof(array_lengthof(Description::data)); - sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}} - Description::data // expected-note{{in instantiation of static data member 'PR7985::Description::data' requested here}} - )); + (void)sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}} + Description::data // expected-note{{in instantiation of static data member 'PR7985::Description::data' requested here}} + )); array_lengthof(Description::data); // expected-error{{no matching function for call to 'array_lengthof'}} } 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::Recovery: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" Index: tools/libclang/CXCursor.cpp =================================================================== --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -288,6 +288,7 @@ case Stmt::ObjCDictionaryLiteralClass: case Stmt::ObjCBoxedExprClass: case Stmt::ObjCSubscriptRefExprClass: + case Stmt::RecoveryExprClass: K = CXCursor_UnexposedExpr; break;