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

llvm-svn: 39368
This commit is contained in:
Steve Naroff 2007-03-28 21:49:40 +00:00
parent d9e7bd46dd
commit c1aadb172f
5 changed files with 83 additions and 28 deletions

View File

@ -225,10 +225,10 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
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 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
} 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::

View File

@ -29,6 +29,20 @@ bool Type::isVoidType() const {
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;
}

View File

@ -225,10 +225,10 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
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 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
} 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::

View File

@ -183,28 +183,39 @@ public:
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; }

View File

@ -488,6 +488,8 @@ DIAG(err_typecheck_subscript_value, ERROR,
"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,