- Combine the two checks into isStaticMember
Hi rsmith,
http://llvm-reviews.chandlerc.com/D1761
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1761?vs=4483&id=4484#toc
Files:
include/clang/Basic/OperatorKinds.h
include/clang/Sema/DeclSpec.h
include/clang/Sema/Sema.h
lib/AST/DeclCXX.cpp
lib/AST/MicrosoftMangle.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaType.cpp
test/CodeGenCXX/mangle-ms.cpp
Index: include/clang/Basic/OperatorKinds.h
===================================================================
--- include/clang/Basic/OperatorKinds.h
+++ include/clang/Basic/OperatorKinds.h
@@ -30,7 +30,19 @@
/// \brief Retrieve the spelling of the given overloaded operator, without
/// the preceding "operator" keyword.
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
-
+
+/// Returns true if the given operator is implicitly static in a record
+/// context.
+inline bool isImplicitlyStaticOperator(OverloadedOperatorKind OOK) {
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ return OOK == OO_New || OOK == OO_Array_New || OOK == OO_Delete ||
+ OOK == OO_Array_Delete;
+}
+
} // end namespace clang
#endif
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h
+++ include/clang/Sema/DeclSpec.h
@@ -2072,6 +2072,13 @@
return (FunctionDefinitionKind)FunctionDefinition;
}
+ /// Returns true if this declares a static member.
+ bool isStaticMember() {
+ return getContext() == MemberContext &&
+ (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ isImplicitlyStaticOperator(getName().OperatorFunctionId.Operator));
+ }
+
void setRedeclaration(bool Val) { Redeclaration = Val; }
bool isRedeclaration() const { return Redeclaration; }
};
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -2538,7 +2538,7 @@
/// Adjust the calling convention of a method to be the ABI default if it
/// wasn't specified explicitly. This handles method types formed from
/// function type typedefs and typename template arguments.
- void adjustMemberFunctionCC(QualType &T);
+ void adjustMemberFunctionCC(QualType &T, bool IsStatic);
/// Get the outermost AttributedType node that sets a calling convention.
/// Valid types should not have multiple attributes with different CCs.
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1281,21 +1281,8 @@
if (MD->getStorageClass() == SC_Static)
return true;
- DeclarationName Name = getDeclName();
- // [class.free]p1:
- // Any allocation function for a class T is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_New ||
- Name.getCXXOverloadedOperator() == OO_Array_New)
- return true;
-
- // [class.free]p6 Any deallocation function for a class X is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_Delete ||
- Name.getCXXOverloadedOperator() == OO_Array_Delete)
- return true;
-
- return false;
+ OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator();
+ return isImplicitlyStaticOperator(OOK);
}
static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -320,9 +320,7 @@
// We should never ever see a FunctionNoProtoType at this point.
// We don't even know how to mangle their types anyway :).
- TypeSourceInfo *TSI = FD->getTypeSourceInfo();
- QualType T = TSI ? TSI->getType() : FD->getType();
- const FunctionProtoType *FT = T->castAs<FunctionProtoType>();
+ const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
bool InStructor = false, InInstMethod = false;
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
-#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
@@ -6488,12 +6487,14 @@
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
- if (DC->isRecord() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- !D.getDeclSpec().isFriendSpecified())
- adjustMemberFunctionCC(R);
-
bool isFriend = false;
+
+ if (DC->isRecord()) {
+ isFriend = D.getDeclSpec().isFriendSpecified();
+ if (!isFriend)
+ adjustMemberFunctionCC(R, D.isStaticMember());
+ }
+
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
@@ -2445,12 +2446,12 @@
assert(D.isFunctionDeclarator());
// If we're inside a record, we're declaring a method, but it could be
- // static.
+ // explicitly or implicitly static.
+ const DeclSpec &DS = D.getDeclSpec();
IsCXXInstanceMethod =
(D.getContext() == Declarator::MemberContext &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- !D.getDeclSpec().isFriendSpecified());
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !DS.isFriendSpecified() && !D.isStaticMember());
}
}
@@ -4529,13 +4530,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;
@@ -4551,7 +4556,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);
Index: test/CodeGenCXX/mangle-ms.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms.cpp
+++ test/CodeGenCXX/mangle-ms.cpp
@@ -304,3 +304,55 @@
int call_templated_inline_function_with_local_type() {
return templated_inline_function_with_local_type<int>();
}
+
+// PR17371
+struct OverloadedNewDelete {
+ // __cdecl
+ void *operator new(__SIZE_TYPE__);
+ void *operator new[](__SIZE_TYPE__);
+ void operator delete(void *);
+ void operator delete[](void *);
+ // __thiscall
+ int operator+(int);
+};
+
+void *OverloadedNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
+void *OverloadedNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
+void OverloadedNewDelete::operator delete(void *) { }
+void OverloadedNewDelete::operator delete[](void *) { }
+int OverloadedNewDelete::operator+(int x) { return x; };
+
+// CHECK-DAG: ??2OverloadedNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??_UOverloadedNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??3OverloadedNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??_VOverloadedNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??HOverloadedNewDelete@@QAEHH@Z
+
+// X64-DAG: ??2OverloadedNewDelete@@SAPEAX_K@Z
+// X64-DAG: ??_UOverloadedNewDelete@@SAPEAX_K@Z
+// X64-DAG: ??3OverloadedNewDelete@@SAXPEAX@Z
+// X64-DAG: ??_VOverloadedNewDelete@@SAXPEAX@Z
+// X64-DAG: ??HOverloadedNewDelete@@QEAAHH@Z
+
+// Indirecting the function type through a typedef will require a calling
+// convention adjustment before building the method decl.
+
+typedef void *__thiscall OperatorNewType(__SIZE_TYPE__);
+typedef void __thiscall OperatorDeleteType(void *);
+
+struct TypedefNewDelete {
+ OperatorNewType operator new;
+ OperatorNewType operator new[];
+ OperatorDeleteType operator delete;
+ OperatorDeleteType operator delete[];
+};
+
+void *TypedefNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
+void *TypedefNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
+void TypedefNewDelete::operator delete(void *) { }
+void TypedefNewDelete::operator delete[](void *) { }
+
+// CHECK-DAG: ??2TypedefNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??_UTypedefNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits