From 33b52ad7d30ebd9119e2c3e34e9294ee830288f6 Mon Sep 17 00:00:00 2001 From: Timur Iskhodzhanov Date: Fri, 22 Feb 2013 12:42:50 +0000 Subject: [PATCH] Fix MergeFunctionDecl implicit CC for static methods. Patch by Alexander Zinenko! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175890 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 5 +- test/SemaCXX/decl-microsoft-call-conv.cpp | 86 +++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 test/SemaCXX/decl-microsoft-call-conv.cpp diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7e44e6b4bd..f062c0386d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2328,9 +2328,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { RequiresAdjustment = true; // Don't complain about mismatches when the default CC is - // effectively the same as the explict one. + // effectively the same as the explict one. Only Old decl contains correct + // information about storage class of CXXMethod. } else if (OldTypeInfo.getCC() == CC_Default && - isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) { + isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) { NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); RequiresAdjustment = true; diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp new file mode 100644 index 0000000000..3175af7f1b --- /dev/null +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -fms-extensions -verify %s + +// Pointers to free functions +void free_func_default(); +void __cdecl free_func_cdecl(); +void __stdcall free_func_stdcall(); // expected-note {{previous declaration is here}} +void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}} + +void __cdecl free_func_default(); // expected-note 2 {{previous declaration is here}} +void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} +void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}} + +void free_func_cdecl(); // expected-note 2 {{previous declaration is here}} +void __stdcall free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} +void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}} + +void __cdecl free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}} +void free_func_stdcall(); // expected-note {{previous declaration is here}} +void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}} + +void __cdecl free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}} +void __stdcall free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}} +void free_func_fastcall(); + +// Overloaded functions may have different calling conventions +void __fastcall free_func_default(int); +void __cdecl free_func_default(int *); + +void __thiscall free_func_cdecl(char *); +void __cdecl free_func_cdecl(double); + + +// Pointers to member functions +struct S { + void member_default1(); // expected-note {{previous declaration is here}} + void member_default2(); + void __cdecl member_cdecl1(); + void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}} + void __thiscall member_thiscall1(); + void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}} + + // Static member functions can't be __thiscall + static void static_member_default1(); + static void static_member_default2(); // expected-note {{previous declaration is here}} + static void __cdecl static_member_cdecl1(); + static void __cdecl static_member_cdecl2(); // expected-note {{previous declaration is here}} + static void __stdcall static_member_stdcall1(); + static void __stdcall static_member_stdcall2(); + + // Variadic functions can't be other than default or __cdecl + void member_variadic_default(int x, ...); + void __cdecl member_variadic_cdecl(int x, ...); + + static void static_member_variadic_default(int x, ...); + static void __cdecl static_member_variadic_cdecl(int x, ...); +}; + +void __cdecl S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} +void __thiscall S::member_default2() {} + +void S::member_cdecl1() {} +void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}} + +void S::member_thiscall1() {} +void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}} + +void __cdecl S::static_member_default1() {} +void __stdcall S::static_member_default2() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} + +void S::static_member_cdecl1() {} +void __stdcall S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} + +void __cdecl S::member_variadic_default(int x, ...) { + (void)x; +} +void S::member_variadic_cdecl(int x, ...) { + (void)x; +} + +void __cdecl S::static_member_variadic_default(int x, ...) { + (void)x; +} +void S::static_member_variadic_cdecl(int x, ...) { + (void)x; +} + -- 2.40.0