Index: cfe/trunk/lib/AST/ItaniumMangle.cpp =================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp +++ cfe/trunk/lib/AST/ItaniumMangle.cpp @@ -1459,8 +1459,6 @@ // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); - // __unaligned is not currently mangled in any way, so remove it. - MethodQuals.removeUnaligned(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } @@ -2140,7 +2138,8 @@ } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // Vendor qualifiers come first. + // Vendor qualifiers come first and if they are order-insensitive they must + // be emitted in reversed alphabetical order, see Itanium ABI 5.1.5. // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { @@ -2176,17 +2175,28 @@ } // The ARC ownership qualifiers start with underscores. - switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // // ::= U "__strong" // ::= U "__weak" // ::= U "__autoreleasing" + // + // Note: we emit __weak first to preserve the order as + // required by the Itanium ABI. + if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak) + mangleVendorQualifier("__weak"); + + // __unaligned (from -fms-extensions) + if (Quals.hasUnaligned()) + mangleVendorQualifier("__unaligned"); + + // Remaining ARC ownership qualifiers. + switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: break; case Qualifiers::OCL_Weak: - mangleVendorQualifier("__weak"); + // Do nothing as we already handled this case above. break; case Qualifiers::OCL_Strong: @@ -4327,7 +4337,7 @@ /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { Qualifiers Qs = T.getQualifiers(); - return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned(); } bool CXXNameMangler::mangleSubstitution(QualType T) { Index: cfe/trunk/test/CodeGenCXX/pr33080.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/pr33080.cpp +++ cfe/trunk/test/CodeGenCXX/pr33080.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm -o- %s | FileCheck %s + +void fa(__unaligned struct A *) {} +// CHECK: define void @_Z2faPU11__unaligned1A( + +void ga(struct A *, struct A *) {} +// CHECK: define void @_Z2gaP1AS0_( + +void gb(__unaligned struct A *, struct A *) {} +// CHECK: define void @_Z2gbPU11__unaligned1APS_( + +void gc(struct A *, __unaligned struct A *) {} +// CHECK: define void @_Z2gcP1APU11__unalignedS_( + +void gd(__unaligned struct A *, __unaligned struct A *) {} +// CHECK: define void @_Z2gdPU11__unaligned1AS1_( + +void hb(__unaligned struct A *, __unaligned const struct A *) {} +// CHECK: define void @_Z2hbPU11__unaligned1APU11__unalignedKS_( + +void ja(__unaligned struct A *, __unaligned struct A *__unaligned *, __unaligned struct A *__unaligned *__unaligned *) {} +// CHECK: define void @_Z2jaPU11__unaligned1APU11__unalignedS1_PU11__unalignedS3_( + +void jb(__unaligned struct A *, __unaligned struct A **, __unaligned struct A *__unaligned *__unaligned *) {} +// CHECK: @_Z2jbPU11__unaligned1APS1_PU11__unalignedPU11__unalignedS1_( + +template +void ta(T &, Q *) {} + +void ia(__unaligned struct A &a) { + ta(a, &a); +} +// CHECK: @_Z2taIU11__unaligned1AS1_EvRT_PT0_( Index: cfe/trunk/test/CodeGenCXX/unaligned-member-qualifier.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/unaligned-member-qualifier.cpp +++ cfe/trunk/test/CodeGenCXX/unaligned-member-qualifier.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -fms-extensions -emit-llvm %s -o- | FileCheck %s + +struct A { + void foo() __unaligned; + void foo() const __unaligned; + void foo() volatile __unaligned; + void foo() const volatile __unaligned; +}; + +void A::foo() __unaligned {} +// CHECK: define void @_ZNU11__unaligned1A3fooEv( + +void A::foo() const __unaligned {} +// CHECK: define void @_ZNU11__unalignedK1A3fooEv( + +void A::foo() volatile __unaligned {} +// CHECK: define void @_ZNU11__unalignedV1A3fooEv( + +void A::foo() const volatile __unaligned {} +// CHECK: define void @_ZNU11__unalignedVK1A3fooEv( Index: cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm =================================================================== --- cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm +++ cfe/trunk/test/CodeGenObjCXX/arc-mangle.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -fblocks -o - %s | FileCheck %s +// RUN: %clang_cc1 -DTEST_UNALIGNED -fms-extensions -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -fblocks -o - %s | FileCheck %s --check-prefix=UNALIGNED // CHECK-LABEL: define {{.*}}void @_Z1fPU8__strongP11objc_object(i8**) void f(__strong id *) {} @@ -32,3 +33,12 @@ // CHECK-LABEL: define weak_odr {{.*}}void @_Z1gIKvEvP10unsigned_cIXplszv1U8__bridgecvPT_v1U8__bridgecvP11objc_objectcvS3_Li0ELi1EEE templatevoid g(unsigned_c*) {} template void g(unsigned_c *); + +#if TEST_UNALIGNED +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU6__weakU11__unalignedP11objc_object(i8**) +void g(__weak __unaligned id *) {} +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU11__unalignedU8__strongP11objc_object(i8**) +void g(__strong __unaligned id *) {} +// UNALIGNED-LABEL: define {{.*}}void @_Z1gPU11__unalignedU15__autoreleasingP11objc_object(i8**) +void g(__autoreleasing __unaligned id *) {} +#endif // TEST_UNALIGNED