kadircet updated this revision to Diff 171259.
kadircet added a comment.

- Add a generic constructor if found none.
- format && add comments.
- Add generic constructors to tests.


Repository:
  rC Clang

https://reviews.llvm.org/D53654

Files:
  include/clang/Sema/CodeCompleteConsumer.h
  lib/Sema/SemaCodeComplete.cpp
  test/CodeCompletion/ctor-initializer.cpp
  test/CodeCompletion/ordinary-name-cxx11.cpp
  test/CodeCompletion/ordinary-name.cpp
  test/CodeCompletion/templates.cpp
  test/Index/complete-ctor-inits.cpp
  test/Index/complete-cxx-inline-methods.cpp

Index: test/Index/complete-cxx-inline-methods.cpp
===================================================================
--- test/Index/complete-cxx-inline-methods.cpp
+++ test/Index/complete-cxx-inline-methods.cpp
@@ -21,6 +21,13 @@
   int value;
   MyCls *object;
 };
+
+template <typename T>
+class X {};
+
+class Y : public X<int> {
+  Y() : X<int>() {}
+};
 }
 
 // RUN: c-index-test -code-completion-at=%s:4:9 -std=c++98 %s | FileCheck %s
@@ -35,10 +42,12 @@
 // CHECK-NEXT: Container Kind: StructDecl
 
 // RUN: c-index-test -code-completion-at=%s:18:41 %s | FileCheck -check-prefix=CHECK-CTOR-INIT %s
-// CHECK-CTOR-INIT: NotImplemented:{TypedText MyCls}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CTOR-INIT: MemberRef:{TypedText object}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CTOR-INIT: MemberRef:{TypedText value}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CTOR-INIT: ClassDecl:{TypedText MyCls}{LeftParen (}{Placeholder MyCls}{RightParen )} (40)
+// CHECK-CTOR-INIT: MemberRef:{TypedText object}{LeftParen (}{Placeholder MyCls *}{RightParen )} (35)
+// CHECK-CTOR-INIT: MemberRef:{TypedText value}{LeftParen (}{Placeholder int}{RightParen )} (35)
 // RUN: c-index-test -code-completion-at=%s:18:55 %s | FileCheck -check-prefix=CHECK-CTOR-INIT-2 %s
-// CHECK-CTOR-INIT-2-NOT: NotImplemented:{TypedText MyCls}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CTOR-INIT-2: MemberRef:{TypedText object}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CTOR-INIT-2: MemberRef:{TypedText value}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CTOR-INIT-2-NOT: ClassDecl:{TypedText MyCls}{LeftParen (}{Placeholder MyCls}{RightParen )} (40)
+// CHECK-CTOR-INIT-2: MemberRef:{TypedText object}{LeftParen (}{Placeholder MyCls *}{RightParen )} (35)
+// CHECK-CTOR-INIT-2: MemberRef:{TypedText value}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// RUN: c-index-test -code-completion-at=%s:29:9 %s | FileCheck -check-prefix=CHECK-CTOR-INIT-3 %s
+// CHECK-CTOR-INIT-3: ClassDecl:{TypedText X<int>}{LeftParen (}{Placeholder X}{RightParen )} (40)
Index: test/Index/complete-ctor-inits.cpp
===================================================================
--- test/Index/complete-ctor-inits.cpp
+++ test/Index/complete-ctor-inits.cpp
@@ -30,27 +30,33 @@
 };
 
 // RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText X<int>}{LeftParen (}{Placeholder int}{RightParen )} (7)
+// CHECK-CC1: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (35)
+// CHECK-CC1: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (35)
 
 // RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC2: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (7)
+// CHECK-CC2: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (7)
 
 // RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (35)
-// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
-// CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (35)
+// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder int}{RightParen )}
+// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder int}{RightParen )} (35)
+// CHECK-CC3-NOT: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder const Virt &}{RightParen )} (35)
+// CHECK-CC3-NOT: CXXConstructor:{TypedText Virt}{LeftParen (}{Placeholder Virt &&}{RightParen )} (35)
+// CHECK-CC3: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder const Y &}{RightParen )} (35)
+// CHECK-CC3: CXXConstructor:{TypedText Y}{LeftParen (}{Placeholder Y &&}{RightParen )} (35)
 
 // RUN: c-index-test -code-completion-at=%s:22:10 -target i386-apple-darwin %s | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC4: MemberRef:{TypedText a}{LeftParen (}{Placeholder int}{RightParen )} (35)
 // RUN: c-index-test -code-completion-at=%s:26:10 %s
