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/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h --- a/clang/include/clang/AST/ComputeDependence.h +++ b/clang/include/clang/AST/ComputeDependence.h @@ -59,6 +59,7 @@ class ArrayTypeTraitExpr; class ExpressionTraitExpr; class CXXNoexceptExpr; +class PackExpansionExpr; class SubstNonTypeTemplateParmExpr; class CoroutineSuspendExpr; class DependentCoawaitExpr; @@ -71,6 +72,7 @@ class CXXUnresolvedConstructExpr; class CXXDependentScopeMemberExpr; class MaterializeTemporaryExpr; +class CXXFoldExpr; class TypeTraitExpr; class ConceptSpecializationExpr; class PredefinedExpr; @@ -134,6 +136,7 @@ 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(CXXUnresolvedConstructExpr *E); ExprDependence computeDependence(CXXDependentScopeMemberExpr *E); ExprDependence computeDependence(MaterializeTemporaryExpr *E); +ExprDependence computeDependence(CXXFoldExpr *E); ExprDependence computeDependence(TypeTraitExpr *E); ExprDependence computeDependence(ConceptSpecializationExpr *E, bool ValueDependent); 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 @@ -20,19 +20,23 @@ 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 @@ /// 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 @@ /// Computes dependencies of a reference with the name having template arguments /// with \p TA dependencies. inline ExprDependence toExprDependence(TemplateArgumentDependence TA) { - auto E = - static_cast(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 @@ } inline TemplateArgumentDependence toTemplateArgumentDependence(ExprDependence ED) { - TemplateArgumentDependence TAD = static_cast( - 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; } 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/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4020,7 +4020,7 @@ 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 @@ 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) {} 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 @@ -120,9 +120,9 @@ } 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(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(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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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()) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4231,6 +4231,7 @@ ILE->setType(baseExpr->getType()); BaseAndUpdaterExprs[1] = ILE; + // FIXME: this is wrong, set it correctly. setDependence(ExprDependence::None); } 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()); }