forked from OSchip/llvm-project
[clang][RecoveryExpr] Clarify the dependence-bits documentation.
The expr dependent-bits described that the expression somehow depends on a template paramter. With RecoveryExpr, we have generalized it to "the expression depends on a template parameter, or an error". This patch updates/cleanups all related comments of dependence-bits. Differential Revision: https://reviews.llvm.org/D83213
This commit is contained in:
parent
26cf6c1513
commit
6ac9e589f8
|
@ -16,8 +16,18 @@ namespace clang {
|
||||||
struct ExprDependenceScope {
|
struct ExprDependenceScope {
|
||||||
enum ExprDependence : uint8_t {
|
enum ExprDependence : uint8_t {
|
||||||
UnexpandedPack = 1,
|
UnexpandedPack = 1,
|
||||||
|
// This expr depends in any way on
|
||||||
|
// - a template parameter, it implies that the resolution of this expr may
|
||||||
|
// cause instantiation to fail
|
||||||
|
// - or an error (often in a non-template context)
|
||||||
|
//
|
||||||
|
// Note that C++ standard doesn't define the instantiation-dependent term,
|
||||||
|
// we follow the formal definition coming from the Itanium C++ ABI, and
|
||||||
|
// extend it to errors.
|
||||||
Instantiation = 2,
|
Instantiation = 2,
|
||||||
|
// The type of this expr depends on a template parameter, or an error.
|
||||||
Type = 4,
|
Type = 4,
|
||||||
|
// The value of this expr depends on a template parameter, or an error.
|
||||||
Value = 8,
|
Value = 8,
|
||||||
|
|
||||||
// clang extension: this expr contains or references an error, and is
|
// clang extension: this expr contains or references an error, and is
|
||||||
|
@ -42,10 +52,14 @@ struct TypeDependenceScope {
|
||||||
/// Whether this type contains an unexpanded parameter pack
|
/// Whether this type contains an unexpanded parameter pack
|
||||||
/// (for C++11 variadic templates)
|
/// (for C++11 variadic templates)
|
||||||
UnexpandedPack = 1,
|
UnexpandedPack = 1,
|
||||||
/// Whether this type somehow involves a template parameter, even
|
/// Whether this type somehow involves
|
||||||
/// if the resolution of the type does not depend on a template parameter.
|
/// - a template parameter, even if the resolution of the type does not
|
||||||
|
/// depend on a template parameter.
|
||||||
|
/// - or an error.
|
||||||
Instantiation = 2,
|
Instantiation = 2,
|
||||||
/// Whether this type is a dependent type (C++ [temp.dep.type]).
|
/// Whether this type
|
||||||
|
/// - is a dependent type (C++ [temp.dep.type])
|
||||||
|
/// - or it somehow involves an error, e.g. decltype(recovery-expr)
|
||||||
Dependent = 4,
|
Dependent = 4,
|
||||||
/// Whether this type is a variably-modified type (C99 6.7.5).
|
/// Whether this type is a variably-modified type (C99 6.7.5).
|
||||||
VariablyModified = 8,
|
VariablyModified = 8,
|
||||||
|
@ -95,16 +109,17 @@ public:
|
||||||
|
|
||||||
// Contains a template parameter pack that wasn't expanded.
|
// Contains a template parameter pack that wasn't expanded.
|
||||||
UnexpandedPack = 1,
|
UnexpandedPack = 1,
|
||||||
// Uses a template parameter, even if it doesn't affect the result.
|
// Depends on a template parameter or an error in some way.
|
||||||
// Validity depends on the template parameter.
|
// Validity depends on how the template is instantiated or the error is
|
||||||
|
// resolved.
|
||||||
Instantiation = 2,
|
Instantiation = 2,
|
||||||
// Expression type depends on template context.
|
// Expression type depends on template context, or an error.
|
||||||
// Value and Instantiation should also be set.
|
// Value and Instantiation should also be set.
|
||||||
Type = 4,
|
Type = 4,
|
||||||
// Expression value depends on template context.
|
// Expression value depends on template context, or an error.
|
||||||
// Instantiation should also be set.
|
// Instantiation should also be set.
|
||||||
Value = 8,
|
Value = 8,
|
||||||
// Depends on template context.
|
// Depends on template context, or an error.
|
||||||
// The type/value distinction is only meaningful for expressions.
|
// The type/value distinction is only meaningful for expressions.
|
||||||
Dependent = Type | Value,
|
Dependent = Type | Value,
|
||||||
// Includes an error, and depends on how it is resolved.
|
// Includes an error, and depends on how it is resolved.
|
||||||
|
|
|
@ -157,9 +157,11 @@ public:
|
||||||
return static_cast<ExprDependence>(ExprBits.Dependent);
|
return static_cast<ExprDependence>(ExprBits.Dependent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isValueDependent - Determines whether this expression is
|
/// Determines whether the value of this expression depends on
|
||||||
/// value-dependent (C++ [temp.dep.constexpr]). For example, the
|
/// - a template parameter (C++ [temp.dep.constexpr])
|
||||||
/// array bound of "Chars" in the following example is
|
/// - or an error, whose resolution is unknown
|
||||||
|
///
|
||||||
|
/// For example, the array bound of "Chars" in the following example is
|
||||||
/// value-dependent.
|
/// value-dependent.
|
||||||
/// @code
|
/// @code
|
||||||
/// template<int Size, char (&Chars)[Size]> struct meta_string;
|
/// template<int Size, char (&Chars)[Size]> struct meta_string;
|
||||||
|
@ -168,10 +170,12 @@ public:
|
||||||
return static_cast<bool>(getDependence() & ExprDependence::Value);
|
return static_cast<bool>(getDependence() & ExprDependence::Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isTypeDependent - Determines whether this expression is
|
/// Determines whether the type of this expression depends on
|
||||||
/// type-dependent (C++ [temp.dep.expr]), which means that its type
|
/// - a template paramter (C++ [temp.dep.expr], which means that its type
|
||||||
/// could change from one template instantiation to the next. For
|
/// could change from one template instantiation to the next)
|
||||||
/// example, the expressions "x" and "x + y" are type-dependent in
|
/// - or an error
|
||||||
|
///
|
||||||
|
/// For example, the expressions "x" and "x + y" are type-dependent in
|
||||||
/// the following code, but "y" is not type-dependent:
|
/// the following code, but "y" is not type-dependent:
|
||||||
/// @code
|
/// @code
|
||||||
/// template<typename T>
|
/// template<typename T>
|
||||||
|
@ -184,8 +188,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this expression is instantiation-dependent, meaning that
|
/// Whether this expression is instantiation-dependent, meaning that
|
||||||
/// it depends in some way on a template parameter, even if neither its type
|
/// it depends in some way on
|
||||||
/// nor (constant) value can change due to the template instantiation.
|
/// - a template parameter (even if neither its type nor (constant) value
|
||||||
|
/// can change due to the template instantiation)
|
||||||
|
/// - or an error
|
||||||
///
|
///
|
||||||
/// In the following example, the expression \c sizeof(sizeof(T() + T())) is
|
/// In the following example, the expression \c sizeof(sizeof(T() + T())) is
|
||||||
/// instantiation-dependent (since it involves a template parameter \c T), but
|
/// instantiation-dependent (since it involves a template parameter \c T), but
|
||||||
|
@ -200,6 +206,12 @@ public:
|
||||||
/// }
|
/// }
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
|
/// \code
|
||||||
|
/// void func(int) {
|
||||||
|
/// func(); // the expression is instantiation-dependent, because it depends
|
||||||
|
/// // on an error.
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
bool isInstantiationDependent() const {
|
bool isInstantiationDependent() const {
|
||||||
return static_cast<bool>(getDependence() & ExprDependence::Instantiation);
|
return static_cast<bool>(getDependence() & ExprDependence::Instantiation);
|
||||||
}
|
}
|
||||||
|
@ -6212,19 +6224,25 @@ public:
|
||||||
/// subexpressions of some expression that we could not construct and source
|
/// subexpressions of some expression that we could not construct and source
|
||||||
/// range covered by the expression.
|
/// range covered by the expression.
|
||||||
///
|
///
|
||||||
/// By default, RecoveryExpr is type-, value- and instantiation-dependent to
|
/// By default, RecoveryExpr uses dependence-bits to take advantage of existing
|
||||||
/// take advantage of existing machinery to deal with dependent code in C++,
|
/// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved
|
||||||
/// e.g. RecoveryExpr is preserved in `decltype(<broken-expr>)` as part of the
|
/// in `decltype(<broken-expr>)` as part of the `DependentDecltypeType`. In
|
||||||
/// `DependentDecltypeType`. In addition to that, clang does not report most
|
/// addition to that, clang does not report most errors on dependent
|
||||||
/// errors on dependent expressions, so we get rid of bogus errors for free.
|
/// expressions, so we get rid of bogus errors for free. However, note that
|
||||||
/// However, note that unlike other dependent expressions, RecoveryExpr can be
|
/// unlike other dependent expressions, RecoveryExpr can be produced in
|
||||||
/// produced in non-template contexts.
|
/// 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
|
/// We will preserve the type in RecoveryExpr when the type is known, e.g.
|
||||||
/// call, a overloaded call where all candidates have the same return type.
|
/// preserving the return type for a broken non-overloaded function call, a
|
||||||
|
/// overloaded call where all candidates have the same return type. In this
|
||||||
|
/// case, the expression is not type-dependent (unless the known type is itself
|
||||||
|
/// dependent)
|
||||||
///
|
///
|
||||||
/// One can also reliably suppress all bogus errors on expressions containing
|
/// One can also reliably suppress all bogus errors on expressions containing
|
||||||
/// recovery expressions by examining results of Expr::containsErrors().
|
/// 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,
|
class RecoveryExpr final : public Expr,
|
||||||
private llvm::TrailingObjects<RecoveryExpr, Expr *> {
|
private llvm::TrailingObjects<RecoveryExpr, Expr *> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -495,13 +495,16 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprDependence clang::computeDependence(RecoveryExpr *E) {
|
ExprDependence clang::computeDependence(RecoveryExpr *E) {
|
||||||
// Mark the expression as value- and instantiation- dependent to reuse
|
// RecoveryExpr is
|
||||||
// existing suppressions for dependent code, e.g. avoiding
|
// - always value-dependent, and therefore instantiation dependent
|
||||||
// constant-evaluation.
|
// - contains errors (ExprDependence::Error), by definition
|
||||||
// FIXME: drop type+value+instantiation once Error is sufficient to suppress
|
// - type-dependent if we don't know the type (fallback to an opaque
|
||||||
// bogus dianostics.
|
// dependent type), or the type is known and dependent, or it has
|
||||||
|
// type-dependent subexpressions.
|
||||||
auto D = toExprDependence(E->getType()->getDependence()) |
|
auto D = toExprDependence(E->getType()->getDependence()) |
|
||||||
ExprDependence::ValueInstantiation | ExprDependence::Error;
|
ExprDependence::ValueInstantiation | ExprDependence::Error;
|
||||||
|
// FIXME: remove the type-dependent bit from subexpressions, if the
|
||||||
|
// RecoveryExpr has a non-dependent type.
|
||||||
for (auto *S : E->subExpressions())
|
for (auto *S : E->subExpressions())
|
||||||
D |= S->getDependence();
|
D |= S->getDependence();
|
||||||
return D;
|
return D;
|
||||||
|
|
|
@ -19180,9 +19180,6 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
|
||||||
|
|
||||||
ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
|
ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
|
||||||
ArrayRef<Expr *> SubExprs, QualType T) {
|
ArrayRef<Expr *> 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)
|
if (!Context.getLangOpts().RecoveryAST)
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue