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