llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangd

Author: Maria Fernanda Guimarães (mafeguimaraes)

<details>
<summary>Changes</summary>

This PR addresses the issue where code completion inside `[...]` in HLSL mixed 
statement and declaration attributes.

Previously, `ParseMicrosoftAttributes` called 
`CodeCompleteAttribute(AS_Microsoft)` without threading the `IsStmt `context, 
causing statement attributes (like `[unroll]`) and declaration attributes (like 
`[numthreads]`) to appear together, alongside semantic annotations (like 
`SV_Target`).

Fixes #<!-- -->214792 

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


6 Files Affected:

- (modified) clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp (+49) 
- (modified) clang/include/clang/Parse/Parser.h (+5-3) 
- (modified) clang/include/clang/Sema/SemaCodeCompletion.h (+5) 
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+13-5) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaCodeComplete.cpp (+35) 


``````````diff
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 163aa483a84e3..b7a311fd9fc6f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2337,12 +2337,13 @@ 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 +3134,8 @@ 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..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) {
+void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs,
+                                      bool IsStmtContext) {
   assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
 
   SourceLocation StartLoc = Tok.getLocation();
@@ -4937,10 +4938,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..cfca5ca715033 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10728,6 +10728,41 @@ 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),

``````````

</details>


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

Reply via email to