[ms-cxxabi] Fix the calling convention for operator new in records
Summary:
Operator new, new[], delete, and delete[] are all implicitly static when
declared inside a record. CXXMethodDecl already knows this, but we need
to account for that before we pick the calling convention for the
function type.
Fixes PR17371.
Reviewers: rsmith
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1761
llvm-svn: 192150
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index e75dc7b..5d4fce7 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
@@ -325,6 +326,13 @@
llvm_unreachable("Invalid TypeSpecType!");
}
+bool Declarator::isStaticMember() {
+ assert(getContext() == MemberContext);
+ return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ CXXMethodDecl::isStaticOverloadedOperator(
+ getName().OperatorFunctionId.Operator);
+}
+
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
/// declaration specifier includes.
///
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f2f2035..1fe8a5f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6494,10 +6494,8 @@
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
- if (DC->isRecord() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- !D.getDeclSpec().isFriendSpecified())
- adjustMemberFunctionCC(R);
+ if (D.isFirstDeclarationOfMember())
+ adjustMemberFunctionCC(R, D.isStaticMember());
bool isFriend = false;
FunctionTemplateDecl *FunctionTemplate = 0;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index accf2fdc..c327fff 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2494,12 +2494,11 @@
assert(D.isFunctionDeclarator());
// If we're inside a record, we're declaring a method, but it could be
- // static.
+ // explicitly or implicitly static.
IsCXXInstanceMethod =
- (D.getContext() == Declarator::MemberContext &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- !D.getDeclSpec().isFriendSpecified());
+ D.isFirstDeclarationOfMember() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !D.isStaticMember();
}
}
@@ -4580,13 +4579,17 @@
return true;
}
-void Sema::adjustMemberFunctionCC(QualType &T) {
+void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
const FunctionType *FT = T->castAs<FunctionType>();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
CallingConv CC = FT->getCallConv();
+
+ // Only adjust types with the default convention. For example, on Windows we
+ // should adjust a __cdecl type to __thiscall for instance methods, and a
+ // __thiscall type to __cdecl for static methods.
CallingConv DefaultCC =
- Context.getDefaultCallingConvention(IsVariadic, /*IsCXXMethod=*/false);
+ Context.getDefaultCallingConvention(IsVariadic, IsStatic);
if (CC != DefaultCC)
return;
@@ -4602,7 +4605,7 @@
// FIXME: This loses sugar. This should probably be fixed with an implicit
// AttributedType node that adjusts the convention.
- CC = Context.getDefaultCallingConvention(IsVariadic, /*IsCXXMethod=*/true);
+ CC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC));
FunctionTypeUnwrapper Unwrapped(*this, T);
T = Unwrapped.wrap(*this, FT);