Index: test/CodeCompletion/templates.cpp
===================================================================
--- test/CodeCompletion/templates.cpp
+++ test/CodeCompletion/templates.cpp
@@ -19,7 +19,9 @@
   v.foo();
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // CHECK-CC1: allocator<<#typename T#>>
+  // CHECK-CC1-NEXT: allocator<<#typename T#>>(<#allocator#>)
   // CHECK-CC1-NEXT: vector<<#typename T#>{#, <#typename Alloc#>#}>
+  // CHECK-CC1-NEXT: vector<<#typename T#>{#, <#typename Alloc#>#}>(<#vector#>)
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:5 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
   // CHECK-CC2: foo
   // CHECK-CC2: in_base
Index: test/CodeCompletion/ordinary-name.cpp
===================================================================
--- test/CodeCompletion/ordinary-name.cpp
+++ test/CodeCompletion/ordinary-name.cpp
@@ -55,6 +55,7 @@
   // CHECK-CC1-NEXT: COMPLETION: wchar_t
   // CHECK-CC1-NEXT: COMPLETION: Pattern : while(<#condition#>){<#statements#>
   // CHECK-CC1: COMPLETION: X : X
+  // CHECK-CC1-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-CC1-NEXT: COMPLETION: y : [#int#]y
   // CHECK-CC1-NEXT: COMPLETION: z : [#void#]z(<#int#>)
 
@@ -171,6 +172,7 @@
   // CHECK-CC4-NEXT: COMPLETION: volatile
   // CHECK-CC4-NEXT: COMPLETION: wchar_t
   // CHECK-CC4-NEXT: COMPLETION: X : X
+  // CHECK-CC4-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-CC4-NEXT: COMPLETION: y : [#int#]y
   // CHECK-CC4-NEXT: COMPLETION: z : [#void#]z(<#int#>)
 
@@ -225,5 +227,6 @@
   // CHECK-NO-RTTI-NEXT: COMPLETION: wchar_t
   // CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : while(<#condition#>){<#statements#>
   // CHECK-NO-RTTI: COMPLETION: X : X
+  // CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-NO-RTTI-NEXT: COMPLETION: y : [#int#]y
   // CHECK-NO-RTTI-NEXT: COMPLETION: z : [#void#]z(<#int#>)
Index: test/CodeCompletion/ordinary-name-cxx11.cpp
===================================================================
--- test/CodeCompletion/ordinary-name-cxx11.cpp
+++ test/CodeCompletion/ordinary-name-cxx11.cpp
@@ -62,6 +62,7 @@
   // CHECK-CC1-NEXT: COMPLETION: wchar_t
   // CHECK-CC1-NEXT: COMPLETION: Pattern : while(<#condition#>){<#statements#>
   // CHECK-CC1: COMPLETION: X : X
+  // CHECK-CC1-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-CC1-NEXT: COMPLETION: y : [#int#]y
   // CHECK-CC1-NEXT: COMPLETION: z : [#void#]z(<#int#>)
 
@@ -197,6 +198,7 @@
   // CHECK-CC4-NEXT: COMPLETION: volatile
   // CHECK-CC4-NEXT: COMPLETION: wchar_t
   // CHECK-CC4-NEXT: COMPLETION: X : X
+  // CHECK-CC4-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-CC4-NEXT: COMPLETION: y : [#int#]y
   // CHECK-CC4-NEXT: COMPLETION: z : [#void#]z(<#int#>)
 
@@ -257,5 +259,6 @@
   // CHECK-NO-RTTI-NEXT: COMPLETION: wchar_t
   // CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : while(<#condition#>){<#statements#>
   // CHECK-NO-RTTI: COMPLETION: X : X
+  // CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : X(<#X#>)
   // CHECK-NO-RTTI-NEXT: COMPLETION: y : [#int#]y
   // CHECK-NO-RTTI-NEXT: COMPLETION: z : [#void#]z(<#int#>)
Index: test/CodeCompletion/ctor-initializer.cpp
===================================================================
--- test/CodeCompletion/ctor-initializer.cpp
+++ test/CodeCompletion/ctor-initializer.cpp
@@ -2,14 +2,14 @@
   Base1() : {}
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
-  // CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
-  // CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
+  // CHECK-CC1: COMPLETION: Pattern : member1(<#int#>)
+  // CHECK-CC1: COMPLETION: Pattern : member2(<#float#>)
 
   Base1(int) : member1(123), {}
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
-  // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
-  // CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
+  // CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#int#>)
+  // CHECK-CC2: COMPLETION: Pattern : member2(<#float#>)
 
   int member1;
   float member2;
