diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,6 +45,7 @@ #include "clang/Sema/Template.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/Casting.h" #include #include #include @@ -14345,7 +14346,16 @@ ActivePolicy = ℘ } + bool ErrorsInCtorInitializer = + llvm::isa_and_nonnull(FD) + ? llvm::any_of(llvm::dyn_cast(FD)->inits(), + [](const auto *Init) { + return Init->getInit() && + Init->getInit()->containsErrors(); + }) + : false; if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + !ErrorsInCtorInitializer && !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose)) FD->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1685,6 +1685,7 @@ // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, CheckConstexprKind Kind) { + assert(!NewFD->isInvalidDecl()); const CXXMethodDecl *MD = dyn_cast(NewFD); if (MD && MD->isInstance()) { // C++11 [dcl.constexpr]p4: diff --git a/clang/test/SemaCXX/invalid-constructor-init.cpp b/clang/test/SemaCXX/invalid-constructor-init.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/invalid-constructor-init.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -frecovery-ast -verify %s + +struct X { + int Y; + constexpr X() : Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}} +}; + +struct X2 { + int Y = foo(); // expected-error {{use of undeclared identifier 'foo'}} \ + // expected-note {{subexpression not valid in a constant expression}} + constexpr X2() {} // expected-error {{constexpr constructor never produces a constant expression}} +}; + +struct CycleDelegate { + int Y; + CycleDelegate(int) : Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}} + // no "delegation cycle" diagnostic emitted! + CycleDelegate(float) : CycleDelegate(1) {} +};