https://github.com/mafeguimaraes updated 
https://github.com/llvm/llvm-project/pull/215353

From ac4a386cff88e9e131b4ae3df9f25a7b218be382 Mon Sep 17 00:00:00 2001
From: Maria Fernanda Guimaraes <[email protected]>
Date: Mon, 10 Aug 2026 17:18:01 +0000
Subject: [PATCH 1/2] Separate statement and declaration attributes in [...]

---
 clang/include/clang/Parse/Parser.h            |  6 +--
 clang/include/clang/Sema/SemaCodeCompletion.h |  5 +++
 clang/lib/Parse/ParseDeclCXX.cpp              | 17 ++++++---
 clang/lib/Parse/ParseStmt.cpp                 |  2 +-
 clang/lib/Sema/SemaCodeComplete.cpp           | 37 +++++++++++++++++++
 5 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 163aa483a84e3..19a1c0a90ad8c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2337,12 +2337,12 @@ class Parser : public CodeCompletionHandler {
     return false;
   }
 
-  bool MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
+  bool MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs, bool 
IsStmtContext = false) {
     bool AttrsParsed = false;
     if ((getLangOpts().MicrosoftExt || getLangOpts().HLSL) &&
         Tok.is(tok::l_square)) {
       ParsedAttributes AttrsWithRange(AttrFactory);
-      ParseMicrosoftAttributes(AttrsWithRange);
+      ParseMicrosoftAttributes(AttrsWithRange, IsStmtContext);
       AttrsParsed = !AttrsWithRange.empty();
       Attrs.takeAllAppendingFrom(AttrsWithRange);
     }
@@ -3133,7 +3133,7 @@ class Parser : public CodeCompletionHandler {
   ///             ms-attribute[opt]
   ///             ms-attribute ms-attribute-seq
   /// \endverbatim
-  void ParseMicrosoftAttributes(ParsedAttributes &Attrs);
+  void ParseMicrosoftAttributes(ParsedAttributes &Attrs, bool IsStmtContext = 
false);
 
   void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
   void ParseNullabilityClassAttributes(ParsedAttributes &attrs);
diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h 
b/clang/include/clang/Sema/SemaCodeCompletion.h
index 7203b19d58898..b9fe3634992c0 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -234,6 +234,11 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
   void CodeCompleteNaturalLanguage();
   void CodeCompleteAvailabilityPlatformName();
+  void CodeCompleteHLSLAttributes(
+      llvm::ArrayRef<AttributeCommonInfo::Syntax> Syntaxes,
+      std::optional<ParsedAttr::Kind> RestrictToKind = std::nullopt,
+      bool RequireStmt = false,
+      std::optional<ParsedAttr::Kind> ExcludeKind = std::nullopt);
   void
   GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
                               CodeCompletionTUInfo &CCTUInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index a3617c3db49c4..08c5d4998bedc 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4921,7 +4921,7 @@ void 
Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
                  ParsedAttr::Form::Microsoft());
 }
 
