From 332975661d287082f64d260ef6ac5f36499d478f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 27 Mar 2009 04:38:56 +0000 Subject: [PATCH] Improve recovery when a constructor fails to type-check. Test case from Anders git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67818 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 14 ++++++++------ test/SemaCXX/constructor-recovery.cpp | 9 +++++++++ test/SemaCXX/constructor.cpp | 2 +- 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 test/SemaCXX/constructor-recovery.cpp diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e9f586583c..fa386ef68d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2294,7 +2294,7 @@ void Sema::AddInitializerToDecl(DeclTy *dcl, ExprArg init, bool DirectInit) { // A class is abstract if at least one function is pure virtual. cast(CurContext)->setAbstract(true); - } else { + } else if (!Method->isInvalidDecl()) { Diag(Method->getLocation(), diag::err_non_virtual_pure) << Method->getDeclName() << Init->getSourceRange(); Method->setInvalidDecl(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bb306e4a0f..f22686020e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1289,20 +1289,22 @@ bool Sema::CheckConstructorDeclarator(Declarator &D, QualType &R, /// well-formedness, issuing any diagnostics required. Returns true if /// the constructor declarator is invalid. bool Sema::CheckConstructor(CXXConstructorDecl *Constructor) { - if (Constructor->isInvalidDecl()) + CXXRecordDecl *ClassDecl + = dyn_cast(Constructor->getDeclContext()); + if (!ClassDecl) return true; - CXXRecordDecl *ClassDecl = cast(Constructor->getDeclContext()); - bool Invalid = false; + bool Invalid = Constructor->isInvalidDecl(); // C++ [class.copy]p3: // A declaration of a constructor for a class X is ill-formed if // its first parameter is of type (optionally cv-qualified) X and // either there are no other parameters or else all other // parameters have default arguments. - if ((Constructor->getNumParams() == 1) || - (Constructor->getNumParams() > 1 && - Constructor->getParamDecl(1)->getDefaultArg() != 0)) { + if (!Constructor->isInvalidDecl() && + ((Constructor->getNumParams() == 1) || + (Constructor->getNumParams() > 1 && + Constructor->getParamDecl(1)->getDefaultArg() != 0))) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { diff --git a/test/SemaCXX/constructor-recovery.cpp b/test/SemaCXX/constructor-recovery.cpp new file mode 100644 index 0000000000..f2f9f43a10 --- /dev/null +++ b/test/SemaCXX/constructor-recovery.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct C { + virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} +}; + +void f() { + C c; +} diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp index 4e3f4177c4..eae5146796 100644 --- a/test/SemaCXX/constructor.cpp +++ b/test/SemaCXX/constructor.cpp @@ -9,7 +9,7 @@ class Foo { ((Foo))(INT); // expected-error{{cannot be redeclared}} - Foo(Foo foo, int i = 17, int j = 42); // expected-error {{copy constructor must pass its first argument by reference}} + Foo(Foo foo, int i = 17, int j = 42); // expected-error{{copy constructor must pass its first argument by reference}} static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}} virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}} -- 2.40.0