forked from qt-creator/qt-creator
		
	...with overloads. https://bugs.llvm.org/show_bug.cgi?id=31093 Change-Id: I2f177794d8d84c91b5bc47da38a3a6c90f8d8d55 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
		
			
				
	
	
		
			127 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
diff --git a/tools/clang/lib/Sema/SemaCodeComplete.cpp b/tools/clang/lib/Sema/SemaCodeComplete.cpp
 | 
						|
index f4b51a19c2..f4b35fd408 100644
 | 
						|
--- a/tools/clang/lib/Sema/SemaCodeComplete.cpp
 | 
						|
+++ b/tools/clang/lib/Sema/SemaCodeComplete.cpp
 | 
						|
@@ -4066,7 +4066,10 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
 | 
						|
       UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
 | 
						|
       TemplateArgs = &TemplateArgsBuffer;
 | 
						|
     }
 | 
						|
-    SmallVector<Expr *, 12> ArgExprs(1, UME->getBase());
 | 
						|
+
 | 
						|
+    // Add the base as first argument (use a nullptr if the base is implicit).
 | 
						|
+    SmallVector<Expr *, 12> ArgExprs(
 | 
						|
+        1, UME->isImplicitAccess() ? nullptr : UME->getBase());
 | 
						|
     ArgExprs.append(Args.begin(), Args.end());
 | 
						|
     UnresolvedSet<8> Decls;
 | 
						|
     Decls.append(UME->decls_begin(), UME->decls_end());
 | 
						|
diff --git a/tools/clang/lib/Sema/SemaOverload.cpp b/tools/clang/lib/Sema/SemaOverload.cpp
 | 
						|
index 40d6e910f1..19547237ac 100644
 | 
						|
--- a/tools/clang/lib/Sema/SemaOverload.cpp
 | 
						|
+++ b/tools/clang/lib/Sema/SemaOverload.cpp
 | 
						|
@@ -6051,31 +6051,44 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
 | 
						|
   for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
 | 
						|
     NamedDecl *D = F.getDecl()->getUnderlyingDecl();
 | 
						|
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
 | 
						|
-      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
 | 
						|
+      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
 | 
						|
+        QualType ObjectType;
 | 
						|
+        Expr::Classification ObjectClassification;
 | 
						|
+        if (Expr *E = Args[0]) {
 | 
						|
+          // Use the explit base to restrict the lookup:
 | 
						|
+          ObjectType = E->getType();
 | 
						|
+          ObjectClassification = E->Classify(Context);
 | 
						|
+        } // .. else there is an implit base.
 | 
						|
         AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
 | 
						|
-                           cast<CXXMethodDecl>(FD)->getParent(),
 | 
						|
-                           Args[0]->getType(), Args[0]->Classify(Context),
 | 
						|
-                           Args.slice(1), CandidateSet,
 | 
						|
+                           cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
 | 
						|
+                           ObjectClassification, Args.slice(1), CandidateSet,
 | 
						|
                            SuppressUserConversions, PartialOverloading);
 | 
						|
-      else
 | 
						|
+      } else {
 | 
						|
         AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
 | 
						|
                              SuppressUserConversions, PartialOverloading);
 | 
						|
+      }
 | 
						|
     } else {
 | 
						|
       FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
 | 
						|
       if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
 | 
						|
-          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
 | 
						|
+          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) {
 | 
						|
+        QualType ObjectType;
 | 
						|
+        Expr::Classification ObjectClassification;
 | 
						|
+        if (Expr *E = Args[0]) {
 | 
						|
+          // Use the explit base to restrict the lookup:
 | 
						|
+          ObjectType = E->getType();
 | 
						|
+          ObjectClassification = E->Classify(Context);
 | 
						|
+        } // .. else there is an implit base.
 | 
						|
         AddMethodTemplateCandidate(FunTmpl, F.getPair(),
 | 
						|
-                              cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
 | 
						|
-                                   ExplicitTemplateArgs,
 | 
						|
-                                   Args[0]->getType(),
 | 
						|
-                                   Args[0]->Classify(Context), Args.slice(1),
 | 
						|
-                                   CandidateSet, SuppressUserConversions,
 | 
						|
+                                   cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
 | 
						|
+                                   ExplicitTemplateArgs, ObjectType, ObjectClassification,
 | 
						|
+                                   Args.slice(1), CandidateSet, SuppressUserConversions,
 | 
						|
                                    PartialOverloading);
 | 
						|
-      else
 | 
						|
+      } else {
 | 
						|
         AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
 | 
						|
                                      ExplicitTemplateArgs, Args,
 | 
						|
                                      CandidateSet, SuppressUserConversions,
 | 
						|
                                      PartialOverloading);
 | 
						|
+      }
 | 
						|
     }
 | 
						|
   }
 | 
						|
 }
 | 
						|
diff --git a/tools/clang/test/CodeCompletion/member-access.cpp b/tools/clang/test/CodeCompletion/member-access.cpp
 | 
						|
index 8f772c0652..8528e18649 100644
 | 
						|
--- a/tools/clang/test/CodeCompletion/member-access.cpp
 | 
						|
+++ b/tools/clang/test/CodeCompletion/member-access.cpp
 | 
						|
@@ -27,16 +27,31 @@ public:
 | 
						|
 
 | 
						|
 void test(const Proxy &p) {
 | 
						|
   p->
 | 
						|
-  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
 | 
						|
-  // CHECK-CC1: Base1 : Base1::
 | 
						|
-  // CHECK-CC1: member1 : [#int#][#Base1::#]member1
 | 
						|
-  // CHECK-CC1: member1 : [#int#][#Base2::#]member1
 | 
						|
-  // CHECK-CC1: member2 : [#float#][#Base1::#]member2
 | 
						|
-  // CHECK-CC1: member3
 | 
						|
-  // CHECK-CC1: member4
 | 
						|
-  // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
 | 
						|
-  // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
 | 
						|
-  // CHECK-CC1: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
 | 
						|
-  // CHECK-CC1: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
 | 
						|
-  // CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
 | 
						|
-  
 | 
						|
+}
 | 
						|
+
 | 
						|
+struct Foo {
 | 
						|
+  void foo() const;
 | 
						|
+  static void foo(bool);
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct Bar {
 | 
						|
+  void foo(bool param) {
 | 
						|
+    Foo::foo(  );// unresolved member expression with an implicit base
 | 
						|
+  }
 | 
						|
+};
 | 
						|
+
 | 
						|
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
 | 
						|
+// CHECK-CC1: Base1 : Base1::
 | 
						|
+// CHECK-CC1: member1 : [#int#][#Base1::#]member1
 | 
						|
+// CHECK-CC1: member1 : [#int#][#Base2::#]member1
 | 
						|
+// CHECK-CC1: member2 : [#float#][#Base1::#]member2
 | 
						|
+// CHECK-CC1: member3
 | 
						|
+// CHECK-CC1: member4
 | 
						|
+// CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
 | 
						|
+// CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
 | 
						|
+// CHECK-CC1: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
 | 
						|
+// CHECK-CC1: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
 | 
						|
+// CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
 | 
						|
+
 | 
						|
+// Make sure this also doesn't crash
 | 
						|
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:39:14 %s
 |