https://github.com/Lancern updated https://github.com/llvm/llvm-project/pull/75937
>From 6e5e6986559a8d8a72901baf60cbc3b9163a7cd7 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Tue, 19 Dec 2023 22:24:23 +0800 Subject: [PATCH 1/3] [clangd][Sema] add noexcept to override functions during code completion --- .../test/completion-override-except-spec.test | 69 +++++++++++++++++++ clang/lib/Sema/SemaCodeComplete.cpp | 22 ++++++ 2 files changed, 91 insertions(+) create mode 100644 clang-tools-extra/clangd/test/completion-override-except-spec.test diff --git a/clang-tools-extra/clangd/test/completion-override-except-spec.test b/clang-tools-extra/clangd/test/completion-override-except-spec.test new file mode 100644 index 00000000000000..19c7f84bc679d8 --- /dev/null +++ b/clang-tools-extra/clangd/test/completion-override-except-spec.test @@ -0,0 +1,69 @@ +# RUN: clangd -lit-test < %s | FileCheck %s +# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck %s +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +--- +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Base {\n virtual void virt_method() noexcept = 0;\n};\n\nstruct Derived : Base {\n virt_\n};"}}} +--- +{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":5,"character":6}}} +# CHECK: "id": 1, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": false, +# CHECK-NEXT: "items": [ +# CHECK-NEXT: { +# CHECK-NEXT: "filterText": "virt_method() noexcept override", +# CHECK-NEXT: "insertText": "void virt_method() noexcept override", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 2, +# CHECK-NEXT: "label": " void virt_method() noexcept override", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}virt_method() noexcept override", +# CHECK-NEXT: "textEdit": { +# CHECK-NEXT: "newText": "void virt_method() noexcept override", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 6, +# CHECK-NEXT: "line": 5 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 2, +# CHECK-NEXT: "line": 5 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: }, +--- +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp","version":2},"contentChanges":[{"text":"struct Base {\n virtual void virt_method() = 0;\n};\n\nstruct Derived : Base {\n virt_\n};"}]}} +--- +{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":5,"character":6}}} +# CHECK: "id": 3, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": false, +# CHECK-NEXT: "items": [ +# CHECK-NEXT: { +# CHECK-NEXT: "filterText": "virt_method() override", +# CHECK-NEXT: "insertText": "void virt_method() override", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 2, +# CHECK-NEXT: "label": " void virt_method() override", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}virt_method() override", +# CHECK-NEXT: "textEdit": { +# CHECK-NEXT: "newText": "void virt_method() override", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 6, +# CHECK-NEXT: "line": 5 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 2, +# CHECK-NEXT: "line": 5 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: }, +--- +{"jsonrpc":"2.0","id":4,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index c44be0df9b0a85..516936311a278d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -25,6 +25,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/HeaderSearch.h" @@ -3292,6 +3293,25 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); } +static void +AddFunctionExceptSpecToCompletionString(CodeCompletionBuilder &Result, + const FunctionDecl *Function) { + const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); + if (!Proto) + return; + + auto ExceptInfo = Proto->getExceptionSpecInfo(); + switch (ExceptInfo.Type) { + case EST_BasicNoexcept: + case EST_NoexceptTrue: + Result.AddInformativeChunk(" noexcept"); + break; + + default: + break; + } +} + /// Add the name of the given declaration static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, const NamedDecl *ND, @@ -3560,6 +3580,7 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); + AddFunctionExceptSpecToCompletionString(Result, Function); }; if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { @@ -3642,6 +3663,7 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); + AddFunctionExceptSpecToCompletionString(Result, Function); return Result.TakeString(); } >From 71022ee5893d91b2c2274bfa924938264d457032 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Thu, 21 Dec 2023 23:24:28 +0800 Subject: [PATCH 2/3] Move tests to clang/test/CodeCompletion/overrides.cpp --- .../test/completion-override-except-spec.test | 69 ------------------- clang/test/CodeCompletion/overrides.cpp | 14 ++++ 2 files changed, 14 insertions(+), 69 deletions(-) delete mode 100644 clang-tools-extra/clangd/test/completion-override-except-spec.test diff --git a/clang-tools-extra/clangd/test/completion-override-except-spec.test b/clang-tools-extra/clangd/test/completion-override-except-spec.test deleted file mode 100644 index 19c7f84bc679d8..00000000000000 --- a/clang-tools-extra/clangd/test/completion-override-except-spec.test +++ /dev/null @@ -1,69 +0,0 @@ -# RUN: clangd -lit-test < %s | FileCheck %s -# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck %s -{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} ---- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Base {\n virtual void virt_method() noexcept = 0;\n};\n\nstruct Derived : Base {\n virt_\n};"}}} ---- -{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":5,"character":6}}} -# CHECK: "id": 1, -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK-NEXT: { -# CHECK-NEXT: "filterText": "virt_method() noexcept override", -# CHECK-NEXT: "insertText": "void virt_method() noexcept override", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": " void virt_method() noexcept override", -# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, -# CHECK-NEXT: "sortText": "{{.*}}virt_method() noexcept override", -# CHECK-NEXT: "textEdit": { -# CHECK-NEXT: "newText": "void virt_method() noexcept override", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 6, -# CHECK-NEXT: "line": 5 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 2, -# CHECK-NEXT: "line": 5 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT: }, ---- -{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp","version":2},"contentChanges":[{"text":"struct Base {\n virtual void virt_method() = 0;\n};\n\nstruct Derived : Base {\n virt_\n};"}]}} ---- -{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":5,"character":6}}} -# CHECK: "id": 3, -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK-NEXT: { -# CHECK-NEXT: "filterText": "virt_method() override", -# CHECK-NEXT: "insertText": "void virt_method() override", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": " void virt_method() override", -# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, -# CHECK-NEXT: "sortText": "{{.*}}virt_method() override", -# CHECK-NEXT: "textEdit": { -# CHECK-NEXT: "newText": "void virt_method() override", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 6, -# CHECK-NEXT: "line": 5 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 2, -# CHECK-NEXT: "line": 5 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT: }, ---- -{"jsonrpc":"2.0","id":4,"method":"shutdown"} ---- -{"jsonrpc":"2.0","method":"exit"} diff --git a/clang/test/CodeCompletion/overrides.cpp b/clang/test/CodeCompletion/overrides.cpp index 7f330904eede98..0a12973f846b75 100644 --- a/clang/test/CodeCompletion/overrides.cpp +++ b/clang/test/CodeCompletion/overrides.cpp @@ -41,3 +41,17 @@ void func() { // Runs completion at empty line on line 37. // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-5):1 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s // CHECK-CC4: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}} + +class NoexceptBase { + public: + virtual void method() noexcept; +}; + +class NoexceptDerived : public NoexceptBase { + public: + met; +}; + +// Runs completion at met^ on line 52. +// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-4):6 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC5: COMPLETION: Pattern : void method() noexcept override{{$}} >From c40dbbb7b609a0a3b2051d1af7a6789fb3f1302b Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Fri, 22 Dec 2023 20:44:14 +0800 Subject: [PATCH 3/3] Add noexcept to decl in override code completion --- clang/lib/Sema/SemaCodeComplete.cpp | 63 +++++++++++++++-------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 516936311a278d..f3d5ee1ba67825 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -184,7 +184,7 @@ class ResultBuilder { /// Overloaded C++ member functions found by SemaLookup. /// Used to determine when one overload is dominated by another. - llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry> + llvm::DenseMap<std::pair<DeclContext *, /*Name*/ uintptr_t>, ShadowMapEntry> OverloadMap; /// If we're potentially referring to a C++ member function, the set @@ -1426,16 +1426,16 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, } // Detect cases where a ref-qualified method cannot be invoked. switch (Method->getRefQualifier()) { - case RQ_LValue: - if (ObjectKind != VK_LValue && !MethodQuals.hasConst()) - return; - break; - case RQ_RValue: - if (ObjectKind == VK_LValue) - return; - break; - case RQ_None: - break; + case RQ_LValue: + if (ObjectKind != VK_LValue && !MethodQuals.hasConst()) + return; + break; + case RQ_RValue: + if (ObjectKind == VK_LValue) + return; + break; + case RQ_None: + break; } /// Check whether this dominates another overloaded method, which should @@ -1483,9 +1483,7 @@ void ResultBuilder::AddResult(Result R) { void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); } /// Exit from the current scope. -void ResultBuilder::ExitScope() { - ShadowMaps.pop_back(); -} +void ResultBuilder::ExitScope() { ShadowMaps.pop_back(); } /// Determines whether this given declaration will be found by /// ordinary name lookup. @@ -2468,7 +2466,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, ReturnType = Method->getReturnType(); else if (SemaRef.getCurBlock() && !SemaRef.getCurBlock()->ReturnType.isNull()) - ReturnType = SemaRef.getCurBlock()->ReturnType;; + ReturnType = SemaRef.getCurBlock()->ReturnType; + ; if (ReturnType.isNull() || ReturnType->isVoidType()) { Builder.AddTypedTextChunk("return"); Builder.AddChunk(CodeCompletionString::CK_SemiColon); @@ -3294,7 +3293,7 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, } static void -AddFunctionExceptSpecToCompletionString(CodeCompletionBuilder &Result, +AddFunctionExceptSpecToCompletionString(std::string &NameAndSignature, const FunctionDecl *Function) { const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); if (!Proto) @@ -3304,7 +3303,7 @@ AddFunctionExceptSpecToCompletionString(CodeCompletionBuilder &Result, switch (ExceptInfo.Type) { case EST_BasicNoexcept: case EST_NoexceptTrue: - Result.AddInformativeChunk(" noexcept"); + NameAndSignature += " noexcept"; break; default: @@ -3527,6 +3526,13 @@ CodeCompletionResult::createCodeCompletionStringForOverride( std::string NameAndSignature; // For overrides all chunks go into the result, none are informative. printOverrideString(*CCS, BeforeName, NameAndSignature); + + // If the virtual function is declared with "noexcept", add it in the result + // code completion string. + const auto *VirtualFunc = dyn_cast<FunctionDecl>(Declaration); + assert(VirtualFunc && "overridden decl must be a function"); + AddFunctionExceptSpecToCompletionString(NameAndSignature, VirtualFunc); + NameAndSignature += " override"; Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName)); @@ -3580,7 +3586,6 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); - AddFunctionExceptSpecToCompletionString(Result, Function); }; if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { @@ -3663,7 +3668,6 @@ CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); - AddFunctionExceptSpecToCompletionString(Result, Function); return Result.TakeString(); } @@ -4770,7 +4774,8 @@ static void AddEnumerators(ResultBuilder &Results, ASTContext &Context, EnumDecl *Enum, DeclContext *CurContext, const CoveredEnumerators &Enumerators) { NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier; - if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) { + if (Context.getLangOpts().CPlusPlus && !Qualifier && + Enumerators.Seen.empty()) { // If there are no prior enumerators in C++, check whether we have to // qualify the names of the enumerators that we suggest, because they // may not be visible in this scope. @@ -5173,8 +5178,7 @@ AddObjCProperties(const CodeCompletionContext &CCContext, AllowNullaryMethods, CurContext, AddedProperties, Results, IsBaseExprStatement, IsClassProperty, /*InOriginalClass*/ false); - } else if (const auto *Category = - dyn_cast<ObjCCategoryDecl>(Container)) { + } else if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { // Look through protocols. for (auto *P : Category->protocols()) AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, @@ -6032,8 +6036,7 @@ void Sema::CodeCompleteCase(Scope *S) { Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal)) - if (auto *Enumerator = - dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + if (auto *Enumerator = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { // We look into the AST of the case statement to determine which // enumerator was named. Alternatively, we could compute the value of // the integral constant expression, then compare it against the @@ -8260,11 +8263,10 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; RecExpr = Conv.get(); } - QualType ReceiverType = RecExpr - ? RecExpr->getType() - : Super ? Context.getObjCObjectPointerType( - Context.getObjCInterfaceType(Super)) - : Context.getObjCIdType(); + QualType ReceiverType = RecExpr ? RecExpr->getType() + : Super ? Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(Super)) + : Context.getObjCIdType(); // If we're messaging an expression with type "id" or "Class", check // whether we know something special about the receiver that allows @@ -10113,8 +10115,7 @@ void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { }; // Helper: scans IncludeDir for nice files, and adds results for each. - auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, - bool IsSystem, + auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem, DirectoryLookup::LookupType_t LookupType) { llvm::SmallString<128> Dir = IncludeDir; if (!NativeRelDir.empty()) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits