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/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.