[cfe-commits] r39368 - in /cfe/cfe/trunk: AST/SemaExpr.cpp AST/Type.cpp Sema/SemaExpr.cpp include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def

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


Author: snaroff
Date: Wed Jul 11 11:43:40 2007
New Revision: 39368

URL: http://llvm.org/viewvc/llvm-project?rev=39368&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
Finish up Sema::ParseArraySubscriptExpr. This involved:
- adding a couple predicates to Type.h (isObjectType, isDerivedType).
- added a diagnostic for subscripting non-object types (e.g. void (*)()).
- pass the correct result type...a minor detail:-)
- added some spec references to Type.h

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

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

==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:43:40 2007
@@ -225,10 +225,10 @@
   TypeRef t2 = ((Expr *)Idx)->getTypeRef();
 
   assert(!t1.isNull() && "no type for array base expression");
-  assert(!t1.isNull() && "no type for array index expression");
+  assert(!t2.isNull() && "no type for array index expression");
 
-  // In C, the expression e1[e2] is by definition precisely equivalent to
-  // the expression *((e1)+(e2)). This means the array "Base" may actually be 
+  // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+  // to the expression *((e1)+(e2)). This means the array "Base" may actually be 
   // in the subscript position. As a result, we need to derive the array base 
   // and index from the expression types.
   
@@ -242,10 +242,24 @@
   } else 
     return Diag(LLoc, diag::err_typecheck_subscript_value);
 
-  if (indexType->isIntegralType())
-    return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, baseType);
-  else 
+  // C99 6.5.2.1p1
+  if (!indexType->isIntegralType())
     return Diag(LLoc, diag::err_typecheck_subscript);
+
+  TypeRef resultType;
+  if (ArrayType *ary = dyn_cast<ArrayType>(baseType)) {
+    resultType = ary->getElementType();
+  } else if (PointerType *ary = dyn_cast<PointerType>(baseType)) {
+    resultType = ary->getPointeeType();
+    // in practice, the following check catches trying to index a pointer
+    // to a function (e.g. void (*)(int)). Functions are not objects in c99.
+    if (!resultType->isObjectType()) {
+      std::string Name;
+      baseType->getAsString(Name);
+      Diag(LLoc, diag::err_typecheck_subscript_not_object, Name);    
+    }
+  } 
+  return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType);
 }
 
 Action::ExprResult Sema::

Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39368&r1=39367&r2=39368&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:43:40 2007
@@ -29,6 +29,20 @@
   return false;
 }
 
+bool Type::isObjectType() const {
+  if (isa<FunctionType>(CanonicalType))
+    return false;
+  else if (CanonicalType->isIncompleteType())
+    return false;
+  else
+    return true;
+}
+
+bool Type::isDerivedType() const {
+  return isPointerType() || isArrayType() || isFunctionType() ||
+         isStructureType() || isUnionType();
+}
+
 bool Type::isFunctionType() const {
   return isa<FunctionType>(CanonicalType) ? true : false;
 }

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:43:40 2007
@@ -225,10 +225,10 @@
   TypeRef t2 = ((Expr *)Idx)->getTypeRef();
 
   assert(!t1.isNull() && "no type for array base expression");
-  assert(!t1.isNull() && "no type for array index expression");
+  assert(!t2.isNull() && "no type for array index expression");
 
-  // In C, the expression e1[e2] is by definition precisely equivalent to
-  // the expression *((e1)+(e2)). This means the array "Base" may actually be 
+  // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+  // to the expression *((e1)+(e2)). This means the array "Base" may actually be 
   // in the subscript position. As a result, we need to derive the array base 
   // and index from the expression types.
   
@@ -242,10 +242,24 @@
   } else 
     return Diag(LLoc, diag::err_typecheck_subscript_value);
 
-  if (indexType->isIntegralType())
-    return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, baseType);
-  else 
+  // C99 6.5.2.1p1
+  if (!indexType->isIntegralType())
     return Diag(LLoc, diag::err_typecheck_subscript);