@@ -25,52 +25,52 @@
 Derived::Derived() : {}
 // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
+// CHECK-CC3: COMPLETION: Base1 : Base1()
+// CHECK-CC3: COMPLETION: Base1 : Base1(<#int#>)
+// CHECK-CC3: COMPLETION: Pattern : deriv1(<#int#>)
 
 Derived::Derived(int) try : {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:32:29 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:32:29 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
 
 Derived::Derived(float) try : Base1(),
 {
 } catch (...) {
 }
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
-// CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:38:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:38:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5-NOT: COMPLETION: Base1 : Base1()
+// CHECK-CC5-NOT: COMPLETION: Base1 : Base1(<#int#>)
+// CHECK-CC5: COMPLETION: Pattern : deriv1(<#int#>)
 
 struct A {
   A() : , member2() {}
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
-  // CHECK-CC6: COMPLETION: Pattern : member1(<#args#>
+  // CHECK-CC6: COMPLETION: Pattern : member1(<#int#>)
   int member1, member2;
 };
 
 struct B {
   B() : member2() {}
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:57:9 %s -o - | FileCheck -check-prefix=CHECK-CC7 %s
-  // CHECK-CC7: COMPLETION: Pattern : member1(<#args#>
+  // CHECK-CC7: COMPLETION: Pattern : member1(<#int#>)
   // Check in the middle and at the end of identifier too.
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:13 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:57:16 %s -o - | FileCheck -check-prefix=CHECK-CC8 %s
-  // CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
+  // CHECK-CC8: COMPLETION: Pattern : member2(<#int#>)
   int member1, member2;
 };
 
 struct Base2 {
-  Base2(int);
+  Base2(int, float x = 3);
 };
 
 struct Composition1 {
-  Composition1() : b2_elem() {}
+  Composition1() : b2_elem(2) {}
   // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
   // CHECK-CC9: OVERLOAD: Base2(<#int#>)
@@ -88,3 +88,7 @@
   // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:84:35 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
   Composition1 c1_elem;
 };
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:84:20 %s -o - | FileCheck -check-prefix=CHECK-CC10 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:84:20 %s -o - | FileCheck -check-prefix=CHECK-CC10 %s
+// CHECK-CC10: Composition1 : c1_elem()
+// CHECK-CC10: Composition1 : c1_elem(<#Base2#>)
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -170,9 +170,14 @@
 
     void AdjustResultPriorityForDecl(Result &R);
 
-    void MaybeAddConstructorResults(Result R);
+    void MaybeAddConstructorResults(
+        Result R, llvm::Optional<StringRef> PreferredTypeName = llvm::None);
 
   public:
+    void AddConstructorResults(
+        const CXXRecordDecl *Record, Result R,
+        llvm::Optional<StringRef> PreferredTypedName = llvm::None);
+
     explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
                            CodeCompletionTUInfo &CCTUInfo,
                            const CodeCompletionContext &CompletionContext,
@@ -808,12 +813,58 @@
   }
 }
 
-void ResultBuilder::MaybeAddConstructorResults(Result R) {
+static void AddTemplateParameterChunks(ASTContext &Context,
+                                       const PrintingPolicy &Policy,
+                                       const TemplateDecl *Template,
+                                       CodeCompletionBuilder &Result,
+                                       unsigned MaxParameters = 0,
+                                       unsigned Start = 0,
+                                       bool InDefaultArg = false);
+
+void ResultBuilder::AddConstructorResults(
+    const CXXRecordDecl *Record, Result R,
+    llvm::Optional<StringRef> PreferredTypedName) {
+  ASTContext &Context = SemaRef.Context;
+  QualType RecordTy = Context.getTypeDeclType(Record);
+  DeclarationName ConstructorName =
+      Context.DeclarationNames.getCXXConstructorName(
+          Context.getCanonicalType(RecordTy));
+  DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
+  // If there are no constructor results, add a generic constructor with
+  // template args and one parameter with type's name.
+  if (Ctors.begin() == Ctors.end()) {
+    CodeCompletionBuilder Result(Allocator, CCTUInfo);
+    Result.AddTypedTextChunk(Result.getAllocator().CopyString(
+        PreferredTypedName ? *PreferredTypedName : Record->getName()));
+    if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+      Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+      AddTemplateParameterChunks(Context, SemaRef.getPrintingPolicy(), Template,
+                                 Result);
+      Result.AddChunk(CodeCompletionString::CK_RightAngle);
+    }
+    Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    Result.AddPlaceholderChunk(
+        Result.getAllocator().CopyString(Record->getName()));
+    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    Results.push_back(
+        CodeCompletionResult(Result.TakeString(), Record, CCP_CodePattern));
+    return;
+  }
+  R.PreferredTypedName = PreferredTypedName;
+  for (DeclContext::lookup_iterator I = Ctors.begin(), E = Ctors.end(); I != E;
+       ++I) {
+    R.Declaration = *I;
+    R.CursorKind = getCursorKindForDecl(R.Declaration);
+    Results.push_back(R);
+  }
+}
+
+void ResultBuilder::MaybeAddConstructorResults(
+    Result R, llvm::Optional<StringRef> PreferredTypedName) {
   if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
       !CompletionContext.wantConstructorResults())
     return;
 
