diff options
Diffstat (limited to 'lib/Sema/SemaPseudoObject.cpp')
-rw-r--r-- | lib/Sema/SemaPseudoObject.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index b135507b1a..560efa5a4e 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -153,6 +153,23 @@ namespace { refExpr->getRBracket()); } }; + + struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> { + Expr *NewBase; + MSPropertyRefRebuilder(Sema &S, Expr *newBase) + : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {} + + typedef MSPropertyRefExpr specific_type; + Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + + return new (S.Context) + MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(), + refExpr->isArrow(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getQualifierLoc(), + refExpr->getMemberLoc()); + } + }; class PseudoOpBuilder { public: @@ -284,6 +301,18 @@ namespace { ExprResult buildSet(Expr *op, SourceLocation, bool); }; + class MSPropertyOpBuilder : public PseudoOpBuilder { + MSPropertyRefExpr *RefExpr; + + public: + MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) : + PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), + RefExpr(refExpr) {} + + Expr *rebuildAndCaptureObject(Expr *); + ExprResult buildGet(); + ExprResult buildSet(Expr *op, SourceLocation, bool); + }; } /// Capture the given expression in an OpaqueValueExpr. @@ -1324,6 +1353,77 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, } //===----------------------------------------------------------------------===// +// MSVC __declspec(property) references +//===----------------------------------------------------------------------===// + +Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + Expr *NewBase = capture(RefExpr->getBaseExpr()); + + syntacticBase = + MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase); + + return syntacticBase; +} + +ExprResult MSPropertyOpBuilder::buildGet() { + if (!RefExpr->getPropertyDecl()->hasGetter()) { + S.Diag(RefExpr->getMemberLoc(), diag::err_no_getter_for_property) + << RefExpr->getPropertyDecl()->getName(); + return ExprError(); + } + + UnqualifiedId GetterName; + IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId(); + GetterName.setIdentifier(II, RefExpr->getMemberLoc()); + CXXScopeSpec SS; + SS.Adopt(RefExpr->getQualifierLoc()); + ExprResult GetterExpr = S.ActOnMemberAccessExpr( + S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), + RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), + GetterName, 0, true); + if (GetterExpr.isInvalid()) { + S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_getter) + << RefExpr->getPropertyDecl()->getName(); + return ExprError(); + } + + MultiExprArg ArgExprs; + return S.ActOnCallExpr(S.getCurScope(), GetterExpr.take(), + RefExpr->getSourceRange().getBegin(), ArgExprs, + RefExpr->getSourceRange().getEnd()); +} + +ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, + bool captureSetValueAsResult) { + if (!RefExpr->getPropertyDecl()->hasSetter()) { + S.Diag(RefExpr->getMemberLoc(), diag::err_no_setter_for_property) + << RefExpr->getPropertyDecl()->getName(); + return ExprError(); + } + + UnqualifiedId SetterName; + IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId(); + SetterName.setIdentifier(II, RefExpr->getMemberLoc()); + CXXScopeSpec SS; + SS.Adopt(RefExpr->getQualifierLoc()); + ExprResult SetterExpr = S.ActOnMemberAccessExpr( + S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), + RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), + SetterName, 0, true); + if (SetterExpr.isInvalid()) { + S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_setter) + << RefExpr->getPropertyDecl()->getName(); + return ExprError(); + } + + SmallVector<Expr*, 1> ArgExprs; + ArgExprs.push_back(op); + return S.ActOnCallExpr(S.getCurScope(), SetterExpr.take(), + RefExpr->getSourceRange().getBegin(), ArgExprs, + op->getSourceRange().getEnd()); +} + +//===----------------------------------------------------------------------===// // General Sema routines. //===----------------------------------------------------------------------===// @@ -1338,6 +1438,10 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) { = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { ObjCSubscriptOpBuilder builder(*this, refExpr); return builder.buildRValueOperation(E); + } else if (MSPropertyRefExpr *refExpr + = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { + MSPropertyOpBuilder builder(*this, refExpr); + return builder.buildRValueOperation(E); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1360,6 +1464,10 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { Diag(opcLoc, diag::err_illegal_container_subscripting_op); return ExprError(); + } else if (MSPropertyRefExpr *refExpr + = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { + MSPropertyOpBuilder builder(*this, refExpr); + return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1389,6 +1497,10 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { ObjCSubscriptOpBuilder builder(*this, refExpr); return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else if (MSPropertyRefExpr *refExpr + = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { + MSPropertyOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1414,6 +1526,10 @@ static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), keyOVE->getSourceExpr()).rebuild(E); + } else if (MSPropertyRefExpr *refExpr + = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { + OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); + return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); } else { llvm_unreachable("unknown pseudo-object kind!"); } |