diff --git a/clang/include/clang/AST/ASTDumperUtils.h b/clang/include/clang/AST/ASTDumperUtils.h --- a/clang/include/clang/AST/ASTDumperUtils.h +++ b/clang/include/clang/AST/ASTDumperUtils.h @@ -62,6 +62,8 @@ 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}; diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -17,11 +17,12 @@ enum ExprDependence : uint8_t { UnexpandedPack = 1, Instantiation = 2, - Type = 4, - Value = 8, + Error = 4, + Type = 8, + Value = 16, None = 0, - All = 15, + All = 31, TypeValue = Type | Value, TypeInstantiation = Type | Instantiation, @@ -32,7 +33,7 @@ }; }; using ExprDependence = ExprDependenceScope::ExprDependence; -static constexpr unsigned ExprDependenceBits = 4; +static constexpr unsigned ExprDependenceBits = 5; struct TypeDependenceScope { enum TypeDependence : uint8_t { @@ -42,13 +43,15 @@ /// Whether this type somehow involves a template parameter, even /// if the resolution of the type does not depend on a template parameter. Instantiation = 2, + /// Placeholder, and is not used in actual Type. + Error = 4, /// Whether this type is a dependent type (C++ [temp.dep.type]). - Dependent = 4, + Dependent = 8, /// Whether this type is a variably-modified type (C99 6.7.5). - VariablyModified = 8, + VariablyModified = 16, None = 0, - All = 15, + All = 31, DependentInstantiation = Dependent | Instantiation, @@ -56,18 +59,19 @@ }; }; using TypeDependence = TypeDependenceScope::TypeDependence; -static constexpr unsigned TypeDependenceBits = 4; +static constexpr unsigned TypeDependenceBits = 5; #define LLVM_COMMON_DEPENDENCE(NAME) \ struct NAME##Scope { \ enum NAME : uint8_t { \ UnexpandedPack = 1, \ Instantiation = 2, \ - Dependent = 4, \ + Error = 4, \ + Dependent = 8, \ \ None = 0, \ DependentInstantiation = Dependent | Instantiation, \ - All = 7, \ + All = 15, \ \ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Dependent) \ }; \ 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 @@ -226,6 +226,12 @@ return static_cast(getDependence() & ExprDependence::UnexpandedPack); } + /// Whether this expression contains subexpressions which had errors, e.g. a + /// TypoExpr. + bool containsErrors() const { + return static_cast(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 @@ 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() { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1496,7 +1496,7 @@ return CachedLocalOrUnnamed; } }; - enum { NumTypeBits = 18 }; + enum { NumTypeBits = 8 + TypeDependenceBits + 6 }; protected: // These classes allow subclasses to somewhat cleanly pack bitfields 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 @@ -623,7 +623,8 @@ 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; } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -126,6 +126,11 @@ if (const auto *E = dyn_cast(Node)) { dumpType(E->getType()); + if (E->containsErrors()) { + ColorScope Color(OS, ShowColors, ErrorsColor); + OS << " contains-errors"; + } + { ColorScope Color(OS, ShowColors, ValueKindColor); switch (E->getValueKind()) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -106,7 +106,8 @@ /// 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 @@ 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 @@ Deps |= ExprDependence::Instantiation; if (ContainsUnexpandedTemplateParameters) Deps |= ExprDependence::UnexpandedPack; + if (ContainsErrors) + Deps |= ExprDependence::Error; E->setDependence(Deps); E->setValueKind(static_cast(Record.readInt())); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2280,6 +2280,7 @@ 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 @@ 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 @@ 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 @@ 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 diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -540,6 +540,7 @@ 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()); }