[cfe-commits] r118052 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLookup.cpp test/Index/complete-synthesized.m

Douglas Gregor dgregor at apple.com
Tue Nov 2 13:36:02 PDT 2010


Author: dgregor
Date: Tue Nov  2 15:36:02 2010
New Revision: 118052

URL: http://llvm.org/viewvc/llvm-project?rev=118052&view=rev
Log:
Teach code completion to provide property results when the property
can be used to automatically synthesize an ivar.

Added:
    cfe/trunk/test/Index/complete-synthesized.m
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=118052&r1=118051&r2=118052&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Nov  2 15:36:02 2010
@@ -1377,6 +1377,14 @@
                                 ObjCIvarDecl **Fields, unsigned nIvars,
                                 SourceLocation Loc);
 
+  /// \brief Determine whether we can synthesize a provisional ivar for the
+  /// given name.
+  ObjCPropertyDecl *canSynthesizeProvisionalIvar(IdentifierInfo *II);
+
+  /// \brief Determine whether we can synthesize a provisional ivar for the
+  /// given property.
+  bool canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property);
+
   /// ImplMethodsVsClassMethods - This is main routine to warn if any method
   /// remains unimplemented in the class or category @implementation.
   void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=118052&r1=118051&r2=118052&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Nov  2 15:36:02 2010
@@ -147,9 +147,13 @@
     /// \brief The selector that we prefer.
     Selector PreferredSelector;
     
-    /// \brief The completion context in which 
+    /// \brief The completion context in which we are gathering results.
     CodeCompletionContext CompletionContext;
     
+    /// \brief If we are in an instance method definition, the @implementation
+    /// object.
+    ObjCImplementationDecl *ObjCImplementation;
+    
     void AdjustResultPriorityForDecl(Result &R);
 
     void MaybeAddConstructorResults(Result R);
@@ -160,7 +164,27 @@
                            LookupFilter Filter = 0)
       : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false),
         HasObjectTypeQualifiers(false), 
-        CompletionContext(CompletionContext) { }
+        CompletionContext(CompletionContext),
+        ObjCImplementation(0) 
+    { 
+      // If this is an Objective-C instance method definition, dig out the 
+      // corresponding implementation.
+      switch (CompletionContext.getKind()) {
+      case CodeCompletionContext::CCC_Expression:
+      case CodeCompletionContext::CCC_ObjCMessageReceiver:
+      case CodeCompletionContext::CCC_ParenthesizedExpression:
+      case CodeCompletionContext::CCC_Statement:
+      case CodeCompletionContext::CCC_Recovery:
+        if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+          if (Method->isInstanceMethod())
+            if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
+              ObjCImplementation = Interface->getImplementation();
+        break;
+          
+      default:
+        break;
+      }
+    }
     
     /// \brief Whether we should include code patterns in the completion
     /// results.
@@ -203,7 +227,7 @@
     void setPreferredSelector(Selector Sel) {
       PreferredSelector = Sel;
     }
-    
+        
     /// \brief Retrieve the code-completion context for which results are
     /// being collected.
     const CodeCompletionContext &getCompletionContext() const { 
@@ -919,9 +943,14 @@
   unsigned IDNS = Decl::IDNS_Ordinary;
   if (SemaRef.getLangOptions().CPlusPlus)
     IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
-  else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
-    return true;
-
+  else if (SemaRef.getLangOptions().ObjC1) {
+    if (isa<ObjCIvarDecl>(ND))
+      return true;
+    if (isa<ObjCPropertyDecl>(ND) &&
+        SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
+      return true;
+  }
+  
   return ND->getIdentifierNamespace() & IDNS;
 }
 
@@ -935,9 +964,14 @@
   unsigned IDNS = Decl::IDNS_Ordinary;
   if (SemaRef.getLangOptions().CPlusPlus)
     IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
-  else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
-    return true;
-  
+  else if (SemaRef.getLangOptions().ObjC1) {
+    if (isa<ObjCIvarDecl>(ND))
+      return true;
+    if (isa<ObjCPropertyDecl>(ND) &&
+        SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
+      return true;
+  }
+ 
   return ND->getIdentifierNamespace() & IDNS;
 }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=118052&r1=118051&r2=118052&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Nov  2 15:36:02 2010
@@ -1027,25 +1027,41 @@
   return true;
 }
 
-static ObjCPropertyDecl *OkToSynthesizeProvisionalIvar(Sema &SemaRef,
-                                                       IdentifierInfo *II,
-                                                       SourceLocation NameLoc) {
-  ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl();
+ObjCPropertyDecl *Sema::canSynthesizeProvisionalIvar(IdentifierInfo *II) {
+  ObjCMethodDecl *CurMeth = getCurMethodDecl();
   ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
   if (!IDecl)
     return 0;
   ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
   if (!ClassImpDecl)
     return 0;
-  ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II);
+  ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II);
   if (!property)
     return 0;
   if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II))
-    if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+    if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic ||
+        PIDecl->getPropertyIvarDecl())
       return 0;
   return property;
 }
 
+bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) {
+  ObjCMethodDecl *CurMeth = getCurMethodDecl();
+  ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+  if (!IDecl)
+    return false;
+  ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+  if (!ClassImpDecl)
+    return false;
+  if (ObjCPropertyImplDecl *PIDecl
+                = ClassImpDecl->FindPropertyImplDecl(Property->getIdentifier()))
+    if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic ||
+        PIDecl->getPropertyIvarDecl())
+      return false;
+  
+  return true;
+}
+
 static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
                                                LookupResult &Lookup,
                                                IdentifierInfo *II,
@@ -1228,8 +1244,7 @@
     if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
         !getLangOptions().ObjCNonFragileABI2 &&
         Var->isFileVarDecl()) {
-      ObjCPropertyDecl *Property = 
-        OkToSynthesizeProvisionalIvar(*this, II, NameLoc);
+      ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II);
       if (Property) {
         Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
         Diag(Property->getLocation(), diag::note_property_declare);

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=118052&r1=118051&r2=118052&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Nov  2 15:36:02 2010
@@ -2630,9 +2630,27 @@
           // For instance methods, look for ivars in the method's interface.
           LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
                                   Result.getNameLoc(), Sema::LookupMemberName);
-          if (ObjCInterfaceDecl *IFace = Method->getClassInterface())
+          if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
             LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, 
                                /*InBaseClass=*/false, Consumer, Visited);
+            
+            // Look for properties from which we can synthesize ivars, if
+            // permitted.
+            if (Result.getSema().getLangOptions().ObjCNonFragileABI2 &&
+                IFace->getImplementation() &&
+                Result.getLookupKind() == Sema::LookupOrdinaryName) {
+              for (ObjCInterfaceDecl::prop_iterator 
+                        P = IFace->prop_begin(),
+                     PEnd = IFace->prop_end();
+                   P != PEnd; ++P) {
+                if (Result.getSema().canSynthesizeProvisionalIvar(*P) &&
+                    !IFace->lookupInstanceVariable((*P)->getIdentifier())) {
+                  Consumer.FoundDecl(*P, Visited.checkHidden(*P), false);
+                  Visited.add(*P);
+                }
+              }                  
+            }                
+          }
         }
 
         // We've already performed all of the name lookup that we need

Added: cfe/trunk/test/Index/complete-synthesized.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-synthesized.m?rev=118052&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-synthesized.m (added)
+++ cfe/trunk/test/Index/complete-synthesized.m Tue Nov  2 15:36:02 2010
@@ -0,0 +1,56 @@
+// Note: this test is line- and column-sensitive. Test commands are at
+// the end.
+
+
+ at interface A
+ at property int prop1;
+ at end
+
+ at interface B : A {
+  float _prop2;
+}
+ at property float prop2;
+ at property short prop3;
+ at end
+
+ at interface B ()
+ at property double prop4;
+ at end
+
+ at implementation B
+ at synthesize prop2 = _prop2;
+
+- (int)method {
+  return _prop2;
+}
+
+ at dynamic prop3;
+
+- (short)method2 {
+  return prop4;
+}
+
+- (short)method3 {
+  return prop3;
+}
+ at end
+
+// RUN: c-index-test -code-completion-at=%s:24:1 -Xclang -fobjc-nonfragile-abi2 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: NotImplemented:{TypedText _Bool} (50)
+// CHECK-CC1: ObjCIvarDecl:{ResultType float}{TypedText _prop2} (35)
+// CHECK-CC1-NOT: prop2
+// CHECK-CC1: ObjCPropertyDecl:{ResultType short}{TypedText prop3} (35)
+// CHECK-CC1: ObjCPropertyDecl:{ResultType double}{TypedText prop4} (35)
+
+// RUN: c-index-test -code-completion-at=%s:30:2 -Xclang -fobjc-nonfragile-abi2 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{TypedText _Bool} (50)
+// CHECK-CC2: ObjCIvarDecl:{ResultType float}{TypedText _prop2} (35)
+// CHECK-CC2-NOT: prop3
+// CHECK-CC2: ObjCPropertyDecl:{ResultType double}{TypedText prop4} (35)
+
+// RUN: c-index-test -code-completion-at=%s:34:2 -Xclang -fobjc-nonfragile-abi2 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: NotImplemented:{TypedText _Bool} (50)
+// CHECK-CC3: ObjCIvarDecl:{ResultType float}{TypedText _prop2} (35)
+// CHECK-CC3: ObjCIvarDecl:{ResultType double}{TypedText prop4}
+// CHECK-CC3-NOT: ObjCPropertyDecl:{ResultType double}{TypedText prop4} (35)
+// CHECK-CC1: restrict





More information about the cfe-commits mailing list