-  ASTContext &Context = SemaRef.Context;
   const NamedDecl *D = R.Declaration;
   const CXXRecordDecl *Record = nullptr;
   if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
@@ -831,19 +882,7 @@
   if (!Record)
     return;
 
-
-  QualType RecordTy = Context.getTypeDeclType(Record);
-  DeclarationName ConstructorName
-    = Context.DeclarationNames.getCXXConstructorName(
-                                           Context.getCanonicalType(RecordTy));
-  DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
-  for (DeclContext::lookup_iterator I = Ctors.begin(),
-                                          E = Ctors.end();
-       I != E; ++I) {
-    R.Declaration = *I;
-    R.CursorKind = getCursorKindForDecl(R.Declaration);
-    Results.push_back(R);
-  }
+  AddConstructorResults(Record, R, PreferredTypedName);
 }
 
 static bool isConstructor(const Decl *ND) {
@@ -2624,9 +2663,9 @@
                                        const PrintingPolicy &Policy,
                                        const TemplateDecl *Template,
                                        CodeCompletionBuilder &Result,
-                                       unsigned MaxParameters = 0,
-                                       unsigned Start = 0,
-                                       bool InDefaultArg = false) {
+                                       unsigned MaxParameters,
+                                       unsigned Start,
+                                       bool InDefaultArg) {
   bool FirstParameter = true;
 
   // Prefer to take the template parameter names from the first declaration of
@@ -2760,9 +2799,10 @@
 }
 
 /// Add the name of the given declaration
-static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
-                              const NamedDecl *ND,
-                              CodeCompletionBuilder &Result) {
+static void
+AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
+                  const NamedDecl *ND, CodeCompletionBuilder &Result,
+                  llvm::Optional<StringRef> PreferredTypedName = llvm::None) {
   DeclarationName Name = ND->getDeclName();
   if (!Name)
     return;
@@ -2809,21 +2849,26 @@
     break;
 
   case DeclarationName::CXXConstructorName: {
+    StringRef TypedText;
     CXXRecordDecl *Record = nullptr;
     QualType Ty = Name.getCXXNameType();
     if (const RecordType *RecordTy = Ty->getAs<RecordType>())
       Record = cast<CXXRecordDecl>(RecordTy->getDecl());
     else if (const InjectedClassNameType *InjectedTy
                                         = Ty->getAs<InjectedClassNameType>())
       Record = InjectedTy->getDecl();
-    else {
-      Result.AddTypedTextChunk(
-                      Result.getAllocator().CopyString(ND->getNameAsString()));
-      break;
-    }
+
+    if(PreferredTypedName)
+      TypedText = *PreferredTypedName;
+    else if (Record)
+      TypedText = Record->getName();
+    else
+      TypedText = ND->getName();
 
     Result.AddTypedTextChunk(
-                  Result.getAllocator().CopyString(Record->getNameAsString()));
+        Result.getAllocator().CopyString(TypedText));
+    if (!Record)
+      break;
     if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
       Result.AddChunk(CodeCompletionString::CK_LeftAngle);
       AddTemplateParameterChunks(Context, Policy, Template, Result);
@@ -2979,7 +3024,7 @@
   if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
                                    Ctx, Policy);
-    AddTypedNameChunk(Ctx, Policy, ND, Result);
+    AddTypedNameChunk(Ctx, Policy, ND, Result, PreferredTypedName);
     Result.AddChunk(CodeCompletionString::CK_LeftParen);
     AddFunctionParameterChunks(PP, Policy, Function, Result);
     Result.AddChunk(CodeCompletionString::CK_RightParen);
@@ -2991,7 +3036,7 @@
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
                                    Ctx, Policy);
     FunctionDecl *Function = FunTmpl->getTemplatedDecl();
