diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -6212,19 +6212,22 @@ /// subexpressions of some expression that we could not construct and source /// range covered by the expression. /// -/// By default, RecoveryExpr is type-, value- and instantiation-dependent to -/// take advantage of existing machinery to deal with dependent code in C++, -/// e.g. RecoveryExpr is preserved in `decltype()` as part of the -/// `DependentDecltypeType`. In addition to that, clang does not report most -/// errors on dependent expressions, so we get rid of bogus errors for free. -/// However, note that unlike other dependent expressions, RecoveryExpr can be -/// produced in non-template contexts. -/// In addition, we will preserve the type in RecoveryExpr when the type is -/// known, e.g. preserving the return type for a broken non-overloaded function -/// call, a overloaded call where all candidates have the same return type. +/// By default, RecoveryExpr uses dependence-bits to take advantage of existing +/// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved +/// in `decltype()` as part of the `DependentDecltypeType`. In +/// addition to that, clang does not report most errors on dependent +/// expressions, so we get rid of bogus errors for free. However, note that +/// unlike other dependent expressions, RecoveryExpr can be produced in +/// non-template contexts. In addition, we will preserve the type in +/// RecoveryExpr when the type is known, e.g. preserving the return type for a +/// broken non-overloaded function call, a overloaded call where all candidates +/// have the same return type. /// /// One can also reliably suppress all bogus errors on expressions containing /// recovery expressions by examining results of Expr::containsErrors(). +/// +/// FIXME: RecoveryExpr is currently generated by default in C++ mode only, as +/// dependence isn't handled properly on several C-only codepaths. class RecoveryExpr final : public Expr, private llvm::TrailingObjects { public: diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -495,11 +495,21 @@ } ExprDependence clang::computeDependence(RecoveryExpr *E) { - // Mark the expression as value- and instantiation- dependent to reuse - // existing suppressions for dependent code, e.g. avoiding - // constant-evaluation. - // FIXME: drop type+value+instantiation once Error is sufficient to suppress - // bogus dianostics. + // A dependent expression (typically in template context) can behave + // differently from one instantiation to another. The dependence-bits describe + // how an expression depends on a template parameter. + // + // We generalize the "dependent" to mean "depends on a template parameter, or + // an error". + // + // RecoveryExpression is + // - always contains-errors: the expression depends on an error; + // - always value-dependent: we never know the value, the value can be + // different or unknown depending on how the error is resolved; + // - always instantiation-dependent: historically, this bit is used to + // determine whether an expression is dependent; + // - type dependent if we don't know the type (fallback to an opequa + // dependent type), or the type is known and dependent; auto D = toExprDependence(E->getType()->getDependence()) | ExprDependence::ValueInstantiation | ExprDependence::Error; for (auto *S : E->subExpressions()) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19210,9 +19210,6 @@ ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef SubExprs, QualType T) { - // FIXME: enable it for C++, RecoveryExpr is type-dependent to suppress - // bogus diagnostics and this trick does not work in C. - // FIXME: use containsErrors() to suppress unwanted diags in C. if (!Context.getLangOpts().RecoveryAST) return ExprError();