Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2694,6 +2694,9 @@ def warn_attribute_after_definition_ignored : Warning< "attribute %0 after definition is ignored">, InGroup; +def warn_always_inline_on_variadic : Warning< + "inlining attribute %0 ignored on variadic function">, + InGroup; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; def warn_cxx11_gnu_attribute_on_type : Warning< Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3886,6 +3886,12 @@ return nullptr; } + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + hasFunctionProto(D) && isFunctionOrMethodVariadic(D)) { + Diag(Range.getBegin(), diag::warn_always_inline_on_variadic) << Ident; + return nullptr; + } + if (D->hasAttr()) return nullptr; Index: test/Sema/ms-forceinline-on-variadic.cpp =================================================================== --- /dev/null +++ test/Sema/ms-forceinline-on-variadic.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -o - -triple i686-unknown-windows-msvc -verify -fms-extensions %s \ +// RUN: | FileCheck %s +// +// (instruction scheduling crash test) +// RUN: %clang_cc1 -S -o - -triple i686-unknown-windows-msvc -fms-extensions %s + +inline __attribute__((always_inline)) void attribute_variadic(int f, ...) { } // expected-warning {{inlining attribute 'always_inline' ignored on variadic function}} + +__forceinline inline void msvc_variadic(int f, ...) { // expected-warning {{inlining attribute '__forceinline' ignored on variadic function}} +// CHECK-DAG: define {{.*}} void [[MSVC_VARIADIC:@".*msvc_variadic.*"]]( + __builtin_va_list ap; + __builtin_va_start(ap, f); + __builtin_va_end(ap); +} + +struct a { + // members are, by default, thiscall; enforce it for the purposes of the test + void __thiscall dispatcher(); +}; + +void __thiscall a::dispatcher() { + msvc_variadic(1, 2, 3); +// CHECK-DAG: define dso_local x86_thiscallcc void @"{{.*dispatcher.*}}"( +// CHECK-DAG: call void {{.*}} [[MSVC_VARIADIC]] +} + +void t() { + a{}.dispatcher(); +}