[clang] [clang] Fix crashes with inheritance model keywords (PR #228207)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 2 04:11:42 PDT 2026
https://github.com/AaronBallman updated https://github.com/llvm/llvm-project/pull/228207
>From 73167de01e77b7566a0ccc8e79d26e62468dec0c Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Thu, 1 Oct 2026 15:19:37 -0400
Subject: [PATCH] [clang] Fix crashes with inheritance model keywords
The inheritance model keywords support a single underscore alias, but
that alias was never added to Attr.td. When we added typo correction
support for attributes in Clang 21, this uncovered a bug with these
keywords when a single underscore variant was used because the
hasAttribute() logic didn't know about these spellings. This adds the
correct spellings for the aliases to Attr.td.
While working on that, I noticed that we were missing an alias for
_single_inheritance, which is supported by MSVC, so that was added as
a drive-by fix.
Fixes #228003
---
clang/docs/ReleaseNotes.md | 3 +++
clang/include/clang/Basic/Attr.td | 11 ++++++++++-
clang/include/clang/Basic/TokenKinds.def | 1 +
clang/test/Parser/MicrosoftExtensions.cpp | 7 +++++++
4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 8160c5298e4197..6052325b0dc526 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -296,6 +296,8 @@ features cannot lower the translation-unit ABI level;
- Clang now recognizes the `[[gnu::flag_enum]]` attribute and treats it equivalent to `[[clang::flag_enum]]`
+- Clang now accepts `_single_inheritance` under `-fms-compatibility` as an alias for `__single_inheritance`; `_multiple_inheritance` and `_virtual_inheritance` were already correctly supported as aliases.
+
### Improvements to Clang's diagnostics
- `-Wfortify-source` now diagnoses when `strlcat`, `__builtin_strlcat`, `strlcpy`, or
@@ -580,6 +582,7 @@ features cannot lower the translation-unit ABI level;
(e.g. `({ s.b; })`) was not subject to integer promotion, unlike an ordinary
bit-field access. (#GH221542)
- No longer crashing due to follow-on diagnostics when there is an invalid operand in a logical operator involving a vector operand. (#GH227588)
+- Fixed a crash due to typo correction mishandling custom keywords `_virtual_inheritance` and `_multiple_inheritance` in `-fms-compatibility` mode. (#GH228003)
#### Bug Fixes to Compiler Builtins
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 6d3f50e1d2e20b..3824a8e21e4cb5 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4623,7 +4623,16 @@ def MSInheritance : InheritableAttr {
let Spellings = [CustomKeyword<"__single_inheritance">,
CustomKeyword<"__multiple_inheritance">,
CustomKeyword<"__virtual_inheritance">,
- CustomKeyword<"__unspecified_inheritance">];
+ CustomKeyword<"__unspecified_inheritance">,
+ // The single underscore spellings are aliases defined in
+ // TokenKinds.def; they must come *after* all of the other
+ // spellings because otherwise the MSInheritanceModel
+ // enumeration will break (we're relying on token
+ // normalization converting the alias to the normal form).
+ CustomKeyword<"_single_inheritance">,
+ CustomKeyword<"_multiple_inheritance">,
+ CustomKeyword<"_virtual_inheritance">
+ ];
let AdditionalMembers = [{
MSInheritanceModel getInheritanceModel() const {
// The spelling enum should agree with MSInheritanceModel.
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 97e5915bcd0d5e..213f2492d96f40 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -657,6 +657,7 @@ ALIAS("_multiple_inheritance", __multiple_inheritance, KEYMSCOMPAT)
ALIAS("_ptr32" , __ptr32 , KEYMSCOMPAT)
ALIAS("_ptr64" , __ptr64 , KEYMSCOMPAT)
ALIAS("_restrict" , restrict , KEYMSCOMPAT)
+ALIAS("_single_inheritance", __single_inheritance, KEYMSCOMPAT)
ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
ALIAS("_thiscall" , __thiscall , KEYMS)
ALIAS("_try" , __try , KEYMSCOMPAT)
diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp
index e32d7fae6af399..ee23596df46f63 100644
--- a/clang/test/Parser/MicrosoftExtensions.cpp
+++ b/clang/test/Parser/MicrosoftExtensions.cpp
@@ -349,6 +349,13 @@ namespace Inheritance {
class __single_inheritance A;
class __multiple_inheritance B;
class __virtual_inheritance C;
+
+ // The single underscore variants are the same as the double underscore ones.
+ // Some of these would crash due to typo correction because the spellings
+ // were missing from Attr.td but supported by TokenKinds.def. See GH228003.
+ class _single_inheritance D;
+ class _multiple_inheritance E;
+ class _virtual_inheritance F;
}
struct StructWithProperty {
More information about the cfe-commits
mailing list