[cfe-commits] r39379 - in /cfe/cfe/trunk: AST/SemaDecl.cpp AST/SemaExpr.cpp Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/AST/Decl.h include/clang/AST/Expr.h include/clang/Basic/DiagnosticKinds.def

Steve Naroff snaroff at apple.com
Wed Jul 11 09:43:47 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:43:47 2007
New Revision: 39379

URL: http://llvm.org/viewvc/llvm-project?rev=39379&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
- Typechecking for ++/-- not operating on canonical type (fixed).
- Many changes to Decl.h...
-- Changed ObjectDecl->ValueDecl.
-- ValueDecl doesn't define a storage class. The storage class is now
defined by VarDecl/FunctionDecl. EnumConstant decls don't need a storage class.
-- FieldDecl now inherits directly from Decl (it is not a value).
- Changed SemaExpr to use the new Decl.h. Also added a couple diagnostics for
bogus storage class usage. For example:
z.c:6:10: error: illegal storage class on function
auto int func();
         ^
z.c:7:14: error: illegal storage class on file-scoped variable
register int b;
             ^

Modified:
    cfe/cfe/trunk/AST/SemaDecl.cpp
    cfe/cfe/trunk/AST/SemaExpr.cpp
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/include/clang/AST/Decl.h
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:43:47 2007
@@ -207,7 +207,7 @@
     return New;
   }
   // We've verified the types match, now check if Old is "extern".
-  if (Old->getStorageClass() != ObjectDecl::Extern) {
+  if (Old->getStorageClass() != VarDecl::Extern) {
     Diag(New->getLocation(), diag::err_redefinition, New->getName());
     Diag(Old->getLocation(), diag::err_previous_definition);
   }
@@ -224,7 +224,6 @@
   return 0;
 }
 
