r295001 - [CodeCompletion] Code complete the missing C++11 keywords
Alex Lorenz via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 13 15:19:40 PST 2017
Author: arphaman
Date: Mon Feb 13 17:19:40 2017
New Revision: 295001
URL: http://llvm.org/viewvc/llvm-project?rev=295001&view=rev
Log:
[CodeCompletion] Code complete the missing C++11 keywords
This commit adds context sensitive code completion support for the C++11
keywords that currently don't have completion results.
The following keywords are supported by this patch:
alignas
constexpr
static_assert
noexcept (as a function/method qualifier)
thread_local
The following special identifiers are also supported:
final (as a method qualifier or class qualifier)
override
rdar://29219185
Differential Revision: https://reviews.llvm.org/D28286
Added:
cfe/trunk/test/CodeCompletion/keywords.cpp
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/test/CodeCompletion/ordinary-name-cxx11.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Feb 13 17:19:40 2017
@@ -2385,10 +2385,10 @@ private:
AR_DeclspecAttributesParsed
};
- void ParseTypeQualifierListOpt(DeclSpec &DS,
- unsigned AttrReqs = AR_AllAttributesParsed,
- bool AtomicAllowed = true,
- bool IdentifierRequired = false);
+ void ParseTypeQualifierListOpt(
+ DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed,
+ bool AtomicAllowed = true, bool IdentifierRequired = false,
+ Optional<llvm::function_ref<void()>> CodeCompletionHandler = None);
void ParseDirectDeclarator(Declarator &D);
void ParseDecompositionDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 13 17:19:40 2017
@@ -9820,6 +9820,8 @@ public:
void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
void CodeCompleteTag(Scope *S, unsigned TagSpec);
void CodeCompleteTypeQualifiers(DeclSpec &DS);
+ void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
+ const VirtSpecifiers *VS = nullptr);
void CodeCompleteBracketDeclarator(Scope *S);
void CodeCompleteCase(Scope *S);
void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Feb 13 17:19:40 2017
@@ -4802,9 +4802,10 @@ bool Parser::isConstructorDeclarator(boo
/// [ only if AttReqs & AR_CXX11AttributesParsed ]
/// Note: vendor can be GNU, MS, etc and can be explicitly controlled via
/// AttrRequirements bitmask values.
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
- bool AtomicAllowed,
- bool IdentifierRequired) {
+void Parser::ParseTypeQualifierListOpt(
+ DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
+ bool IdentifierRequired,
+ Optional<llvm::function_ref<void()>> CodeCompletionHandler) {
if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) &&
isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -4822,7 +4823,10 @@ void Parser::ParseTypeQualifierListOpt(D
switch (Tok.getKind()) {
case tok::code_completion:
- Actions.CodeCompleteTypeQualifiers(DS);
+ if (CodeCompletionHandler)
+ (*CodeCompletionHandler)();
+ else
+ Actions.CodeCompleteTypeQualifiers(DS);
return cutOffParsing();
case tok::kw_const:
@@ -5748,7 +5752,11 @@ void Parser::ParseFunctionDeclarator(Dec
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
- /*AtomicAllowed*/ false);
+ /*AtomicAllowed*/ false,
+ /*IdentifierRequired=*/false,
+ llvm::function_ref<void()>([&]() {
+ Actions.CodeCompleteFunctionQualifiers(DS, D);
+ }));
if (!DS.getSourceRange().getEnd().isInvalid()) {
EndLoc = DS.getSourceRange().getEnd();
ConstQualifierLoc = DS.getConstSpecLoc();
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Feb 13 17:19:40 2017
@@ -2285,7 +2285,11 @@ void Parser::MaybeParseAndDiagnoseDeclSp
// GNU-style and C++11 attributes are not allowed here, but they will be
// handled by the caller. Diagnose everything else.
- ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false);
+ ParseTypeQualifierListOpt(
+ DS, AR_NoAttributesParsed, false,
+ /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {
+ Actions.CodeCompleteFunctionQualifiers(DS, D, &VS);
+ }));
D.ExtendWithDeclSpec(DS);
if (D.isFunctionDeclarator()) {
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Feb 13 17:19:40 2017
@@ -1370,6 +1370,21 @@ static void AddStorageSpecifiers(Sema::P
// in C++0x as a type specifier.
Results.AddResult(Result("extern"));
Results.AddResult(Result("static"));
+
+ if (LangOpts.CPlusPlus11) {
+ CodeCompletionAllocator &Allocator = Results.getAllocator();
+ CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
+
+ // alignas
+ Builder.AddTypedTextChunk("alignas");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ Results.AddResult(Result("constexpr"));
+ Results.AddResult(Result("thread_local"));
+ }
}
static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
@@ -1527,6 +1542,21 @@ static void addThisCompletion(Sema &S, R
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
+static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
+ ResultBuilder &Results,
+ const LangOptions &LangOpts) {
+ if (!LangOpts.CPlusPlus11)
+ return;
+
+ Builder.AddTypedTextChunk("static_assert");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_Comma);
+ Builder.AddPlaceholderChunk("message");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+}
+
/// \brief Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
@@ -1611,6 +1641,8 @@ static void AddOrdinaryNameResults(Sema:
Results.AddResult(Result(Builder.TakeString()));
}
+ AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
+
if (CCC == Sema::PCC_Class) {
AddTypedefResult(Results);
@@ -1824,6 +1856,8 @@ static void AddOrdinaryNameResults(Sema:
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("identifier");
Results.AddResult(Result(Builder.TakeString()));
+
+ AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
}
// Fall through (for statement expressions).
@@ -3483,6 +3517,11 @@ void Sema::CodeCompleteDeclSpec(Scope *S
Results.AddResult(Result("restrict"));
if (getLangOpts().CPlusPlus) {
+ if (getLangOpts().CPlusPlus11 &&
+ (DS.getTypeSpecType() == DeclSpec::TST_class ||
+ DS.getTypeSpecType() == DeclSpec::TST_struct))
+ Results.AddResult("final");
+
if (AllowNonIdentifiers) {
Results.AddResult(Result("operator"));
}
@@ -4013,30 +4052,54 @@ void Sema::CodeCompleteTag(Scope *S, uns
Results.data(),Results.size());
}
-void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
- ResultBuilder Results(*this, CodeCompleter->getAllocator(),
- CodeCompleter->getCodeCompletionTUInfo(),
- CodeCompletionContext::CCC_TypeQualifiers);
- Results.EnterNewScope();
+static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
+ const LangOptions &LangOpts) {
if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
Results.AddResult("const");
if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
Results.AddResult("volatile");
- if (getLangOpts().C99 &&
- !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
+ if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
Results.AddResult("restrict");
- if (getLangOpts().C11 &&
- !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
+ if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
Results.AddResult("_Atomic");
- if (getLangOpts().MSVCCompat &&
- !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
+ if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
Results.AddResult("__unaligned");
+}
+
+void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext::CCC_TypeQualifiers);
+ Results.EnterNewScope();
+ AddTypeQualifierResults(DS, Results, LangOpts);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
Results.getCompletionContext(),
Results.data(), Results.size());
}
+void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
+ const VirtSpecifiers *VS) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(),
+ CodeCompletionContext::CCC_TypeQualifiers);
+ Results.EnterNewScope();
+ AddTypeQualifierResults(DS, Results, LangOpts);
+ if (LangOpts.CPlusPlus11) {
+ Results.AddResult("noexcept");
+ if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
+ !D.isStaticMember()) {
+ if (!VS || !VS->isFinalSpecified())
+ Results.AddResult("final");
+ if (!VS || !VS->isOverrideSpecified())
+ Results.AddResult("override");
+ }
+ }
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
void Sema::CodeCompleteBracketDeclarator(Scope *S) {
CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
}
Added: cfe/trunk/test/CodeCompletion/keywords.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/keywords.cpp?rev=295001&view=auto
==============================================================================
--- cfe/trunk/test/CodeCompletion/keywords.cpp (added)
+++ cfe/trunk/test/CodeCompletion/keywords.cpp Mon Feb 13 17:19:40 2017
@@ -0,0 +1,79 @@
+int function(int x) {
+ return x + 1;
+}
+
+int variable = 0;
+
+class Class {
+public:
+ Class() { }
+
+ int method(int x) {
+ return x + 1;
+ }
+
+ virtual void virtualMethod() {
+ }
+
+ static void staticMethod() {
+ }
+
+ static int staticVar;
+};
+
+class SubClass : public Class {
+ void virtualMethod() override final {
+ }
+};
+
+struct Struct {
+};
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:1:1 %s | FileCheck --check-prefix=CHECK-TOP-LEVEL %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:5:1 %s | FileCheck --check-prefix=CHECK-TOP-LEVEL %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:11:1 %s | FileCheck --check-prefix=CHECK-TOP-LEVEL %s
+// CHECK-TOP-LEVEL: alignas(<#expression#>)
+// CHECK-TOP-LEVEL: constexpr
+// CHECK-TOP-LEVEL: static_assert(<#expression#>, <#message#>)
+// CHECK-TOP-LEVEL: thread_local
+// CHECK-TOP-LEVEL-NOT: final
+// CHECK-TOP-LEVEL-NOT: noexcept
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:1:14 %s | FileCheck --check-prefix=CHECK-PARAM %s
+// CHECK-PARAM-NOT: alignas
+// CHECK-PARAM-NOT: constexpr
+// CHECK-PARAM-NOT: final
+// CHECK-PARAM-NOT: thread_local
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:21:10 %s | FileCheck --check-prefix=CHECK-STATICVAR1 %s
+// CHECK-STATICVAR1: constexpr
+// CHECK-STATICVAR1: thread_local
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:7:13 %s | FileCheck --check-prefix=CHECK-CLASS-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:24:16 %s | FileCheck --check-prefix=CHECK-CLASS-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:29:15 %s | FileCheck --check-prefix=CHECK-CLASS-QUALIFIER %s
+// CHECK-CLASS-QUALIFIER: final
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:1:21 %s | FileCheck --check-prefix=CHECK-FUNCTION-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:9:11 %s | FileCheck --check-prefix=CHECK-FUNCTION-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:18:30 %s | FileCheck --check-prefix=CHECK-FUNCTION-QUALIFIER %s
+// CHECK-FUNCTION-QUALIFIER: noexcept
+// CHECK-FUNCTION-QUALIFIER-NOT: final
+// CHECK-FUNCTION-QUALIFIER-NOT: override
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:11:21 %s | FileCheck --check-prefix=CHECK-METHOD-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:15:32 %s | FileCheck --check-prefix=CHECK-METHOD-QUALIFIER %s
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:25:24 %s | FileCheck --check-prefix=CHECK-METHOD-QUALIFIER %s
+// CHECK-METHOD-QUALIFIER: final
+// CHECK-METHOD-QUALIFIER: noexcept
+// CHECK-METHOD-QUALIFIER: override
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:25:33 %s | FileCheck --check-prefix=CHECK-OVERRIDE-SPECIFIED %s
+// CHECK-OVERRIDE-SPECIFIED: final
+// CHECK-OVERRIDE-SPECIFIED: noexcept
+// CHECK-OVERRIDE-SPECIFIED-NOT: override
+
+// RUN: %clang_cc1 -std=c++11 -code-completion-at=%s:25:39 %s | FileCheck --check-prefix=CHECK-OVERRIDE-FINAL-SPECIFIED %s
+// CHECK-OVERRIDE-FINAL-SPECIFIED: noexcept
+// CHECK-OVERRIDE-FINAL-SPECIFIED-NOT: final
+// CHECK-OVERRIDE-FINAL-SPECIFIED-NOT: override
Modified: cfe/trunk/test/CodeCompletion/ordinary-name-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/ordinary-name-cxx11.cpp?rev=295001&r1=295000&r2=295001&view=diff
==============================================================================
--- cfe/trunk/test/CodeCompletion/ordinary-name-cxx11.cpp (original)
+++ cfe/trunk/test/CodeCompletion/ordinary-name-cxx11.cpp Mon Feb 13 17:19:40 2017
@@ -39,10 +39,12 @@ void foo() {
// CHECK-CC1-NEXT: COMPLETION: Pattern : [#size_t#]sizeof(<#expression-or-type#>)
// CHECK-CC1-NEXT: COMPLETION: Pattern : [#size_t#]sizeof...(<#parameter-pack#>)
// CHECK-CC1-NEXT: COMPLETION: static
+ // CHECK-CC1-NEXT: COMPLETION: Pattern : static_assert(<#expression#>, <#message#>)
// CHECK-CC1-NEXT: COMPLETION: Pattern : static_cast<<#type#>>(<#expression#>)
// CHECK-CC1-NEXT: COMPLETION: struct
// CHECK-CC1-NEXT: COMPLETION: Pattern : switch(<#condition#>){
// CHECK-CC1: COMPLETION: t : t
+ // CHECK-CC1-NEXT: COMPLETION: thread_local
// CHECK-CC1-NEXT: COMPLETION: Pattern : [#void#]throw <#expression#>
// CHECK-CC1-NEXT: COMPLETION: Pattern : [#bool#]true
// CHECK-CC1-NEXT: COMPLETION: Pattern : try{<#statements#>
@@ -72,6 +74,7 @@ void foo() {
// CHECK-CC2-NEXT: COMPLETION: char32
// CHECK-CC2-NEXT: COMPLETION: class
// CHECK-CC2-NEXT: COMPLETION: const
+ // CHECK-CC2-NEXT: COMPLETION: constexpr
// CHECK-CC2-NEXT: COMPLETION: Pattern : decltype(<#expression#>)
// CHECK-CC2-NEXT: COMPLETION: double
// CHECK-CC2-NEXT: COMPLETION: enum
@@ -86,10 +89,12 @@ void foo() {
// CHECK-CC2-NEXT: COMPLETION: short
// CHECK-CC2-NEXT: COMPLETION: signed
// CHECK-CC2-NEXT: COMPLETION: static
+ // CHECK-CC2-NEXT: COMPLETION: Pattern : static_assert(<#expression#>, <#message#>)
// CHECK-CC2-NEXT: COMPLETION: struct
// CHECK-CC2-NEXT: COMPLETION: t : t
// CHECK-CC2-NEXT: COMPLETION: Pattern : template <#declaration#>
// CHECK-CC2-NEXT: COMPLETION: Pattern : template<<#parameters#>>
+ // CHECK-CC2-NEXT: COMPLETION: thread_local
// CHECK-CC2-NEXT: COMPLETION: TYPEDEF : TYPEDEF
// CHECK-CC2-NEXT: COMPLETION: Pattern : typedef <#type#> <#name#>
// CHECK-CC2-NEXT: COMPLETION: Pattern : typename <#qualifier#>::<#name#>
@@ -111,6 +116,7 @@ void foo() {
// CHECK-CC3-NEXT: COMPLETION: char32_t
// CHECK-CC3-NEXT: COMPLETION: class
// CHECK-CC3-NEXT: COMPLETION: const
+ // CHECK-CC3-NEXT: COMPLETION: constexpr
// CHECK-CC3-NEXT: COMPLETION: Pattern : decltype(<#expression#>)
// CHECK-CC3-NEXT: COMPLETION: double
// CHECK-CC3-NEXT: COMPLETION: enum
@@ -129,8 +135,10 @@ void foo() {
// CHECK-CC3-NEXT: COMPLETION: short
// CHECK-CC3-NEXT: COMPLETION: signed
// CHECK-CC3-NEXT: COMPLETION: static
+ // CHECK-CC3-NEXT: COMPLETION: Pattern : static_assert(<#expression#>, <#message#>)
// CHECK-CC3-NEXT: COMPLETION: struct
// CHECK-CC3-NEXT: COMPLETION: Pattern : template<<#parameters#>>
+ // CHECK-CC3-NEXT: COMPLETION: thread_local
// CHECK-CC3-NEXT: COMPLETION: Pattern : typedef <#type#> <#name#>
// CHECK-CC3-NEXT: COMPLETION: Pattern : typename <#qualifier#>::<#name#>
// CHECK-CC3-NEXT: COMPLETION: Pattern : typeof <#expression#>
@@ -227,6 +235,7 @@ void foo() {
// CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : [#size_t#]sizeof(<#expression-or-type#>)
// CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : [#size_t#]sizeof...(<#parameter-pack#>)
// CHECK-NO-RTTI-NEXT: COMPLETION: static
+ // CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : static_assert(<#expression#>, <#message#>)
// CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : static_cast<<#type#>>(<#expression#>)
// CHECK-NO-RTTI-NEXT: COMPLETION: struct
// CHECK-NO-RTTI-NEXT: COMPLETION: Pattern : switch(<#condition#>){
More information about the cfe-commits
mailing list