Submitted by:
Reviewed by:
Finish up Sema::ParseMemberReferenceExpr. This involved:
- added a getMember() function to RecordDecl.
- added stronger typing for "Members" (from Decl->FieldDecl).
- added a dignostic for members not found.
- changed MemberExpr to install the correct TypeRef.
- In general, simplified and cleaned up the routing.

llvm-svn: 39364
This commit is contained in:
Steve Naroff 2007-03-26 23:09:51 +00:00
parent cceab1a8b7
commit cc3214299b
10 changed files with 60 additions and 48 deletions

View File

@ -65,12 +65,25 @@ void EnumDecl::defineElements(EnumConstantDecl **Elts, unsigned NumElts) {
/// defineBody - When created, RecordDecl's correspond to a forward declared
/// record. This method is used to mark the decl as being defined, with the
/// specified contents.
void RecordDecl::defineBody(Decl **members, unsigned numMembers) {
void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) {
assert(!isDefinition() && "Cannot redefine record!");
setDefinition(true);
NumMembers = numMembers;
if (numMembers) {
Members = new Decl*[numMembers];
Members = new FieldDecl*[numMembers];
memcpy(Members, members, numMembers*sizeof(Decl*));
}
}
FieldDecl* RecordDecl::getMember(IdentifierInfo *name) {
if (Members == 0 || NumMembers < 0)
return 0;
// linear search. When C++ classes come along, will likely need to revisit.
for (int i = 0; i < NumMembers; ++i) {
if (Members[i]->getIdentifier() == name)
return Members[i];
}
return 0;
}

View File

@ -570,7 +570,7 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
// Verify that all the fields are okay.
unsigned NumNamedMembers = 0;
SmallVector<Decl*, 32> RecFields;
SmallVector<FieldDecl*, 32> RecFields;
SmallSet<const IdentifierInfo*, 32> FieldIDs;
for (unsigned i = 0; i != NumFields; ++i) {

View File

@ -262,21 +262,18 @@ ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
}
RecordDecl *RD;
// derive the structure/union definition from the type.
if (BT->isStructureType() || BT->isUnionType()) {
TagDecl *TD = cast<TagType>(BT)->getDecl();
if (isa<RecordType>(BT)) { // get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(BT)->getDecl();
if (BT->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, TD->getName());
if (!(RD = dyn_cast<RecordDecl>(TD)))
return Diag(OpLoc, diag::err_typecheck_internal_error);
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
Decl *MemberDecl = 0;
// TODO: Look up MemberDecl.
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
if (FieldDecl *MemberDecl = RD->getMember(&Member))
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
else
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
}
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
}
/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.

View File

@ -41,7 +41,7 @@ bool Type::isArrayType() const {
return isa<ArrayType>(CanonicalType) ? true : false;
}
bool Type::isStructureType() const {
bool Type::isStructureType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
if (TT->getDecl()->getKind() == Decl::Struct)
return true;

View File

@ -570,7 +570,7 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
// Verify that all the fields are okay.
unsigned NumNamedMembers = 0;
SmallVector<Decl*, 32> RecFields;
SmallVector<FieldDecl*, 32> RecFields;
SmallSet<const IdentifierInfo*, 32> FieldIDs;
for (unsigned i = 0; i != NumFields; ++i) {

View File

@ -262,21 +262,18 @@ ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
}
RecordDecl *RD;
// derive the structure/union definition from the type.
if (BT->isStructureType() || BT->isUnionType()) {
TagDecl *TD = cast<TagType>(BT)->getDecl();
if (isa<RecordType>(BT)) { // get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(BT)->getDecl();
if (BT->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, TD->getName());
if (!(RD = dyn_cast<RecordDecl>(TD)))
return Diag(OpLoc, diag::err_typecheck_internal_error);
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
Decl *MemberDecl = 0;
// TODO: Look up MemberDecl.
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
if (FieldDecl *MemberDecl = RD->getMember(&Member))
return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
else
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
}
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
}
/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.

View File

@ -171,8 +171,8 @@ public:
};
/// FunctionDecl - An instance of this class is created to represent a function
/// declaration or definition.
/// FieldDecl - An instance of this class is created by Sema::ParseField to
/// represent a member of a struct/union/class.
class FieldDecl : public ObjectDecl {
public:
FieldDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
@ -312,7 +312,7 @@ class RecordDecl : public TagDecl {
bool HasFlexibleArrayMember : 1;
/// Members/NumMembers - This is a new[]'d array of pointers to Decls.
Decl **Members; // Null if not defined.
FieldDecl **Members; // Null if not defined.
int NumMembers; // -1 if not defined.
public:
RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id) :TagDecl(DK, L, Id){
@ -328,8 +328,12 @@ public:
/// defineBody - When created, RecordDecl's correspond to a forward declared
/// record. This method is used to mark the decl as being defined, with the
/// specified contents.
void defineBody(Decl **Members, unsigned numMembers);
void defineBody(FieldDecl **Members, unsigned numMembers);
/// getMember - If the member doesn't exist, or there are no members, this
/// function will return 0;
FieldDecl *getMember(IdentifierInfo *name);
static bool classof(const Decl *D) {
return D->getKind() == Struct || D->getKind() == Union ||
D->getKind() == Class;

View File

@ -258,15 +258,15 @@ public:
///
class MemberExpr : public Expr {
Expr *Base;
Decl *MemberDecl;
FieldDecl *MemberDecl;
bool IsArrow; // True if this is "X->F", false if this is "X.F".
public:
MemberExpr(Expr *base, bool isarrow, Decl *memberdecl)
: Expr(MemberExprClass),
MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl)
: Expr(MemberExprClass, memberdecl->getType()),
Base(base), MemberDecl(memberdecl), IsArrow(isarrow) {}
Expr *getBase() { return Base; }
Decl *getMemberDecl() { return MemberDecl; }
FieldDecl *getMemberDecl() { return MemberDecl; }
bool isArrow() const { return IsArrow; }
virtual void visit(StmtVisitor &Visitor);

View File

@ -191,12 +191,13 @@ public:
bool isScalarType() const; // arithmetic + pointers
bool isAggregateType() const; // arrays, structures
/// FIXME: consider adding classes to complete the "isa" support.
bool isVoidType() const;
bool isFunctionType() const;
bool isPointerType() const;
bool isArrayType() const;
bool isStructureType() const;
bool isUnionType() 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

View File

@ -485,13 +485,13 @@ DIAG(err_typecheck_subscript_value, ERROR,
DIAG(err_typecheck_subscript, ERROR,
"array subscript is not an integer")
DIAG(err_typecheck_member_reference_structUnion, ERROR,
"member reference is neither a structure or union")
"member reference is not a structure or union")
DIAG(err_typecheck_member_reference_arrow, ERROR,
"member reference is not a pointer")
DIAG(err_typecheck_incomplete_tag, ERROR,
"incomplete definition of struct/union '%s'")
DIAG(err_typecheck_internal_error, ERROR,
"*internal* typechecking error")
"incomplete definition of type '%s'")
DIAG(err_typecheck_no_member, ERROR,
"no member named '%s'")
// Statements.
DIAG(err_continue_not_in_loop, ERROR,