[cfe-commits] r153709 - in /cfe/trunk: include/clang/AST/ExprObjC.h lib/AST/StmtDumper.cpp lib/Sema/SemaPseudoObject.cpp lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp test/Index/get-cursor.m tools/libclang/CIndex.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Mar 29 17:19:19 PDT 2012


Author: akirtzidis
Date: Thu Mar 29 19:19:18 2012
New Revision: 153709

URL: http://llvm.org/viewvc/llvm-project?rev=153709&view=rev
Log:
Add info to ObjCPropertyRefExpr to indicate whether the dot syntax property
reference is going to message the setter, the getter, or both.

Having this info on the ObjCPropertyRefExpr node makes it easier for AST
clients (like libclang) to reason about the meaning of the property reference.

[AST/Sema]
-Use 2 bits (with a PointerIntPair) in ObjCPropertyRefExpr to record the above info
-Have ObjCPropertyOpBuilder set the info appropriately.

[libclang]
-When there is an implicit property reference (property syntax using methods)
have clang_getCursorReferenced return a cursor for the method. If the property
reference is going to result in messaging both the getter and the setter choose
to return a cursor for the setter because it is less obvious from source inspection
that the setter is getting called.

The general idea has the seal of approval by John.

rdar://11151621

Modified:
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/lib/AST/StmtDumper.cpp
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/Index/get-cursor.m
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Thu Mar 29 19:19:18 2012
@@ -510,7 +510,18 @@
   /// if the bool is false, this is an explicit property reference;
   /// the pointer is an ObjCPropertyDecl and Setter is always null.
   llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
-  ObjCMethodDecl *Setter;
+
+  /// \brief Indicates whether the property reference will result in a message
+  /// to the getter, the setter, or both.
+  /// This applies to both implicit and explicit property references.
+  enum MethodRefFlags {
+    MethodRef_None = 0,
+    MethodRef_Getter = 0x1,
+    MethodRef_Setter = 0x2
+  };
+
+  /// \brief Contains the Setter method pointer and MethodRefFlags bit flags.
+  llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
 
   // FIXME: Maybe we should store the property identifier here,
   // because it's not rederivable from the other data when there's an
@@ -533,7 +544,7 @@
            /*TypeDependent=*/false, base->isValueDependent(),
            base->isInstantiationDependent(),
            base->containsUnexpandedParameterPack()),
-      PropertyOrGetter(PD, false), Setter(0),
+      PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
       IdLoc(l), ReceiverLoc(), Receiver(base) {
     assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
   }
@@ -544,7 +555,7 @@
     : Expr(ObjCPropertyRefExprClass, t, VK, OK,
            /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
            st->containsUnexpandedParameterPack()),
-      PropertyOrGetter(PD, false), Setter(0),
+      PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
       IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
     assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
   }
@@ -555,7 +566,7 @@
     : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
            Base->isValueDependent(), Base->isInstantiationDependent(),
            Base->containsUnexpandedParameterPack()),
-      PropertyOrGetter(Getter, true), Setter(Setter),
+      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
       IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
     assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
   }
@@ -565,7 +576,7 @@
                       SourceLocation IdLoc,
                       SourceLocation SuperLoc, QualType SuperTy)
     : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
-      PropertyOrGetter(Getter, true), Setter(Setter),
+      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
       IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
     assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
   }
@@ -575,7 +586,7 @@
                       SourceLocation IdLoc,
                       SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
     : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
-      PropertyOrGetter(Getter, true), Setter(Setter),
+      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
       IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
     assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
   }
@@ -598,7 +609,7 @@
 
   ObjCMethodDecl *getImplicitPropertySetter() const {
     assert(isImplicitProperty());
-    return Setter;
+    return SetterAndMethodRefFlags.getPointer();
   }
 
   Selector getGetterSelector() const {
@@ -613,6 +624,28 @@
     return getExplicitProperty()->getSetterName();
   }
 
