namespace {
-static const DeclContext *GetLocalClassFunctionDeclContext(
- const DeclContext *DC) {
- if (isa<CXXRecordDecl>(DC)) {
- while (!DC->isNamespace() && !DC->isTranslationUnit() &&
- !isa<FunctionDecl>(DC))
- DC = DC->getParent();
- if (isa<FunctionDecl>(DC))
- return DC;
+static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
+ const DeclContext *DC = dyn_cast<DeclContext>(ND);
+ if (!DC)
+ DC = ND->getDeclContext();
+ while (!DC->isNamespace() && !DC->isTranslationUnit()) {
+ if (isa<FunctionDecl>(DC->getParent()))
+ return dyn_cast<CXXRecordDecl>(DC);
+ DC = DC->getParent();
}
return 0;
}
//
const DeclContext *DC = ND->getDeclContext();
- if (GetLocalClassFunctionDeclContext(DC)) {
- mangleLocalName(ND);
- return;
- }
-
// If this is an extern variable declared locally, the relevant DeclContext
// is that of the containing namespace, or the translation unit.
if (isa<FunctionDecl>(DC) && ND->hasLinkage())
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = DC->getParent();
+ else if (GetLocalClassDecl(ND)) {
+ mangleLocalName(ND);
+ return;
+ }
while (isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(MD);
- }
- else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) {
- mangleFunctionEncoding(cast<FunctionDecl>(CDC));
+ } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
+ mangleFunctionEncoding(cast<FunctionDecl>(RD->getDeclContext()));
Out << 'E';
- mangleNestedName(ND, DC, true /*NoFunction*/);
- // FIXME. This still does not cover all cases.
+ // Mangle the name relative to the closest enclosing function.
+ if (ND == RD) // equality ok because RD derived from ND above
+ mangleUnqualifiedName(ND);
+ else
+ mangleNestedName(ND, DC, true /*NoFunction*/);
+
unsigned disc;
- if (Context.getNextDiscriminator(ND, disc)) {
+ if (Context.getNextDiscriminator(RD, disc)) {
if (disc < 10)
Out << '_' << disc;
else
--- /dev/null
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: @_ZTVZ3foovEN1C1DE =
+// CHECK: @_ZTVZN1A3fooEiE1B =
+// CHECK: define {{.*}} @_ZZZ3foovEN1C3barEvEN1E3bazEv(
+
+// Itanium C++ ABI examples.
+struct A {
+ void foo (int) {
+ struct B { virtual ~B() {} };
+ B();
+ }
+};
+void foo () {
+ struct C {
+ struct D { virtual ~D() {} };
+ void bar () {
+ struct E {
+ void baz() { }
+ };
+ E().baz();
+ }
+ };
+ A().foo(0);
+ C::D();
+ C().bar();
+}
--- /dev/null
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: @_ZTVZN1J1KEvE1C = {{.*}} @_ZTIZN1J1KEvE1C {{.*}} @_ZZN1J1KEvENK1C1FEv
+// CHECK: @_ZTIZN1J1KEvE1C = {{.*}} @_ZTSZN1J1KEvE1C
+// CHECK: @_ZTVZ1GvE1C_1 = {{.*}} @_ZTIZ1GvE1C_1 {{.*}} @_ZZ1GvENK1C1FE_1v
+// CHECK: @_ZTIZ1GvE1C_1 = {{.*}} @_ZTSZ1GvE1C_1
+// CHECK: @_ZTVZ1GvE1C_0 = {{.*}} @_ZTIZ1GvE1C_0 {{.*}} @_ZZ1GvENK1C1FE_0v
+// CHECK: @_ZTIZ1GvE1C_0 = {{.*}} @_ZTSZ1GvE1C_0
+// CHECK: @_ZTVZ1GvE1C = {{.*}} @_ZTIZ1GvE1C {{.*}} @_ZZ1GvENK1C1FEv
+// CHECK: @_ZTIZ1GvE1C = {{.*}} @_ZTSZ1GvE1C
+
+// CHECK: define {{.*}} @_ZZN1J1KEvEN1CC2Ev(
+// CHECK: define {{.*}} @_ZZN1J1KEvENK1C1FEv(
+// CHECK: define {{.*}} @_ZZ1GvEN1CC2E_1v(
+// CHECK: define {{.*}} @_ZZ1GvENK1C1FE_1v(
+// CHECK: define {{.*}} @_ZZ1GvENK1C1HE_1v(
+// CHECK: define {{.*}} @_ZZ1GvEN1CC2E_0v(
+// CHECK: define {{.*}} @_ZZ1GvENK1C1FE_0v(
+// CHECK: define {{.*}} @_ZZ1GvENK1C1GE_0v(
+// CHECK: define {{.*}} @_ZZ1GvEN1CC2Ev(
+// CHECK: define {{.*}} @_ZZ1GvENK1C1FEv(
+
+struct I {
+ virtual void F() const = 0;
+};
+
+void Go(const I &i);
+
+void G() {
+ {
+ struct C : I {
+ void F() const {}
+ };
+ Go(C());
+ }
+ {
+ struct C : I {
+ void F() const { G(); }
+ void G() const {}
+ };
+ Go(C());
+ }
+ {
+ struct C : I {
+ void F() const { H(); }
+ void H() const {}
+ };
+ Go(C());
+ }
+}
+
+struct J {
+ void K();
+};
+
+void J::K() {
+ struct C : I {
+ void F() const {}
+ };
+ Go(C());
+}
--- /dev/null
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: @_ZTVZZ1HvEN1S1IEvE1S =
+
+// CHECK: define {{.*}} @_Z2L1v(
+// CHECK: define {{.*}} @_ZZ2L1vEN1S2L2Ev(
+// CHECK: define {{.*}} @_ZZ2L1vEN1S2L2E_0v(
+// CHECK: define {{.*}} @_ZZ1FvEN1S1T1S1T1GEv(
+// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2E_0vEN1S3L3cEv(
+// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2E_0vEN1S3L3dE_0v(
+// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2EvEN1S3L3aEv(
+// CHECK: define {{.*}} @_ZZZ2L1vEN1S2L2EvEN1S3L3bE_0v(
+
+void L1() {
+ {
+ struct S {
+ void L2() {
+ {
+ struct S {
+ void L3a() {}
+ };
+ S().L3a();
+ }
+ {
+ struct S {
+ void L3b() {}
+ };
+ S().L3b();
+ }
+ }
+ };
+ S().L2();
+ }
+ {
+ struct S {
+ void L2() {
+ {
+ struct S {
+ void L3c() {}
+ };
+ S().L3c();
+ }
+ {
+ struct S {
+ void L3d() {}
+ };
+ S().L3d();
+ }
+ }
+ };
+ S().L2();
+ }
+}
+
+void F() {
+ struct S {
+ struct T {
+ struct S {
+ struct T {
+ void G() {}
+ };
+ };
+ };
+ };
+ S::T::S::T().G();
+}
+
+struct B { virtual void Foo() = 0; };
+void G(const B &);
+
+void H() {
+ struct S {
+ void I() {
+ struct S : B {
+ virtual void Foo() {}
+ };
+ G(S());
+ }
+ };
+ S().I();
+}