diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2008-02-06 22:48:16 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2008-02-06 22:48:16 +0000 |
commit | 510190777c4bd53e960eea4665b204778fec1b64 (patch) | |
tree | db38a8a65c77dd9e8c50f9ac76d6eabf940e25df | |
parent | c8edf6bd5f76bf50411d037c83d36847edfa68f0 (diff) |
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
-rw-r--r-- | AST/StmtSerialization.cpp | 4 | ||||
-rw-r--r-- | Driver/RewriteTest.cpp | 2 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 15 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 7 | ||||
-rw-r--r-- | test/Sema/assign.c | 4 |
5 files changed, 23 insertions, 9 deletions
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<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 { 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<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(), 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}} +} |