Submitted by:
Reviewed by:
Added size expression to ArrayType. This was needed to implement
Type::isIncompleteType(). At the moment, there is no support for
determining if we have a constant expression (which won't be too
difficult now that we have support for literal parsing/ast's).
Nevertheless, the parser will allow "struct foo { int a[b]; }"
(which is illegal). There is still significant work to fully analyze
array types. The good news is "carbon.h" goes from 288 bogus errors
down to 26!

llvm-svn: 39355
This commit is contained in:
Steve Naroff 2007-03-14 19:55:17 +00:00
parent 4f88b3113e
commit b7d4924eb1
5 changed files with 27 additions and 17 deletions

View File

@ -155,12 +155,10 @@ TypeRef ASTContext::getPointerType(TypeRef T) {
/// specified element type.
TypeRef ASTContext::getArrayType(TypeRef EltTy,ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals, Expr *NumElts) {
#warning "IGNORING SIZE"
// Unique array types, to guarantee there is only one array of a particular
// structure.
FoldingSetNodeID ID;
ArrayType::Profile(ID, ASM, EltTypeQuals, EltTy);
ArrayType::Profile(ID, ASM, EltTypeQuals, EltTy, NumElts);
void *InsertPos = 0;
if (ArrayType *ATP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
@ -178,7 +176,7 @@ TypeRef ASTContext::getArrayType(TypeRef EltTy,ArrayType::ArraySizeModifier ASM,
assert(NewIP == 0 && "Shouldn't be in the map!");
}
ArrayType *New = new ArrayType(EltTy, ASM, EltTypeQuals, Canonical);
ArrayType *New = new ArrayType(EltTy, ASM, EltTypeQuals, Canonical, NumElts);
ArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return New;

View File

@ -41,11 +41,16 @@ bool Type::isIncompleteType() const {
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
// forward declaration, but not a full definition (C99 6.2.5p22).
return !cast<TaggedType>(this)->getDecl()->isDefinition();
case Array:
// An array of unknown size is an incomplete type (C99 6.2.5p22).
// FIXME: Implement this.
return true; // cast<ArrayType>(this)-> blah.
// In C99, an unknown size is permitted in 4 instances:
// - The array being declared is a formal parameter of a function.
// - The declarator is accompanied by an initializer from which the array
// can be deduced (char foo[] = "whatever").
// - Forward declarations (extern int matrix[][7]).
// - The last component of a structure (flexible array idiom).
// Clients of this routine will need to determine if the size is required.
return cast<ArrayType>(this)->getSizeExpression() == 0;
}
}

View File

@ -473,7 +473,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
// constant: integer-constant
// constant: floating-constant
Actions.ParseNumericConstant(Tok);
Res = Actions.ParseNumericConstant(Tok);
ConsumeToken();
// These can be followed by postfix-expr pieces.

View File

@ -25,6 +25,7 @@ namespace clang {
class TagDecl;
class RecordDecl;
class EnumDecl;
class Expr;
/// TypeRef - For efficiency, we don't store CVR-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@ -267,29 +268,34 @@ private:
/// ElementType - The element type of the array.
TypeRef ElementType;
/// FIXME: Capture size for VLA or constant size.
/// FIXME: Update Profile()!
/// Use this to implement Type::isIncompleteType.
ArrayType(TypeRef et, ArraySizeModifier sm, unsigned tq, Type *can)
: Type(Array, can), SizeModifier(sm), IndexTypeQuals(tq), ElementType(et) {}
/// SizeExpr - The size is either a constant or assignment expression (for
/// Variable Length Arrays). VLA's are only permitted within a function block.
Expr *SizeExpr;
ArrayType(TypeRef et, ArraySizeModifier sm, unsigned tq, Type *can, Expr *e)
: Type(Array, can), SizeModifier(sm), IndexTypeQuals(tq), ElementType(et),
SizeExpr(e) {}
friend class ASTContext; // ASTContext creates these.
public:
TypeRef getElementType() const { return ElementType; }
ArraySizeModifier getSizeModifier() const { return SizeModifier; }
unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
Expr *getSizeExpression() const { return SizeExpr; }
virtual void getAsString(std::string &InnerString) const;
void Profile(FoldingSetNodeID &ID) {
Profile(ID, getSizeModifier(), getIndexTypeQualifier(), getElementType());
Profile(ID, getSizeModifier(), getIndexTypeQualifier(), getElementType(),
getSizeExpression());
}
static void Profile(FoldingSetNodeID &ID, ArraySizeModifier SizeModifier,
unsigned IndexTypeQuals, TypeRef ElementType) {
unsigned IndexTypeQuals, TypeRef ElementType,
Expr *SizeExpr) {
ID.AddInteger(SizeModifier);
ID.AddInteger(IndexTypeQuals);
ID.AddPointer(ElementType.getAsOpaquePtr());
ID.AddPointer(SizeExpr);
}
static bool classof(const Type *T) { return T->getTypeClass() == Array; }

View File

@ -253,7 +253,8 @@ struct DeclaratorChunk {
bool isStar : 1;
/// This is the size of the array, or null if [] or [*] was specified.
/// FIXME: make this be an expression* when we have expressions.
/// Since the parser is multi-purpose, and we don't want to impose a root
/// expression class on all clients, NumElts is untyped.
void *NumElts;
void destroy() {}
};