aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-12-20 23:49:58 +0000
committerDouglas Gregor <dgregor@apple.com>2008-12-20 23:49:58 +0000
commit86f194083504938df72135b5b66bf0c5cafd9498 (patch)
tree49bf351536460b89340a2e8b6251c3747a98d1de /lib/AST/Expr.cpp
parent4306d3cb9116605728252e2738df24b9f6ab53c3 (diff)
Add support for member references (E1.E2, E1->E2) with C++ semantics,
which can refer to static data members, enumerators, and member functions as well as to non-static data members. Implement correct lvalue computation for member references in C++. Compute the result type of non-static data members of reference type properly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61294 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp69
1 files changed, 53 insertions, 16 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 8aaea7ac9f..adad2a472a 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -407,8 +407,43 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
return LV_Valid;
break;
}
- case MemberExprClass: { // C99 6.5.2.3p4
+ case MemberExprClass: {
const MemberExpr *m = cast<MemberExpr>(this);
+ if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4:
+ NamedDecl *Member = m->getMemberDecl();
+ // C++ [expr.ref]p4:
+ // If E2 is declared to have type "reference to T", then E1.E2
+ // is an lvalue.
+ if (ValueDecl *Value = dyn_cast<ValueDecl>(Member))
+ if (Value->getType()->isReferenceType())
+ return LV_Valid;
+
+ // -- If E2 is a static data member [...] then E1.E2 is an lvalue.
+ if (isa<CXXClassVarDecl>(Member))
+ return LV_Valid;
+
+ // -- If E2 is a non-static data member [...]. If E1 is an
+ // lvalue, then E1.E2 is an lvalue.
+ if (isa<FieldDecl>(Member))
+ return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx);
+
+ // -- If it refers to a static member function [...], then
+ // E1.E2 is an lvalue.
+ // -- Otherwise, if E1.E2 refers to a non-static member
+ // function [...], then E1.E2 is not an lvalue.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member))
+ return Method->isStatic()? LV_Valid : LV_MemberFunction;
+
+ // -- If E2 is a member enumerator [...], the expression E1.E2
+ // is not an lvalue.
+ if (isa<EnumConstantDecl>(Member))
+ return LV_InvalidExpression;
+
+ // Not an lvalue.
+ return LV_InvalidExpression;
+ }
+
+ // C99 6.5.2.3p4
return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx);
}
case UnaryOperatorClass:
@@ -542,6 +577,7 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid)
return MLV_LValueCast;
return MLV_InvalidExpression;
+ case LV_MemberFunction: return MLV_MemberFunction;
}
QualType CT = Ctx.getCanonicalType(getType());
@@ -1113,7 +1149,8 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const
bool Expr::isBitField() {
Expr *E = this->IgnoreParenCasts();
if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
- return MemRef->getMemberDecl()->isBitField();
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
+ return Field->isBitField();
return false;
}
@@ -1245,21 +1282,21 @@ static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E) {
RecordDecl *RD = Ty->getAsRecordType()->getDecl();
const ASTRecordLayout &RL = C.getASTRecordLayout(RD);
- FieldDecl *FD = ME->getMemberDecl();
-
- // FIXME: This is linear time. And the fact that we're indexing
- // into the layout by position in the record means that we're
- // either stuck numbering the fields in the AST or we have to keep
- // the linear search (yuck and yuck).
- unsigned i = 0;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- Field != FieldEnd; (void)++Field, ++i) {
- if (*Field == FD)
- break;
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ // FIXME: This is linear time. And the fact that we're indexing
+ // into the layout by position in the record means that we're
+ // either stuck numbering the fields in the AST or we have to keep
+ // the linear search (yuck and yuck).
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
+ break;
+ }
+
+ return RL.getFieldOffset(i) + evaluateOffsetOf(C, ME->getBase());
}
-
- return RL.getFieldOffset(i) + evaluateOffsetOf(C, ME->getBase());
} else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
const Expr *Base = ASE->getBase();