[cfe-commits] r145480 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaPseudoObject.cpp lib/Sema/TreeTransform.h test/CodeGenObjCXX/property-reference.mm

John McCall rjmccall at apple.com
Tue Nov 29 20:42:32 PST 2011


Author: rjmccall
Date: Tue Nov 29 22:42:31 2011
New Revision: 145480

URL: http://llvm.org/viewvc/llvm-project?rev=145480&view=rev
Log:
Fix the instantiation of pseudo-object expressions.  This is a
really bad way to go about this, but I'm not sure there's a better
choice without substantial changes to TreeTransform --- most
notably, preserving implicit semantic nodes instead of discarding
and rebuilding them.


Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CodeGenObjCXX/property-reference.mm

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=145480&r1=145479&r2=145480&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Nov 29 22:42:31 2011
@@ -127,6 +127,7 @@
   class ParmVarDecl;
   class Preprocessor;
   class PseudoDestructorTypeStorage;
+  class PseudoObjectExpr;
   class QualType;
   class StandardConversionSequence;
   class Stmt;
@@ -5803,6 +5804,7 @@
                                          BinaryOperatorKind Opcode,
                                          Expr *LHS, Expr *RHS);
   ExprResult checkPseudoObjectRValue(Expr *E);
+  Expr *recreateSyntacticForm(PseudoObjectExpr *E);
 
   QualType CheckConditionalOperands( // C99 6.5.15
     ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,

Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=145480&r1=145479&r2=145480&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Nov 29 22:42:31 2011
@@ -790,3 +790,54 @@
     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);
+  }
+}

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=145480&r1=145479&r2=145480&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Nov 29 22:42:31 2011
@@ -6104,8 +6104,14 @@
 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

Modified: cfe/trunk/test/CodeGenObjCXX/property-reference.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/property-reference.mm?rev=145480&r1=145479&r2=145480&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/property-reference.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/property-reference.mm Tue Nov 29 22:42:31 2011
@@ -52,3 +52,45 @@
 // CHECK:      call [[A]]* @_ZN5test11AaSERKS0_(
 // CHECK-NEXT: ret void
 
+// rdar://problem/10497174
+ at interface Test2
+ at property int prop;
+ at end
+
+// The fact that these are all non-dependent is critical.
+template <class T> void test2(Test2 *a) {
+  int x = a.prop;
+  a.prop = x;
+  a.prop += x;
+}
+template void test2<int>(Test2*);
+// CHECK: define weak_odr void @_Z5test2IiEvP5Test2(
+// CHECK: [[X:%.*]] = alloca i32,
+// CHECK:      @objc_msgSend
+// CHECK:      store i32 {{%.*}}, i32* [[X]],
+// CHECK:      load i32* [[X]],
+// CHECK:      @objc_msgSend
+// CHECK:      @objc_msgSend
+// CHECK:      load i32* [[X]],
+// CHECK-NEXT: add nsw
+// CHECK:      @objc_msgSend
+// CHECK-NEXT: ret void
+
+// Same as the previous test, but instantiation-dependent.
+template <class T> void test3(Test2 *a) {
+  int x = (sizeof(T), a).prop;
+  a.prop = (sizeof(T), x);
+  a.prop += (sizeof(T), x);
+}
+template void test3<int>(Test2*);
+// CHECK: define weak_odr void @_Z5test3IiEvP5Test2(
+// CHECK: [[X:%.*]] = alloca i32,
+// CHECK:      @objc_msgSend
+// CHECK:      store i32 {{%.*}}, i32* [[X]],
+// CHECK:      load i32* [[X]],
+// CHECK:      @objc_msgSend
+// CHECK:      @objc_msgSend
+// CHECK:      load i32* [[X]],
+// CHECK-NEXT: add nsw
+// CHECK:      @objc_msgSend
+// CHECK-NEXT: ret void





More information about the cfe-commits mailing list