aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-02-06 22:48:16 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-02-06 22:48:16 +0000
commit510190777c4bd53e960eea4665b204778fec1b64 (patch)
treedb38a8a65c77dd9e8c50f9ac76d6eabf940e25df
parentc8edf6bd5f76bf50411d037c83d36847edfa68f0 (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.cpp4
-rw-r--r--Driver/RewriteTest.cpp2
-rw-r--r--Sema/SemaExpr.cpp15
-rw-r--r--include/clang/AST/Expr.h7
-rw-r--r--test/Sema/assign.c4
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}}
+}