[clang] [clang] Add support for MSVC force inline attrs (PR #185282)
Trung Nguyen via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 07:50:33 PDT 2026
https://github.com/trungnt2910 updated https://github.com/llvm/llvm-project/pull/185282
>From 825d065ef2d32e3374104b7b607abade434701a9 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Mon, 9 Mar 2026 01:28:03 +1100
Subject: [PATCH 1/9] [clang] Add support for `[[msvc::forceinline]]`
This is equivalent to Microsoft's `__forceinline` when placed before
a function declaration.
Unlike `__forceinline`, `[[msvc::forceinline]]` works with lambdas.
This is implemented as an alias of `[[clang::always_inline]]`.
---
clang/include/clang/Basic/Attr.td | 3 ++-
clang/test/CodeGen/attr-ms-forceinline.cpp | 16 ++++++++++++++++
clang/test/Sema/attr-ms-forceinline.cpp | 9 +++++++++
3 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGen/attr-ms-forceinline.cpp
create mode 100644 clang/test/Sema/attr-ms-forceinline.cpp
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index befd671393c7c..446a5abc250e8 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -927,7 +927,8 @@ def AlignNatural : InheritableAttr {
def AlwaysInline : DeclOrStmtAttr {
let Spellings = [GCC<"always_inline">, CXX11<"clang", "always_inline">,
- C23<"clang", "always_inline">, CustomKeyword<"__forceinline">];
+ C23<"clang", "always_inline">, CustomKeyword<"__forceinline">,
+ CXX11<"msvc", "forceinline">, C23<"msvc", "forceinline">];
let Accessors = [Accessor<"isClangAlwaysInline", [CXX11<"clang", "always_inline">,
C23<"clang", "always_inline">]>];
let Subjects = SubjectList<[Function, Stmt], WarnDiag,
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
new file mode 100644
index 0000000000000..240e58b8a8e52
--- /dev/null
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -o - | FileCheck %s
+
+[[msvc::forceinline]] void func() {}
+
+void call_func() {
+// CHECK-LABEL: @"?call_func@@YAXXZ"()
+// CHECK-NOT: call void @"?func@@YAXXZ"()
+ func();
+}
+
+void call_lambda() {
+// CHECK-LABEL: @"?call_lambda@@YAXXZ"()
+// CHECK-NOT: call void @"??R<lambda_
+ auto lambda = [] [[msvc::forceinline]] () {};
+ lambda();
+}
diff --git a/clang/test/Sema/attr-ms-forceinline.cpp b/clang/test/Sema/attr-ms-forceinline.cpp
new file mode 100644
index 0000000000000..6e5ac191ce8d1
--- /dev/null
+++ b/clang/test/Sema/attr-ms-forceinline.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -std=c++23 -triple x86_64-windows %s
+// expected-no-diagnostics
+
+[[msvc::forceinline]] void func(void) {}
+
+void lambda() {
+ auto l = [] [[msvc::forceinline]] () {};
+ l();
+}
>From 72a2f22ab2e02aaf034539343ca7d6a4ad458fd8 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <57174311+trungnt2910 at users.noreply.github.com>
Date: Wed, 18 Mar 2026 07:21:16 +1100
Subject: [PATCH 2/9] [clang] Try removing triple from test
---
clang/test/Sema/attr-ms-forceinline.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/Sema/attr-ms-forceinline.cpp b/clang/test/Sema/attr-ms-forceinline.cpp
index 6e5ac191ce8d1..619c7c8fb62da 100644
--- a/clang/test/Sema/attr-ms-forceinline.cpp
+++ b/clang/test/Sema/attr-ms-forceinline.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -std=c++23 -triple x86_64-windows %s
+// RUN: %clang_cc1 -verify -fsyntax-only -std=c++23 %s
// expected-no-diagnostics
[[msvc::forceinline]] void func(void) {}
>From b1d3deed72d24a44e8a864fd913499eee586334f Mon Sep 17 00:00:00 2001
From: Trung Nguyen <57174311+trungnt2910 at users.noreply.github.com>
Date: Fri, 27 Mar 2026 23:31:42 +1100
Subject: [PATCH 3/9] Test [[msvc::forceinline]] with non-MSVC triple
This ensures that the feature is not artificially restricted to the MSVC compatibility mode.
---
clang/test/CodeGen/attr-ms-forceinline.cpp | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
index 240e58b8a8e52..580fea044a803 100644
--- a/clang/test/CodeGen/attr-ms-forceinline.cpp
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -1,16 +1,21 @@
-// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -o - | FileCheck -check-prefix=CHECK-MSVC %s
+// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck -check-prefix=CHECK-LINUX %s
[[msvc::forceinline]] void func() {}
void call_func() {
-// CHECK-LABEL: @"?call_func@@YAXXZ"()
-// CHECK-NOT: call void @"?func@@YAXXZ"()
+// CHECK-MSVC-LABEL: @"?call_func@@YAXXZ"()
+// CHECK-MSVC-NOT: call void @"?func@@YAXXZ"()
+// CHECK-LINUX-LABEL: @_Z9call_funcv()
+// CHECK-LINUX-NOT: call void @_Z4funcv()
func();
}
void call_lambda() {
-// CHECK-LABEL: @"?call_lambda@@YAXXZ"()
-// CHECK-NOT: call void @"??R<lambda_
+// CHECK-MSVC-LABEL: @"?call_lambda@@YAXXZ"()
+// CHECK-MSVC-NOT: call void @"??R<lambda_
+// CHECK-LINUX-LABEL: @_Z11call_lambdav()
+// CHECK-LINUX-NOT: call void @"_ZZ11call_lambdavENK3$_0clEv"
auto lambda = [] [[msvc::forceinline]] () {};
lambda();
}
>From b4e09722a11c9b6c53dff529f38611cebf131fd0 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Tue, 31 Mar 2026 23:30:48 +1100
Subject: [PATCH 4/9] [clang] Address review feedback
- Add tests for C23 and later attributes. They are identical to the C++
tests except for the lambda.
- Added sema tests for:
+ Applying `[[msvc::forceinline]]` to a statement.
+ Applying `[[msvc::forceinline_calls]]` to a function.
+ Passing unwanted arguments to the attributes.
+ Using the attributes without enabling MS extensions (they are
ignored).
- Add support for `[[msvc::forceinline_calls]]`.
- Guard the two attributes with `-fms-extensions`.
---
clang/include/clang/Basic/Attr.td | 9 ++++-
.../clang/Basic/DiagnosticSemaKinds.td | 5 +++
clang/lib/Sema/SemaDeclAttr.cpp | 12 ++++++
clang/lib/Sema/SemaStmtAttr.cpp | 12 +++++-
clang/test/CodeGen/attr-ms-forceinline.cpp | 31 +++++++++++-----
clang/test/Sema/attr-ms-forceinline.c | 32 ++++++++++++++++
clang/test/Sema/attr-ms-forceinline.cpp | 37 +++++++++++++++++--
7 files changed, 122 insertions(+), 16 deletions(-)
create mode 100644 clang/test/Sema/attr-ms-forceinline.c
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 446a5abc250e8..6a1c91c58ff29 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -928,9 +928,14 @@ def AlignNatural : InheritableAttr {
def AlwaysInline : DeclOrStmtAttr {
let Spellings = [GCC<"always_inline">, CXX11<"clang", "always_inline">,
C23<"clang", "always_inline">, CustomKeyword<"__forceinline">,
- CXX11<"msvc", "forceinline">, C23<"msvc", "forceinline">];
+ CXX11<"msvc", "forceinline">, C23<"msvc", "forceinline">,
+ CXX11<"msvc", "forceinline_calls">, C23<"msvc", "forceinline_calls">];
let Accessors = [Accessor<"isClangAlwaysInline", [CXX11<"clang", "always_inline">,
- C23<"clang", "always_inline">]>];
+ C23<"clang", "always_inline">]>,
+ Accessor<"isMSVCForceInline", [CXX11<"msvc", "forceinline">,
+ C23<"msvc", "forceinline">]>,
+ Accessor<"isMSVCForceInlineCalls", [CXX11<"msvc", "forceinline_calls">,
+ C23<"msvc", "forceinline_calls">]>];
let Subjects = SubjectList<[Function, Stmt], WarnDiag,
"functions and statements">;
let Documentation = [AlwaysInlineDocs];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0e6b3f51a5231..ebf3245221dbc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3269,6 +3269,11 @@ def warn_function_attribute_ignored_in_stmt : Warning<
"use '%0' on statements">,
InGroup<IgnoredAttributes>;
+def warn_stmt_attribute_ignored_in_function : Warning<
+ "attribute is ignored on this function as it only applies to statements; "
+ "use '%0' for functions">,
+ InGroup<IgnoredAttributes>;
+
def err_musttail_needs_trivial_args : Error<
"tail call requires that the return value, all parameters, and any "
"temporaries created by the expression are trivially destructible">;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 1b7f41061061d..94ff47790a1d4 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5130,6 +5130,18 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D,
}
static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ AlwaysInlineAttr AIA(S.Context, AL);
+ if (!S.getLangOpts().MicrosoftExt &&
+ (AIA.isMSVCForceInline() || AIA.isMSVCForceInlineCalls())) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
+ return;
+ }
+ if (AIA.isMSVCForceInlineCalls()) {
+ S.Diag(AL.getLoc(), diag::warn_stmt_attribute_ignored_in_function)
+ << "[[msvc::forceinline]]";
+ return;
+ }
+
if (AlwaysInlineAttr *Inline =
S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName()))
D->addAttr(Inline);
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 27fd5563cc40e..f45c4333f94f6 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -312,7 +312,17 @@ static Attr *handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
static Attr *handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
AlwaysInlineAttr AIA(S.Context, A);
- if (!AIA.isClangAlwaysInline()) {
+ if (!S.getLangOpts().MicrosoftExt &&
+ (AIA.isMSVCForceInline() || AIA.isMSVCForceInlineCalls())) {
+ S.Diag(St->getBeginLoc(), diag::warn_attribute_ignored) << A;
+ return nullptr;
+ }
+ if (AIA.isMSVCForceInline()) {
+ S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt)
+ << "[[msvc::forceinline_calls]]";
+ return nullptr;
+ }
+ if (!AIA.isClangAlwaysInline() && !AIA.isMSVCForceInlineCalls()) {
S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt)
<< "[[clang::always_inline]]";
return nullptr;
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
index 580fea044a803..dd9e00f536e20 100644
--- a/clang/test/CodeGen/attr-ms-forceinline.cpp
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -1,14 +1,16 @@
-// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -o - | FileCheck -check-prefix=CHECK-MSVC %s
-// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck -check-prefix=CHECK-LINUX %s
+// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -fms-extensions -o - | FileCheck -check-prefix=CHECK-MSVC %s
+// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-unknown-linux-gnu -fms-extensions -o - | FileCheck -check-prefix=CHECK-LINUX %s
-[[msvc::forceinline]] void func() {}
+[[msvc::forceinline]] void foo() {}
-void call_func() {
-// CHECK-MSVC-LABEL: @"?call_func@@YAXXZ"()
-// CHECK-MSVC-NOT: call void @"?func@@YAXXZ"()
-// CHECK-LINUX-LABEL: @_Z9call_funcv()
-// CHECK-LINUX-NOT: call void @_Z4funcv()
- func();
+void bar() {}
+
+void call_foo() {
+// CHECK-MSVC-LABEL: @"?call_foo@@YAXXZ"()
+// CHECK-MSVC-NOT: call void @"?foo@@YAXXZ"()
+// CHECK-LINUX-LABEL: @_Z8call_foov()
+// CHECK-LINUX-NOT: call void @_Z3foov()
+ foo();
}
void call_lambda() {
@@ -19,3 +21,14 @@ void call_lambda() {
auto lambda = [] [[msvc::forceinline]] () {};
lambda();
}
+
+void call_bar_stmt() {
+// CHECK-MSVC-LABEL: @"?call_bar_stmt@@YAXXZ"()
+// CHECK-MSVC: call void @"?bar@@YAXXZ"() #[[ALWAYSINLINEATTR:[0-9]+]]
+// CHECK-LINUX-LABEL: @_Z13call_bar_stmtv()
+// CHECK-LINUX: call void @_Z3barv() #[[ALWAYSINLINEATTR:[0-9]+]]
+ [[msvc::forceinline_calls]] bar();
+}
+
+// CHECK-MSVC: attributes #[[ALWAYSINLINEATTR]] = { alwaysinline }
+// CHECK-LINUX: attributes #[[ALWAYSINLINEATTR]] = { alwaysinline }
diff --git a/clang/test/Sema/attr-ms-forceinline.c b/clang/test/Sema/attr-ms-forceinline.c
new file mode 100644
index 0000000000000..bda31ea3eff97
--- /dev/null
+++ b/clang/test/Sema/attr-ms-forceinline.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -verify=ms-ext -fms-extensions -fsyntax-only -std=c23 %s
+// RUN: %clang_cc1 -verify=no-ms-ext -fsyntax-only -std=c23 %s
+
+void foo(void);
+
+[[msvc::forceinline]] void func(void) {}
+// no-ms-ext-warning at -1 {{'msvc::forceinline' attribute ignored}}
+
+void stmt_forceinline(void) {
+ [[msvc::forceinline]] func();
+ // ms-ext-warning at -1 {{attribute is ignored on this statement as it only applies to functions; use '[[msvc::forceinline_calls]]' on statements}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+}
+
+[[msvc::forceinline_calls]] void func2(void) {}
+// ms-ext-warning at -1 {{attribute is ignored on this function as it only applies to statements; use '[[msvc::forceinline]]' for functions}}
+// no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+
+void stmt_forceinline_calls(void) {
+ [[msvc::forceinline_calls]] foo();
+ // no-ms-ext-warning at -1 {{'msvc::forceinline_calls' attribute ignored}}
+}
+
+[[msvc::forceinline(0)]] void func3(void);
+// ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
+// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+
+void func4(void) {
+ [[msvc::forceinline_calls("foo")]] foo();
+ // ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+}
diff --git a/clang/test/Sema/attr-ms-forceinline.cpp b/clang/test/Sema/attr-ms-forceinline.cpp
index 619c7c8fb62da..5292470514a9e 100644
--- a/clang/test/Sema/attr-ms-forceinline.cpp
+++ b/clang/test/Sema/attr-ms-forceinline.cpp
@@ -1,9 +1,38 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -std=c++23 %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -verify=ms-ext -fms-extensions -fsyntax-only -std=c++23 %s
+// RUN: %clang_cc1 -verify=no-ms-ext -fsyntax-only -std=c++23 %s
-[[msvc::forceinline]] void func(void) {}
+void foo();
-void lambda() {
+[[msvc::forceinline]] void func() {}
+// no-ms-ext-warning at -1 {{'msvc::forceinline' attribute ignored}}
+
+void lambda_func() {
auto l = [] [[msvc::forceinline]] () {};
+ // no-ms-ext-warning at -1 {{'msvc::forceinline' attribute ignored}}
l();
}
+
+void stmt_forceinline() {
+ [[msvc::forceinline]] func();
+ // ms-ext-warning at -1 {{attribute is ignored on this statement as it only applies to functions; use '[[msvc::forceinline_calls]]' on statements}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+}
+
+[[msvc::forceinline_calls]] void func2() {}
+// ms-ext-warning at -1 {{attribute is ignored on this function as it only applies to statements; use '[[msvc::forceinline]]' for functions}}
+// no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+
+void stmt_forceinline_calls() {
+ [[msvc::forceinline_calls]] foo();
+ // no-ms-ext-warning at -1 {{'msvc::forceinline_calls' attribute ignored}}
+}
+
+[[msvc::forceinline(0)]] void func3();
+// ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
+// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+
+void func4() {
+ [[msvc::forceinline_calls("foo")]] foo();
+ // ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+}
>From 0ab171d706ee963093d9276fd69b53a9902f0006 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Wed, 1 Apr 2026 00:09:53 +1100
Subject: [PATCH 5/9] [clang] Fix test failures
---
clang/test/CodeGen/attr-ms-forceinline.cpp | 2 +-
clang/test/Sema/attr-ms-forceinline.c | 6 +++---
clang/test/Sema/attr-ms-forceinline.cpp | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
index dd9e00f536e20..a44f5d05b29af 100644
--- a/clang/test/CodeGen/attr-ms-forceinline.cpp
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -3,7 +3,7 @@
[[msvc::forceinline]] void foo() {}
-void bar() {}
+void bar();
void call_foo() {
// CHECK-MSVC-LABEL: @"?call_foo@@YAXXZ"()
diff --git a/clang/test/Sema/attr-ms-forceinline.c b/clang/test/Sema/attr-ms-forceinline.c
index bda31ea3eff97..d80cabdba67b8 100644
--- a/clang/test/Sema/attr-ms-forceinline.c
+++ b/clang/test/Sema/attr-ms-forceinline.c
@@ -26,7 +26,7 @@ void stmt_forceinline_calls(void) {
// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
void func4(void) {
- [[msvc::forceinline_calls("foo")]] foo();
- // ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
- // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+ [[msvc::forceinline_calls("foo")]] foo();
+ // ms-ext-error at -1 {{'msvc::forceinline_calls' attribute takes no arguments}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
}
diff --git a/clang/test/Sema/attr-ms-forceinline.cpp b/clang/test/Sema/attr-ms-forceinline.cpp
index 5292470514a9e..72b165b25c021 100644
--- a/clang/test/Sema/attr-ms-forceinline.cpp
+++ b/clang/test/Sema/attr-ms-forceinline.cpp
@@ -32,7 +32,7 @@ void stmt_forceinline_calls() {
// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
void func4() {
- [[msvc::forceinline_calls("foo")]] foo();
- // ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
- // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+ [[msvc::forceinline_calls("foo")]] foo();
+ // ms-ext-error at -1 {{'msvc::forceinline_calls' attribute takes no arguments}}
+ // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
}
>From 42593afba9436b6ef48d8ca6f2e842f9541261e2 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Wed, 1 Apr 2026 00:32:28 +1100
Subject: [PATCH 6/9] [clang] Fix last test errors
---
clang/test/Sema/attr-ms-forceinline.c | 4 ++--
clang/test/Sema/attr-ms-forceinline.cpp | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/test/Sema/attr-ms-forceinline.c b/clang/test/Sema/attr-ms-forceinline.c
index d80cabdba67b8..1da92e89f2178 100644
--- a/clang/test/Sema/attr-ms-forceinline.c
+++ b/clang/test/Sema/attr-ms-forceinline.c
@@ -23,10 +23,10 @@ void stmt_forceinline_calls(void) {
[[msvc::forceinline(0)]] void func3(void);
// ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
-// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+// no-ms-ext-error at -2 {{'msvc::forceinline' attribute takes no arguments}}
void func4(void) {
[[msvc::forceinline_calls("foo")]] foo();
// ms-ext-error at -1 {{'msvc::forceinline_calls' attribute takes no arguments}}
- // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+ // no-ms-ext-error at -2 {{'msvc::forceinline_calls' attribute takes no arguments}}
}
diff --git a/clang/test/Sema/attr-ms-forceinline.cpp b/clang/test/Sema/attr-ms-forceinline.cpp
index 72b165b25c021..5e1d2b3eeee85 100644
--- a/clang/test/Sema/attr-ms-forceinline.cpp
+++ b/clang/test/Sema/attr-ms-forceinline.cpp
@@ -29,10 +29,10 @@ void stmt_forceinline_calls() {
[[msvc::forceinline(0)]] void func3();
// ms-ext-error at -1 {{'msvc::forceinline' attribute takes no arguments}}
-// no-ms-ext-warning at -2 {{'msvc::forceinline' attribute ignored}}
+// no-ms-ext-error at -2 {{'msvc::forceinline' attribute takes no arguments}}
void func4() {
[[msvc::forceinline_calls("foo")]] foo();
// ms-ext-error at -1 {{'msvc::forceinline_calls' attribute takes no arguments}}
- // no-ms-ext-warning at -2 {{'msvc::forceinline_calls' attribute ignored}}
+ // no-ms-ext-error at -2 {{'msvc::forceinline_calls' attribute takes no arguments}}
}
>From fd131e6980cfdb7a00e8bb9fec719b7146b779bd Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Wed, 1 Apr 2026 00:55:41 +1100
Subject: [PATCH 7/9] [clang] Document attributes in release notes
---
clang/docs/ReleaseNotes.rst | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5d07bfc210e05..f3885b636a21c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -207,6 +207,10 @@ Attribute Changes in Clang
type-level control over overflow behavior. There is also an accompanying type
specifier for each behavior kind via `__ob_wrap` and `__ob_trap`.
+- Added support for ``[[msvc::forceinline]]`` for functions and ``[[msvc::forceinline_calls]]`` for
+ statements. Both are aliases to ``[clang::always_inlines]`` with additional checks to ensure that
+ they are only accepted in places where MSVC also does.
+
Improvements to Clang's diagnostics
-----------------------------------
- Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
@@ -273,13 +277,13 @@ Improvements to Clang's diagnostics
when accessing a member function on a past-the-end array element.
(#GH179128)
-- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
+- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
-- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
+- Clang now emits ``-Wsizeof-pointer-memaccess`` when snprintf/vsnprintf use the sizeof
the destination buffer(dynamically allocated) in the len parameter(#GH162366)
- ``-Wunsafe-buffer-usage`` now warns about unsafe two-parameter constructors of
@@ -337,12 +341,12 @@ Bug Fixes to C++ Support
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
-- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
+- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
when used inside decltype in the return type. (#GH180460)
- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
- Fixed a crash on ``typeid`` of incomplete local types during template instantiation. (#GH63242), (#GH176397)
-- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
- MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
+- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching
+ MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported
and produce a warning. (#GH162640)
- Fix initialization of GRO when GRO-return type mismatches, as part of CWG2563. (#GH98744)
>From bb639a4491fc267cfce2d8fd988608904f039e83 Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Wed, 1 Apr 2026 01:28:30 +1100
Subject: [PATCH 8/9] [clang] Test for attributes instead
---
clang/test/CodeGen/attr-ms-forceinline.cpp | 42 +++++++++++-----------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
index a44f5d05b29af..aca13f54b4e77 100644
--- a/clang/test/CodeGen/attr-ms-forceinline.cpp
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -1,34 +1,32 @@
-// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-pc-windows-msvc -fms-extensions -o - | FileCheck -check-prefix=CHECK-MSVC %s
-// RUN: %clang_cc1 -std=c++23 -emit-llvm %s -triple x86_64-unknown-linux-gnu -fms-extensions -o - | FileCheck -check-prefix=CHECK-LINUX %s
+// RUN: %clang_cc1 -std=c++23 -disable-llvm-passes -emit-llvm %s -triple x86_64-pc-windows-msvc -fms-extensions -o - | FileCheck -check-prefix=CHECK-MSVC %s
+// RUN: %clang_cc1 -std=c++23 -disable-llvm-passes -emit-llvm %s -triple x86_64-unknown-linux-gnu -fms-extensions -o - | FileCheck -check-prefix=CHECK-LINUX %s
+// CHECK-MSVC: define {{.*}} @"?foo@@YAXXZ"() #[[ATTR_FOO:[0-9]+]]
+// CHECK-LINUX: define {{.*}} @_Z3foov() #[[ATTR_FOO:[0-9]+]]
[[msvc::forceinline]] void foo() {}
void bar();
-void call_foo() {
-// CHECK-MSVC-LABEL: @"?call_foo@@YAXXZ"()
-// CHECK-MSVC-NOT: call void @"?foo@@YAXXZ"()
-// CHECK-LINUX-LABEL: @_Z8call_foov()
-// CHECK-LINUX-NOT: call void @_Z3foov()
- foo();
-}
-
void call_lambda() {
-// CHECK-MSVC-LABEL: @"?call_lambda@@YAXXZ"()
-// CHECK-MSVC-NOT: call void @"??R<lambda_
-// CHECK-LINUX-LABEL: @_Z11call_lambdav()
-// CHECK-LINUX-NOT: call void @"_ZZ11call_lambdavENK3$_0clEv"
- auto lambda = [] [[msvc::forceinline]] () {};
+ auto lambda = [] [[msvc::forceinline]] () { bar(); };
lambda();
}
-void call_bar_stmt() {
-// CHECK-MSVC-LABEL: @"?call_bar_stmt@@YAXXZ"()
-// CHECK-MSVC: call void @"?bar@@YAXXZ"() #[[ALWAYSINLINEATTR:[0-9]+]]
-// CHECK-LINUX-LABEL: @_Z13call_bar_stmtv()
-// CHECK-LINUX: call void @_Z3barv() #[[ALWAYSINLINEATTR:[0-9]+]]
+// CHECK-MSVC: define internal void @"??R<lambda_0>@?0??call_lambda@@YAXXZ at QEBA?A?<auto>@@XZ"{{.*}} #[[ATTR_LAMBDA:[0-9]+]]
+// CHECK-LINUX: define internal void @"_ZZ11call_lambdavENK3$_0clEv"{{.*}} #[[ATTR_LAMBDA:[0-9]+]]
+
+void call_bar() {
+// CHECK-MSVC-LABEL: define {{.*}} @"?call_bar@@YAXXZ"()
+// CHECK-MSVC: call void @"?bar@@YAXXZ"() #[[ATTR_CALLSITE:[0-9]+]]
+// CHECK-LINUX-LABEL: define {{.*}} @_Z8call_barv()
+// CHECK-LINUX: call void @_Z3barv() #[[ATTR_CALLSITE:[0-9]+]]
[[msvc::forceinline_calls]] bar();
}
-// CHECK-MSVC: attributes #[[ALWAYSINLINEATTR]] = { alwaysinline }
-// CHECK-LINUX: attributes #[[ALWAYSINLINEATTR]] = { alwaysinline }
+// CHECK-MSVC: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}} }
+// CHECK-MSVC: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}} }
+// CHECK-MSVC: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
+
+// CHECK-LINUX: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}} }
+// CHECK-LINUX: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}} }
+// CHECK-LINUX: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
>From 9eebca78f74a49fe99fcc1bd46725a311c26577d Mon Sep 17 00:00:00 2001
From: Trung Nguyen <trungnt282910 at gmail.com>
Date: Wed, 1 Apr 2026 01:49:07 +1100
Subject: [PATCH 9/9] [clang] Fix test failure
---
clang/test/CodeGen/attr-ms-forceinline.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/test/CodeGen/attr-ms-forceinline.cpp b/clang/test/CodeGen/attr-ms-forceinline.cpp
index aca13f54b4e77..e2e1d9c394623 100644
--- a/clang/test/CodeGen/attr-ms-forceinline.cpp
+++ b/clang/test/CodeGen/attr-ms-forceinline.cpp
@@ -23,10 +23,10 @@ void call_bar() {
[[msvc::forceinline_calls]] bar();
}
-// CHECK-MSVC: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}} }
-// CHECK-MSVC: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}} }
-// CHECK-MSVC: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
+// CHECK-MSVC-DAG: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}}}
+// CHECK-MSVC-DAG: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}}}
+// CHECK-MSVC-DAG: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
-// CHECK-LINUX: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}} }
-// CHECK-LINUX: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}} }
-// CHECK-LINUX: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
+// CHECK-LINUX-DAG: attributes #[[ATTR_FOO]] = { alwaysinline {{.*}}}
+// CHECK-LINUX-DAG: attributes #[[ATTR_LAMBDA]] = { alwaysinline {{.*}}}
+// CHECK-LINUX-DAG: attributes #[[ATTR_CALLSITE]] = { alwaysinline }
More information about the cfe-commits
mailing list