diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 69 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 2 |
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); |