diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 720fff759c4ec1..b2f0ed185e0b5c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -131,6 +131,9 @@ Attribute Changes in Clang - ``#pragma clang attribute push`` now supports multiple attributes within a single directive. +- The ``__declspec(naked)`` attribute can no longer be written on a member + function in Microsoft compatibility mode, matching the behavior of cl.exe. + Windows Support --------------- diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4ac45145e6e8a9..b99a970061c0c1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2158,6 +2158,14 @@ static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << AL << Triple.getArchName(); return; } + + // This form is not allowed to be written on a member function (static or + // nonstatic) when in Microsoft compatibility mode. + if (S.getLangOpts().MSVCCompat && isa(D)) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str) + << AL << "non-member functions"; + return; + } } D->addAttr(::new (S.Context) NakedAttr(S.Context, AL)); diff --git a/clang/test/Sema/attr-naked.cpp b/clang/test/Sema/attr-naked.cpp index eaa8e223b83e10..a9c0fed4b99fca 100644 --- a/clang/test/Sema/attr-naked.cpp +++ b/clang/test/Sema/attr-naked.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only -triple arm-none-linux +// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -DDECLSPEC -triple i686-pc-win32 + class Foo { void bar(); static void bar2(); @@ -13,3 +15,12 @@ void __attribute__((naked)) Foo::bar() { // expected-note{{attribute is here}} void __attribute__((naked)) Foo::bar2() { asm("mov r2, %0" : : "r"(s)); // static member reference is OK } + +struct Bar { +#ifdef DECLSPEC + __declspec(naked) void func1(); // expected-error {{'naked' attribute only applies to non-member functions}} + __declspec(naked) static void func2(); // expected-error {{'naked' attribute only applies to non-member functions}} +#endif + __attribute__((naked)) void func3(); // OK + __attribute__((naked)) static void func4(); // OK +};