-
 Action::DeclTy *
 Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 
                       DeclTy *LastInGroup) {
@@ -249,9 +248,21 @@
     New = NewTD;
   } else if (D.isFunctionDeclarator()) {
     TypeRef R = GetTypeForDeclarator(D, S);
-    if (R.isNull()) return 0;
+    if (R.isNull()) return 0; // FIXME: "auto func();" passes through...
     
-    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R);
+    FunctionDecl::StorageClass SC;
+    switch (D.getDeclSpec().getStorageClassSpec()) {
+      default: assert(0 && "Unknown storage class!");
+      case DeclSpec::SCS_auto:        
+      case DeclSpec::SCS_register:
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func, R);
+        return 0;
+      case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break;
+    }
+
+    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC);
     
     // Merge the decl with the existing one if appropriate.
     if (PrevDecl) {
@@ -263,25 +274,23 @@
     TypeRef R = GetTypeForDeclarator(D, S);
     if (R.isNull()) return 0;
 
-    ObjectDecl::StorageClass SC;
+    VarDecl *NewVD;
+    VarDecl::StorageClass SC;
     switch (D.getDeclSpec().getStorageClassSpec()) {
       default: assert(0 && "Unknown storage class!");
-      case DeclSpec::SCS_unspecified: SC = ObjectDecl::None; break;
-      case DeclSpec::SCS_extern:      SC = ObjectDecl::Extern; break;
-      case DeclSpec::SCS_static:      SC = ObjectDecl::Static; break;
-      // The following 2 should never be seen in this context.
-      case DeclSpec::SCS_auto:        SC = ObjectDecl::Auto; break;
-      case DeclSpec::SCS_register:    SC = ObjectDecl::Register; break;
-    }
-    VarDecl *NewVD;
-    
+      case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = VarDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = VarDecl::Static; break;
+      case DeclSpec::SCS_auto:        SC = VarDecl::Auto; break;
+      case DeclSpec::SCS_register:    SC = VarDecl::Register; break;
+    }    
     if (S->getParent() == 0) {
       // File scope. C99 6.9.2p2: A declaration of an identifier for and 
       // object that has file scope without an initializer, and without a
       // storage-class specifier or with the storage-class specifier "static",
       // constitutes a tentative definition. Note: A tentative definition with
       // external linkage is valid (C99 6.2.2p5).
-      if (!Init && SC == ObjectDecl::Static) {
+      if (!Init && SC == VarDecl::Static) {
         // C99 6.9.2p3: If the declaration of an identifier for an object is
         // a tentative definition and has internal linkage (C99 6.2.2p3), the  
         // declared type shall not be an incomplete type.
@@ -290,11 +299,16 @@
           return 0;
         }
       }
+      // FIXME: Find C99 spec reference
+      if (SC == VarDecl::Auto || SC == VarDecl::Register) {
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope, R);
+        return 0;
+      }
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC);
     } else { 
       // Block scope. C99 6.7p7: If an identifier for an object is declared with
       // no linkage (C99 6.2.2p6), the type for the object shall be complete...
-      if (SC != ObjectDecl::Extern) {
+      if (SC != VarDecl::Extern) {
         if (R->isIncompleteType()) {
           Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, R);
           return 0;
@@ -341,7 +355,7 @@
   // FIXME: Handle storage class (auto, register). No declarator?
   VarDecl *New = new ParmVarDecl(PI.IdentLoc, II, 
                                  TypeRef::getFromOpaquePtr(PI.TypeInfo), 
-                                 ObjectDecl::None);
+                                 VarDecl::None);
 
   // If this has an identifier, add it to the scope stack.
   if (II) {

Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:43:47 2007
@@ -75,9 +75,9 @@
     }
   }
   
-  if (ObjectDecl *OD = dyn_cast<ObjectDecl>(D)) {
-    return new DeclRefExpr(OD);
-  } else if (isa<TypedefDecl>(D))
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    return new DeclRefExpr(VD, VD->getType());
+  if (isa<TypedefDecl>(D))
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
 
   assert(0 && "Invalid decl");
@@ -425,23 +425,26 @@
 Action::ExprResult
 Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
                                                unsigned OpCode) {
-  TypeRef type = op->getTypeRef();
+  TypeRef qType = op->getTypeRef();
 
-  assert(!type.isNull() && "no type for increment/decrement expression");
+  assert(!qType.isNull() && "no type for increment/decrement expression");
+
+  Type *canonType = qType->getCanonicalType();
   
-  if (const PointerType *pt = dyn_cast<PointerType>(type)) {
-    if (!pt->getPointeeType()->isObjectType()) // C99 6.5.6p2
-      return Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, type);    
-  } else if (!type->isRealType()) // C99 6.5.2.4: isRealType excludes complex.
+  // C99 6.5.2.4p1
+  if (const PointerType *pt = dyn_cast<PointerType>(canonType)) {
+    if (!pt->getPointeeType()->isObjectType()) // C99 6.5.2.4p2, 6.5.6p2
+      return Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, qType);    
+  } else if (!canonType->isRealType()) { 
     // FIXME: Allow Complex as a GCC extension.
-    return Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, type);    
-
+    return Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, qType);    
+  }
   // At this point, we know we have a real or pointer type. As a result, the
   // following predicate is overkill (i.e. it will check for types we know we
   // don't have in this context). Nevertheless, we model the C99 spec closely.
-  if (!type.isModifiableLvalue())
-    return Diag(OpLoc, diag::err_typecheck_not_modifiable, type);
+  if (!qType.isModifiableLvalue())
+    return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
 
-  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, type);
+  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
 }
 

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:43:47 2007
@@ -207,7 +207,7 @@
     return New;
   }
   // We've verified the types match, now check if Old is "extern".
-  if (Old->getStorageClass() != ObjectDecl::Extern) {
+  if (Old->getStorageClass() != VarDecl::Extern) {
     Diag(New->getLocation(), diag::err_redefinition, New->getName());
     Diag(Old->getLocation(), diag::err_previous_definition);
   }
@@ -224,7 +224,6 @@
   return 0;
 }
 
