]> granicus.if.org Git - clang/commitdiff
Make sure to propagate qualifiers through the member operator.
authorEli Friedman <eli.friedman@gmail.com>
Wed, 6 Feb 2008 22:48:16 +0000 (22:48 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 6 Feb 2008 22:48:16 +0000 (22:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46830 91177308-0d34-0410-b5e6-96231b3b80d8

AST/StmtSerialization.cpp
Driver/RewriteTest.cpp
Sema/SemaExpr.cpp
include/clang/AST/Expr.h
test/Sema/assign.c

index f075e1c12d14707cad657b5a38f4fb16f6d4146f..1915748111b9e6ea0ab67a8d5deeb442d7208a12 100644 (file)
@@ -686,6 +686,7 @@ void MemberExpr::EmitImpl(Serializer& S) const {
   S.EmitPtr(MemberDecl);
   S.EmitBool(IsArrow);
   S.EmitOwnedPtr(Base);
+  S.Emit(getType());
 }
 
 MemberExpr* MemberExpr::CreateImpl(Deserializer& D) {
@@ -693,8 +694,9 @@ MemberExpr* MemberExpr::CreateImpl(Deserializer& D) {
   FieldDecl* MemberDecl = cast<FieldDecl>(D.ReadPtr<Decl>());
   bool IsArrow = D.ReadBool();
   Expr* base = D.ReadOwnedPtr<Expr>();
+  QualType T = QualType::ReadVal(D);
   
-  return new MemberExpr(base,IsArrow,MemberDecl,L); 
+  return new MemberExpr(base,IsArrow,MemberDecl,L,T); 
 }
 
 void NullStmt::EmitImpl(Serializer& S) const {
index 178cf4e4cf9f8be5067bdd6932c0a61f8efbe321..beabe92659ed9e74c63d81e22de56e744220b1f0 100644 (file)
@@ -746,7 +746,7 @@ Stmt *RewriteTest::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
   ObjCIvarDecl *D = IV->getDecl();
   if (IV->isFreeIvar()) {
     Expr *Replacement = new MemberExpr(IV->getBase(), true, D, 
-                                       IV->getLocation());
+                                       IV->getLocation(), D->getType());
     ReplaceStmt(IV, Replacement);
     delete IV;
     return Replacement;
index 4c8a1d953fe0eb297c670c410e5901c6b5694c97..f2bcc12ccf92ed96e8600cb1e3a5baf2f10d7ab1 100644 (file)
@@ -532,7 +532,15 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
     if (!MemberDecl)
       return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName(),
                   SourceRange(MemberLoc));
-    return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl, MemberLoc);
+
+    // Figure out the type of the member; see C99 6.5.2.3p3
+    QualType MemberType = MemberDecl->getType();
+    unsigned combinedQualifiers =
+        MemberType.getQualifiers() | BaseType.getQualifiers();
+    MemberType = MemberType.getQualifiedType(combinedQualifiers);
+
+    return new MemberExpr(BaseExpr, OpKind==tok::arrow, MemberDecl,
+                          MemberLoc, MemberType);
   } else if (BaseType->isOCUVectorType() && OpKind == tok::period) {
     // Component access limited to variables (reject vec4.rg.g).
     if (!isa<DeclRefExpr>(BaseExpr)) 
@@ -2050,8 +2058,9 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
     
     // FIXME: C++: Verify that MemberDecl isn't a static field.
     // FIXME: Verify that MemberDecl isn't a bitfield.
-    
-    Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd);
+    // MemberDecl->getType() doesn't get the right qualifiers, but it doesn't
+    // matter here.
+    Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd, MemberDecl->getType());
   }
   
   return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
index 370e18d05f1be1583f4a11ab1a28c7bbec497425..c667a89ed9671b7e46cd359922affcb7c86db37e 100644 (file)
@@ -650,10 +650,11 @@ class MemberExpr : public Expr {
   SourceLocation MemberLoc;
   bool IsArrow;      // True if this is "X->F", false if this is "X.F".
 public:
-  MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl, SourceLocation l) 
-    : Expr(MemberExprClass, memberdecl->getType()),
+  MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl, SourceLocation l,
+             QualType ty) 
+    : Expr(MemberExprClass, ty),
       Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {}
-  
+
   Expr *getBase() const { return Base; }
   FieldDecl *getMemberDecl() const { return MemberDecl; }
   bool isArrow() const { return IsArrow; }
index 43f4ba7b9a5f2a0ec3dc3657498b3c43dabd79d6..b94d5835ee8bdf4fa93ea38aedd99452c2e33c14 100644 (file)
@@ -2,4 +2,6 @@
 
 void *test1(void) { return 0; }
 
-
+void test2 (const struct {int a;} *x) {
+  x->a = 10; // expected-error {{read-only variable is not assignable}}
+}