-void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) {
+void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs, bool 
IsStmtContext) {
   assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
 
   SourceLocation StartLoc = Tok.getLocation();
@@ -4937,10 +4937,17 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes 
&Attrs) {
                 StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
       if (Tok.is(tok::code_completion)) {
         cutOffParsing();
-        Actions.CodeCompletion().CodeCompleteAttribute(
-            AttributeCommonInfo::AS_Microsoft,
-            SemaCodeCompletion::AttributeCompletion::Attribute,
-            /*Scope=*/nullptr);
+        if (getLangOpts().HLSL) {
+          Actions.CodeCompletion().CodeCompleteHLSLAttributes(
+              {AttributeCommonInfo::AS_Microsoft}, /*Kind=*/std::nullopt,
+              /*RequireStmt=*/IsStmtContext,
+              /*ExcludeKind=*/ParsedAttr::AT_HLSLParsedSemantic);
+        } else {
+            Actions.CodeCompletion().CodeCompleteAttribute(
+                AttributeCommonInfo::AS_Microsoft,
+                SemaCodeCompletion::AttributeCompletion::Attribute,
+              /*Scope=*/nullptr);
+          }
         break;
       }
       if (Tok.isNot(tok::identifier)) // ']', but also eof
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 219bcd980e860..b6d587cf96856 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -73,7 +73,7 @@ StmtResult Parser::ParseStatementOrDeclaration(StmtVector 
&Stmts,
     MaybeParseGNUAttributes(GNUOrMSAttrs);
 
   if (getLangOpts().HLSL)
-    MaybeParseMicrosoftAttributes(GNUOrMSAttrs);
+    MaybeParseMicrosoftAttributes(GNUOrMSAttrs, /*IsStmtContext=*/true);
 
   StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
       Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUOrMSAttrs,
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index bd239adb0f215..3cfbb2b746106 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10728,6 +10728,43 @@ void SemaCodeCompletion::GatherGlobalCodeCompletions(
                  Builder.data() + Builder.size());
 }
 
+void SemaCodeCompletion::CodeCompleteHLSLAttributes(
+    llvm::ArrayRef<AttributeCommonInfo::Syntax> Syntaxes,
+    std::optional<ParsedAttr::Kind> RestrictToKind,
+    bool RequireStmt,
+    std::optional<ParsedAttr::Kind> ExcludeKind) {
+  ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
+                        CodeCompleter->getCodeCompletionTUInfo(),
+                        CodeCompletionContext::CCC_Attribute);
+
+  for (const auto *A : ParsedAttrInfo::getAllBuiltin()) {
+    if (!A->acceptsLangOpts(getLangOpts()))
+      continue;
+    if (RestrictToKind && A->AttrKind != *RestrictToKind)
+      continue;
+    if (ExcludeKind && A->AttrKind == *ExcludeKind)
+      continue;
+    if (A->IsStmt != RequireStmt)
+      continue;
+
+    for (const auto &S : A->Spellings) {
+      if (!llvm::is_contained(Syntaxes, S.Syntax))
+        continue;
+
+      CodeCompletionBuilder CCB(Results.getAllocator(),
+                                Results.getCodeCompletionTUInfo());
+      CCB.AddTypedTextChunk(
+          Results.getAllocator().CopyString(S.NormalizedFullName));
+      Results.AddResult(CodeCompletionResult(CCB.TakeString(), CCP_Keyword));
+    }
+  }
+
+  HandleCodeCompleteResults(&SemaRef, CodeCompleter,
+                            Results.getCompletionContext(), Results.data(),
+                            Results.size());
+}
+
+
 SemaCodeCompletion::SemaCodeCompletion(Sema &S,
                                        CodeCompleteConsumer 
*CompletionConsumer)
     : SemaBase(S), CodeCompleter(CompletionConsumer),

From 76e3e4cb2c85f420207cd583a9e6fb23a9f1709b Mon Sep 17 00:00:00 2001
From: Maria Fernanda Guimaraes <[email protected]>
Date: Mon, 10 Aug 2026 17:39:05 +0000
Subject: [PATCH 2/2] Add tests for bracket attribute code completion

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 49 +++++++++++++++++++
 clang/include/clang/Parse/Parser.h            |  6 ++-
 clang/lib/Parse/ParseDeclCXX.cpp              | 11 +++--
 clang/lib/Sema/SemaCodeComplete.cpp           |  4 +-
 4 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 4c1cab7b11e60..dca5ab072f537 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -5163,6 +5163,55 @@ TEST(CompletionTest, FuzzyMatchMacro) {
   }
 }
 
