Support for constructors and new expressions.

http://reviews.llvm.org/D6880

Files:
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseExpr.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/SemaCodeComplete.cpp
  test/Index/complete-constructor-params.cpp
  test/Index/complete-exprs.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1362,12 +1362,9 @@
   typedef SmallVector<SourceLocation, 20> CommaLocsTy;
 
   /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
-  bool
-  ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
-                      SmallVectorImpl<SourceLocation> &CommaLocs,
-                      void (Sema::*Completer)(Scope *S, Expr *Data,
-                                              ArrayRef<Expr *> Args) = nullptr,
-                      Expr *Data = nullptr);
+  bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
+                           SmallVectorImpl<SourceLocation> &CommaLocs,
+                           std::function<void()> Completer = {});
 
   /// ParseSimpleExpressionList - A simple comma-separated list of expressions,
   /// used for misc language extensions.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -8405,6 +8405,8 @@
   void CodeCompleteTypeQualifiers(DeclSpec &DS);
   void CodeCompleteCase(Scope *S);
   void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args);
+  void CodeCompleteConstructor(Scope *S, CXXRecordDecl *DC, SourceLocation Loc,
+                               ArrayRef<Expr *> Args);
   void CodeCompleteInitializer(Scope *S, Decl *D);
   void CodeCompleteReturn(Scope *S);
   void CodeCompleteAfterIf(Scope *S);
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -1990,7 +1990,12 @@
       Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
     }
 
-    if (ParseExpressionList(Exprs, CommaLocs)) {
+    if (ParseExpressionList(Exprs, CommaLocs, [&] {
+          QualType T = cast<VarDecl>(ThisDecl)->getCanonicalDecl()->getType();
+          Actions.CodeCompleteConstructor(getCurScope(),
+                                          T->getAsCXXRecordDecl(),
+                                          ThisDecl->getLocation(), Exprs);
+       })) {
       Actions.ActOnInitializerError(ThisDecl);
       SkipUntil(tok::r_paren, StopAtSemi);
 
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1441,8 +1441,9 @@
 
       if (OpKind == tok::l_paren || !LHS.isInvalid()) {
         if (Tok.isNot(tok::r_paren)) {
-          if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
-                                  LHS.get())) {
+          if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
+                Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+             })) {
             (void)Actions.CorrectDelayedTyposInExpr(LHS);
             LHS = ExprError();
           }
@@ -2488,17 +2489,14 @@
 /// [C++0x]   assignment-expression
 /// [C++0x]   braced-init-list
 /// \endverbatim
-bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
+bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
                                  SmallVectorImpl<SourceLocation> &CommaLocs,
-                                 void (Sema::*Completer)(Scope *S,
-                                                         Expr *Data,
-                                                         ArrayRef<Expr *> Args),
-                                 Expr *Data) {
+                                 std::function<void()> Completer) {
   bool SawError = false;
   while (1) {
     if (Tok.is(tok::code_completion)) {
       if (Completer)
-        (Actions.*Completer)(getCurScope(), Data, Exprs);
+        Completer();
       else
         Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
       cutOffParsing();
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -1598,7 +1598,12 @@
     CommaLocsTy CommaLocs;
 
     if (Tok.isNot(tok::r_paren)) {
-      if (ParseExpressionList(Exprs, CommaLocs)) {
+      if (ParseExpressionList(Exprs, CommaLocs, [&] {
+            QualType T = TypeRep.get()->getCanonicalTypeInternal();
+            Actions.CodeCompleteConstructor(getCurScope(),
+                                            T->getAsCXXRecordDecl(),
+                                            DS.getLocEnd(), Exprs);
+         })) {
         SkipUntil(tok::r_paren, StopAtSemi);
         return ExprError();
       }
@@ -2664,7 +2669,15 @@
     ConstructorLParen = T.getOpenLocation();
     if (Tok.isNot(tok::r_paren)) {
       CommaLocsTy CommaLocs;
-      if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+      if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
+            ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(),
+                                                       DeclaratorInfo).get();
+            QualType T = TypeRep.get()->getCanonicalTypeInternal();
+            Actions.CodeCompleteConstructor(getCurScope(),
+                                            T->getAsCXXRecordDecl(),
+                                            DeclaratorInfo.getLocEnd(),
+                                            ConstructorArgs);
+      })) {
         SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
         return ExprError();
       }
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -3824,8 +3824,6 @@
   // name code-completion whenever we can't produce specific
   // results. This will do "parameter completion" solely.
 
-  // FIXME: Provide support for constructors
-
   Expr *Fn = (Expr *)FnIn;
 
   // Ignore type-dependent call expressions entirely.
@@ -3953,6 +3951,64 @@
   }
 }
 
