diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -588,12 +588,18 @@ } template bool ByteCodeExprGen::discard(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope Scope(this, /*NewDiscardResult=*/true); return this->Visit(E); } template bool ByteCodeExprGen::visit(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope Scope(this, /*NewDiscardResult=*/false); return this->Visit(E); } @@ -1156,6 +1162,7 @@ /// We need to evaluate the initializer and return its value. template bool ByteCodeExprGen::visitDecl(const VarDecl *VD) { + assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); std::optional VarT = classify(VD->getType()); // Create and initialize the variable. diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -84,3 +84,18 @@ return 5; } static_assert(a() == 5, ""); + +constexpr int invalid() { + // Invalid expression in visit(). + while(huh) {} // expected-error {{use of undeclared identifier}} \ + // ref-error {{use of undeclared identifier}} + + return 0; +} + +constexpr void invalid2() { + int i = 0; + // Invalid expression in discard(). + huh(); // expected-error {{use of undeclared identifier}} \ + // ref-error {{use of undeclared identifier}} +}