+  /// \brief True if the property reference will result in a message to the
+  /// getter.
+  /// This applies to both implicit and explicit property references.
+  bool isMessagingGetter() const {
+    return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
+  }
+
+  /// \brief True if the property reference will result in a message to the
+  /// setter.
+  /// This applies to both implicit and explicit property references.
+  bool isMessagingSetter() const {
+    return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
+  }
+
+  void setIsMessagingGetter(bool val = true) {
+    setMethodRefFlag(MethodRef_Getter, val);
+  }
+
+  void setIsMessagingSetter(bool val = true) {
+    setMethodRefFlag(MethodRef_Setter, val);
+  }
+
   const Expr *getBase() const { 
     return cast<Expr>(Receiver.get<Stmt*>()); 
   }
@@ -689,15 +722,19 @@
 
 private:
   friend class ASTStmtReader;
-  void setExplicitProperty(ObjCPropertyDecl *D) {
+  friend class ASTStmtWriter;
+  void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
     PropertyOrGetter.setPointer(D);
     PropertyOrGetter.setInt(false);
-    Setter = 0;
+    SetterAndMethodRefFlags.setPointer(0);
+    SetterAndMethodRefFlags.setInt(methRefFlags);
   }
-  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) {
+  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+                           unsigned methRefFlags) {
     PropertyOrGetter.setPointer(Getter);
     PropertyOrGetter.setInt(true);
-    this->Setter = Setter;
+    SetterAndMethodRefFlags.setPointer(Setter);
+    SetterAndMethodRefFlags.setInt(methRefFlags);
   }
   void setBase(Expr *Base) { Receiver = Base; }
   void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
@@ -705,6 +742,15 @@
 
   void setLocation(SourceLocation L) { IdLoc = L; }
   void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
+
+  void setMethodRefFlag(MethodRefFlags flag, bool val) {
+    unsigned f = SetterAndMethodRefFlags.getInt();
+    if (val)
+      f |= flag;
+    else
+      f &= ~flag;
+    SetterAndMethodRefFlags.setInt(f);
+  }
 };
   
 /// ObjCSubscriptRefExpr - used for array and dictionary subscripting.

Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Thu Mar 29 19:19:18 2012
@@ -686,6 +686,14 @@
 
   if (Node->isSuperReceiver())
     OS << " super";
+
+  OS << " Messaging=";
+  if (Node->isMessagingGetter() && Node->isMessagingSetter())
+    OS << "Getter&Setter";
+  else if (Node->isMessagingGetter())
+    OS << "Getter";
+  else if (Node->isMessagingSetter())
+    OS << "Setter";
 }
 
 void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {

Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Thu Mar 29 19:19:18 2012
@@ -208,6 +208,7 @@
   /// A PseudoOpBuilder for Objective-C @properties.
   class ObjCPropertyOpBuilder : public PseudoOpBuilder {
     ObjCPropertyRefExpr *RefExpr;
+    ObjCPropertyRefExpr *SyntacticRefExpr;
     OpaqueValueExpr *InstanceReceiver;
     ObjCMethodDecl *Getter;
 
@@ -217,7 +218,7 @@
   public:
     ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
       PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
-      InstanceReceiver(0), Getter(0), Setter(0) {
+      SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
     }
 
     ExprResult buildRValueOperation(Expr *op);
@@ -538,6 +539,10 @@
       ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
   }
 
+  if (ObjCPropertyRefExpr *
+        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
+    SyntacticRefExpr = refE;
+
   return syntacticBase;
 }
 
@@ -545,7 +550,10 @@
 ExprResult ObjCPropertyOpBuilder::buildGet() {
   findGetter();
   assert(Getter);
-  
+
+  if (SyntacticRefExpr)
+    SyntacticRefExpr->setIsMessagingGetter();
+
   QualType receiverType;
   if (RefExpr->isClassReceiver()) {
     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
@@ -581,6 +589,9 @@
   bool hasSetter = findSetter();
   assert(hasSetter); (void) hasSetter;
 
+  if (SyntacticRefExpr)
+    SyntacticRefExpr->setIsMessagingSetter();
+
   QualType receiverType;
   if (RefExpr->isClassReceiver()) {
     receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Thu Mar 29 19:19:18 2012
@@ -887,13 +887,15 @@
 
 void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
   VisitExpr(E);
+  unsigned MethodRefFlags = Record[Idx++];
   bool Implicit = Record[Idx++] != 0;
   if (Implicit) {
     ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
     ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
-    E->setImplicitProperty(Getter, Setter);
+    E->setImplicitProperty(Getter, Setter, MethodRefFlags);
   } else {
-    E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx));
+    E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx),
+                           MethodRefFlags);
   }
   E->setLocation(ReadSourceLocation(Record, Idx));
   E->setReceiverLocation(ReadSourceLocation(Record, Idx));

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Thu Mar 29 19:19:18 2012
@@ -851,6 +851,7 @@
 
 void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
   VisitExpr(E);