+
+  TypeRef resultType;
+  if (ArrayType *ary = dyn_cast<ArrayType>(baseType)) {
+    resultType = ary->getElementType();
+  } else if (PointerType *ary = dyn_cast<PointerType>(baseType)) {
+    resultType = ary->getPointeeType();
+    // in practice, the following check catches trying to index a pointer
+    // to a function (e.g. void (*)(int)). Functions are not objects in c99.
+    if (!resultType->isObjectType()) {
+      std::string Name;
+      baseType->getAsString(Name);
+      Diag(LLoc, diag::err_typecheck_subscript_not_object, Name);    
+    }
+  } 
+  return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType);
 }
 
 Action::ExprResult Sema::

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

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:43:40 2007
@@ -183,28 +183,39 @@
   bool isCanonical() const { return CanonicalType == this; }
   Type *getCanonicalType() const { return CanonicalType; }
 
-  /// Helper methods to distinguish type categories. All type predicates
-  /// operate on the canonical type, ignoring typedefs.
-  bool isIntegralType() const;   // short/int/long, char, bool, enum { ... }
-  bool isFloatingType() const;   // float, double, long double, complex
-  bool isArithmeticType() const; // integral + floating
-  bool isScalarType() const;     // arithmetic + pointers
-  bool isAggregateType() const;  // arrays, structures
+  /// Types are partitioned into 3 broad categories (C99 6.2.5p1): 
+  /// object types, function types, and incomplete types.
   
-  /// FIXME: consider adding classes to complete the "isa" support.
-  bool isVoidType() const;       
+  /// isObjectType - types that fully describe objects. An object is a region
+  /// of memory that can be examined and stored into (H&S).
+  bool isObjectType() const;
+
+  /// isFunctionType - types that describe functions.
   bool isFunctionType() const;   
-  bool isPointerType() const;
-  bool isArrayType() const;
-  bool isStructureType() const;  // no isa<StructType>(t) support 
-  bool isUnionType() const;      // no isa<UnionType>(t) support
-  
-  /// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1)
-  /// - a type that can describe objects, but which lacks information needed to
+
+  /// isIncompleteType - Return true if this is an incomplete type.
+  /// A type that can describe objects, but which lacks information needed to
   /// determine its size (e.g. void, or a fwd declared struct). Clients of this
   /// routine will need to determine if the size is actually required.  
   bool isIncompleteType() const;
   
+  /// Helper methods to distinguish type categories. All type predicates
+  /// operate on the canonical type, ignoring typedefs.
+  bool isIntegralType() const;   // C99 6.2.5p17 (int, char, bool, enum)
+  bool isFloatingType() const;   // C99 6.2.5p11 (float, double, long double)
+  bool isArithmeticType() const; // C99 6.2.5p18 (integral + floating)
+  bool isVoidType() const;       // C99 6.2.5p19
+
+  /// Derived types (C99 6.2.5p20). isFunctionType() is also a derived type.
+  bool isDerivedType() const;
+  bool isPointerType() const;
+  bool isArrayType() const;
+  bool isStructureType() const;   
+  bool isUnionType() const;
+  
+  bool isScalarType() const;     // C99 6.2.5p21 (arithmetic + pointers)
+  bool isAggregateType() const;  // C99 6.2.5p21 (arrays, structures)
+
   virtual void getAsString(std::string &InnerString) const = 0;
   
   static bool classof(const Type *) { return true; }

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=39368&r1=39367&r2=39368&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:43:40 2007
@@ -488,6 +488,8 @@
      "subscripted value is neither array nor pointer")
 DIAG(err_typecheck_subscript, ERROR,
      "array subscript is not an integer")
+DIAG(err_typecheck_subscript_not_object, ERROR,
+     "illegal subscript of non-object type '%s'")
 DIAG(err_typecheck_member_reference_structUnion, ERROR,
      "member reference is not a structure or union")
 DIAG(err_typecheck_member_reference_arrow, ERROR,





More information about the cfe-commits mailing list