]> granicus.if.org Git - clang/commitdiff
Improve recovery when a constructor fails to type-check. Test case from Anders
authorDouglas Gregor <dgregor@apple.com>
Fri, 27 Mar 2009 04:38:56 +0000 (04:38 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 27 Mar 2009 04:38:56 +0000 (04:38 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67818 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/constructor-recovery.cpp [new file with mode: 0644]
test/SemaCXX/constructor.cpp

index e9f586583c97a6a6f3555a4aba5267eb2245e2d6..fa386ef68d449188035b2d4f67530f6a0e57c3a4 100644 (file)
@@ -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<CXXRecordDecl>(CurContext)->setAbstract(true);
-      } else {
+      } else if (!Method->isInvalidDecl()) {
         Diag(Method->getLocation(), diag::err_non_virtual_pure)
           << Method->getDeclName() << Init->getSourceRange();
         Method->setInvalidDecl();
index bb306e4a0f110efe0489f3e541499d71415f7998..f22686020e44c40b5f5516e6bc7400522f8337c2 100644 (file)
@@ -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<CXXRecordDecl>(Constructor->getDeclContext());
+  if (!ClassDecl)
     return true;
 
-  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(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 (file)
index 0000000..f2f9f43
--- /dev/null
@@ -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;
+}
index 4e3f4177c40dff3c32292ce249f51f25bb51459f..eae51467961275d1bd6cf4d524aa50578946f8d0 100644 (file)
@@ -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'}}