avt77 updated this revision to Diff 132607.
avt77 added a comment.

I re-implemented the patch. Now it works properly with const methods in CXX 
classes.


https://reviews.llvm.org/D42530

Files:
  lib/AST/ExprClassification.cpp
  lib/Sema/SemaExpr.cpp
  test/Sema/assign.c
  test/Sema/typedef-retain.c
  test/SemaCXX/anonymous-union.cpp
  test/SemaCXX/err_typecheck_assign_const.cpp

Index: test/SemaCXX/err_typecheck_assign_const.cpp
===================================================================
--- test/SemaCXX/err_typecheck_assign_const.cpp
+++ test/SemaCXX/err_typecheck_assign_const.cpp
@@ -129,3 +129,23 @@
   Func &bar();
   bar()() = 0; // expected-error {{read-only variable is not assignable}}
 }
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+struct OhNo {
+  float4 v;
+  void AssignMe() const { v.x = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+                                        expected-note {{member function 'OhNo::AssignMe' is declared const here}}
+};
+
+typedef float float4_2 __attribute__((__vector_size__(16)));
+struct OhNo2 {
+  float4_2 v;
+  void AssignMe() const { v[0] = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+                                        expected-note {{member function 'OhNo2::AssignMe' is declared const here}}
+};
+
+struct OhNo3 {
+  float v[4];
+  void AssignMe() const { v[0] = 1; } // expected-error {{cannot assign to non-static data member within const member function 'AssignMe'}} \
+                                        expected-note {{member function 'OhNo3::AssignMe' is declared const here}}
+};
Index: test/SemaCXX/anonymous-union.cpp
===================================================================
--- test/SemaCXX/anonymous-union.cpp
+++ test/SemaCXX/anonymous-union.cpp
@@ -40,7 +40,8 @@
 }
 
 void X::test_unqual_references_const() const { // expected-note 2{{member function 'X::test_unqual_references_const' is declared const here}}
-  d = 0.0;
+  // TODO: it seems we should not see any error here becuase 'd' is mutable
+  d = 0.0; // expected-error {{read-only variable is not assignable}}
   f2 = 0; // expected-error{{cannot assign to non-static data member within const member function 'test_unqual_references_const'}}
   a = 0; // expected-error{{cannot assign to non-static data member within const member function 'test_unqual_references_const'}}
 }
Index: test/Sema/typedef-retain.c
===================================================================
--- test/Sema/typedef-retain.c
+++ test/Sema/typedef-retain.c
@@ -16,8 +16,8 @@
 typedef int a[5];
 void test3() {
   typedef const a b;
-  b r;
-  r[0]=10;  // expected-error {{read-only variable is not assignable}}
+  b r;      // expected-note {{variable 'r' declared const here}}
+  r[0]=10;  // expected-error {{cannot assign to variable 'r' with const-qualified type 'b' (aka 'int const[5]')}}
 }
 
 int test4(const a y) {
Index: test/Sema/assign.c
===================================================================
--- test/Sema/assign.c
+++ test/Sema/assign.c
@@ -11,10 +11,10 @@
 
 typedef int arr[10];
 void test3() {
-  const arr b;
-  const int b2[10]; 
-  b[4] = 1; // expected-error {{read-only variable is not assignable}}
-  b2[4] = 1; // expected-error {{read-only variable is not assignable}}
+  const arr b;  // expected-note {{variable 'b' declared const here}}
+  const int b2[10];   // expected-note {{variable 'b2' declared const here}}
+  b[4] = 1; // expected-error {{cannot assign to variable 'b' with const-qualified type 'const arr' (aka 'int const[10]')}}
+  b2[4] = 1; // expected-error {{cannot assign to variable 'b2' with const-qualified type 'const int [10]'}}
 }
 
 typedef struct I {
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -10321,7 +10321,7 @@
 /// 'const' due to being captured within a block?
 enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
 static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
-  assert(E->isLValue() && E->getType().isConstQualified());
+  assert(E->isLValue());
   E = E->IgnoreParens();
 
   // Must be a reference to a declaration from an enclosing scope.
@@ -10401,10 +10401,8 @@
       const ValueDecl *VD = ME->getMemberDecl();
       if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
         // Mutable fields can be modified even if the class is const.
-        if (Field->isMutable()) {
-          assert(DiagnosticEmitted && "Expected diagnostic not emitted.");
+        if (Field->isMutable())
           break;
-        }
 
         if (!IsTypeModifiable(Field->getType(), IsDereference)) {
           if (!DiagnosticEmitted) {
@@ -10434,8 +10432,16 @@
         // Static fields do not inherit constness from parents.
         break;
       }
-      break;
-    } // End MemberExpr
+      break; // End MemberExpr
+    } else if (const ArraySubscriptExpr *ASE =
+                   dyn_cast<ArraySubscriptExpr>(E)) {
+      E = ASE->getBase()->IgnoreParenImpCasts();
+      continue;
+    } else if (const ExtVectorElementExpr *EVE =
+                   dyn_cast<ExtVectorElementExpr>(E)) {
+      E = EVE->getBase()->IgnoreParenImpCasts();
+      continue;
+    }
     break;
   }
 
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp
+++ lib/AST/ExprClassification.cpp
@@ -642,7 +642,28 @@
   if (const RecordType *R = CT->getAs<RecordType>())
     if (R->hasConstFields())
       return Cl::CM_ConstQualifiedField;
-
+  // CXXThis can't point to const marked field of the given class
+  // to be modifiable
+  while (true) {
+    if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+      E = ME->getBase()->IgnoreParenImpCasts();
+      continue;
+    } else if (const ArraySubscriptExpr *ASE =
+                   dyn_cast<ArraySubscriptExpr>(E)) {
+      E = ASE->getBase()->IgnoreParenImpCasts();
+      continue;
+    } else if (const ExtVectorElementExpr *EVE =
+                   dyn_cast<ExtVectorElementExpr>(E)) {
+      E = EVE->getBase()->IgnoreParenImpCasts();
+      continue;
+    } else if (const CXXThisExpr *CXXThis = dyn_cast<CXXThisExpr>(E)) {
+      CT = Ctx.getCanonicalType(
+          CXXThis->getType().getTypePtr()->getPointeeType());
+      if (CT.isConstQualified())
+        return Cl::CM_ConstQualified;
+    }
+    break;
+  }
   return Cl::CM_Modifiable;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to