+static void configureHLSL(TestTU &TU, bool EnableMatrix = false) {
+  TU.Filename = "TestTU.hlsl";
+  TU.ExtraArgs.push_back("-x");
+  TU.ExtraArgs.push_back("hlsl");
+  if (EnableMatrix)
+    TU.ExtraArgs.push_back("-fenable-matrix");
+  TU.ExtraArgs.push_back("--target=dxil-pc-shadermodel6.3-library");
+}
+
+TEST(CompletionTest, HLSLBracketAttributes) {
+  Annotations DeclContext(R"hlsl(
+    [^]
+    void main() {}
+  )hlsl");
+
+  TestTU TUDecl = TestTU::withCode(DeclContext.code());
+  configureHLSL(TUDecl);
+  auto ResultsDecl = completions(TUDecl, DeclContext.point());
+
+  EXPECT_THAT(ResultsDecl.Completions,
+              Contains(Field(&CodeCompletion::Name, "numthreads")));
+  EXPECT_THAT(ResultsDecl.Completions,
+              Contains(Field(&CodeCompletion::Name, "WaveSize")));
+  EXPECT_THAT(ResultsDecl.Completions,
+              Not(Contains(Field(&CodeCompletion::Name, "unroll"))));
+  EXPECT_THAT(ResultsDecl.Completions,
+              Not(Contains(Field(&CodeCompletion::Name, "SV_Target"))));
+
+  Annotations StmtContext(R"hlsl(
+    void main() {
+      [^]
+      for (int i = 0; i < 4; i++) {}
+    }
+  )hlsl");
+
+  TestTU TUStmt = TestTU::withCode(StmtContext.code());
+  configureHLSL(TUStmt);
+  auto ResultsStmt = completions(TUStmt, StmtContext.point());
+
+  EXPECT_THAT(ResultsStmt.Completions,
+              Contains(Field(&CodeCompletion::Name, "unroll")));
+  EXPECT_THAT(ResultsStmt.Completions,
+              Contains(Field(&CodeCompletion::Name, "loop")));
+  EXPECT_THAT(ResultsStmt.Completions,
+              Not(Contains(Field(&CodeCompletion::Name, "numthreads"))));
+  EXPECT_THAT(ResultsStmt.Completions,
+              Not(Contains(Field(&CodeCompletion::Name, "SV_Target"))));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 19a1c0a90ad8c..b7a311fd9fc6f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2337,7 +2337,8 @@ class Parser : public CodeCompletionHandler {
     return false;
   }
 
-  bool MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs, bool 
IsStmtContext = false) {
+  bool MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs,
+                                     bool IsStmtContext = false) {
     bool AttrsParsed = false;
     if ((getLangOpts().MicrosoftExt || getLangOpts().HLSL) &&
         Tok.is(tok::l_square)) {
@@ -3133,7 +3134,8 @@ class Parser : public CodeCompletionHandler {
   ///             ms-attribute[opt]
   ///             ms-attribute ms-attribute-seq
   /// \endverbatim
-  void ParseMicrosoftAttributes(ParsedAttributes &Attrs, bool IsStmtContext = 
false);
+  void ParseMicrosoftAttributes(ParsedAttributes &Attrs,
+                                bool IsStmtContext = false);
 
   void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
   void ParseNullabilityClassAttributes(ParsedAttributes &attrs);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 08c5d4998bedc..0f01b9aae31f6 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4921,7 +4921,8 @@ void 
Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
                  ParsedAttr::Form::Microsoft());
 }
 
-void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs, bool 
IsStmtContext) {
+void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs,
+                                      bool IsStmtContext) {
   assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
 
   SourceLocation StartLoc = Tok.getLocation();
@@ -4943,11 +4944,11 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes 
&Attrs, bool IsStmtContex
               /*RequireStmt=*/IsStmtContext,
               /*ExcludeKind=*/ParsedAttr::AT_HLSLParsedSemantic);
         } else {
-            Actions.CodeCompletion().CodeCompleteAttribute(
-                AttributeCommonInfo::AS_Microsoft,
-                SemaCodeCompletion::AttributeCompletion::Attribute,
+          Actions.CodeCompletion().CodeCompleteAttribute(
+              AttributeCommonInfo::AS_Microsoft,
+              SemaCodeCompletion::AttributeCompletion::Attribute,
               /*Scope=*/nullptr);
-          }
+        }
         break;
       }
       if (Tok.isNot(tok::identifier)) // ']', but also eof
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 3cfbb2b746106..cfca5ca715033 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10730,8 +10730,7 @@ void SemaCodeCompletion::GatherGlobalCodeCompletions(
 
 void SemaCodeCompletion::CodeCompleteHLSLAttributes(
     llvm::ArrayRef<AttributeCommonInfo::Syntax> Syntaxes,
-    std::optional<ParsedAttr::Kind> RestrictToKind,
-    bool RequireStmt,
+    std::optional<ParsedAttr::Kind> RestrictToKind, bool RequireStmt,
     std::optional<ParsedAttr::Kind> ExcludeKind) {
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
                         CodeCompleter->getCodeCompletionTUInfo(),
@@ -10764,7 +10763,6 @@ void SemaCodeCompletion::CodeCompleteHLSLAttributes(
                             Results.size());
 }
 
-
 SemaCodeCompletion::SemaCodeCompletion(Sema &S,
                                        CodeCompleteConsumer 
*CompletionConsumer)
     : SemaBase(S), CodeCompleter(CompletionConsumer),

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to