Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 53cd9bb

Browse files
PR24595: Ignore calling convention modifiers for structors in MS ABI.
MS compiler ignores calling convention modifiers for structors. This patch makes clang do the same (for MS ABI). This fixes PR24595 and makes vswriter.h header (from Windows SDK 8.1) compilable. Differential Revision: http://reviews.llvm.org/D12402 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247619 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 146b63d commit 53cd9bb

File tree

8 files changed

+68
-17
lines changed

8 files changed

+68
-17
lines changed

include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,6 +2375,9 @@ def err_cconv_varargs : Error<
23752375
def warn_cconv_varargs : Warning<
23762376
"%0 calling convention ignored on variadic function">,
23772377
InGroup<IgnoredAttributes>;
2378+
def warn_cconv_structors : Warning<
2379+
"%0 calling convention ignored on constructor/destructor">,
2380+
InGroup<IgnoredAttributes>;
23782381
def err_regparm_mismatch : Error<"function declared with regparm(%0) "
23792382
"attribute was previously declared "
23802383
"%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;

include/clang/Sema/DeclSpec.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,9 @@ class Declarator {
22082208
/// redeclaration time if the decl is static.
22092209
bool isStaticMember();
22102210

2211+
/// Returns true if this declares a constructor or a destructor.
2212+
bool isCtorOrDtor();
2213+
22112214
void setRedeclaration(bool Val) { Redeclaration = Val; }
22122215
bool isRedeclaration() const { return Redeclaration; }
22132216
};

include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2919,7 +2919,8 @@ class Sema {
29192919
/// Adjust the calling convention of a method to be the ABI default if it
29202920
/// wasn't specified explicitly. This handles method types formed from
29212921
/// function type typedefs and typename template arguments.
2922-
void adjustMemberFunctionCC(QualType &T, bool IsStatic);
2922+
void adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
2923+
SourceLocation Loc);
29232924

29242925
// Check if there is an explicit attribute, but only look through parens.
29252926
// The intent is to look for an attribute on the current declarator, but not

lib/Sema/DeclSpec.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ bool Declarator::isStaticMember() {
351351
getName().OperatorFunctionId.Operator));
352352
}
353353

354+
bool Declarator::isCtorOrDtor() {
355+
return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
356+
(getName().getKind() == UnqualifiedId::IK_DestructorName);
357+
}
358+
354359
bool DeclSpec::hasTagDefinition() const {
355360
if (!TypeSpecOwned)
356361
return false;

lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7244,7 +7244,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
72447244
<< DeclSpec::getSpecifierName(TSCS);
72457245

72467246
if (D.isFirstDeclarationOfMember())
7247-
adjustMemberFunctionCC(R, D.isStaticMember());
7247+
adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(),
7248+
D.getIdentifierLoc());
72487249

72497250
bool isFriend = false;
72507251
FunctionTemplateDecl *FunctionTemplate = nullptr;

lib/Sema/SemaType.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,8 +2269,11 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
22692269

22702270
// Adjust the default free function calling convention to the default method
22712271
// calling convention.
2272+
bool IsCtorOrDtor =
2273+
(Entity.getNameKind() == DeclarationName::CXXConstructorName) ||
2274+
(Entity.getNameKind() == DeclarationName::CXXDestructorName);
22722275
if (T->isFunctionType())
2273-
adjustMemberFunctionCC(T, /*IsStatic=*/false);
2276+
adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc);
22742277

22752278
return Context.getMemberPointerType(T, Class.getTypePtr());
22762279
}
@@ -5842,25 +5845,41 @@ bool Sema::hasExplicitCallingConv(QualType &T) {
58425845
return false;
58435846
}
58445847

