[clang-tools-extra] [clang] [Sema][clangd] add noexcept to override functions during code completion (PR #75937)

via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 19 06:31:51 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangd

Author: Sirui Mu (Lancern)

<details>
<summary>Changes</summary>

If a virtual function is declared with `noexcept`, functions that override this function in the derived classes must be declared with `noexcept` as well. This PR updates code completion in clang Sema. It adds `noexcept` specifier to override functions in the code completion result if the functions override a `noexcept` virtual function.

---
Full diff: https://github.com/llvm/llvm-project/pull/75937.diff


2 Files Affected:

- (added) clang-tools-extra/clangd/test/completion-override-except-spec.test (+69) 
- (modified) clang/lib/Sema/SemaCodeComplete.cpp (+22) 


``````````diff
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();
   }
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/75937


More information about the cfe-commits mailing list