]> granicus.if.org Git - clang/commitdiff
Move the "invalid decl" idiom up to Decl (where we have some bits to steal:-)
authorSteve Naroff <snaroff@apple.com>
Tue, 28 Aug 2007 18:45:29 +0000 (18:45 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 28 Aug 2007 18:45:29 +0000 (18:45 +0000)
Converted ParmVarDecl, FileVarDecl, BlockVarDecl, and Sema::ParseIdentifierExpr() to use the idiom.

Updated array-constraint.c to make sure we no longer get "undeclared identifier" errors:-)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41552 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/SemaDecl.cpp
Sema/SemaExpr.cpp
include/clang/AST/Decl.h
test/Sema/array-constraint.c

index 6ccdf2c396a6bfb9618da36eebfa7a65af93483e..d91420d16fd6213863dfdd9697c33e0f2da64844 100644 (file)
@@ -356,7 +356,9 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
     New = NewFD;
   } else {
     QualType R = GetTypeForDeclarator(D, S);
-    if (R.isNull()) return 0;
+    
+    assert(!R.isNull() && "GetTypeForDeclarator() returned null type");
+    bool InvalidDecl = false;
 
     VarDecl *NewVD;
     VarDecl::StorageClass SC;
@@ -381,7 +383,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
         if (R->isIncompleteType()) {
           Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
                R.getAsString());
-          return 0;
+          InvalidDecl = true;
         }
       }
       // C99 6.9p2: The storage-class specifiers auto and register shall not
@@ -389,13 +391,13 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
       if (SC == VarDecl::Auto || SC == VarDecl::Register) {
         Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope,
              R.getAsString());
-        return 0;
+        InvalidDecl = true;
       }
       // C99 6.7.5.2p2: If an identifier is declared to be an object with 
       // static storage duration, it shall not have a variable length array.
       if (const ArrayType *ary = R->getAsArrayType()) {
         if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
-          return 0;
+          InvalidDecl = true;
       }
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
     } else { 
@@ -405,7 +407,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
         if (R->isIncompleteType()) {
           Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type,
                R.getAsString());
-          return 0;
+          InvalidDecl = true;
         }
       }
       if (SC == VarDecl::Static) {
@@ -413,11 +415,14 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
         // static storage duration, it shall not have a variable length array.
         if (const ArrayType *ary = R->getAsArrayType()) {
           if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
-            return 0;
+            InvalidDecl = true;
         }
       }
       NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
-    }    
+    }
+    if (InvalidDecl)
+      NewVD->setInvalidDecl();
+      
     // Handle attributes prior to checking for duplicates in MergeVarDecl
     HandleDeclAttributes(NewVD, D.getDeclSpec().getAttributes(),
                          D.getAttributes());
@@ -507,8 +512,10 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
     parmDeclType = Context.getPointerType(parmDeclType);
   
   ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, parmDeclType, 
-                                     VarDecl::None, 0, PI.InvalidType);
-
+                                     VarDecl::None, 0);
+  if (PI.InvalidType)
+    New->setInvalidDecl();
+    
   // If this has an identifier, add it to the scope stack.
   if (II) {
     New->setNext(II->getFETokenInfo<Decl>());
index af0e6d4e8e2dd65f2554af1116ff62b8e3edf7dc..bea6e999124d8ec04b9de5609cc3c8e96c2cb2ce 100644 (file)
@@ -75,10 +75,8 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
     }
   }
   if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
-    ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD);
-    
-    // FIXME: generalize this for all decls.
-    if (PVD && PVD->getInvalidType())
+    // Only create DeclRefExpr's for valid Decl's.
+    if (VD->getInvalidDecl())
       return true;
     return new DeclRefExpr(VD, VD->getType(), Loc);
   }
index 7c805930454685b9b74455f8e9feecd4ad34f30f..563921c572c0678398f5267d45879ae324ab2515 100644 (file)
@@ -49,8 +49,11 @@ public:
   };
 private:
   /// DeclKind - This indicates which class this is.
-  Kind DeclKind;
+  Kind DeclKind   :  8;
   
+  /// InvalidDecl - This indicates a semantic error occurred.
+  int InvalidDecl :  1;
+
   /// Loc - The location that this decl.
   SourceLocation Loc;
   
@@ -70,7 +73,8 @@ private:
   
 protected:
   Decl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *NextDecl)
-    : DeclKind(DK), Loc(L), Identifier(Id), Next(0), NextDeclarator(NextDecl) {
+    : DeclKind(DK), InvalidDecl(0), Loc(L), Identifier(Id), Next(0), 
+      NextDeclarator(NextDecl) {
     if (Decl::CollectingStats()) addDeclKind(DK);
   }
   virtual ~Decl();
@@ -84,6 +88,11 @@ public:
   Kind getKind() const { return DeclKind; }
   Decl *getNext() const { return Next; }
   void setNext(Decl *N) { Next = N; }
+
+  /// setInvalidDecl - Indicates the Decl had a semantic error. This
+  /// allows for graceful error recovery.
+  void setInvalidDecl() { InvalidDecl = 1; }
+  int getInvalidDecl() const { return InvalidDecl; }
   
   /// getNextDeclarator - If this decl was part of a multi-declarator
   /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
@@ -221,13 +230,10 @@ public:
 
 /// ParmVarDecl - Represent a parameter to a function.
 class ParmVarDecl : public VarDecl {
-  bool InvalidType;
 public:
   ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
-              Decl *PrevDecl, bool flag)
-    : VarDecl(ParmVariable, L, Id, T, S, PrevDecl), InvalidType(flag) {}
-
-  bool getInvalidType() const { return InvalidType; }
+              Decl *PrevDecl)
+    : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {}
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == ParmVariable; }
index b1095bdc1941adaa5610473757a17a661fb818bf..4d1c2f16007375be913d11308021b405f2a7f8d4 100644 (file)
@@ -5,6 +5,12 @@ struct s* t (struct s z[]) {   // expected-error {{array has incomplete element
   return z;
 }
 
+void ff() { 
+  struct s v, *p; // expected-error {{variable has incomplete type 'struct s'}}
+
+  p = &v;
+}
+
 void *k (void l[2]) {          // expected-error {{array has incomplete element type}}
   return l; 
 }