diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaPseudoObject.cpp | 51 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 10 |
2 files changed, 59 insertions, 2 deletions
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 3bd671d10c..08b3fc82ca 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -790,3 +790,54 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, llvm_unreachable("unknown pseudo-object kind!"); } } + +/// Given a pseudo-object reference, rebuild it without the opaque +/// 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)) { + OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); + return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Given a pseudo-object expression, recreate what it looks like +/// syntactically without the attendant OpaqueValueExprs. +/// +/// This is a hack which should be removed when TreeTransform is +/// capable of rebuilding a tree without stripping implicit +/// operations. +Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { + Expr *syntax = E->getSyntacticForm(); + if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { + Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); + return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), + uop->getValueKind(), uop->getObjectKind(), + uop->getOperatorLoc()); + } else if (CompoundAssignOperator *cop + = dyn_cast<CompoundAssignOperator>(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); + Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); + return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), + cop->getType(), + cop->getValueKind(), + cop->getObjectKind(), + cop->getComputationLHSType(), + cop->getComputationResultType(), + cop->getOperatorLoc()); + } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); + Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); + return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), + bop->getType(), bop->getValueKind(), + bop->getObjectKind(), + bop->getOperatorLoc()); + } else { + assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); + return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); + } +} diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7c1dafb87f..d7bdbafaba 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6104,8 +6104,14 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformPseudoObjectExpr(PseudoObjectExpr *E) { - // Rebuild the syntactic form. - ExprResult result = getDerived().TransformExpr(E->getSyntacticForm()); + // Rebuild the syntactic form. The original syntactic form has + // opaque-value expressions in it, so strip those away and rebuild + // the result. This is a really awful way of doing this, but the + // better solution (rebuilding the semantic expressions and + // rebinding OVEs as necessary) doesn't work; we'd need + // TreeTransform to not strip away implicit conversions. + Expr *newSyntacticForm = SemaRef.recreateSyntacticForm(E); + ExprResult result = getDerived().TransformExpr(newSyntacticForm); if (result.isInvalid()) return ExprError(); // If that gives us a pseudo-object result back, the pseudo-object |