-
 Action::DeclTy *
 Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 
                       DeclTy *LastInGroup) {
@@ -249,9 +248,21 @@
     New = NewTD;
   } else if (D.isFunctionDeclarator()) {
     TypeRef R = GetTypeForDeclarator(D, S);
-    if (R.isNull()) return 0;
+    if (R.isNull()) return 0; // FIXME: "auto func();" passes through...
     
-    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R);
+    FunctionDecl::StorageClass SC;
+    switch (D.getDeclSpec().getStorageClassSpec()) {
+      default: assert(0 && "Unknown storage class!");
+      case DeclSpec::SCS_auto:        
+      case DeclSpec::SCS_register:
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func, R);
+        return 0;
+      case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = FunctionDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break;
+    }
+
+    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC);
     
     // Merge the decl with the existing one if appropriate.
     if (PrevDecl) {
@@ -263,25 +274,23 @@
     TypeRef R = GetTypeForDeclarator(D, S);
     if (R.isNull()) return 0;
 
-    ObjectDecl::StorageClass SC;
+    VarDecl *NewVD;
+    VarDecl::StorageClass SC;
     switch (D.getDeclSpec().getStorageClassSpec()) {
       default: assert(0 && "Unknown storage class!");
-      case DeclSpec::SCS_unspecified: SC = ObjectDecl::None; break;
-      case DeclSpec::SCS_extern:      SC = ObjectDecl::Extern; break;
-      case DeclSpec::SCS_static:      SC = ObjectDecl::Static; break;
-      // The following 2 should never be seen in this context.
-      case DeclSpec::SCS_auto:        SC = ObjectDecl::Auto; break;
-      case DeclSpec::SCS_register:    SC = ObjectDecl::Register; break;
-    }
-    VarDecl *NewVD;
-    
+      case DeclSpec::SCS_unspecified: SC = VarDecl::None; break;
+      case DeclSpec::SCS_extern:      SC = VarDecl::Extern; break;
+      case DeclSpec::SCS_static:      SC = VarDecl::Static; break;
+      case DeclSpec::SCS_auto:        SC = VarDecl::Auto; break;
+      case DeclSpec::SCS_register:    SC = VarDecl::Register; break;
+    }    
     if (S->getParent() == 0) {
       // File scope. C99 6.9.2p2: A declaration of an identifier for and 
       // object that has file scope without an initializer, and without a
       // storage-class specifier or with the storage-class specifier "static",
       // constitutes a tentative definition. Note: A tentative definition with
       // external linkage is valid (C99 6.2.2p5).
-      if (!Init && SC == ObjectDecl::Static) {
+      if (!Init && SC == VarDecl::Static) {
         // C99 6.9.2p3: If the declaration of an identifier for an object is
         // a tentative definition and has internal linkage (C99 6.2.2p3), the  
         // declared type shall not be an incomplete type.
@@ -290,11 +299,16 @@
           return 0;
         }
       }
+      // FIXME: Find C99 spec reference
+      if (SC == VarDecl::Auto || SC == VarDecl::Register) {
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope, R);
+        return 0;
+      }
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC);
     } else { 
       // Block scope. C99 6.7p7: If an identifier for an object is declared with
       // no linkage (C99 6.2.2p6), the type for the object shall be complete...
-      if (SC != ObjectDecl::Extern) {
+      if (SC != VarDecl::Extern) {
         if (R->isIncompleteType()) {
           Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, R);
           return 0;
@@ -341,7 +355,7 @@
   // FIXME: Handle storage class (auto, register). No declarator?
   VarDecl *New = new ParmVarDecl(PI.IdentLoc, II, 
                                  TypeRef::getFromOpaquePtr(PI.TypeInfo), 
-                                 ObjectDecl::None);
+                                 VarDecl::None);
 
   // If this has an identifier, add it to the scope stack.
   if (II) {

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:43:47 2007
@@ -75,9 +75,9 @@
     }
   }
   
-  if (ObjectDecl *OD = dyn_cast<ObjectDecl>(D)) {
-    return new DeclRefExpr(OD);
-  } else if (isa<TypedefDecl>(D))
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    return new DeclRefExpr(VD, VD->getType());
+  if (isa<TypedefDecl>(D))
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
 
   assert(0 && "Invalid decl");
@@ -425,23 +425,26 @@
 Action::ExprResult
 Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
                                                unsigned OpCode) {
-  TypeRef type = op->getTypeRef();
+  TypeRef qType = op->getTypeRef();
 
-  assert(!type.isNull() && "no type for increment/decrement expression");
+  assert(!qType.isNull() && "no type for increment/decrement expression");
+
+  Type *canonType = qType->getCanonicalType();
   
-  if (const PointerType *pt = dyn_cast<PointerType>(type)) {
-    if (!pt->getPointeeType()->isObjectType()) // C99 6.5.6p2
-      return Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, type);    
-  } else if (!type->isRealType()) // C99 6.5.2.4: isRealType excludes complex.
+  // C99 6.5.2.4p1
+  if (const PointerType *pt = dyn_cast<PointerType>(canonType)) {
+    if (!pt->getPointeeType()->isObjectType()) // C99 6.5.2.4p2, 6.5.6p2
+      return Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, qType);    
+  } else if (!canonType->isRealType()) { 
     // FIXME: Allow Complex as a GCC extension.
-    return Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, type);    
-
+    return Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, qType);    
+  }
   // At this point, we know we have a real or pointer type. As a result, the
   // following predicate is overkill (i.e. it will check for types we know we
   // don't have in this context). Nevertheless, we model the C99 spec closely.