-    AddTypedNameChunk(Ctx, Policy, Function, Result);
+    AddTypedNameChunk(Ctx, Policy, Function, Result, PreferredTypedName);
 
     // Figure out which template parameters are deduced (or have default
     // arguments).
@@ -5073,11 +5118,27 @@
   }
 
   // Add completions for base classes.
+  PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
   CodeCompletionBuilder Builder(Results.getAllocator(),
                                 Results.getCodeCompletionTUInfo());
-  PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
   bool SawLastInitializer = Initializers.empty();
   CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+  auto AddBase = [&](const CXXBaseSpecifier &Base) {
+    const auto *ND = Base.getType()->getAsCXXRecordDecl();
+    Results.AddConstructorResults(
+        ND,
+        CodeCompletionResult(ND, SawLastInitializer ? CCP_NextInitializer
+                                                    : CCP_MemberDeclaration),
+        StringRef(Builder.getAllocator().CopyString(
+            Base.getType().getAsString(Policy))));
+  };
+  auto AddField = [&](const FieldDecl *FD, CodeCompletionString *CCS) {
+    Results.AddResult(CodeCompletionResult(
+        CCS, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
+        CXCursor_MemberRef, CXAvailability_Available, FD));
+  };
+
   for (const auto &Base : ClassDecl->bases()) {
     if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
              .second) {
@@ -5089,15 +5150,7 @@
       continue;
     }
 
-    Builder.AddTypedTextChunk(
-               Results.getAllocator().CopyString(
-                          Base.getType().getAsString(Policy)));
-    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
-    Builder.AddPlaceholderChunk("args");
-    Builder.AddChunk(CodeCompletionString::CK_RightParen);
-    Results.AddResult(CodeCompletionResult(Builder.TakeString(),
-                                   SawLastInitializer? CCP_NextInitializer
-                                                     : CCP_MemberDeclaration));
+    AddBase(Base);
     SawLastInitializer = false;
   }
 
@@ -5113,15 +5166,7 @@
       continue;
     }
 
-    Builder.AddTypedTextChunk(
-               Builder.getAllocator().CopyString(
-                          Base.getType().getAsString(Policy)));
-    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
-    Builder.AddPlaceholderChunk("args");
-    Builder.AddChunk(CodeCompletionString::CK_RightParen);
-    Results.AddResult(CodeCompletionResult(Builder.TakeString(),
-                                   SawLastInitializer? CCP_NextInitializer
-                                                     : CCP_MemberDeclaration));
+    AddBase(Base);
     SawLastInitializer = false;
   }
 
@@ -5139,18 +5184,25 @@
     if (!Field->getDeclName())
       continue;
 
-    Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
-                                         Field->getIdentifier()->getName()));
-    Builder.AddChunk(CodeCompletionString::CK_LeftParen);
-    Builder.AddPlaceholderChunk("args");
-    Builder.AddChunk(CodeCompletionString::CK_RightParen);
-    Results.AddResult(CodeCompletionResult(Builder.TakeString(),
-                                   SawLastInitializer? CCP_NextInitializer
-                                                     : CCP_MemberDeclaration,
-                                           CXCursor_MemberRef,
-                                           CXAvailability_Available,
-                                           Field));
     SawLastInitializer = false;
+    StringRef FieldName = Field->getIdentifier()->getName();
+    // Check if field is a cxx class/struct/union, if not it can't have a
+    // constructor.
+    const CXXRecordDecl *RD = Field->getType()->getAsCXXRecordDecl();
+    if (!RD) {
+      Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(FieldName));
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
+          Field->getType().getAsString(Policy)));
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      AddField(Field, Builder.TakeString());
+      continue;
+    }
+    Results.AddConstructorResults(
+        RD,
+        CodeCompletionResult(Field, SawLastInitializer ? CCP_NextInitializer
+                                                       : CCP_MemberDeclaration),
+        Field->getIdentifier()->getName());
   }
   Results.ExitScope();
 
Index: include/clang/Sema/CodeCompleteConsumer.h
===================================================================
--- include/clang/Sema/CodeCompleteConsumer.h
+++ include/clang/Sema/CodeCompleteConsumer.h
@@ -763,6 +763,11 @@
   /// referring to. In the latter case, the declaration might be NULL.
   const NamedDecl *Declaration = nullptr;
 
+  /// When Kind == RK_Declaration and a FieldDecl has been passed as
+  /// Declaration, this will hold the identifiers name. To be used later on when
+  /// generating constructors for the variable.
+  llvm::Optional<StringRef> PreferredTypedName = llvm::None;
+
   union {
     /// When Kind == RK_Keyword, the string representing the keyword
     /// or symbol's spelling.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to