From: Eli Friedman Date: Wed, 6 Feb 2008 22:48:16 +0000 (+0000) Subject: Make sure to propagate qualifiers through the member operator. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=510190777c4bd53e960eea4665b204778fec1b64;p=clang Make sure to propagate qualifiers through the member operator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46830 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/StmtSerialization.cpp b/AST/StmtSerialization.cpp index f075e1c12d..1915748111 100644 --- a/AST/StmtSerialization.cpp +++ b/AST/StmtSerialization.cpp @@ -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(D.ReadPtr()); bool IsArrow = D.ReadBool(); Expr* base = D.ReadOwnedPtr(); + 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 { diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index 178cf4e4cf..beabe92659 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -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; diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 4c8a1d953f..f2bcc12ccf 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -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(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(), diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 370e18d05f..c667a89ed9 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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; } diff --git a/test/Sema/assign.c b/test/Sema/assign.c index 43f4ba7b9a..b94d5835ee 100644 --- a/test/Sema/assign.c +++ b/test/Sema/assign.c @@ -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}} +}