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
