summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/Expr.cpp69
-rw-r--r--clang/lib/AST/ExprConstant.cpp5
-rw-r--r--clang/lib/AST/StmtPrinter.cpp5
-rw-r--r--clang/lib/AST/StmtSerialization.cpp2
4 files changed, 59 insertions, 22 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 8aaea7ac9f3..adad2a472ac 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/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();
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 681016793f9..11f07fb1166 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -153,7 +153,10 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
RecordDecl *RD = Ty->getAsRecordType()->getDecl();
const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
- FieldDecl *FD = E->getMemberDecl();
+
+ FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
+ if (!FD) // FIXME: deal with other kinds of member expressions
+ return APValue();
// FIXME: This is linear time.
unsigned i = 0;
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 94bca638663..4061aa14979 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -702,10 +702,7 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) {
void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
-
- FieldDecl *Field = Node->getMemberDecl();
- assert(Field && "MemberExpr should alway reference a field!");
- OS << Field->getNameAsString();
+ OS << Node->getMemberDecl()->getNameAsString();
}
void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
PrintExpr(Node->getBase());
diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp
index 686ee68b201..d12ecd0d93a 100644
--- a/clang/lib/AST/StmtSerialization.cpp
+++ b/clang/lib/AST/StmtSerialization.cpp
@@ -761,7 +761,7 @@ void MemberExpr::EmitImpl(Serializer& S) const {
MemberExpr* MemberExpr::CreateImpl(Deserializer& D, ASTContext& C) {
SourceLocation L = SourceLocation::ReadVal(D);
- FieldDecl* MemberDecl = cast<FieldDecl>(D.ReadPtr<Decl>());
+ NamedDecl* MemberDecl = cast<NamedDecl>(D.ReadPtr<Decl>());
bool IsArrow = D.ReadBool();
QualType T = QualType::ReadVal(D);
Expr* base = D.ReadOwnedPtr<Expr>(C);
OpenPOWER on IntegriCloud