summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/Mangle.cpp29
-rw-r--r--clang/test/CodeGenCXX/mangle.cpp22
-rw-r--r--clang/test/CodeGenCXX/member-functions.cpp2
3 files changed, 43 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp
index 6c28d22f6b6..089d77764e4 100644
--- a/clang/lib/CodeGen/Mangle.cpp
+++ b/clang/lib/CodeGen/Mangle.cpp
@@ -480,10 +480,17 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType()));
break;
- case DeclarationName::CXXOperatorName:
- mangleOperatorName(Name.getCXXOverloadedOperator(),
- cast<FunctionDecl>(ND)->getNumParams());
+ case DeclarationName::CXXOperatorName: {
+ unsigned Arity = cast<FunctionDecl>(ND)->getNumParams();
+
+ // If we have a C++ member function, we need to include the 'this' pointer.
+ // FIXME: This does not make sense for operators that are static, but their
+ // names stay the same regardless of the arity (operator new for instance).
+ if (isa<CXXMethodDecl>(ND))
+ Arity++;
+ mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
break;
+ }
case DeclarationName::CXXLiteralOperatorName:
// FIXME: This mangling is not yet official.
@@ -611,16 +618,24 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
case OO_Array_Delete: Out << "da"; break;
// ::= ps # + (unary)
// ::= pl # +
- case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
+ case OO_Plus:
+ assert((Arity == 1 || Arity == 2) && "Invalid arity!");
+ Out << (Arity == 1? "ps" : "pl"); break;
// ::= ng # - (unary)
// ::= mi # -
- case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
+ case OO_Minus:
+ assert((Arity == 1 || Arity == 2) && "Invalid arity!");
+ Out << (Arity == 1? "ng" : "mi"); break;
// ::= ad # & (unary)
// ::= an # &
- case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
+ case OO_Amp:
+ assert((Arity == 1 || Arity == 2) && "Invalid arity!");
+ Out << (Arity == 1? "ad" : "an"); break;
// ::= de # * (unary)
// ::= ml # *
- case OO_Star: Out << (Arity == 1? "de" : "ml"); break;
+ case OO_Star:
+ assert((Arity == 1 || Arity == 2) && "Invalid arity!");
+ Out << (Arity == 1? "de" : "ml"); break;
// ::= co # ~
case OO_Tilde: Out << "co"; break;
// ::= dv # /
diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp
index 090a3f17eef..88465cf9d98 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -141,7 +141,7 @@ int f(struct a *x) {
// PR5017
extern "C" {
struct Debug {
- const Debug& operator<< (unsigned a) const { }
+ const Debug& operator<< (unsigned a) const { return *this; }
};
Debug dbg;
// CHECK: @_ZNK5DebuglsEj
@@ -270,5 +270,23 @@ template void f4<1>(int (*)[4]);
// CHECK: define void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
template <bool b> void f4(int (*)[b ? 1 : 2]) { };
template void f4<true>(int (*)[1]);
-
}
+
+struct Ops {
+ Ops& operator+(const Ops&);
+ Ops& operator-(const Ops&);
+ Ops& operator&(const Ops&);
+ Ops& operator*(const Ops&);
+
+ void *v;
+};
+
+// CHECK: define %struct.Ops* @_ZN3OpsplERKS_
+Ops& Ops::operator+(const Ops&) { return *this; }
+// CHECK: define %struct.Ops* @_ZN3OpsmiERKS_
+Ops& Ops::operator-(const Ops&) { return *this; }
+// CHECK: define %struct.Ops* @_ZN3OpsanERKS_
+Ops& Ops::operator&(const Ops&) { return *this; }
+// CHECK: define %struct.Ops* @_ZN3OpsmlERKS_
+Ops& Ops::operator*(const Ops&) { return *this; }
+
diff --git a/clang/test/CodeGenCXX/member-functions.cpp b/clang/test/CodeGenCXX/member-functions.cpp
index ebc9ed758be..087e62c5bb3 100644
--- a/clang/test/CodeGenCXX/member-functions.cpp
+++ b/clang/test/CodeGenCXX/member-functions.cpp
@@ -58,6 +58,6 @@ struct T {
void test3() {
T t1, t2;
- // RUN: grep "call i64 @_ZN1TpsERKS_" %t
+ // RUN: grep "call i64 @_ZN1TplERKS_" %t
T result = t1 + t2;
}
OpenPOWER on IntegriCloud