forked from OSchip/llvm-project
Bug #:
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:
parent
cceab1a8b7
commit
cc3214299b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue