[clang] [clang][CodeComplete] Add code completion for if constexpr and consteval (PR #124315)

Letu Ren via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 13 03:11:30 PDT 2025


https://github.com/FantasqueX updated https://github.com/llvm/llvm-project/pull/124315

>From e3f118c1435c0f87588c5c51ba01af1aa8136d1d Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Sat, 25 Jan 2025 01:23:52 +0800
Subject: [PATCH 01/15] [Sema] Add code completion for if constexpr

C++17 supports `if constexpr` statement. This patch implements this in
code completion.
---
 clang/include/clang/Sema/SemaCodeCompletion.h |  1 +
 clang/lib/Parse/ParseStmt.cpp                 |  8 ++++++++
 clang/lib/Sema/SemaCodeComplete.cpp           | 15 +++++++++++++++
 3 files changed, 24 insertions(+)

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index e931596c215d3..af44745d5d123 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,6 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
+  void CodeCompleteIfConstExpr(Scope *S) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index cd4504630f871..3f9900dd997ad 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1553,6 +1553,14 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
       IsConsteval = true;
       ConstevalLoc = ConsumeToken();
     }
+
+    if (Tok.is(tok::code_completion)) {
+      if (getLangOpts().CPlusPlus17) {
+        cutOffParsing();
+        Actions.CodeCompletion().CodeCompleteIfConstExpr(getCurScope());
+        return StmtError();
+      }
+    }
   }
   if (!IsConsteval && (NotLocation.isValid() || Tok.isNot(tok::l_paren))) {
     Diag(Tok, diag::err_expected_lparen_after) << "if";
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index db467d76b5d32..1a893c866a911 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,6 +6749,21 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
+void SemaCodeCompletion::CodeCompleteIfConstExpr(Scope *S) const {
+  ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_SymbolOrNewName);
+  Results.EnterNewScope();
+
+  Results.AddResult(CodeCompletionResult("constexpr"));
+
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(&SemaRef, CodeCompleter,
+                            Results.getCompletionContext(), Results.data(),
+                            Results.size());
+}
+
 void SemaCodeCompletion::CodeCompleteAfterIf(Scope *S, bool IsBracedThen) {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),

>From 5b3a919475b6c47def9bdd4c5bdf083852173b5c Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Mon, 3 Feb 2025 22:49:38 +0800
Subject: [PATCH 02/15] Add test for if constexpr completion

---
 clang/test/CodeCompletion/if-constexpr.cpp | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 clang/test/CodeCompletion/if-constexpr.cpp

diff --git a/clang/test/CodeCompletion/if-constexpr.cpp b/clang/test/CodeCompletion/if-constexpr.cpp
new file mode 100644
index 0000000000000..48a89b4799cbc
--- /dev/null
+++ b/clang/test/CodeCompletion/if-constexpr.cpp
@@ -0,0 +1,4 @@
+void test() {
+  if c
+  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:%(line-1):7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: constexpr

>From 4e0d4a7fcaf982dd41df7b5fae411f670afa3e56 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Sat, 15 Feb 2025 18:03:38 +0800
Subject: [PATCH 03/15] rename function

---
 clang/include/clang/Sema/SemaCodeCompletion.h | 2 +-
 clang/lib/Parse/ParseStmt.cpp                 | 2 +-
 clang/lib/Sema/SemaCodeComplete.cpp           | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index af44745d5d123..c79e6ec13634b 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,7 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
-  void CodeCompleteIfConstExpr(Scope *S) const;
+  void CodeCompleteIfConstexpr(Scope *S) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 3f9900dd997ad..fd7f707d87516 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1557,7 +1557,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
     if (Tok.is(tok::code_completion)) {
       if (getLangOpts().CPlusPlus17) {
         cutOffParsing();
-        Actions.CodeCompletion().CodeCompleteIfConstExpr(getCurScope());
+        Actions.CodeCompletion().CodeCompleteIfConstexpr(getCurScope());
         return StmtError();
       }
     }
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 1a893c866a911..53ad888d0d791 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,7 +6749,7 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConstExpr(Scope *S) const {
+void SemaCodeCompletion::CodeCompleteIfConstexpr(Scope *S) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_SymbolOrNewName);

>From 932ab1e33f636822ac4ecbcd445729246624aac3 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Sat, 15 Feb 2025 19:10:02 +0800
Subject: [PATCH 04/15] use CCC_Other instead

---
 clang/lib/Sema/SemaCodeComplete.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 53ad888d0d791..d402c577d22c8 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6752,11 +6752,9 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
 void SemaCodeCompletion::CodeCompleteIfConstexpr(Scope *S) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
-                        CodeCompletionContext::CCC_SymbolOrNewName);
+                        CodeCompletionContext::CCC_Other);
   Results.EnterNewScope();
