From: Steve Naroff Date: Thu, 26 Jul 2007 03:11:44 +0000 (+0000) Subject: Various improvements to Sema::ParseMemberReferenceExpr(). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dfa6aae5a119a527e537c35566ba3272fd8c5d74;p=clang 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(). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40508 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Type.cpp b/AST/Type.cpp index b09d3afa63..867a409d83 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -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(this)) + return RTy; + + // If this is a typedef for an record type, strip the typedef off without + // losing all typedef information. + if (isa(CanonicalType)) + return cast(cast(this)->LookThroughTypedefs()); +} + bool Type::isStructureType() const { if (const TagType *TT = dyn_cast(CanonicalType)) { if (TT->getDecl()->getKind() == Decl::Struct) diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 955ac683e3..cd19872a1a 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -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(Base); + assert(BaseExpr && "no record expression"); - assert(!qualifiedType.isNull() && "no type for member expression"); + QualType BaseType = BaseExpr->getType(); + assert(!BaseType.isNull() && "no type for member expression"); - QualType canonType = qualifiedType.getCanonicalType(); - if (OpKind == tok::arrow) { - if (PointerType *PT = dyn_cast(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(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(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. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 0f4770860c..c6c31245ff 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -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(TagType::getDecl()); } - RecordDecl *getDecl() { + RecordDecl *getDecl() const { return reinterpret_cast(TagType::getDecl()); }