]> granicus.if.org Git - clang/commitdiff
Fix PR6327: restore invariants when there's a parse error in an initializer.
authorJohn McCall <rjmccall@apple.com>
Wed, 31 Mar 2010 02:13:20 +0000 (02:13 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 31 Mar 2010 02:13:20 +0000 (02:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99980 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/Sema/init.c
test/SemaCXX/invalid-member-expr.cpp

index 1909607e2d27958ecefa5ee2e22ae7757fdf0f66..72e7f17704d72550373093a1a0cc61ce9211cd52 100644 (file)
@@ -828,6 +828,7 @@ public:
   virtual void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init);
   void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
   void ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto);
+  virtual void ActOnInitializerError(DeclPtrTy Dcl);
   virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
   virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
                                                  DeclPtrTy *Group,
index b60804a1898250eea811ae495966f978748d60f6..51514e77a2c216c457fe94a3b1c2e62125b4c39e 100644 (file)
@@ -3797,6 +3797,41 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
   return;
 }
 
+/// ActOnInitializerError - Given that there was an error parsing an
+/// initializer for the given declaration, try to return to some form
+/// of sanity.
+void Sema::ActOnInitializerError(DeclPtrTy dcl) {
+  // Our main concern here is re-establishing invariants like "a
+  // variable's type is either dependent or complete".
+  Decl *D = dcl.getAs<Decl>();
+  if (!D || D->isInvalidDecl()) return;
+
+  VarDecl *VD = dyn_cast<VarDecl>(D);
+  if (!VD) return;
+
+  QualType Ty = VD->getType();
+  if (Ty->isDependentType()) return;
+
+  // Require a complete type.
+  if (RequireCompleteType(VD->getLocation(), 
+                          Context.getBaseElementType(Ty),
+                          diag::err_typecheck_decl_incomplete_type)) {
+    VD->setInvalidDecl();
+    return;
+  }
+
+  // Require an abstract type.
+  if (RequireNonAbstractType(VD->getLocation(), Ty,
+                             diag::err_abstract_type_in_decl,
+                             AbstractVariableType)) {
+    VD->setInvalidDecl();
+    return;
+  }
+
+  // Don't bother complaining about constructors or destructors,
+  // though.
+}
+
 void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
                                   bool TypeContainsUndeducedAuto) {
   Decl *RealDecl = dcl.getAs<Decl>();
index c2712480c6164e939413f65e6c3b1f7481e0c5c7..b9867cf5027b558ed13da5cd6ac281161d8586b9 100644 (file)
@@ -75,7 +75,8 @@ int sym_fw1a_scr[] = {
 };
 
 // PR3001
-struct s1 s2 = {
+struct s1 s2 = { // expected-error {{variable has incomplete type 'struct s1'}}  \
+                 // expected-note {{forward declaration of 'struct s1'}}
     .a = sizeof(struct s3), // expected-error {{invalid application of 'sizeof'}} \
                             // expected-note{{forward declaration of 'struct s3'}}
     .b = bogus // expected-error {{use of undeclared identifier 'bogus'}}
index 7b17afbf818107b92c9fae5fa0f091f644e924df..7307a47f8282c1595a303816d6f8108b44041662 100644 (file)
@@ -19,3 +19,21 @@ void test2() {
   x->operator; // expected-error{{missing type specifier after 'operator'}}
   x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
 }
+
+// PR6327
+namespace test3 {
+  template <class A, class B> struct pair {};
+
+  void test0() {
+    pair<int, int> z = minmax({}); // expected-error {{expected expression}}
+  }
+
+  struct string {
+    class iterator {};
+  };
+
+  void test1() {
+    string s;
+    string::iterator i = s.foo(); // expected-error {{no member named 'foo'}}
+  }
+}