forked from OSchip/llvm-project
[AST] Add a flag indicating if any subexpression had errors
The only subexpression that is considered an error now is TypoExpr, but we plan to add expressions with errors to improve editor tooling on broken code. We intend to use the same mechanism to guard against spurious diagnostics on those as well. See the follow-up revision for an actual usage of the flag. Original patch from Ilya. Reviewers: sammccall Reviewed By: sammccall Tags: #clang Differential Revision: https://reviews.llvm.org/D65591
This commit is contained in:
parent
5d881dd8a8
commit
4b0f1e12c2
|
@ -62,6 +62,8 @@ static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false};
|
|||
static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false};
|
||||
// bitfield/objcproperty/objcsubscript/vectorcomponent
|
||||
static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false};
|
||||
// contains-errors
|
||||
static const TerminalColor ErrorsColor = {llvm::raw_ostream::RED, true};
|
||||
|
||||
// Null statements
|
||||
static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false};
|
||||
|
|
|
@ -59,6 +59,7 @@ class CXXDeleteExpr;
|
|||
class ArrayTypeTraitExpr;
|
||||
class ExpressionTraitExpr;
|
||||
class CXXNoexceptExpr;
|
||||
class PackExpansionExpr;
|
||||
class SubstNonTypeTemplateParmExpr;
|
||||
class CoroutineSuspendExpr;
|
||||
class DependentCoawaitExpr;
|
||||
|
@ -71,6 +72,7 @@ class LambdaExpr;
|
|||
class CXXUnresolvedConstructExpr;
|
||||
class CXXDependentScopeMemberExpr;
|
||||
class MaterializeTemporaryExpr;
|
||||
class CXXFoldExpr;
|
||||
class TypeTraitExpr;
|
||||
class ConceptSpecializationExpr;
|
||||
class PredefinedExpr;
|
||||
|
@ -134,6 +136,7 @@ ExprDependence computeDependence(CXXDeleteExpr *E);
|
|||
ExprDependence computeDependence(ArrayTypeTraitExpr *E);
|
||||
ExprDependence computeDependence(ExpressionTraitExpr *E);
|
||||
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
|
||||
ExprDependence computeDependence(PackExpansionExpr *E);
|
||||
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
|
||||
ExprDependence computeDependence(CoroutineSuspendExpr *E);
|
||||
ExprDependence computeDependence(DependentCoawaitExpr *E);
|
||||
|
@ -149,6 +152,7 @@ ExprDependence computeDependence(LambdaExpr *E,
|
|||
ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
|
||||
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
|
||||
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
|
||||
ExprDependence computeDependence(CXXFoldExpr *E);
|
||||
ExprDependence computeDependence(TypeTraitExpr *E);
|
||||
ExprDependence computeDependence(ConceptSpecializationExpr *E,
|
||||
bool ValueDependent);
|
||||
|
|
|
@ -20,19 +20,23 @@ struct ExprDependenceScope {
|
|||
Type = 4,
|
||||
Value = 8,
|
||||
|
||||
// clang extension: this expr contains or references an error, and is
|
||||
// considered dependent on how that error is resolved.
|
||||
Error = 16,
|
||||
|
||||
None = 0,
|
||||
All = 15,
|
||||
All = 31,
|
||||
|
||||
TypeValue = Type | Value,
|
||||
TypeInstantiation = Type | Instantiation,
|
||||
ValueInstantiation = Value | Instantiation,
|
||||
TypeValueInstantiation = Type | Value | Instantiation,
|
||||
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Value)
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
|
||||
};
|
||||
};
|
||||
using ExprDependence = ExprDependenceScope::ExprDependence;
|
||||
static constexpr unsigned ExprDependenceBits = 4;
|
||||
static constexpr unsigned ExprDependenceBits = 5;
|
||||
|
||||
struct TypeDependenceScope {
|
||||
enum TypeDependence : uint8_t {
|
||||
|
@ -47,6 +51,8 @@ struct TypeDependenceScope {
|
|||
/// Whether this type is a variably-modified type (C99 6.7.5).
|
||||
VariablyModified = 8,
|
||||
|
||||
// FIXME: add Error bit.
|
||||
|
||||
None = 0,
|
||||
All = 15,
|
||||
|
||||
|
@ -83,11 +89,14 @@ LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
|
|||
/// Computes dependencies of a reference with the name having template arguments
|
||||
/// with \p TA dependencies.
|
||||
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
|
||||
auto E =
|
||||
static_cast<ExprDependence>(TA & ~TemplateArgumentDependence::Dependent);
|
||||
auto D = ExprDependence::None;
|
||||
if (TA & TemplateArgumentDependence::UnexpandedPack)
|
||||
D |= ExprDependence::UnexpandedPack;
|
||||
if (TA & TemplateArgumentDependence::Instantiation)
|
||||
D |= ExprDependence::Instantiation;
|
||||
if (TA & TemplateArgumentDependence::Dependent)
|
||||
return E | ExprDependence::Type | ExprDependence::Value;
|
||||
return E;
|
||||
D |= ExprDependence::Type | ExprDependence::Value;
|
||||
return D;
|
||||
}
|
||||
inline ExprDependence toExprDependence(TypeDependence TD) {
|
||||
// This hack works because TypeDependence and TemplateArgumentDependence
|
||||
|
@ -127,10 +136,13 @@ toTemplateArgumentDependence(TemplateNameDependence D) {
|
|||
}
|
||||
inline TemplateArgumentDependence
|
||||
toTemplateArgumentDependence(ExprDependence ED) {
|
||||
TemplateArgumentDependence TAD = static_cast<TemplateArgumentDependence>(
|
||||
ED & ~(ExprDependence::Type | ExprDependence::Value));
|
||||
TemplateArgumentDependence TAD = TemplateArgumentDependence::None;
|
||||
if (ED & (ExprDependence::Type | ExprDependence::Value))
|
||||
TAD |= TemplateArgumentDependence::Dependent;
|
||||
if (ED & ExprDependence::Instantiation)
|
||||
TAD |= TemplateArgumentDependence::Instantiation;
|
||||
if (ED & ExprDependence::UnexpandedPack)
|
||||
TAD |= TemplateArgumentDependence::UnexpandedPack;
|
||||
return TAD;
|
||||
}
|
||||
|
||||
|
|
|
@ -226,6 +226,12 @@ public:
|
|||
return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
|
||||
}
|
||||
|
||||
/// Whether this expression contains subexpressions which had errors, e.g. a
|
||||
/// TypoExpr.
|
||||
bool containsErrors() const {
|
||||
return static_cast<bool>(getDependence() & ExprDependence::Error);
|
||||
}
|
||||
|
||||
/// getExprLoc - Return the preferred location for the arrow when diagnosing
|
||||
/// a problem with a generic expression.
|
||||
SourceLocation getExprLoc() const LLVM_READONLY;
|
||||
|
@ -5881,7 +5887,8 @@ class TypoExpr : public Expr {
|
|||
public:
|
||||
TypoExpr(QualType T) : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary) {
|
||||
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
|
||||
setDependence(ExprDependence::TypeValueInstantiation);
|
||||
setDependence(ExprDependence::TypeValueInstantiation |
|
||||
ExprDependence::Error);
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
|
|
|
@ -4020,7 +4020,7 @@ public:
|
|||
EllipsisLoc(EllipsisLoc),
|
||||
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0),
|
||||
Pattern(Pattern) {
|
||||
setDependence(ExprDependence::TypeValueInstantiation);
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}
|
||||
|
@ -4531,7 +4531,7 @@ public:
|
|||
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
|
||||
SubExprs[0] = LHS;
|
||||
SubExprs[1] = RHS;
|
||||
setDependence(ExprDependence::TypeValueInstantiation);
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
|
||||
|
|
|
@ -1496,7 +1496,7 @@ private:
|
|||
return CachedLocalOrUnnamed;
|
||||
}
|
||||
};
|
||||
enum { NumTypeBits = 18 };
|
||||
enum { NumTypeBits = 8 + TypeDependenceBits + 6 };
|
||||
|
||||
protected:
|
||||
// These classes allow subclasses to somewhat cleanly pack bitfields
|
||||
|
|
|
@ -120,9 +120,9 @@ ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
|
|||
}
|
||||
|
||||
ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
|
||||
auto D = ExprDependence::None;
|
||||
if (E->getType()->isDependentType())
|
||||
D |= ExprDependence::Type;
|
||||
// FIXME: why is unexpanded-pack not propagated?
|
||||
auto D = toExprDependence(E->getType()->getDependence()) &
|
||||
~ExprDependence::UnexpandedPack;
|
||||
// Note: we treat a statement-expression in a dependent context as always
|
||||
// being value- and instantiation-dependent. This matches the behavior of
|
||||
// lambda-expressions and GCC.
|
||||
|
@ -172,7 +172,7 @@ ExprDependence clang::computeDependence(VAArgExpr *E) {
|
|||
|
||||
ExprDependence clang::computeDependence(NoInitExpr *E) {
|
||||
return toExprDependence(E->getType()->getDependence()) &
|
||||
ExprDependence::Instantiation;
|
||||
(ExprDependence::Instantiation & ExprDependence::Error);
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
|
||||
|
@ -213,8 +213,8 @@ ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
|
|||
|
||||
ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
|
||||
auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
|
||||
if (E->getType()->isDependentType())
|
||||
D |= ExprDependence::Type;
|
||||
D |= toExprDependence(E->getType()->getDependence()) &
|
||||
(ExprDependence::Type | ExprDependence::Error);
|
||||
return D;
|
||||
}
|
||||
|
||||
|
@ -296,13 +296,19 @@ ExprDependence clang::computeDependence(CXXNoexceptExpr *E, CanThrowResult CT) {
|
|||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(PackExpansionExpr *E) {
|
||||
return (E->getPattern()->getDependence() & ~ExprDependence::UnexpandedPack) |
|
||||
ExprDependence::TypeValueInstantiation;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(SubstNonTypeTemplateParmExpr *E) {
|
||||
return E->getReplacement()->getDependence();
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CoroutineSuspendExpr *E) {
|
||||
if (auto *Resume = E->getResumeExpr())
|
||||
return (Resume->getDependence() & ExprDependence::TypeValue) |
|
||||
return (Resume->getDependence() &
|
||||
(ExprDependence::TypeValue | ExprDependence::Error)) |
|
||||
(E->getCommonExpr()->getDependence() & ~ExprDependence::TypeValue);
|
||||
return E->getCommonExpr()->getDependence() |
|
||||
ExprDependence::TypeValueInstantiation;
|
||||
|
@ -377,6 +383,7 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
|
|||
|
||||
if (Decl->isParameterPack())
|
||||
Deps |= ExprDependence::UnexpandedPack;
|
||||
Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
|
||||
|
||||
// (TD) C++ [temp.dep.expr]p3:
|
||||
// An id-expression is type-dependent if it contains:
|
||||
|
@ -496,6 +503,10 @@ ExprDependence clang::computeDependence(GenericSelectionExpr *E,
|
|||
bool ContainsUnexpandedPack) {
|
||||
auto D = ContainsUnexpandedPack ? ExprDependence::UnexpandedPack
|
||||
: ExprDependence::None;
|
||||
for (auto *AE : E->getAssocExprs())
|
||||
D |= AE->getDependence() & ExprDependence::Error;
|
||||
D |= E->getControllingExpr()->getDependence() & ExprDependence::Error;
|
||||
|
||||
if (E->isResultDependent())
|
||||
return D | ExprDependence::TypeValueInstantiation;
|
||||
return D | (E->getResultExpr()->getDependence() &
|
||||
|
@ -623,7 +634,8 @@ ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
|
|||
if (E->getType()->getContainedDeducedType())
|
||||
D |= ExprDependence::Type;
|
||||
for (auto *A : E->arguments())
|
||||
D |= A->getDependence() & ExprDependence::UnexpandedPack;
|
||||
D |= A->getDependence() &
|
||||
(ExprDependence::UnexpandedPack | ExprDependence::Error);
|
||||
return D;
|
||||
}
|
||||
|
||||
|
@ -643,6 +655,15 @@ ExprDependence clang::computeDependence(MaterializeTemporaryExpr *E) {
|
|||
return E->getSubExpr()->getDependence();
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXFoldExpr *E) {
|
||||
auto D = ExprDependence::TypeValueInstantiation;
|
||||
for (const auto *C : {E->getLHS(), E->getRHS()}) {
|
||||
if (C)
|
||||
D |= C->getDependence() & ~ExprDependence::UnexpandedPack;
|
||||
}
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(TypeTraitExpr *E) {
|
||||
auto D = ExprDependence::None;
|
||||
for (const auto *A : E->getArgs())
|
||||
|
|
|
@ -4231,6 +4231,7 @@ DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
|
|||
ILE->setType(baseExpr->getType());
|
||||
BaseAndUpdaterExprs[1] = ILE;
|
||||
|
||||
// FIXME: this is wrong, set it correctly.
|
||||
setDependence(ExprDependence::None);
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,11 @@ void TextNodeDumper::Visit(const Stmt *Node) {
|
|||
if (const auto *E = dyn_cast<Expr>(Node)) {
|
||||
dumpType(E->getType());
|
||||
|
||||
if (E->containsErrors()) {
|
||||
ColorScope Color(OS, ShowColors, ErrorsColor);
|
||||
OS << " contains-errors";
|
||||
}
|
||||
|
||||
{
|
||||
ColorScope Color(OS, ShowColors, ValueKindColor);
|
||||
switch (E->getValueKind()) {
|
||||
|
|
|
@ -106,7 +106,8 @@ namespace clang {
|
|||
|
||||
/// The number of record fields required for the Expr class
|
||||
/// itself.
|
||||
static const unsigned NumExprFields = NumStmtFields + 7;
|
||||
static const unsigned NumExprFields =
|
||||
NumStmtFields + ExprDependenceBits + 3;
|
||||
|
||||
/// Read and initialize a ExplicitTemplateArgumentList structure.
|
||||
void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
|
||||
|
@ -517,6 +518,7 @@ void ASTStmtReader::VisitExpr(Expr *E) {
|
|||
bool ValueDependent = Record.readInt();
|
||||
bool InstantiationDependent = Record.readInt();
|
||||
bool ContainsUnexpandedTemplateParameters = Record.readInt();
|
||||
bool ContainsErrors = Record.readInt();
|
||||
auto Deps = ExprDependence::None;
|
||||
if (TypeDependent)
|
||||
Deps |= ExprDependence::Type;
|
||||
|
@ -526,6 +528,8 @@ void ASTStmtReader::VisitExpr(Expr *E) {
|
|||
Deps |= ExprDependence::Instantiation;
|
||||
if (ContainsUnexpandedTemplateParameters)
|
||||
Deps |= ExprDependence::UnexpandedPack;
|
||||
if (ContainsErrors)
|
||||
Deps |= ExprDependence::Error;
|
||||
E->setDependence(Deps);
|
||||
|
||||
E->setValueKind(static_cast<ExprValueKind>(Record.readInt()));
|
||||
|
|
|
@ -2280,6 +2280,7 @@ void ASTWriter::WriteDeclAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ContainsErrors
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
|
||||
//DeclRefExpr
|
||||
|
@ -2303,6 +2304,7 @@ void ASTWriter::WriteDeclAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ContainsErrors
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
|
||||
//Integer Literal
|
||||
|
@ -2321,6 +2323,7 @@ void ASTWriter::WriteDeclAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ContainsErrors
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
|
||||
//Character Literal
|
||||
|
@ -2339,6 +2342,7 @@ void ASTWriter::WriteDeclAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ContainsErrors
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
|
||||
// CastExpr
|
||||
|
|
|
@ -540,6 +540,7 @@ void ASTStmtWriter::VisitExpr(Expr *E) {
|
|||
Record.push_back(E->isValueDependent());
|
||||
Record.push_back(E->isInstantiationDependent());
|
||||
Record.push_back(E->containsUnexpandedParameterPack());
|
||||
Record.push_back(E->containsErrors());
|
||||
Record.push_back(E->getValueKind());
|
||||
Record.push_back(E->getObjectKind());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue