Skip to content

Commit 4b0f1e1

Browse files
committed
[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
1 parent 5d881dd commit 4b0f1e1

File tree

12 files changed

+83
-22
lines changed

12 files changed

+83
-22
lines changed

clang/include/clang/AST/ASTDumperUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false};
6262
static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false};
6363
// bitfield/objcproperty/objcsubscript/vectorcomponent
6464
static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false};
65+
// contains-errors
66+
static const TerminalColor ErrorsColor = {llvm::raw_ostream::RED, true};
6567

6668
// Null statements
6769
static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false};

clang/include/clang/AST/ComputeDependence.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class CXXDeleteExpr;
5959
class ArrayTypeTraitExpr;
6060
class ExpressionTraitExpr;
6161
class CXXNoexceptExpr;
62+
class PackExpansionExpr;
6263
class SubstNonTypeTemplateParmExpr;
6364
class CoroutineSuspendExpr;
6465
class DependentCoawaitExpr;
@@ -71,6 +72,7 @@ class LambdaExpr;
7172
class CXXUnresolvedConstructExpr;
7273
class CXXDependentScopeMemberExpr;
7374
class MaterializeTemporaryExpr;
75+
class CXXFoldExpr;
7476
class TypeTraitExpr;
7577
class ConceptSpecializationExpr;
7678
class PredefinedExpr;
@@ -134,6 +136,7 @@ ExprDependence computeDependence(CXXDeleteExpr *E);
134136
ExprDependence computeDependence(ArrayTypeTraitExpr *E);
135137
ExprDependence computeDependence(ExpressionTraitExpr *E);
136138
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
139+
ExprDependence computeDependence(PackExpansionExpr *E);
137140
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
138141
ExprDependence computeDependence(CoroutineSuspendExpr *E);
139142
ExprDependence computeDependence(DependentCoawaitExpr *E);
@@ -149,6 +152,7 @@ ExprDependence computeDependence(LambdaExpr *E,
149152
ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
150153
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
151154
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
155+
ExprDependence computeDependence(CXXFoldExpr *E);
152156
ExprDependence computeDependence(TypeTraitExpr *E);
153157
ExprDependence computeDependence(ConceptSpecializationExpr *E,
154158
bool ValueDependent);

clang/include/clang/AST/DependenceFlags.h

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@ struct ExprDependenceScope {
2020
Type = 4,
2121
Value = 8,
2222

23+
// clang extension: this expr contains or references an error, and is
24+
// considered dependent on how that error is resolved.
25+
Error = 16,
26+
2327
None = 0,
24-
All = 15,
28+
All = 31,
2529

2630
TypeValue = Type | Value,
2731
TypeInstantiation = Type | Instantiation,
2832
ValueInstantiation = Value | Instantiation,
2933
TypeValueInstantiation = Type | Value | Instantiation,
3034

31-
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Value)
35+
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
3236
};
3337
};
3438
using ExprDependence = ExprDependenceScope::ExprDependence;
35-
static constexpr unsigned ExprDependenceBits = 4;
39+
static constexpr unsigned ExprDependenceBits = 5;
3640

3741
struct TypeDependenceScope {
3842
enum TypeDependence : uint8_t {
@@ -47,6 +51,8 @@ struct TypeDependenceScope {
4751
/// Whether this type is a variably-modified type (C99 6.7.5).
4852
VariablyModified = 8,
4953

54+
// FIXME: add Error bit.
55+
5056
None = 0,
5157
All = 15,
5258

@@ -83,11 +89,14 @@ LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
8389
/// Computes dependencies of a reference with the name having template arguments
8490
/// with \p TA dependencies.
8591
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
86-
auto E =
87-
static_cast<ExprDependence>(TA & ~TemplateArgumentDependence::Dependent);
92+
auto D = ExprDependence::None;
93+
if (TA & TemplateArgumentDependence::UnexpandedPack)
94+
D |= ExprDependence::UnexpandedPack;
95+
if (TA & TemplateArgumentDependence::Instantiation)
96+
D |= ExprDependence::Instantiation;
8897
if (TA & TemplateArgumentDependence::Dependent)
89-
return E | ExprDependence::Type | ExprDependence::Value;
90-
return E;
98+
D |= ExprDependence::Type | ExprDependence::Value;
99+
return D;
91100
}
92101
inline ExprDependence toExprDependence(TypeDependence TD) {
93102
// This hack works because TypeDependence and TemplateArgumentDependence
@@ -127,10 +136,13 @@ toTemplateArgumentDependence(TemplateNameDependence D) {
127136
}
128137
inline TemplateArgumentDependence
129138
toTemplateArgumentDependence(ExprDependence ED) {
130-
TemplateArgumentDependence TAD = static_cast<TemplateArgumentDependence>(
131-
ED & ~(ExprDependence::Type | ExprDependence::Value));
139+
TemplateArgumentDependence TAD = TemplateArgumentDependence::None;
132140
if (ED & (ExprDependence::Type | ExprDependence::Value))
133141
TAD |= TemplateArgumentDependence::Dependent;
142+
if (ED & ExprDependence::Instantiation)
143+
TAD |= TemplateArgumentDependence::Instantiation;
144+
if (ED & ExprDependence::UnexpandedPack)
145+
TAD |= TemplateArgumentDependence::UnexpandedPack;
134146
return TAD;
135147
}
136148

clang/include/clang/AST/Expr.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ class Expr : public ValueStmt {
226226
return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
227227
}
228228

229+
/// Whether this expression contains subexpressions which had errors, e.g. a
230+
/// TypoExpr.
231+
bool containsErrors() const {
232+
return static_cast<bool>(getDependence() & ExprDependence::Error);
233+
}
234+
229235
/// getExprLoc - Return the preferred location for the arrow when diagnosing
230236
/// a problem with a generic expression.
231237
SourceLocation getExprLoc() const LLVM_READONLY;
@@ -5881,7 +5887,8 @@ class TypoExpr : public Expr {
58815887
public:
58825888
TypoExpr(QualType T) : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary) {
58835889
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
5884-
setDependence(ExprDependence::TypeValueInstantiation);
5890+
setDependence(ExprDependence::TypeValueInstantiation |
5891+
ExprDependence::Error);
58855892
}
58865893

58875894
child_range children() {

clang/include/clang/AST/ExprCXX.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4020,7 +4020,7 @@ class PackExpansionExpr : public Expr {
40204020
EllipsisLoc(EllipsisLoc),
40214021
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0),
40224022
Pattern(Pattern) {
4023-
setDependence(ExprDependence::TypeValueInstantiation);
4023+
setDependence(computeDependence(this));
40244024
}
40254025

40264026
PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}
@@ -4531,7 +4531,7 @@ class CXXFoldExpr : public Expr {
45314531
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
45324532
SubExprs[0] = LHS;
45334533
SubExprs[1] = RHS;
4534-
setDependence(ExprDependence::TypeValueInstantiation);
4534+
setDependence(computeDependence(this));
45354535
}
45364536

45374537
CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
14961496
return CachedLocalOrUnnamed;
14971497
}
14981498
};
1499-
enum { NumTypeBits = 18 };
1499+
enum { NumTypeBits = 8 + TypeDependenceBits + 6 };
15001500

15011501
protected:
15021502
// These classes allow subclasses to somewhat cleanly pack bitfields

clang/lib/AST/ComputeDependence.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
120120
}
121121

122122
ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
123-
auto D = ExprDependence::None;
124-
if (E->getType()->isDependentType())
125-
D |= ExprDependence::Type;
123+
// FIXME: why is unexpanded-pack not propagated?
124+
auto D = toExprDependence(E->getType()->getDependence()) &
125+
~ExprDependence::UnexpandedPack;
126126
// Note: we treat a statement-expression in a dependent context as always
127127
// being value- and instantiation-dependent. This matches the behavior of
128128
// lambda-expressions and GCC.
@@ -172,7 +172,7 @@ ExprDependence clang::computeDependence(VAArgExpr *E) {
172172

173173
ExprDependence clang::computeDependence(NoInitExpr *E) {
174174
return toExprDependence(E->getType()->getDependence()) &
175-
ExprDependence::Instantiation;
175+
(ExprDependence::Instantiation & ExprDependence::Error);
176176
}
177177

178178
ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
@@ -213,8 +213,8 @@ ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
213213

214214
ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
215215
auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
216-
if (E->getType()->isDependentType())
217-
D |= ExprDependence::Type;
216+
D |= toExprDependence(E->getType()->getDependence()) &
217+
(ExprDependence::Type | ExprDependence::Error);
218218
return D;
219219
}
220220

@@ -296,13 +296,19 @@ ExprDependence clang::computeDependence(CXXNoexceptExpr *E, CanThrowResult CT) {
296296
return D;
297297
}
298298

299+
ExprDependence clang::computeDependence(PackExpansionExpr *E) {
300+
return (E->getPattern()->getDependence() & ~ExprDependence::UnexpandedPack) |
301+
ExprDependence::TypeValueInstantiation;
302+
}
303+
299304
ExprDependence clang::computeDependence(SubstNonTypeTemplateParmExpr *E) {
300305
return E->getReplacement()->getDependence();
301306
}
302307

303308
ExprDependence clang::computeDependence(CoroutineSuspendExpr *E) {
304309
if (auto *Resume = E->getResumeExpr())
305-
return (Resume->getDependence() & ExprDependence::TypeValue) |
310+
return (Resume->getDependence() &
311+
(ExprDependence::TypeValue | ExprDependence::Error)) |
306312
(E->getCommonExpr()->getDependence() & ~ExprDependence::TypeValue);
307313
return E->getCommonExpr()->getDependence() |
308314
ExprDependence::TypeValueInstantiation;
@@ -377,6 +383,7 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
377383

378384
if (Decl->isParameterPack())
379385
Deps |= ExprDependence::UnexpandedPack;
386+
Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
380387

381388
// (TD) C++ [temp.dep.expr]p3:
382389
// An id-expression is type-dependent if it contains:
@@ -496,6 +503,10 @@ ExprDependence clang::computeDependence(GenericSelectionExpr *E,
496503
bool ContainsUnexpandedPack) {
497504
auto D = ContainsUnexpandedPack ? ExprDependence::UnexpandedPack
498505
: ExprDependence::None;
506+
for (auto *AE : E->getAssocExprs())
507+
D |= AE->getDependence() & ExprDependence::Error;
508+
D |= E->getControllingExpr()->getDependence() & ExprDependence::Error;
509+
499510
if (E->isResultDependent())
500511
return D | ExprDependence::TypeValueInstantiation;
501512
return D | (E->getResultExpr()->getDependence() &
@@ -623,7 +634,8 @@ ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
623634
if (E->getType()->getContainedDeducedType())
624635
D |= ExprDependence::Type;
625636
for (auto *A : E->arguments())
626-
D |= A->getDependence() & ExprDependence::UnexpandedPack;
637+
D |= A->getDependence() &
638+
(ExprDependence::UnexpandedPack | ExprDependence::Error);
627639
return D;
628640
}
629641

@@ -643,6 +655,15 @@ ExprDependence clang::computeDependence(MaterializeTemporaryExpr *E) {
643655
return E->getSubExpr()->getDependence();
644656
}
645657

658+
ExprDependence clang::computeDependence(CXXFoldExpr *E) {
659+
auto D = ExprDependence::TypeValueInstantiation;
660+
for (const auto *C : {E->getLHS(), E->getRHS()}) {
661+
if (C)
662+
D |= C->getDependence() & ~ExprDependence::UnexpandedPack;
663+
}
664+
return D;
665+
}
666+
646667
ExprDependence clang::computeDependence(TypeTraitExpr *E) {
647668
auto D = ExprDependence::None;
648669
for (const auto *A : E->getArgs())

clang/lib/AST/Expr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4231,6 +4231,7 @@ DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
42314231
ILE->setType(baseExpr->getType());
42324232
BaseAndUpdaterExprs[1] = ILE;
42334233

4234+
// FIXME: this is wrong, set it correctly.
42344235
setDependence(ExprDependence::None);
42354236
}
42364237

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ void TextNodeDumper::Visit(const Stmt *Node) {
126126
if (const auto *E = dyn_cast<Expr>(Node)) {
127127
dumpType(E->getType());
128128

129+
if (E->containsErrors()) {
130+
ColorScope Color(OS, ShowColors, ErrorsColor);
131+
OS << " contains-errors";
132+
}
133+
129134
{
130135
ColorScope Color(OS, ShowColors, ValueKindColor);
131136
switch (E->getValueKind()) {

clang/lib/Serialization/ASTReaderStmt.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ namespace clang {
106106

107107
/// The number of record fields required for the Expr class
108108
/// itself.
109-
static const unsigned NumExprFields = NumStmtFields + 7;
109+
static const unsigned NumExprFields =
110+
NumStmtFields + ExprDependenceBits + 3;
110111

111112
/// Read and initialize a ExplicitTemplateArgumentList structure.
112113
void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
@@ -517,6 +518,7 @@ void ASTStmtReader::VisitExpr(Expr *E) {
517518
bool ValueDependent = Record.readInt();
518519
bool InstantiationDependent = Record.readInt();
519520
bool ContainsUnexpandedTemplateParameters = Record.readInt();
521+
bool ContainsErrors = Record.readInt();
520522
auto Deps = ExprDependence::None;
521523
if (TypeDependent)
522524
Deps |= ExprDependence::Type;
@@ -526,6 +528,8 @@ void ASTStmtReader::VisitExpr(Expr *E) {
526528
Deps |= ExprDependence::Instantiation;
527529
if (ContainsUnexpandedTemplateParameters)
528530
Deps |= ExprDependence::UnexpandedPack;
531+
if (ContainsErrors)
532+
Deps |= ExprDependence::Error;
529533
E->setDependence(Deps);
530534

531535
E->setValueKind(static_cast<ExprValueKind>(Record.readInt()));

0 commit comments

Comments
 (0)