Implement effects of 'mutable', and a few comments from Chris on its parsing.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59470 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 4037404..6be9eaf 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -22,9 +22,9 @@
  
 CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                                    SourceLocation L, IdentifierInfo *Id,
-                                   QualType T, Expr *BW) {
+                                   QualType T, bool Mut, Expr *BW) {
   void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
-  return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
+  return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW);
 }
 
 CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9c0a40e..fdc4aff 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1149,6 +1149,7 @@
       // an error here
       Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
       InvalidDecl = true;
+      break;
     }
 
     IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -2603,7 +2604,9 @@
   if (getLangOptions().CPlusPlus) {
     // FIXME: Replace CXXFieldDecls with FieldDecls for simple structs.
     NewFD = CXXFieldDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
-                                 Loc, II, T, BitWidth);
+                                 Loc, II, T,
+                                 D.getDeclSpec().getStorageClassSpec() ==
+                                   DeclSpec::SCS_mutable, BitWidth);
     if (II)
       PushOnScopeChains(NewFD, S);
   }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f601fe4..68dcdc8 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -447,6 +447,8 @@
         else
           Diag(DS.getThreadSpecLoc(),
                diag::err_mutable_function);
+        // FIXME: It would be nicer if the keyword was ignored only for this
+        // declarator. Otherwise we could get follow-up errors.
         D.getMutableDeclSpec().ClearStorageClassSpecs();
       } else {
         QualType T = GetTypeForDeclarator(D, S);
@@ -460,6 +462,8 @@
             Diag(DS.getStorageClassSpecLoc(), err);
           else
             Diag(DS.getThreadSpecLoc(), err);
+          // FIXME: It would be nicer if the keyword was ignored only for this
+          // declarator. Otherwise we could get follow-up errors.
           D.getMutableDeclSpec().ClearStorageClassSpecs();
         }
       }
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0506b40..2b621f2 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -951,6 +951,10 @@
     QualType MemberType = MemberDecl->getType();
     unsigned combinedQualifiers =
         MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
+    if (CXXFieldDecl *CXXMember = dyn_cast<CXXFieldDecl>(MemberDecl)) {
+      if (CXXMember->isMutable())
+        combinedQualifiers &= ~QualType::Const;
+    }
     MemberType = MemberType.getQualifiedType(combinedQualifiers);
 
     return new MemberExpr(BaseExpr, OpKind == tok::arrow, MemberDecl,