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; 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/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 Exprs); + static bool hasAnyErrorArguments(ArrayRef 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 { +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 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 @@ -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/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/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 @@ -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/Basic/StmtNodes.td =================================================================== --- include/clang/Basic/StmtNodes.td +++ include/clang/Basic/StmtNodes.td @@ -192,6 +192,7 @@ def BlockExpr : DStmt; def OpaqueValueExpr : DStmt; def TypoExpr : DStmt; +def RecoveryExpr : DStmt; // Microsoft Extensions. def MSPropertyRefExpr : DStmt; 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/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: 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: 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 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 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()); +} + +RecoveryExpr *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(). + if (T.isNull()) + T = Ctx.ErrorTy; + 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 @@ -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/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/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/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/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 @@ -2376,6 +2376,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 @@ -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/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 Error: + 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::Error: 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::Error: 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::Error: 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::Error: #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::Error: #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::Error: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" 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/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/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/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(); const VectorType *RHSVecType = RHSType->getAs(); 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/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/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 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/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((Expr *)Args[0])) { - SourceRange Brackets; - - // Scavange the location of the brackets from the entity, if we can. - if (auto *DD = dyn_cast_or_null(Entity.getDecl())) { - if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { - TypeLoc TL = TInfo->getTypeLoc(); - if (IncompleteArrayTypeLoc ArrayLoc = - TL.getAs()) - 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((Expr *)Args[0])) { + SourceRange Brackets; + + // Scavange the location of the brackets from the entity, if we can. + if (auto *DD = dyn_cast_or_null(Entity.getDecl())) { + if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { + TypeLoc TL = TInfo->getTypeLoc(); + if (IncompleteArrayTypeLoc ArrayLoc = + TL.getAs()) + 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/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 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 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/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/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/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9391,6 +9391,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::Error: + ID = PREDEF_TYPE_ERROR_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_ERROR_ID: + T = Context.ErrorTy; + break; case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break; 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/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/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/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::Error: #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 @@ -289,6 +289,7 @@ case Stmt::ObjCDictionaryLiteralClass: case Stmt::ObjCBoxedExprClass: case Stmt::ObjCSubscriptRefExprClass: + case Stmt::RecoveryExprClass: K = CXCursor_UnexposedExpr; break;