Skip to content

Allow 'inline' on some declarations in MS compatibility mode #125250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ Resolutions to C++ Defect Reports
C Language Changes
------------------

- Clang now allows an ``inline`` specifier on a typedef declaration of a
function type in Microsoft compatibility mode. #GH124869

C2y Feature Support
^^^^^^^^^^^^^^^^^^^

Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,8 @@ def MicrosoftStaticAssert : DiagGroup<"microsoft-static-assert">;
def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">;
def MicrosoftStringLiteralFromPredefined : DiagGroup<
"microsoft-string-literal-from-predefined">;
def MicrosoftInlineOnNonFunction : DiagGroup<
"microsoft-inline-on-non-function">;

// Aliases.
def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
Expand All @@ -1322,7 +1324,7 @@ def Microsoft : DiagGroup<"microsoft",
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftStaticAssert,
MicrosoftInitFromPredefined, MicrosoftStringLiteralFromPredefined,
MicrosoftInconsistentDllImport]>;
MicrosoftInconsistentDllImport, MicrosoftInlineOnNonFunction]>;

def ClangClPch : DiagGroup<"clang-cl-pch">;

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ def ext_use_out_of_scope_declaration : ExtWarn<
InGroup<DiagGroup<"out-of-scope-function">>;
def err_inline_non_function : Error<
"'inline' can only appear on functions%select{| and non-local variables}0">;
def warn_ms_inline_non_function : ExtWarn<err_inline_non_function.Summary>,
InGroup<MicrosoftInlineOnNonFunction>;
def err_noreturn_non_function : Error<
"'_Noreturn' can only appear on functions">;
def warn_qual_return_type : Warning<
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6681,7 +6681,10 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
DiagnoseFunctionSpecifiers(D.getDeclSpec());

if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
Diag(D.getDeclSpec().getInlineSpecLoc(),
(getLangOpts().MSVCCompat && !getLangOpts().CPlusPlus)
? diag::warn_ms_inline_non_function
: diag::err_inline_non_function)
<< getLangOpts().CPlusPlus17;
if (D.getDeclSpec().hasConstexprSpecifier())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
Expand Down
16 changes: 14 additions & 2 deletions clang/test/Sema/MicrosoftCompatibility.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-compatibility -DMSVCCOMPAT -triple i686-pc-win32
// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions -triple i686-pc-win32
// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify=expected,compat -fms-compatibility -DMSVCCOMPAT -triple i686-pc-win32
// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify=expected,ext -fms-extensions -triple i686-pc-win32

#ifdef MSVCCOMPAT
enum ENUM1; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
Expand Down Expand Up @@ -35,3 +35,15 @@ size_t x;
#else
size_t x; // expected-error {{unknown type name 'size_t'}}
#endif

/* Microsoft allows inline, __inline, and __forceinline to appear on a typedef
of a function type; this is used in their system headers such as ufxclient.h
See GitHub #124869 for more details.
*/
typedef int inline Foo1(int); // compat-warning {{'inline' can only appear on functions}} \
ext-error {{'inline' can only appear on functions}}
typedef int __inline Foo2(int); // compat-warning {{'inline' can only appear on functions}} \
ext-error {{'inline' can only appear on functions}}
typedef int __forceinline Foo(int); // compat-warning {{'inline' can only appear on functions}} \
ext-error {{'inline' can only appear on functions}} \
expected-warning {{'__forceinline' attribute only applies to functions and statements}}
7 changes: 7 additions & 0 deletions clang/test/Sema/MicrosoftCompatibility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ struct cls {
};

char * cls::* __uptr wrong2 = &cls::m; // expected-error {{'__uptr' attribute cannot be used with pointers to members}}

// Microsoft allows inline, __inline, and __forceinline to appear on a typedef
// of a function type, but only in C. See GitHub #124869 for more details.
typedef int inline Foo1(int); // expected-error {{'inline' can only appear on functions}}
typedef int __inline Foo2(int); // expected-error {{'inline' can only appear on functions}}
typedef int __forceinline Foo(int); // expected-error {{'inline' can only appear on functions}} \
expected-warning {{'__forceinline' attribute only applies to functions and statements}}