forked from OSchip/llvm-project
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 llvm-svn: 39368
This commit is contained in:
parent
d9e7bd46dd
commit
c1aadb172f
|
@ -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::
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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::
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue