[cfe-commits] r112193 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Sema/CodeCompleteConsumer.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-memfunc-cvquals.cpp

Douglas Gregor dgregor at apple.com
Thu Aug 26 09:36:48 PDT 2010


Author: dgregor
Date: Thu Aug 26 11:36:48 2010
New Revision: 112193

URL: http://llvm.org/viewvc/llvm-project?rev=112193&view=rev
Log:
When code-completing a potential call to a C++ non-static member
function, take into account the qualifiers on the object argument
(e.g., what will become "this"), filtering around uncallable member
functions and giving a slight priority boost to those with
exactly-matching qualifiers.

Added:
    cfe/trunk/test/Index/complete-memfunc-cvquals.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=112193&r1=112192&r2=112193&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Aug 26 11:36:48 2010
@@ -1073,8 +1073,6 @@
 
   bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
   
-  /// \brief Retrieves the "canonical" declaration of
-
   /// \brief Retrieves the "canonical" nested name specifier for a
   /// given nested name specifier.
   ///

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=112193&r1=112192&r2=112193&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Aug 26 11:36:48 2010
@@ -289,7 +289,18 @@
     L += R;
     return L;
   }
+  
+  Qualifiers &operator-=(Qualifiers R) {
+    Mask = Mask & ~(R.Mask);
+    return *this;
+  }
 
+  /// \brief Compute the difference between two qualifier sets.
+  friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
+    L -= R;
+    return L;
+  }
+  
   std::string getAsString() const;
   std::string getAsString(const PrintingPolicy &Policy) const {
     std::string Buffer;

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=112193&r1=112192&r2=112193&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Thu Aug 26 11:36:48 2010
@@ -55,7 +55,7 @@
   CCP_Unlikely = 80
 };
 
-/// \brief Priority value deltas that are applied to code-completion results
+/// \brief Priority value deltas that are added to code-completion results
 /// based on the context of the result.
 enum {
   /// \brief The result is in a base class.
@@ -64,7 +64,10 @@
   ///
   /// Since everything converts to "void", we don't give as drastic an 
   /// adjustment for matching void.
-  CCD_VoidMatch = -5
+  CCD_VoidMatch = -5,
+  /// \brief The result is a C++ non-static member function whose qualifiers
+  /// exactly match the object type on which the member function can be called.
+  CCD_ObjectQualifierMatch = -1
 };
 
 /// \brief Priority value factors by which we will divide or multiply the

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=112193&r1=112192&r2=112193&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Aug 26 11:36:48 2010
@@ -136,11 +136,19 @@
     /// different levels of, e.g., the inheritance hierarchy.
     std::list<ShadowMap> ShadowMaps;
     
+    /// \brief If we're potentially referring to a C++ member function, the set
+    /// of qualifiers applied to the object type.
+    Qualifiers ObjectTypeQualifiers;
+    
+    /// \brief Whether the \p ObjectTypeQualifiers field is active.
+    bool HasObjectTypeQualifiers;
+    
     void AdjustResultPriorityForPreferredType(Result &R);
 
   public:
     explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
-      : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
+      : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false),
+        HasObjectTypeQualifiers(false) { }
     
     /// \brief Whether we should include code patterns in the completion
     /// results.
@@ -167,6 +175,18 @@
       PreferredType = SemaRef.Context.getCanonicalType(T); 
     }
     
+    /// \brief Set the cv-qualifiers on the object type, for us in filtering
+    /// calls to member functions.
+    ///
+    /// When there are qualifiers in this set, they will be used to filter
+    /// out member functions that aren't available (because there will be a 
+    /// cv-qualifier mismatch) or prefer functions with an exact qualifier
+    /// match.
+    void setObjectTypeQualifiers(Qualifiers Quals) {
+      ObjectTypeQualifiers = Quals;
+      HasObjectTypeQualifiers = true;
+    }
+    
     /// \brief Specify whether nested-name-specifiers are allowed.
     void allowNestedNameSpecifiers(bool Allow = true) {
       AllowNestedNameSpecifiers = Allow;
@@ -770,6 +790,20 @@
   if (!PreferredType.isNull())
     AdjustResultPriorityForPreferredType(R);
   
+  if (HasObjectTypeQualifiers)
+    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+      if (Method->isInstance()) {
+        Qualifiers MethodQuals
+                        = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+        if (ObjectTypeQualifiers == MethodQuals)
+          R.Priority += CCD_ObjectQualifierMatch;
+        else if (ObjectTypeQualifiers - MethodQuals) {
+          // The method cannot be invoked, because doing so would drop 
+          // qualifiers.
+          return;
+        }
+      }
+  
   // Insert this result into the set of results.
   Results.push_back(R);
 }
@@ -2364,6 +2398,13 @@
     break;
   }
 
+  // If we are in a C++ non-static member function, check the qualifiers on
+  // the member function to filter/prioritize the results list.
+  if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
+    if (CurMethod->isInstance())
+      Results.setObjectTypeQualifiers(
+                      Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
+  
   CodeCompletionDeclConsumer Consumer(Results, CurContext);
   LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
                      CodeCompleter->includeGlobals());
@@ -2566,7 +2607,7 @@
     if (const PointerType *Ptr = BaseType->getAs<PointerType>())
       BaseType = Ptr->getPointeeType();
     else if (BaseType->isObjCObjectPointerType())
-    /*Do nothing*/ ;
+      /*Do nothing*/ ;
     else
       return;
   }
@@ -2574,6 +2615,10 @@
   ResultBuilder Results(*this, &ResultBuilder::IsMember);
   Results.EnterNewScope();
   if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+    // Indicate that we are performing a member access, and the cv-qualifiers
+    // for the base object type.
+    Results.setObjectTypeQualifiers(BaseType.getQualifiers());
+    
     // Access to a C/C++ class, struct, or union.
     Results.allowNestedNameSpecifiers();
     CodeCompletionDeclConsumer Consumer(Results, CurContext);

Added: cfe/trunk/test/Index/complete-memfunc-cvquals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-memfunc-cvquals.cpp?rev=112193&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-memfunc-cvquals.cpp (added)
+++ cfe/trunk/test/Index/complete-memfunc-cvquals.cpp Thu Aug 26 11:36:48 2010
@@ -0,0 +1,78 @@
+// The run lines are below, because this test is line- and
+// column-number sensitive.
+struct Foo {
+  void babble() const volatile;
+  void bar();
+  void baz() const;
+  void bingo() volatile;
+  void theend() const volatile;
+};
+
+template<typename T>
+struct smart_ptr {
+  T *operator->();
+  const T* operator->() const;
+};
+
+void text(Foo f, Foo *fp, const Foo &fc, const Foo *fcp,
+          smart_ptr<Foo> sf, const smart_ptr<Foo> &sfc, Foo volatile *fvp) {
+  f.bar();
+  fp->bar();
+  fc.baz();
+  fcp->baz();
+  sf->bar();
+  sfc->baz();
+  fvp->babble();
+}
+
+void Foo::bar() {
+  
+}
+
+void Foo::baz() const {
+
+}
+
+void Foo::bingo() volatile {
+
+}
+
+// Check member access expressions.
+// RUN: c-index-test -code-completion-at=%s:19:5 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// RUN: c-index-test -code-completion-at=%s:20:7 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// RUN: c-index-test -code-completion-at=%s:23:7 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// CHECK-NOQUALS: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (20)
+// CHECK-NOQUALS: FunctionDecl:{ResultType void}{TypedText bar}{LeftParen (}{RightParen )} (19)
+// CHECK-NOQUALS: FunctionDecl:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative  const} (20)
+// CHECK-NOQUALS: FunctionDecl:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative  volatile} (20)
+// RUN: c-index-test -code-completion-at=%s:21:6 %s | FileCheck -check-prefix=CHECK-CONST %s
+// RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CONST %s
+// RUN: c-index-test -code-completion-at=%s:24:8 %s | FileCheck -check-prefix=CHECK-CONST %s
+// CHECK-CONST: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (20)
+// CHECK-CONST-NOT: bar
+// CHECK-CONST: FunctionDecl:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative  const} (19)
+// CHECK-CONST-NOT: bingo
+// CHECK-CONST: theend
+// RUN: c-index-test -code-completion-at=%s:25:8 %s | FileCheck -check-prefix=CHECK-VOLATILE %s
+// CHECK-VOLATILE: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (20)
+// CHECK-VOLATILE-NOT: baz
+// CHECK-VOLATILE: FunctionDecl:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative  volatile} (19)
+
+// Check implicit member access expressions.
+// RUN: c-index-test -code-completion-at=%s:29:2 %s | FileCheck -check-prefix=CHECK-IMPLICIT-NOQUALS %s
+// CHECK-IMPLICIT-NOQUALS: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (15)
+// CHECK-IMPLICIT-NOQUALS: FunctionDecl:{ResultType void}{TypedText bar}{LeftParen (}{RightParen )} (14)
+// CHECK-IMPLICIT-NOQUALS: FunctionDecl:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative  const} (15)
+// CHECK-IMPLICIT-NOQUALS: FunctionDecl:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative  volatile} (15)
+
+// RUN: c-index-test -code-completion-at=%s:33:1 %s | FileCheck -check-prefix=CHECK-IMPLICIT-CONST %s
+// CHECK-IMPLICIT-CONST: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (15)
+// CHECK-IMPLICIT-CONST-NOT: bar
+// CHECK-IMPLICIT-CONST: FunctionDecl:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative  const} (14)
+// CHECK-IMPLICIT-CONST-NOT: bingo
+// CHECK-IMPLICIT-CONST: theend
+
+// RUN: c-index-test -code-completion-at=%s:37:1 %s | FileCheck -check-prefix=CHECK-IMPLICIT-VOLATILE %s
+// CHECK-IMPLICIT-VOLATILE: FunctionDecl:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative  const volatile} (15)
+// CHECK-IMPLICIT-VOLATILE-NOT: baz
+// CHECK-IMPLICIT-VOLATILE: FunctionDecl:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative  volatile} (14)

Propchange: cfe/trunk/test/Index/complete-memfunc-cvquals.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Index/complete-memfunc-cvquals.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Index/complete-memfunc-cvquals.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list