+void Sema::CodeCompleteConstructor(Scope *S, CXXRecordDecl *DC,
+                                   SourceLocation Loc, ArrayRef<Expr *> Args) {
+  if (!CodeCompleter)
+    return;
+
+  // FIXME: Provide support for completing constructors of templates that are
+  // being declared for the first time.
+  OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
+
+  typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+  SmallVector<ResultCandidate, 8> Results;
+
+  for(auto C : LookupConstructors(DC)) {
+    if (auto FD = dyn_cast<FunctionDecl>(C)) {
+      AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
+                           Args, CandidateSet,
+                           /*SuppressUsedConversions=*/false,
+                           /*PartialOverloading=*/true);
+    } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
+      AddTemplateOverloadCandidate(FTD,
+                                   DeclAccessPair::make(FTD, C->getAccess()),
+                                   /*ExplicitTemplateArgs=*/nullptr,
+                                   Args, CandidateSet,
+                                   /*SuppressUsedConversions=*/false,
+                                   /*PartialOverloading=*/true);
+    }
+  }
+
+  if (!CandidateSet.empty()) {
+    // Sort the overload candidate set by placing the best overloads first.
+    std::stable_sort(
+        CandidateSet.begin(), CandidateSet.end(),
+        [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
+          return isBetterOverloadCandidate(*this, X, Y, Loc);
+        });
+
+    // Add the overload candidates as code-completion results.
+    for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+                                     CandEnd = CandidateSet.end();
+         Cand != CandEnd; ++Cand) {
+      if (Cand->Viable || Cand->FailureKind == ovl_fail_too_many_arguments)
+        Results.push_back(ResultCandidate(Cand->Function));
+    }
+  }
+
+  if (!Results.empty()) {
+    // An empty ResultBuilder solely to set CodeCompletionContext
+    ResultBuilder r(*this, CodeCompleter->getAllocator(),
+                    CodeCompleter->getCodeCompletionTUInfo(),
+                    mapCodeCompletionContext(*this, PCC_Expression));
+    HandleCodeCompleteResults(this, CodeCompleter, r.getCompletionContext(),
+                              r.data(), r.size());
+
+    CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
+                                             Results.size());
+  }
+}
+
 void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
   ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
   if (!VD) {
Index: test/Index/complete-constructor-params.cpp
===================================================================
--- /dev/null
+++ test/Index/complete-constructor-params.cpp
@@ -0,0 +1,147 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+template<class T>
+struct S {
+  template<class U>
+  S(T, U, U) {}
+};
+
+int main() {
+  S<int>(42, 42, 42);  // <- no completion since it's the first specialization. Fix?
+  S<int>(42, 42, 42);  // <- since there's a specialization already, we get completions.
+  S<int> s(42, 42, 42);
+
+  S<int>(42, 42, 42,);
+  S<int> z(42, 42, 42,);
+}
+
+// RUN: c-index-test -code-completion-at=%s:11:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: Completion contexts:
+// CHECK-CC1-NEXT: Unknown
+// CHECK-CC1-NEXT: Any type
+// CHECK-CC1-NEXT: Any value
+// CHECK-CC1-NEXT: Objective-C object value
+// CHECK-CC1-NEXT: Objective-C selector value
+// CHECK-CC1-NEXT: C++ class type value
+// CHECK-CC1-NEXT: Dot member access
+// CHECK-CC1-NEXT: Arrow member access
+// CHECK-CC1-NEXT: Objective-C property access
+// CHECK-CC1-NEXT: Enum tag
+// CHECK-CC1-NEXT: Union tag
+// CHECK-CC1-NEXT: Struct tag
+// CHECK-CC1-NEXT: Class name
+// CHECK-CC1-NEXT: Namespace or namespace alias
+// CHECK-CC1-NEXT: Nested name specifier
+// CHECK-CC1-NEXT: Objective-C interface
+// CHECK-CC1-NEXT: Objective-C protocol
+// CHECK-CC1-NEXT: Objective-C category
+// CHECK-CC1-NEXT: Objective-C instance method
+// CHECK-CC1-NEXT: Objective-C class method
+// CHECK-CC1-NEXT: Objective-C selector name
+// CHECK-CC1-NEXT: Macro name
+// CHECK-CC1-NEXT: Natural language
+
+// RUN: c-index-test -code-completion-at=%s:12:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{Text S}{LeftParen (}{CurrentParameter const S<int> &}{RightParen )} (1)
+// CHECK-CC2: NotImplemented:{Text S}{LeftParen (}{CurrentParameter int}{Comma , }{Text U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC2: Completion contexts:
+// CHECK-CC2-NEXT: Any type
+// CHECK-CC2-NEXT: Any value
+// CHECK-CC2-NEXT: Enum tag
+// CHECK-CC2-NEXT: Union tag
+// CHECK-CC2-NEXT: Struct tag
+// CHECK-CC2-NEXT: Class name
+// CHECK-CC2-NEXT: Nested name specifier
+// CHECK-CC2-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:12:13 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{CurrentParameter U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC3: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC3: Completion contexts:
+// CHECK-CC3-NEXT: Any type
+// CHECK-CC3-NEXT: Any value
+// CHECK-CC3-NEXT: Enum tag
+// CHECK-CC3-NEXT: Union tag
+// CHECK-CC3-NEXT: Struct tag
+// CHECK-CC3-NEXT: Class name
+// CHECK-CC3-NEXT: Nested name specifier
+// CHECK-CC3-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:12:17 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{Text int}{Comma , }{CurrentParameter int}{RightParen )} (1)
+// CHECK-CC4: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC4: Completion contexts:
+// CHECK-CC4-NEXT: Any type
+// CHECK-CC4-NEXT: Any value
+// CHECK-CC4-NEXT: Enum tag
+// CHECK-CC4-NEXT: Union tag
+// CHECK-CC4-NEXT: Struct tag
+// CHECK-CC4-NEXT: Class name
+// CHECK-CC4-NEXT: Nested name specifier
+// CHECK-CC4-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:13:12 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: NotImplemented:{Text S}{LeftParen (}{CurrentParameter const S<int> &}{RightParen )} (1)
+// CHECK-CC5: NotImplemented:{Text S}{LeftParen (}{CurrentParameter int}{Comma , }{Text U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC5: Completion contexts:
+// CHECK-CC5-NEXT: Any type
+// CHECK-CC5-NEXT: Any value
+// CHECK-CC5-NEXT: Enum tag
+// CHECK-CC5-NEXT: Union tag
+// CHECK-CC5-NEXT: Struct tag
+// CHECK-CC5-NEXT: Class name
+// CHECK-CC5-NEXT: Nested name specifier
+// CHECK-CC5-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:13:15 %s | FileCheck -check-prefix=CHECK-CC6 %s
+// CHECK-CC6: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{CurrentParameter U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC6: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC6: Completion contexts:
+// CHECK-CC6-NEXT: Any type
+// CHECK-CC6-NEXT: Any value
+// CHECK-CC6-NEXT: Enum tag
+// CHECK-CC6-NEXT: Union tag
+// CHECK-CC6-NEXT: Struct tag
+// CHECK-CC6-NEXT: Class name
+// CHECK-CC6-NEXT: Nested name specifier
+// CHECK-CC6-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:13:19 %s | FileCheck -check-prefix=CHECK-CC7 %s
+// CHECK-CC7: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{Text int}{Comma , }{CurrentParameter int}{RightParen )} (1)
+// CHECK-CC7: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC7: Completion contexts:
+// CHECK-CC7-NEXT: Any type
+// CHECK-CC7-NEXT: Any value
+// CHECK-CC7-NEXT: Enum tag
+// CHECK-CC7-NEXT: Union tag
+// CHECK-CC7-NEXT: Struct tag
+// CHECK-CC7-NEXT: Class name
+// CHECK-CC7-NEXT: Nested name specifier
+// CHECK-CC7-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:15:21 %s | FileCheck -check-prefix=CHECK-CC8 %s
+// CHECK-CC8: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{Text U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC8: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC8: Completion contexts:
+// CHECK-CC8-NEXT: Any type
+// CHECK-CC8-NEXT: Any value
+// CHECK-CC8-NEXT: Enum tag
+// CHECK-CC8-NEXT: Union tag
+// CHECK-CC8-NEXT: Struct tag
+// CHECK-CC8-NEXT: Class name
+// CHECK-CC8-NEXT: Nested name specifier
+// CHECK-CC8-NEXT: Objective-C interface
+
+// RUN: c-index-test -code-completion-at=%s:16:23 %s | FileCheck -check-prefix=CHECK-CC9 %s
+// CHECK-CC9: NotImplemented:{Text S}{LeftParen (}{Text int}{Comma , }{Text U}{Comma , }{Text U}{RightParen )} (1)
+// CHECK-CC9: NotImplemented:{Text S}{LeftParen (}{Text const S<int> &}{RightParen )} (1)
+// CHECK-CC9: Completion contexts:
+// CHECK-CC9-NEXT: Any type
+// CHECK-CC9-NEXT: Any value
+// CHECK-CC9-NEXT: Enum tag
+// CHECK-CC9-NEXT: Union tag
+// CHECK-CC9-NEXT: Struct tag
+// CHECK-CC9-NEXT: Class name
+// CHECK-CC9-NEXT: Nested name specifier
+// CHECK-CC9-NEXT: Objective-C interface
Index: test/Index/complete-exprs.cpp
===================================================================
--- test/Index/complete-exprs.cpp
+++ test/Index/complete-exprs.cpp
@@ -66,14 +66,6 @@
 // CHECK-CC2-NOT: CXXConstructor
 // CHECK-CC2: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
 
-// RUN: c-index-test -code-completion-at=%s:26:15 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: NotImplemented:{TypedText float} (50)
-// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText foo}{LeftParen (}{RightParen )} (50)
-// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{RightParen )} (50)
-// CHECK-CC3: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
-// CHECK-CC3: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder const T &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50)
-// CHECK-CC3: FunctionTemplate:{ResultType void}{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50)
-
 // RUN: c-index-test -code-completion-at=%s:34:1 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: NotImplemented:{ResultType const X *}{TypedText this} (40)
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to