diff options
-rw-r--r-- | clang/include/clang/Sema/Action.h | 16 | ||||
-rw-r--r-- | clang/include/clang/Sema/CodeCompleteConsumer.h | 7 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 49 | ||||
-rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 41 | ||||
-rw-r--r-- | clang/test/Index/complete-declarators.cpp | 39 | ||||
-rw-r--r-- | clang/test/Index/complete-declarators.m | 29 |
9 files changed, 178 insertions, 22 deletions
diff --git a/clang/include/clang/Sema/Action.h b/clang/include/clang/Sema/Action.h index 87cafafaadc..cc2b71adbb4 100644 --- a/clang/include/clang/Sema/Action.h +++ b/clang/include/clang/Sema/Action.h @@ -2798,6 +2798,22 @@ public: virtual void CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext) { } + /// \brief Code completion for a declarator name. + /// + /// + /// + /// \param S The scope in which code completion occurs. + /// + /// \param AllowNonIdentifiers Whether non-identifier names are allowed in + /// this context, e.g., operator+. + /// + /// \param AllowNestedNameSpecifiers Whether nested-name-specifiers are + /// allowed in this context, e.g., because it is a top-level declaration or + /// a friend declaration. + virtual void CodeCompleteDeclarator(Scope *S, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { } + /// \brief Code completion for a member access expression. /// /// This code completion action is invoked when the code-completion token diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 82ea46c290c..aadc4592f27 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -164,7 +164,12 @@ public: /// is expected. CCC_Namespace, /// \brief Code completion occurred where a type name is expected. - CCC_Type + CCC_Type, + /// \brief Code completion occurred where a new name is expected. + CCC_Name, + /// \brief Code completion occurred where a new name is expected and a + /// qualified name is permissible. + CCC_PotentiallyQualifiedName }; private: diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0bd672f5d12..a8a3562a539 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4640,6 +4640,9 @@ public: //@{ virtual void CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext); + virtual void CodeCompleteDeclarator(Scope *S, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers); virtual void CodeCompleteExpression(Scope *S, QualType T, bool IntegralConstantExpression = false); virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 9aa9f5b6cca..c7d47309cfe 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -235,7 +235,8 @@ void ASTUnit::CacheCodeCompletionResults() { | (1 << (CodeCompletionContext::CCC_EnumTag - 1)) | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)) - | (1 << (CodeCompletionContext::CCC_Type - 1)); + | (1 << (CodeCompletionContext::CCC_Type - 1)) + | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1)); if (isa<NamespaceDecl>(Results[I].Declaration) || isa<NamespaceAliasDecl>(Results[I].Declaration)) @@ -275,7 +276,10 @@ void ASTUnit::CacheCodeCompletionResults() { | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) | (1 << (CodeCompletionContext::CCC_Statement - 1)) | (1 << (CodeCompletionContext::CCC_Expression - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_Name - 1)) + | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1)); + CachedResult.Priority = Results[I].Priority; CachedResult.Kind = Results[I].CursorKind; CachedResult.TypeClass = STC_Void; @@ -1532,6 +1536,8 @@ void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_MemberAccess: case CodeCompletionContext::CCC_Namespace: case CodeCompletionContext::CCC_Type: + case CodeCompletionContext::CCC_Name: + case CodeCompletionContext::CCC_PotentiallyQualifiedName: break; case CodeCompletionContext::CCC_EnumTag: diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 371d8ad02e8..8265f3701e6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -853,21 +853,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, - DeclSpecContext DSContext) { - if (Tok.is(tok::code_completion)) { - Action::ParserCompletionContext CCC = Action::PCC_Namespace; - if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) - CCC = DSContext == DSC_class? Action::PCC_MemberTemplate - : Action::PCC_Template; - else if (DSContext == DSC_class) - CCC = Action::PCC_Class; - else if (ObjCImpDecl) - CCC = Action::PCC_ObjCImplementation; - - Actions.CodeCompleteOrdinaryName(getCurScope(), CCC); - ConsumeCodeCompletionToken(); - } - + DeclSpecContext DSContext) { DS.SetRangeStart(Tok.getLocation()); while (1) { bool isInvalid = false; @@ -884,6 +870,38 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DS.Finish(Diags, PP); return; + case tok::code_completion: { + Action::ParserCompletionContext CCC = Action::PCC_Namespace; + if (DS.hasTypeSpecifier()) { + bool AllowNonIdentifiers + = (getCurScope()->getFlags() & (Scope::ControlScope | + Scope::BlockScope | + Scope::TemplateParamScope | + Scope::FunctionPrototypeScope | + Scope::AtCatchScope)) == 0; + bool AllowNestedNameSpecifiers + = DSContext == DSC_top_level || + (DSContext == DSC_class && DS.isFriendSpecified()); + + Actions.CodeCompleteDeclarator(getCurScope(), AllowNonIdentifiers, + AllowNestedNameSpecifiers); + ConsumeCodeCompletionToken(); + return; + } + + if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) + CCC = DSContext == DSC_class? Action::PCC_MemberTemplate + : Action::PCC_Template; + else if (DSContext == DSC_class) + CCC = Action::PCC_Class; + else if (ObjCImpDecl) + CCC = Action::PCC_ObjCImplementation; + + Actions.CodeCompleteOrdinaryName(getCurScope(), CCC); + ConsumeCodeCompletionToken(); + return; + } + case tok::coloncolon: // ::foo::bar // C++ scope specifier. Annotate and loop, or bail out on error. if (TryAnnotateCXXScopeToken(true)) { @@ -2501,6 +2519,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser) { if (Diags.hasAllExtensionsSilenced()) D.setExtension(); + // C++ member pointers start with a '::' or a nested-name. // Member pointers get special handling, since there's no place for the // scope spec in the generic path below. diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 1b456edeecc..aafe9996d4d 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -774,9 +774,9 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) { /// __attribute__((unused)) /// Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, - tok::TokenKind mType, - Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind) { + tok::TokenKind mType, + Decl *IDecl, + tok::ObjCKeywordKind MethodImplKind) { ParsingDeclRAIIObject PD(*this); if (Tok.is(tok::code_completion)) { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 34d0c4aa390..bdcc3ac5466 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -2222,7 +2222,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, void Sema::CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext) { typedef CodeCompleteConsumer::Result Result; - ResultBuilder Results(*this); + ResultBuilder Results(*this); // Determine how to filter results, e.g., so that the names of // values (functions, enumerators, function templates, etc.) are @@ -2268,6 +2268,45 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, Results.data(),Results.size()); } +void Sema::CodeCompleteDeclarator(Scope *S, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Type qualifiers can come after names. + Results.AddResult(Result("const")); + Results.AddResult(Result("volatile")); + if (getLangOptions().C99) + Results.AddResult(Result("restrict")); + + if (getLangOptions().CPlusPlus) { + if (AllowNonIdentifiers) { + Results.AddResult(Result("operator")); + } + + // Add nested-name-specifiers. + if (AllowNestedNameSpecifiers) { + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals()); + } + } + Results.ExitScope(); + + // Allow macros for names. + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, + AllowNestedNameSpecifiers + ? CodeCompletionContext::CCC_PotentiallyQualifiedName + : CodeCompletionContext::CCC_Name, + Results.data(), Results.size()); +} + /// \brief Perform code-completion in an expression context when we know what /// type we're looking for. /// diff --git a/clang/test/Index/complete-declarators.cpp b/clang/test/Index/complete-declarators.cpp new file mode 100644 index 00000000000..ba16e22ec1f --- /dev/null +++ b/clang/test/Index/complete-declarators.cpp @@ -0,0 +1,39 @@ +// This test is line- and column-sensitive, so test commands are at the bottom. +namespace N { + struct X { + int f(X); + }; +} + +int g(int a); + +struct Y { }; + +struct Z { + int member; + friend int N::X::f(N::X); +}; + +// RUN: c-index-test -code-completion-at=%s:8:5 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: NotImplemented:{TypedText const} (30) +// CHECK-CC1: NotImplemented:{TypedText N}{Text ::} (75) +// CHECK-CC1: NotImplemented:{TypedText operator} (30) +// CHECK-CC1: NotImplemented:{TypedText volatile} (30) +// RUN: c-index-test -code-completion-at=%s:8:11 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: NotImplemented:{TypedText const} (30) +// CHECK-CC2-NOT: NotImplemented:{TypedText N}{Text ::} (75) +// CHECK-CC2-NOT: NotImplemented:{TypedText operator} (30) +// CHECK-CC2: NotImplemented:{TypedText volatile} (30) +// RUN: c-index-test -code-completion-at=%s:13:7 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: NotImplemented:{TypedText const} (30) +// CHECK-CC3-NOT: NotImplemented:{TypedText N}{Text ::} (75) +// CHECK-CC3: NotImplemented:{TypedText operator} (30) +// CHECK-CC3: NotImplemented:{TypedText volatile} (30) +// RUN: c-index-test -code-completion-at=%s:14:14 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: NotImplemented:{TypedText const} (30) +// CHECK-CC4: NotImplemented:{TypedText N}{Text ::} (75) +// CHECK-CC4: NotImplemented:{TypedText operator} (30) +// CHECK-CC4: NotImplemented:{TypedText volatile} (30) +// CHECK-CC4: StructDecl:{TypedText Y} (40) +// CHECK-CC4: StructDecl:{TypedText Z} (20) + diff --git a/clang/test/Index/complete-declarators.m b/clang/test/Index/complete-declarators.m new file mode 100644 index 00000000000..d2c3f61cd8a --- /dev/null +++ b/clang/test/Index/complete-declarators.m @@ -0,0 +1,29 @@ +// This test is line- and column-sensitive, so test commands are at the bottom. +@protocol P +- (int)method:(id)param1; +@end + +@interface A <P> +- (int)method:(id)param1; + +@property int prop1; +@end + +@implementation A +- (int)method:(id)param1 { + for(id x in param1) { + int y; + } +} +@end + +// RUN: c-index-test -code-completion-at=%s:7:19 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1-NOT: NotImplemented:{TypedText extern} (30) +// CHECK-CC1: NotImplemented:{TypedText param1} (30) +// RUN: c-index-test -code-completion-at=%s:9:15 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: c-index-test -code-completion-at=%s:14:10 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: c-index-test -code-completion-at=%s:15:9 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: NotImplemented:{TypedText const} (30) +// CHECK-CC2-NOT: int +// CHECK-CC2: NotImplemented:{TypedText restrict} (30) +// CHECK-CC2: NotImplemented:{TypedText volatile} (30) |