+  Record.push_back(E->SetterAndMethodRefFlags.getInt());
   Record.push_back(E->isImplicitProperty());
   if (E->isImplicitProperty()) {
     Writer.AddDeclRef(E->getImplicitPropertyGetter(), Record);

Modified: cfe/trunk/test/Index/get-cursor.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/get-cursor.m?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/test/Index/get-cursor.m (original)
+++ cfe/trunk/test/Index/get-cursor.m Thu Mar 29 19:19:18 2012
@@ -41,6 +41,17 @@
 }
 @end
 
+ at interface Test2
+-(int)implicitProp;
+-(void)setImplicitProp:(int)x;
+ at end
+
+void foo1(Test2 *test2) {
+  int x = test2.implicitProp;
+  test2.implicitProp = x;
+  ++test2.implicitProp;
+}
+
 // RUN: c-index-test -cursor-at=%s:4:28 -cursor-at=%s:5:28 %s | FileCheck -check-prefix=CHECK-PROP %s
 // CHECK-PROP: ObjCPropertyDecl=foo1:4:26
 // CHECK-PROP: ObjCPropertyDecl=foo2:5:27
@@ -54,6 +65,10 @@
 // RUN: c-index-test -cursor-at=%s:37:17 %s | FileCheck -check-prefix=CHECK-IN-IMPL %s
 // CHECK-IN-IMPL: VarDecl=i:37:17
 
-// RUN: c-index-test -cursor-at=%s:38:6 -cursor-at=%s:40:11 %s | FileCheck -check-prefix=CHECK-MEMBERREF %s
+// RUN: c-index-test -cursor-at=%s:38:6 -cursor-at=%s:40:11 \
+// RUN:   -cursor-at=%s:50:20 -cursor-at=%s:51:15 -cursor-at=%s:52:20 %s | FileCheck -check-prefix=CHECK-MEMBERREF %s
 // CHECK-MEMBERREF: 38:6 MemberRefExpr=x:34:16 SingleRefName=[38:6 - 38:7] RefName=[38:6 - 38:7] Extent=[38:3 - 38:7]
 // CHECK-MEMBERREF: 40:9 MemberRefExpr=name:23:21 Extent=[40:3 - 40:13] Spelling=name
+// CHECK-MEMBERREF: 50:17 MemberRefExpr=implicitProp:45:7 Extent=[50:11 - 50:29] Spelling=implicitProp
+// CHECK-MEMBERREF: 51:9 MemberRefExpr=setImplicitProp::46:8 Extent=[51:3 - 51:21]
+// CHECK-MEMBERREF: 52:11 MemberRefExpr=setImplicitProp::46:8 Extent=[52:5 - 52:23]

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=153709&r1=153708&r2=153709&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Mar 29 19:19:18 2012
@@ -2901,8 +2901,17 @@
     return ME->getMemberDecl();
   if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
     return RE->getDecl();
-  if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E))
-    return PRE->isExplicitProperty() ? PRE->getExplicitProperty() : 0;
+  if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+    if (PRE->isExplicitProperty())
+      return PRE->getExplicitProperty();
+    // It could be messaging both getter and setter as in:
+    // ++myobj.myprop;
+    // in which case prefer to associate the setter since it is less obvious
+    // from inspecting the source that the setter is going to get called.
+    if (PRE->isMessagingSetter())
+      return PRE->getImplicitPropertySetter();
+    return PRE->getImplicitPropertyGetter();
+  }
   if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
     return getDeclFromExpr(POE->getSyntacticForm());
   if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))





More information about the cfe-commits mailing list