5845-
void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
5848+
void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
5849+
SourceLocation Loc) {
58465850
FunctionTypeUnwrapper Unwrapped(*this, T);
58475851
const FunctionType *FT = Unwrapped.get();
58485852
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
58495853
cast<FunctionProtoType>(FT)->isVariadic());
5850-
5851-
// Only adjust types with the default convention. For example, on Windows we
5852-
// should adjust a __cdecl type to __thiscall for instance methods, and a
5853-
// __thiscall type to __cdecl for static methods.
58545854
CallingConv CurCC = FT->getCallConv();
5855-
CallingConv FromCC =
5856-
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
58575855
CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
5858-
if (CurCC != FromCC || FromCC == ToCC)
5859-
return;
58605856

5861-
if (hasExplicitCallingConv(T))
5857+
if (CurCC == ToCC)
58625858
return;
58635859

5860+
// MS compiler ignores explicit calling convention attributes on structors. We
5861+
// should do the same.
5862+
if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
5863+
// Issue a warning on ignored calling convention -- except of __stdcall.
5864+
// Again, this is what MS compiler does.
5865+
if (CurCC != CC_X86StdCall)
5866+
Diag(Loc, diag::warn_cconv_structors)
5867+
<< FunctionType::getNameForCallConv(CurCC);
5868+
// Default adjustment.
5869+
} else {
5870+
// Only adjust types with the default convention. For example, on Windows
5871+
// we should adjust a __cdecl type to __thiscall for instance methods, and a
5872+
// __thiscall type to __cdecl for static methods.
5873+
CallingConv DefaultCC =
5874+
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
5875+
5876+
if (CurCC != DefaultCC || DefaultCC == ToCC)
5877+
return;
5878+
5879+
if (hasExplicitCallingConv(T))
5880+
return;
5881+
}
5882+
58645883
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
58655884
QualType Wrapped = Unwrapped.wrap(*this, FT);
58665885
T = Context.getAdjustedType(T, Wrapped);

test/CodeGenCXX/microsoft-abi-structors.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// RUN: FileCheck --check-prefix DTORS %s < %t
66
// RUN: FileCheck --check-prefix DTORS2 %s < %t
77
// RUN: FileCheck --check-prefix DTORS3 %s < %t
8+
// RUN: FileCheck --check-prefix DTORS4 %s < %t
89
//
910
// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s
1011

@@ -407,9 +408,7 @@ B::B(short *a) {}
407408
// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
408409
// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
409410
// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
410-
411-
// FIXME: This should be x86_thiscallcc. MSVC ignores explicit CCs on structors.
412-
// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z"
411+
// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAF@Z"
413412
// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
414413

415414
void construct_b() {
@@ -458,3 +457,18 @@ void *getA() {
458457
// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
459458
// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
460459
// CHECK: (%"struct.(anonymous namespace)::A"* %this)
460+
461+
// Check that we correctly transform __stdcall to __thiscall for ctors and
462+
// dtors.
463+
class G {
464+
public:
465+
__stdcall G() {};
466+
// DTORS4: define linkonce_odr x86_thiscallcc %class.G* @"\01??0G@@QAE@XZ"
467+
__stdcall ~G() {};
468+
// DTORS4: define linkonce_odr x86_thiscallcc void @"\01??1G@@QAE@XZ"
469+
};
470+
471+
extern void testG() {
472+
G g;
473+
}
474+

test/SemaCXX/decl-microsoft-call-conv.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-win32 -fms-extensions -verify %s
1+
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-win32 -fms-extensions -DMSABI -verify %s
22
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -verify %s
33
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -fms-extensions -verify %s
44

@@ -74,6 +74,11 @@ struct S {
7474

7575
static void static_member_variadic_default(int x, ...);
7676
static void __cdecl static_member_variadic_cdecl(int x, ...);
77+
78+
// Structors can't be other than default in MS ABI environment
79+
#ifdef MSABI
80+
__vectorcall S(); // expected-warning {{vectorcall calling convention ignored on constructor/destructor}}
81+
#endif
7782
};
7883

7984
void __cdecl S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}

0 commit comments

Comments
 (0)