https://github.com/vgvassilev updated 
https://github.com/llvm/llvm-project/pull/208909

>From db66bdd98bec5a9fe997ff0f31fee42d283aa39c Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <[email protected]>
Date: Sat, 11 Jul 2026 12:38:09 +0000
Subject: [PATCH] [Basic] Fix crash computing the spelling index of an unknown
 scoped attribute

AttributeCommonInfo::getAttributeSpellingListIndex() aborts for an unknown
attribute that has a scope, such as [[ns::foo]]. It calls
calculateAttributeSpellingListIndex(), which runs name/scope string-switches
generated for the known attributes. Those switches intentionally have no
default: getScopeFromNormalizedScopeName() falls off the end and hits
llvm_unreachable ("Fell off the end of a string-switch") for the unknown scope.

Any caller that asks a scoped unknown attribute for its spelling index therefore
crashes. An unrecognized attribute has no entry in those tables and carries a
single no-spelling, so short-circuit calculateAttributeSpellingListIndex() for
UnknownAttribute and return index 0 before the switches run.

Add a unit test that constructs an unknown scoped AttributeCommonInfo and asks
for its spelling index; it aborts without the fix.
---
 clang/lib/Basic/Attributes.cpp   |  9 +++++++++
 clang/unittests/AST/AttrTest.cpp | 23 +++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 5878a4e3f83a4..8ee45a338c57c 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -240,6 +240,15 @@ getScopeFromNormalizedScopeName(StringRef ScopeName) {
 }
 
 unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
+  // An unknown attribute (getParsedKind() == UnknownAttribute) has no entry in
+  // the generated spelling tables. The name/scope StringSwitches below assume 
a
+  // known attribute and intentionally have no default, so computing an index
+  // for an unknown *scoped* attribute such as [[ns::foo]] would fall off the
+  // end (getScopeFromNormalizedScopeName aborts). It has a single no-spelling,
+  // so report index 0 instead.
+  if (getParsedKind() == AttributeCommonInfo::UnknownAttribute)
+    return 0;
+
   // Both variables will be used in tablegen generated
   // attribute spell list index matching code.
   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
diff --git a/clang/unittests/AST/AttrTest.cpp b/clang/unittests/AST/AttrTest.cpp
index bbf1c0f9a382b..cbdc3a1cc59a9 100644
--- a/clang/unittests/AST/AttrTest.cpp
+++ b/clang/unittests/AST/AttrTest.cpp
@@ -7,9 +7,12 @@
 
//===----------------------------------------------------------------------===//
 
 #include "clang/AST/Attr.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/AttributeScopeInfo.h"
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Tooling/Tooling.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -249,4 +252,24 @@ TEST(Attr, RegularKeywordAttribute) {
   ASSERT_TRUE(Streaming->isRegularKeywordAttribute());
 }
 
+// getAttributeSpellingListIndex() must not crash for an unknown *scoped*
+// attribute such as [[ns::foo]]. Such an attribute has no entry in the
+// generated spelling tables, and the name/scope string-switches used to 
compute
+// the index have no default case; the computation must short-circuit for an
+// unknown attribute and report the single no-spelling instead of falling off
+// the end.
+TEST(Attr, UnknownScopedAttributeSpellingIndex) {
+  auto AST = clang::tooling::buildASTFromCode("");
+  auto &Ctx = AST->getASTContext();
+  const clang::IdentifierInfo *Name = &Ctx.Idents.get("foo");
+  const clang::IdentifierInfo *Scope = &Ctx.Idents.get("ns");
+
+  clang::AttributeCommonInfo CI(
+      Name, clang::AttributeScopeInfo(Scope, clang::SourceLocation()),
+      clang::SourceRange(), clang::AttributeCommonInfo::Form::CXX11());
+
+  ASSERT_EQ(CI.getParsedKind(), clang::AttributeCommonInfo::UnknownAttribute);
+  EXPECT_EQ(CI.getAttributeSpellingListIndex(), 0u);
+}
+
 } // namespace

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

Reply via email to