Various improvements to Sema::ParseMemberReferenceExpr().

- Added source range support to Diag's.
- Used the new type predicate API to remove dealing with the canonical
type explicitly.
- Added Type::isRecordType().
- Removed some casts.
- Removed a const qualifier from RecordType::getDecl(). 

llvm-svn: 40508
This commit is contained in:
Steve Naroff 2007-07-26 03:11:44 +00:00
parent 6e082ad617
commit 185616f293
3 changed files with 39 additions and 25 deletions

View File

@ -96,6 +96,17 @@ const ArrayType *Type::isArrayType() const {
return 0;
}
const RecordType *Type::isRecordType() const {
// If this is directly a reference type, return it.
if (const RecordType *RTy = dyn_cast<RecordType>(this))
return RTy;
// If this is a typedef for an record type, strip the typedef off without
// losing all typedef information.
if (isa<RecordType>(CanonicalType))
return cast<RecordType>(cast<TypedefType>(this)->LookThroughTypedefs());
}
bool Type::isStructureType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
if (TT->getDecl()->getKind() == Decl::Struct)

View File

@ -343,34 +343,35 @@ Action::ExprResult Sema::
ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
IdentifierInfo &Member) {
QualType qualifiedType = ((Expr *)Base)->getType();
Expr *BaseExpr = static_cast<Expr *>(Base);
assert(BaseExpr && "no record expression");
assert(!qualifiedType.isNull() && "no type for member expression");
QualType canonType = qualifiedType.getCanonicalType();
QualType BaseType = BaseExpr->getType();
assert(!BaseType.isNull() && "no type for member expression");
if (OpKind == tok::arrow) {
if (PointerType *PT = dyn_cast<PointerType>(canonType)) {
qualifiedType = PT->getPointeeType();
canonType = qualifiedType.getCanonicalType();
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
if (const PointerType *PT = BaseType->isPointerType())
BaseType = PT->getPointeeType();
else
return Diag(OpLoc, diag::err_typecheck_member_reference_arrow,
SourceRange(MemberLoc));
}
if (!isa<RecordType>(canonType))
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
// Get the member decl from the struct/union definition.
FieldDecl *MemberDecl;
if (const RecordType *RTy = BaseType->isRecordType()) {
RecordDecl *RDecl = RTy->getDecl();
if (RTy->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RDecl->getName(),
BaseExpr->getSourceRange());
// The record definition is complete, now make sure the member is valid.
if (!(MemberDecl = RDecl->getMember(&Member)))
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(),
SourceRange(MemberLoc));
} else
return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
SourceRange(MemberLoc));
// get the struct/union definition from the type.
RecordDecl *RD = cast<RecordType>(canonType)->getDecl();
if (canonType->isIncompleteType())
return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
FieldDecl *MemberDecl = RD->getMember(&Member);
if (!MemberDecl)
return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
return new MemberExpr((Expr*)Base, OpKind == tok::arrow,
MemberDecl, MemberLoc);
return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl, MemberLoc);
}
/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.

View File

@ -36,6 +36,7 @@ namespace clang {
class ReferenceType;
class VectorType;
class ArrayType;
class RecordType;
/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@ -239,6 +240,7 @@ public:
const PointerType *isPointerType() const;
const ReferenceType *isReferenceType() const;
const ArrayType *isArrayType() const;
const RecordType *isRecordType() const;
bool isStructureType() const;
bool isUnionType() const;
@ -650,10 +652,10 @@ class RecordType : public TagType {
RecordType(); // DO NOT IMPLEMENT
public:
const RecordDecl *getDecl() const {
const RecordDecl *getDecl() {
return reinterpret_cast<RecordDecl*>(TagType::getDecl());
}
RecordDecl *getDecl() {
RecordDecl *getDecl() const {
return reinterpret_cast<RecordDecl*>(TagType::getDecl());
}