-  if (!type.isModifiableLvalue())
-    return Diag(OpLoc, diag::err_typecheck_not_modifiable, type);
+  if (!qType.isModifiableLvalue())
+    return Diag(OpLoc, diag::err_typecheck_not_modifiable, qType);
 
-  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, type);
+  return new UnaryOperator(op, (UnaryOperator::Opcode)OpCode, qType);
 }
 

Modified: cfe/cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Decl.h?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:43:47 2007
@@ -30,16 +30,12 @@
 class Decl {
 public:
   enum Kind {
-    FIRST_ObjectDecl,
-    Function, 
-    BlockVariable, FileVariable, ParmVariable, // subclasses of VarDecl
-    Field, 
-    EnumConstant,
-    LAST_ObjectDecl,
-    FIRST_TypeDecl,
-    Typedef, 
-    Struct, Union, Class, Enum, // subclasses of TagDecl
-    LAST_TypeDecl
+    // Concrete sub-classes of ValueDecl
+    Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
+    // Concrete sub-classes of TypeDecl
+    Typedef, Struct, Union, Class, Enum, 
+    // Concrete sub-class of Decl
+    Field
   };
 
   /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
@@ -104,56 +100,58 @@
   static bool classof(const Decl *) { return true; }
 };
 
-/// ObjectDecl - Represents a declaration of a value.
-class ObjectDecl : public Decl {
-public:
-  enum StorageClass {
-    None, Extern, Static, Auto, Register
-  };
-private:
+/// ValueDecl - Represent the declaration of a variable (in which case it is 
+/// an lvalue) a function (in which case it is a function designator) or
+/// an enum constant. 
+class ValueDecl : public Decl {
   TypeRef DeclType;
-  StorageClass SClass;
 protected:
-  ObjectDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T,
-             StorageClass S = None): Decl(DK, L, Id), DeclType(T), SClass(S) {}
+  ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T): 
+             Decl(DK, L, Id), DeclType(T) {}
 public:
   // FIXME: should rename to getTypeRef/getCanonicalTypeRef to distinguish
   // TypeRef's from Type's...
   TypeRef getType() const { return DeclType; }
   TypeRef getCanonicalType() const { return DeclType.getCanonicalType(); }
-  StorageClass getStorageClass() const { return SClass; }
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
-    return D->getKind() > FIRST_ObjectDecl && D->getKind() < LAST_ObjectDecl;
+    return D->getKind() >= Function && D->getKind() <= EnumConstant;
   }
-  static bool classof(const ObjectDecl *D) { return true; }
+  static bool classof(const ValueDecl *D) { return true; }
 };
 
 /// VarDecl - An instance of this class is created to represent a variable
 /// declaration or definition.
-class VarDecl : public ObjectDecl {
-  // TODO: Initializer.
-protected:
-  VarDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S)
-    : ObjectDecl(DK, L, Id, T, S) {}
-public:  
+class VarDecl : public ValueDecl {
+public:
+  enum StorageClass {
+    None, Extern, Static, Auto, Register
+  };
+  StorageClass getStorageClass() const { return SClass; }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { 
     return D->getKind() >= BlockVariable && D->getKind() <= ParmVariable; 
   }
   static bool classof(const VarDecl *D) { return true; }
+protected:
+  VarDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, TypeRef T,
+          StorageClass SC)
+    : ValueDecl(DK, L, Id, T) {}
+private:
+  StorageClass SClass;
+  // TODO: Initializer.
 };
 
 /// BlockVarDecl - Represent a local variable declaration.
 class BlockVarDecl : public VarDecl {
 public:
-  BlockVarDecl(SourceLocation L, IdentifierInfo *Id, 
-                     TypeRef T, StorageClass S)
+  BlockVarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S)
     : VarDecl(BlockVariable, L, Id, T, S) {}
   
   // Implement isa/cast/dyncast/etc.
-  static bool classof(const VarDecl *D) { return D->getKind() == BlockVariable; }
+  static bool classof(const Decl *D) { return D->getKind() == BlockVariable; }
   static bool classof(const BlockVarDecl *D) { return true; }
 };
 
@@ -163,8 +161,7 @@
 /// pointer to the decl's scope, which is transient).
 class FileVarDecl : public VarDecl {
 public:
-  FileVarDecl(SourceLocation L, IdentifierInfo *Id, 
-                    TypeRef T, StorageClass S)
+  FileVarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S)
     : VarDecl(FileVariable, L, Id, T, S) {}
   
   // Implement isa/cast/dyncast/etc.
@@ -175,34 +172,26 @@
 /// ParmVarDecl - Represent a parameter to a function.
 class ParmVarDecl : public VarDecl {
 public:
-  ParmVarDecl(SourceLocation L, IdentifierInfo *Id, 
-                     TypeRef T, StorageClass S)
+  ParmVarDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S)
     : VarDecl(ParmVariable, L, Id, T, S) {}
   
   // Implement isa/cast/dyncast/etc.
-  static bool classof(const VarDecl *D) { return D->getKind() == ParmVariable; }
+  static bool classof(const Decl *D) { return D->getKind() == ParmVariable; }
   static bool classof(const ParmVarDecl *D) { return true; }
 };
 
 /// FunctionDecl - An instance of this class is created to represent a function
 /// declaration or definition.
-class FunctionDecl : public ObjectDecl {
-  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
-  /// parameters of this function.  This is null if a prototype or if there are
-  /// no formals.  TODO: we could allocate this space immediately after the
-  /// FunctionDecl object to save an allocation like FunctionType does.
-  VarDecl **ParamInfo;
-  
-  Stmt *Body;  // Null if a prototype.
-  
-  /// DeclChain - Linked list of declarations that are defined inside this
-  /// function.
-  Decl *DeclChain;
+class FunctionDecl : public ValueDecl {
 public:
-  FunctionDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
-    : ObjectDecl(Function, L, Id, T), ParamInfo(0), Body(0), DeclChain(0) {}
+  enum StorageClass {
+    None, Extern, Static
+  };
+  FunctionDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T, StorageClass S=None)
+    : ValueDecl(Function, L, Id, T), 
+      ParamInfo(0), Body(0), DeclChain(0), SClass(S) {}
   virtual ~FunctionDecl();
-  
+
   Stmt *getBody() const { return Body; }
   void setBody(Stmt *B) { Body = B; }
   
@@ -215,19 +204,39 @@
     return ParamInfo[i];
   }
   void setParams(VarDecl **NewParamInfo, unsigned NumParams);
+
+  StorageClass getStorageClass() const { return SClass; }
     
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == Function; }
   static bool classof(const FunctionDecl *D) { return true; }
+private:
+  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
+  /// parameters of this function.  This is null if a prototype or if there are
+  /// no formals.  TODO: we could allocate this space immediately after the
+  /// FunctionDecl object to save an allocation like FunctionType does.
+  VarDecl **ParamInfo;
+  
+  Stmt *Body;  // Null if a prototype.
+  
+  /// DeclChain - Linked list of declarations that are defined inside this
+  /// function.
+  Decl *DeclChain;
+
+  StorageClass SClass;
 };
 
 
 /// FieldDecl - An instance of this class is created by Sema::ParseField to 
 /// represent a member of a struct/union/class.
-class FieldDecl : public ObjectDecl {
+class FieldDecl : public Decl {
+  TypeRef DeclType;
 public:
   FieldDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
-    : ObjectDecl(Field, L, Id, T) {}
+    : Decl(Field, L, Id), DeclType(T) {}
+
+  TypeRef getType() const { return DeclType; }
+  TypeRef getCanonicalType() const { return DeclType.getCanonicalType(); }
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
@@ -240,18 +249,17 @@
 /// that is defined.  For example, in "enum X {a,b}", each of a/b are
 /// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
 /// TagType for the X EnumDecl.
-class EnumConstantDecl : public ObjectDecl {
+class EnumConstantDecl : public ValueDecl {
 public:
   // FIXME: Capture value info.
   EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
-    : ObjectDecl(EnumConstant, L, Id, T) {}
-  
+    : ValueDecl(EnumConstant, L, Id, T) {}
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() == EnumConstant;
   }
   static bool classof(const EnumConstantDecl *D) { return true; }
-  
 };
 
 
@@ -270,7 +278,7 @@
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
-    return D->getKind() > FIRST_TypeDecl && D->getKind() < LAST_TypeDecl;
+    return D->getKind() >= Typedef && D->getKind() <= Enum;
   }
   static bool classof(const TypeDecl *D) { return true; }
 };
@@ -323,7 +331,7 @@
     return D->getKind() == Struct || D->getKind() == Union ||
            D->getKind() == Class || D->getKind() == Enum;
   }
-  static bool classof(const ObjectDecl *D) { return true; }
+  static bool classof(const TagDecl *D) { return true; }
 protected:
   void setDefinition(bool V) { IsDefinition = V; }
 };

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:43:47 2007
@@ -33,7 +33,7 @@
   Expr(StmtClass SC, TypeRef T=0) : Stmt(SC), TR(T) {}
   ~Expr() {}
 public:  
-  // FIXME: the return type of getType is inconsistent with ObjectDecl.
+  // FIXME: the return type of getType is inconsistent with Decls.
   // this is confusing and needs to be reconciled (by making one conform).
   Type *getType() const { return TR.getTypePtr(); }
   TypeRef getTypeRef() const { return TR; }
@@ -53,11 +53,11 @@
 /// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
 /// enum, etc.
 class DeclRefExpr : public Expr {
-  ObjectDecl *D;
+  Decl *D; // a ValueDecl or EnumConstantDecl
 public:
-  DeclRefExpr(ObjectDecl *d) : Expr(DeclRefExprClass, d->getType()), D(d) {}
+  DeclRefExpr(Decl *d, TypeRef t) : Expr(DeclRefExprClass, t), D(d) {}
   
-  ObjectDecl *getDecl() const { return D; }
+  Decl *getDecl() const { return D; }
   
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39379&r1=39378&r2=39379&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:43:47 2007
@@ -506,6 +506,10 @@
      "arithmetic on pointer to incomplete type '%s'")
 DIAG(err_typecheck_decl_incomplete_type, ERROR,
      "variable has incomplete type '%s'")
+DIAG(err_typecheck_sclass_fscope, ERROR,
+     "illegal storage class on file-scoped variable")
+DIAG(err_typecheck_sclass_func, ERROR,
+     "illegal storage class on function")
 
 // Statements.
 DIAG(err_continue_not_in_loop, ERROR,





More information about the cfe-commits mailing list