diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-11-25 12:01:00 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-11-25 12:01:00 +0000 |
commit | 0a368f60e758e26a0fb895549cb560c2e8432658 (patch) | |
tree | b50ca0cb95cc290b81f9ab0ab110f6f0f62be30e /lib/Sema/SemaPseudoObject.cpp | |
parent | 1b0e2ec43d8a7c5b66ed4722808ae62f830c7010 (diff) |
[MSVC] 'property' with an empty array in array subscript expression.
MSVC supports 'property' attribute and allows to apply it to the declaration of an empty array in a class or structure definition.
For example:
```
__declspec(property(get=GetX, put=PutX)) int x[];
```
The above statement indicates that x[] can be used with one or more array indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and p->x[a][b] = i will be turned into p->PutX(a, b, i);
Differential Revision: http://reviews.llvm.org/D13336
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaPseudoObject.cpp')
-rw-r--r-- | lib/Sema/SemaPseudoObject.cpp | 242 |
1 files changed, 132 insertions, 110 deletions
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 8998a7e8bc..f94fb17c8b 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -44,17 +44,76 @@ using namespace sema; namespace { // Basically just a very focused copy of TreeTransform. - template <class T> struct Rebuilder { + struct Rebuilder { Sema &S; - Rebuilder(Sema &S) : S(S) {} + unsigned MSPropertySubscriptCount; + typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy; + const SpecificRebuilderRefTy &SpecificCallback; + Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback) + : S(S), MSPropertySubscriptCount(0), + SpecificCallback(SpecificCallback) {} + + Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) { + // Fortunately, the constraint that we're rebuilding something + // with a base limits the number of cases here. + if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) + return refExpr; - T &getDerived() { return static_cast<T&>(*this); } + if (refExpr->isExplicitProperty()) { + return new (S.Context) ObjCPropertyRefExpr( + refExpr->getExplicitProperty(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + } + return new (S.Context) ObjCPropertyRefExpr( + refExpr->getImplicitPropertyGetter(), + refExpr->getImplicitPropertySetter(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + } + Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + assert(refExpr->getKeyExpr()); + + return new (S.Context) ObjCSubscriptRefExpr( + SpecificCallback(refExpr->getBaseExpr(), 0), + SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(), + refExpr->getRBracket()); + } + Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + + return new (S.Context) MSPropertyRefExpr( + SpecificCallback(refExpr->getBaseExpr(), 0), + refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getQualifierLoc(), + refExpr->getMemberLoc()); + } + Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) { + assert(refExpr->getBase()); + assert(refExpr->getIdx()); + + auto *NewBase = rebuild(refExpr->getBase()); + ++MSPropertySubscriptCount; + return new (S.Context) MSPropertySubscriptExpr( + NewBase, + SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount), + refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getRBracketLoc()); + } Expr *rebuild(Expr *e) { // Fast path: nothing to look through. - if (typename T::specific_type *specific - = dyn_cast<typename T::specific_type>(e)) - return getDerived().rebuildSpecific(specific); + if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e)) + return rebuildObjCPropertyRefExpr(PRE); + if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e)) + return rebuildObjCSubscriptRefExpr(SRE); + if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e)) + return rebuildMSPropertyRefExpr(MSPRE); + if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e)) + return rebuildMSPropertySubscriptExpr(MSPSE); // Otherwise, we should look through and rebuild anything that // IgnoreParens would. @@ -125,72 +184,6 @@ namespace { } }; - struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { - Expr *NewBase; - ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) - : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} - - typedef ObjCPropertyRefExpr specific_type; - Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { - // Fortunately, the constraint that we're rebuilding something - // with a base limits the number of cases here. - assert(refExpr->isObjectReceiver()); - - if (refExpr->isExplicitProperty()) { - return new (S.Context) - ObjCPropertyRefExpr(refExpr->getExplicitProperty(), - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(), refExpr->getLocation(), - NewBase); - } - return new (S.Context) - ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), - refExpr->getImplicitPropertySetter(), - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(),refExpr->getLocation(), - NewBase); - } - }; - - struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { - Expr *NewBase; - Expr *NewKeyExpr; - ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) - : Rebuilder<ObjCSubscriptRefRebuilder>(S), - NewBase(newBase), NewKeyExpr(newKeyExpr) {} - - typedef ObjCSubscriptRefExpr specific_type; - Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { - assert(refExpr->getBaseExpr()); - assert(refExpr->getKeyExpr()); - - return new (S.Context) - ObjCSubscriptRefExpr(NewBase, - NewKeyExpr, - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), - refExpr->setAtIndexMethodDecl(), - 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: Sema &S; @@ -329,11 +322,19 @@ namespace { class MSPropertyOpBuilder : public PseudoOpBuilder { MSPropertyRefExpr *RefExpr; OpaqueValueExpr *InstanceBase; + SmallVector<Expr *, 4> CallArgs; + + MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E); public: MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), RefExpr(refExpr), InstanceBase(nullptr) {} + MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr) + : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), + InstanceBase(nullptr) { + RefExpr = getBaseMSProperty(refExpr); + } Expr *rebuildAndCaptureObject(Expr *) override; ExprResult buildGet() override; @@ -674,9 +675,9 @@ Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { // form to use the OVE as its base. if (RefExpr->isObjectReceiver()) { InstanceReceiver = capture(RefExpr->getBase()); - - syntacticBase = - ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); + syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * { + return InstanceReceiver; + }).rebuild(syntacticBase); } if (ObjCPropertyRefExpr * @@ -994,11 +995,19 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { // form to use the OVE as its base expression. InstanceBase = capture(RefExpr->getBaseExpr()); InstanceKey = capture(RefExpr->getKeyExpr()); - + syntacticBase = - ObjCSubscriptRefRebuilder(S, InstanceBase, - InstanceKey).rebuild(syntacticBase); - + Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { + switch (Idx) { + case 0: + return InstanceBase; + case 1: + return InstanceKey; + default: + llvm_unreachable("Unexpected index for ObjCSubscriptExpr"); + } + }).rebuild(syntacticBase); + return syntacticBase; } @@ -1400,11 +1409,30 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, // MSVC __declspec(property) references //===----------------------------------------------------------------------===// +MSPropertyRefExpr * +MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { + CallArgs.insert(CallArgs.begin(), E->getIdx()); + Expr *Base = E->getBase()->IgnoreParens(); + while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) { + CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx()); + Base = MSPropSubscript->getBase()->IgnoreParens(); + } + return cast<MSPropertyRefExpr>(Base); +} + Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { InstanceBase = capture(RefExpr->getBaseExpr()); - - syntacticBase = - MSPropertyRefRebuilder(S, InstanceBase).rebuild(syntacticBase); + std::for_each(CallArgs.begin(), CallArgs.end(), + [this](Expr *&Arg) { Arg = capture(Arg); }); + syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { + switch (Idx) { + case 0: + return InstanceBase; + default: + assert(Idx <= CallArgs.size()); + return CallArgs[Idx - 1]; + } + }).rebuild(syntacticBase); return syntacticBase; } @@ -1432,9 +1460,8 @@ ExprResult MSPropertyOpBuilder::buildGet() { return ExprError(); } - MultiExprArg ArgExprs; return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(), - RefExpr->getSourceRange().getBegin(), ArgExprs, + RefExpr->getSourceRange().getBegin(), CallArgs, RefExpr->getSourceRange().getEnd()); } @@ -1462,7 +1489,8 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, return ExprError(); } - SmallVector<Expr*, 1> ArgExprs; + SmallVector<Expr*, 4> ArgExprs; + ArgExprs.append(CallArgs.begin(), CallArgs.end()); ArgExprs.push_back(op); return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(), RefExpr->getSourceRange().getBegin(), ArgExprs, @@ -1488,6 +1516,10 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) { = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { MSPropertyOpBuilder builder(*this, refExpr); return builder.buildRValueOperation(E); + } else if (MSPropertySubscriptExpr *RefExpr = + dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildRValueOperation(E); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1514,6 +1546,10 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { MSPropertyOpBuilder builder(*this, refExpr); return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); + } else if (MSPropertySubscriptExpr *RefExpr + = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1545,8 +1581,12 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 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); + MSPropertyOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else if (MSPropertySubscriptExpr *RefExpr + = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1556,29 +1596,11 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, /// values. Basically, undo the behavior of rebuildAndCaptureObject. /// This should never operate in-place. static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { - Expr *opaqueRef = E->IgnoreParens(); - if (ObjCPropertyRefExpr *refExpr - = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { - // Class and super property references don't have opaque values in them. - if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) - return E; - - assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); - OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); - return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); - } else if (ObjCSubscriptRefExpr *refExpr - = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { - OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); - 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!"); - } + return Rebuilder(S, + [=](Expr *E, unsigned) -> Expr * { + return cast<OpaqueValueExpr>(E)->getSourceExpr(); + }) + .rebuild(E); } /// Given a pseudo-object expression, recreate what it looks like |