-
   Results.AddResult(CodeCompletionResult("constexpr"));
-
   Results.ExitScope();
 
   HandleCodeCompleteResults(&SemaRef, CodeCompleter,

>From 2955dc9d1b1e8441b933c7267bd7385365537bc5 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Mon, 17 Feb 2025 20:48:22 +0800
Subject: [PATCH 05/15] Add consteval

---
 clang/include/clang/Sema/SemaCodeCompletion.h | 2 +-
 clang/lib/Parse/ParseStmt.cpp                 | 8 +++-----
 clang/lib/Sema/SemaCodeComplete.cpp           | 9 +++++++--
 clang/test/CodeCompletion/if-const.cpp        | 6 ++++++
 clang/test/CodeCompletion/if-constexpr.cpp    | 4 ----
 5 files changed, 17 insertions(+), 12 deletions(-)
 create mode 100644 clang/test/CodeCompletion/if-const.cpp
 delete mode 100644 clang/test/CodeCompletion/if-constexpr.cpp

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index c79e6ec13634b..b930210f5f905 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,7 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
-  void CodeCompleteIfConstexpr(Scope *S) const;
+  void CodeCompleteIfConst(Scope *S) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index fd7f707d87516..1c83697a4f421 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1555,11 +1555,9 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
     }
 
     if (Tok.is(tok::code_completion)) {
-      if (getLangOpts().CPlusPlus17) {
-        cutOffParsing();
-        Actions.CodeCompletion().CodeCompleteIfConstexpr(getCurScope());
-        return StmtError();
-      }
+      cutOffParsing();
+      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope());
+      return StmtError();
     }
   }
   if (!IsConsteval && (NotLocation.isValid() || Tok.isNot(tok::l_paren))) {
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index d402c577d22c8..5ef59b4e333a4 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,12 +6749,17 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConstexpr(Scope *S) const {
+void SemaCodeCompletion::CodeCompleteIfConst(Scope *S) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
   Results.EnterNewScope();
-  Results.AddResult(CodeCompletionResult("constexpr"));
+  if (getLangOpts().CPlusPlus17) {
+    Results.AddResult(CodeCompletionResult("constexpr"));
+  }
+  if (getLangOpts().CPlusPlus23) {
+    Results.AddResult(CodeCompletionResult("consteval"));
+  }
   Results.ExitScope();
 
   HandleCodeCompleteResults(&SemaRef, CodeCompleter,
diff --git a/clang/test/CodeCompletion/if-const.cpp b/clang/test/CodeCompletion/if-const.cpp
new file mode 100644
index 0000000000000..3c795dcc00ab9
--- /dev/null
+++ b/clang/test/CodeCompletion/if-const.cpp
@@ -0,0 +1,6 @@
+void test() {
+  if c
+  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:2:7 %s -o - | FileCheck -check-prefix=CHECK-CXX17 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:2:7 %s -o - | FileCheck -check-prefix=CHECK-CXX23 %s
+  // CHECK-CXX17: constexpr
+  // CHECK-CXX23: consteval
diff --git a/clang/test/CodeCompletion/if-constexpr.cpp b/clang/test/CodeCompletion/if-constexpr.cpp
deleted file mode 100644
index 48a89b4799cbc..0000000000000
--- a/clang/test/CodeCompletion/if-constexpr.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-void test() {
-  if c
-  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:%(line-1):7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
-  // CHECK-CC1: constexpr

>From 23196140331e0b15dd7bcb3406599af100c4aaf9 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Mon, 24 Feb 2025 01:20:45 +0800
Subject: [PATCH 06/15] support code snippet completion

---
 clang/lib/Sema/SemaCodeComplete.cpp | 31 +++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 5ef59b4e333a4..95ba8b936038c 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6753,12 +6753,39 @@ void SemaCodeCompletion::CodeCompleteIfConst(Scope *S) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
+  CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo());
   Results.EnterNewScope();
   if (getLangOpts().CPlusPlus17) {
-    Results.AddResult(CodeCompletionResult("constexpr"));
+    if (Results.includeCodePatterns()) {
+      Builder.AddTypedTextChunk("constexpr");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+      Builder.AddPlaceholderChunk("condition");
+      Builder.AddChunk(CodeCompletionString::CK_RightParen);
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult({Builder.TakeString()});
+    } else {
+      Results.AddResult({"constexpr"});
+    }
   }
   if (getLangOpts().CPlusPlus23) {
-    Results.AddResult(CodeCompletionResult("consteval"));
+    if (Results.includeCodePatterns()) {
+      Builder.AddTypedTextChunk("consteval");
+      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddPlaceholderChunk("statements");
+      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.AddResult({Builder.TakeString()});
+    } else {
+      Results.AddResult({"consteval"});
+    }
   }
   Results.ExitScope();
 

>From bdec8c22e57aa3951e28347d0968ffd30c11bea0 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Mon, 24 Feb 2025 01:25:58 +0800
Subject: [PATCH 07/15] format code

---
 clang/lib/Sema/SemaCodeComplete.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 95ba8b936038c..3e294e066bce4 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6753,7 +6753,8 @@ void SemaCodeCompletion::CodeCompleteIfConst(Scope *S) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
-  CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo());
+  CodeCompletionBuilder Builder(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
   Results.EnterNewScope();
   if (getLangOpts().CPlusPlus17) {
     if (Results.includeCodePatterns()) {

>From 19f55169aed1820be5e5306856c875b7d0ef3a73 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Tue, 25 Feb 2025 14:12:28 +0800
Subject: [PATCH 08/15] Add if not test

---
 clang/include/clang/Sema/SemaCodeCompletion.h |  2 +-
 clang/lib/Parse/ParseStmt.cpp                 |  2 +-
 clang/lib/Sema/SemaCodeComplete.cpp           | 34 ++++++++++---------
 clang/test/CodeCompletion/if-const.cpp        | 13 +++++--
 4 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index b930210f5f905..66a621f684d81 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,7 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
-  void CodeCompleteIfConst(Scope *S) const;
+  void CodeCompleteIfConst(Scope *S, bool AfterExclaim) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 1c83697a4f421..2b41552efe8f8 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1556,7 +1556,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
 
     if (Tok.is(tok::code_completion)) {
       cutOffParsing();
-      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope());
+      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope(), NotLocation.isValid());
       return StmtError();
     }
   }
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 3e294e066bce4..fe812b6e2b4d4 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,7 +6749,7 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConst(Scope *S) const {
+void SemaCodeCompletion::CodeCompleteIfConst(Scope *S, bool AfterExclaim) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
@@ -6757,21 +6757,23 @@ void SemaCodeCompletion::CodeCompleteIfConst(Scope *S) const {
                                 Results.getCodeCompletionTUInfo());
   Results.EnterNewScope();
   if (getLangOpts().CPlusPlus17) {
-    if (Results.includeCodePatterns()) {
-      Builder.AddTypedTextChunk("constexpr");
-      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
-      Builder.AddChunk(CodeCompletionString::CK_LeftParen);
-      Builder.AddPlaceholderChunk("condition");
-      Builder.AddChunk(CodeCompletionString::CK_RightParen);
-      Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
-      Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
-      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
-      Builder.AddPlaceholderChunk("statements");
-      Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
-      Builder.AddChunk(CodeCompletionString::CK_RightBrace);
-      Results.AddResult({Builder.TakeString()});
-    } else {
-      Results.AddResult({"constexpr"});
+    if (!AfterExclaim) {
+      if (Results.includeCodePatterns()) {
+        Builder.AddTypedTextChunk("constexpr");
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+        Builder.AddPlaceholderChunk("condition");
+        Builder.AddChunk(CodeCompletionString::CK_RightParen);
+        Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+        Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+        Builder.AddPlaceholderChunk("statements");
+        Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+        Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+        Results.AddResult({Builder.TakeString()});
+      } else {
+        Results.AddResult({"constexpr"});
+      }
     }
   }
   if (getLangOpts().CPlusPlus23) {
diff --git a/clang/test/CodeCompletion/if-const.cpp b/clang/test/CodeCompletion/if-const.cpp
index 3c795dcc00ab9..82311ce437321 100644
--- a/clang/test/CodeCompletion/if-const.cpp
+++ b/clang/test/CodeCompletion/if-const.cpp
@@ -1,6 +1,13 @@
+template <bool Flag>
 void test() {
-  if c
-  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:2:7 %s -o - | FileCheck -check-prefix=CHECK-CXX17 %s
-  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:2:7 %s -o - | FileCheck -check-prefix=CHECK-CXX23 %s
+  if constexpr (Flag) {
+    return;
+  }
+  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:3:7 %s -o - | FileCheck -check-prefix=CHECK-CXX17 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:3:7 %s -o - | FileCheck -check-prefix=CHECK-CXX23 %s
   // CHECK-CXX17: constexpr
   // CHECK-CXX23: consteval
+  if !c
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CHECK-CXX23-NOT %s
+  // CHECK-CXX23-NOT: consteval
+}

>From d1abbf27e53d9cc4a0bccef97b16337b43874caf Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Tue, 25 Feb 2025 14:12:58 +0800
Subject: [PATCH 09/15] format code

---
 clang/lib/Parse/ParseStmt.cpp       | 3 ++-
 clang/lib/Sema/SemaCodeComplete.cpp | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 2b41552efe8f8..244a6e2f0a6a6 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1556,7 +1556,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
 
     if (Tok.is(tok::code_completion)) {
       cutOffParsing();
-      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope(), NotLocation.isValid());
+      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope(),
+                                                   NotLocation.isValid());
       return StmtError();
     }
   }
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index fe812b6e2b4d4..112d08e212274 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,7 +6749,8 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConst(Scope *S, bool AfterExclaim) const {
+void SemaCodeCompletion::CodeCompleteIfConst(Scope *S,
+                                             bool AfterExclaim) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);

>From e3089194694d58a4b7053071454cf134f1bd0c8f Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Sat, 8 Mar 2025 00:51:41 +0800
Subject: [PATCH 10/15] Add pattern tests

---
 clang/test/CodeCompletion/if-const.cpp | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/clang/test/CodeCompletion/if-const.cpp b/clang/test/CodeCompletion/if-const.cpp
index 82311ce437321..43fef83b671f1 100644
--- a/clang/test/CodeCompletion/if-const.cpp
+++ b/clang/test/CodeCompletion/if-const.cpp
@@ -3,11 +3,24 @@ void test() {
   if constexpr (Flag) {
     return;
   }
-  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:3:7 %s -o - | FileCheck -check-prefix=CHECK-CXX17 %s
-  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:3:7 %s -o - | FileCheck -check-prefix=CHECK-CXX23 %s
-  // CHECK-CXX17: constexpr
-  // CHECK-CXX23: consteval
+  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-at=%s:3:7 %s | FileCheck -check-prefix=CHECK-CXX17 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++17 -code-completion-patterns -code-completion-at=%s:3:7 %s | FileCheck -check-prefix=CHECK-PATTERN-CXX17 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:3:7 %s | FileCheck -check-prefix=CHECK-CXX23 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-patterns -code-completion-at=%s:3:7 %s | FileCheck -check-prefix=CHECK-PATTERN-CXX23 %s
+  // CHECK-CXX17: COMPLETION: constexpr
+  // CHECK-PATTERN-CXX17: COMPLETION: Pattern : constexpr (<#condition#>) {
+  // CHECK-PATTERN-CXX17: <#statements#>
+  // CHECK-PATTERN-CXX17: }
+  // CHECK-CXX23: COMPLETION: consteval
+  // CHECK-PATTERN-CXX23: COMPLETION: Pattern : consteval {
+  // CHECK-PATTERN-CXX23: <#statements#>
+  // CHECK-PATTERN-CXX23: }
   if !c
-  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:10:8 %s -o - | FileCheck -check-prefix=CHECK-CXX23-NOT %s
-  // CHECK-CXX23-NOT: consteval
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-CXX23-EXCLAIM %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-patterns -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-PATTERN-CXX23-EXCLAIM %s
+  // CHECK-CXX23-EXCLAIM: COMPLETION: consteval
+  // CHECK-CXX23-EXCLAIM-NOT: constexpr
+  // CHECK-PATTERN-CXX23-EXCLAIM: COMPLETION: Pattern : consteval {
+  // CHECK-PATTERN-CXX23-EXCLAIM: <#statements#>
+  // CHECK-PATTERN-CXX23-EXCLAIM: }
 }

>From f49496e3116821f7f917249fbe163335e91bb8c5 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 13 Mar 2025 16:14:24 +0800
Subject: [PATCH 11/15] remove unused argument

---
 clang/include/clang/Sema/SemaCodeCompletion.h | 2 +-
 clang/lib/Parse/ParseStmt.cpp                 | 3 +--
 clang/lib/Sema/SemaCodeComplete.cpp           | 3 +--
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index 66a621f684d81..7c0eb49b38cab 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,7 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
-  void CodeCompleteIfConst(Scope *S, bool AfterExclaim) const;
+  void CodeCompleteIfConst(bool AfterExclaim) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 244a6e2f0a6a6..c778b69489c35 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1556,8 +1556,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
 
     if (Tok.is(tok::code_completion)) {
       cutOffParsing();
-      Actions.CodeCompletion().CodeCompleteIfConst(getCurScope(),
-                                                   NotLocation.isValid());
+      Actions.CodeCompletion().CodeCompleteIfConst(NotLocation.isValid());
       return StmtError();
     }
   }
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 112d08e212274..7da7454470a66 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,8 +6749,7 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConst(Scope *S,
-                                             bool AfterExclaim) const {
+void SemaCodeCompletion::CodeCompleteIfConst(bool AfterExclaim) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);

>From f67da438b89bc14a8699580a1d6b91a263889061 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 13 Mar 2025 16:21:38 +0800
Subject: [PATCH 12/15] add more tests

---
 clang/test/CodeCompletion/if-const.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang/test/CodeCompletion/if-const.cpp b/clang/test/CodeCompletion/if-const.cpp
index 43fef83b671f1..4839798faf719 100644
--- a/clang/test/CodeCompletion/if-const.cpp
+++ b/clang/test/CodeCompletion/if-const.cpp
@@ -12,12 +12,16 @@ void test() {
   // CHECK-PATTERN-CXX17: <#statements#>
   // CHECK-PATTERN-CXX17: }
   // CHECK-CXX23: COMPLETION: consteval
+  // CHECK-CXX23: COMPLETION: constexpr
   // CHECK-PATTERN-CXX23: COMPLETION: Pattern : consteval {
   // CHECK-PATTERN-CXX23: <#statements#>
   // CHECK-PATTERN-CXX23: }
+  // CHECK-PATTERN-CXX23: COMPLETION: Pattern : constexpr (<#condition#>) {
+  // CHECK-PATTERN-CXX23: <#statements#>
+  // CHECK-PATTERN-CXX23: }
   if !c
-  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-CXX23-EXCLAIM %s
-  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-patterns -code-completion-at=%s:18:8 %s -o - | FileCheck -check-prefix=CHECK-PATTERN-CXX23-EXCLAIM %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-at=%s:22:8 %s -o - | FileCheck -check-prefix=CHECK-CXX23-EXCLAIM %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++23 -code-completion-patterns -code-completion-at=%s:22:8 %s -o - | FileCheck -check-prefix=CHECK-PATTERN-CXX23-EXCLAIM %s
   // CHECK-CXX23-EXCLAIM: COMPLETION: consteval
   // CHECK-CXX23-EXCLAIM-NOT: constexpr
   // CHECK-PATTERN-CXX23-EXCLAIM: COMPLETION: Pattern : consteval {

>From ecbd1156eb5a8e224ecfae94e0bc07a7807a9ac5 Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 13 Mar 2025 16:54:04 +0800
Subject: [PATCH 13/15] rename code complete method

---
 clang/include/clang/Sema/SemaCodeCompletion.h | 2 +-
 clang/lib/Parse/ParseStmt.cpp                 | 2 +-
 clang/lib/Sema/SemaCodeComplete.cpp           | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h
index 7c0eb49b38cab..72159de3a6e72 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -152,7 +152,7 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteDesignator(const QualType BaseType,
                               llvm::ArrayRef<Expr *> InitExprs,
                               const Designation &D);
-  void CodeCompleteIfConst(bool AfterExclaim) const;
+  void CodeCompleteKeywordAfterIf(bool AfterExclaim) const;
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index c778b69489c35..a07824f500e1b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1556,7 +1556,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
 
     if (Tok.is(tok::code_completion)) {
       cutOffParsing();
-      Actions.CodeCompletion().CodeCompleteIfConst(NotLocation.isValid());
+      Actions.CodeCompletion().CodeCompleteKeywordAfterIf(NotLocation.isValid());
       return StmtError();
     }
   }
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 7da7454470a66..08bdf1a0e81e5 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6749,7 +6749,7 @@ void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {
   CodeCompleteExpression(S, Data);
 }
 
-void SemaCodeCompletion::CodeCompleteIfConst(bool AfterExclaim) const {
+void SemaCodeCompletion::CodeCompleteKeywordAfterIf(bool AfterExclaim) const {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);

>From bb6250507b04567e885b68d91e0bfe1a00f0634d Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 13 Mar 2025 17:14:40 +0800
Subject: [PATCH 14/15] move code complete in else block

---
 clang/lib/Parse/ParseStmt.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index a07824f500e1b..897494e84a63c 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1552,9 +1552,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
                                           : diag::ext_consteval_if);
       IsConsteval = true;
       ConstevalLoc = ConsumeToken();
-    }
-
-    if (Tok.is(tok::code_completion)) {
+    } else if (Tok.is(tok::code_completion)) {
       cutOffParsing();
       Actions.CodeCompletion().CodeCompleteKeywordAfterIf(NotLocation.isValid());
       return StmtError();

>From 490554f8da086805db6ddafc5947a04ca1ce707c Mon Sep 17 00:00:00 2001
From: Letu Ren <fantasquex at gmail.com>
Date: Thu, 13 Mar 2025 18:11:07 +0800
Subject: [PATCH 15/15] remove a new scope

---
 clang/lib/Sema/SemaCodeComplete.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 08bdf1a0e81e5..2003701b65654 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6755,7 +6755,6 @@ void SemaCodeCompletion::CodeCompleteKeywordAfterIf(bool AfterExclaim) const {
                         CodeCompletionContext::CCC_Other);
   CodeCompletionBuilder Builder(Results.getAllocator(),
                                 Results.getCodeCompletionTUInfo());
-  Results.EnterNewScope();
   if (getLangOpts().CPlusPlus17) {
     if (!AfterExclaim) {
       if (Results.includeCodePatterns()) {
@@ -6790,7 +6789,6 @@ void SemaCodeCompletion::CodeCompleteKeywordAfterIf(bool AfterExclaim) const {
       Results.AddResult({"consteval"});
     }
   }
-  Results.ExitScope();
 
   HandleCodeCompleteResults(&SemaRef, CodeCompleter,
                             Results.getCompletionContext(), Results.data(),



More information about the cfe-commits mailing list