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 b09d3af..867a409 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -96,6 +96,17 @@
   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)
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 955ac68..cd19872 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -343,34 +343,35 @@
 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 BaseType = BaseExpr->getType();
+  assert(!BaseType.isNull() && "no type for member expression");
   
-  QualType canonType = qualifiedType.getCanonicalType();
-
   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.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 0f47708..c6c3124 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -36,6 +36,7 @@
   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 @@
   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 @@
   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());
   }