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 @@ -12554,12 +12554,17 @@ InitializationSequence InitSeq(*this, Entity, Kind, None); ExprResult Init = InitSeq.Perform(*this, Entity, Kind, None); - // If default-init fails, leave var uninitialized but valid, for recovery. - if (Init.get()) { Var->setInit(MaybeCreateExprWithCleanups(Init.get())); // This is important for template substitution. Var->setInitStyle(VarDecl::CallInit); + } else if (Init.isInvalid()) { + // If default-init fails, attach a recovery-expr initializer to track + // that initialization was attempted and failed. + auto RecoveryExpr = + CreateRecoveryExpr(Var->getLocation(), Var->getLocation(), {}); + if (RecoveryExpr.get()) + Var->setInit(RecoveryExpr.get()); } CheckCompleteVariableDeclaration(Var); 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 @@ -15002,6 +15002,10 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; + // If initializing the variable failed, don't also diagnose problems with + // the desctructor, they're likely related. + if (VD->getInit() && VD->getInit()->containsErrors()) + return; CXXRecordDecl *ClassDecl = cast(Record->getDecl()); if (ClassDecl->isInvalidDecl()) return; diff --git a/clang/test/SemaCXX/recovery-default-init.cpp b/clang/test/SemaCXX/recovery-default-init.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/recovery-default-init.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -fsyntax-only -frecovery-ast -verify -std=c++11 + +// NOTE: the test can be merged into existing tests once -frecovery-ast is on +// by default. + +struct Foo { // expected-note {{candidate constructor (the implicit copy constructor) not viable}} + Foo(int); // expected-note {{candidate constructor not viable}} + ~Foo() = delete; +}; + +void test() { + // we expect the "attempt to use a deleted function" diagnostic is suppressed. + Foo foo; // expected-error {{no matching constructor for initialization of}} +}