Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -3639,6 +3639,7 @@ attr_null_unspecified, attr_objc_kindof, attr_objc_inert_unsafe_unretained, + attr_unaligned, }; private: Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2075,8 +2075,10 @@ }]; } -def Unaligned : IgnoredAttr { +def Unaligned : TypeAttr { let Spellings = [Keyword<"__unaligned">]; + let LangOpts = [MicrosoftExt]; + let Documentation = [UnalignedDocs]; } def LoopHint : Attr { Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1957,3 +1957,18 @@ The system will crash if the wrong handler is used. }]; } + +def UnalignedDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``__unaligned`` modifier declares a pointer with an unaligned address. +It is available under the ``-fms-extensions`` flag for MSVC compatibility. +See the documentation for `__unaligned`_ on MSDN. + +.. _`__unaligned`: https://msdn.microsoft.com/en-us/library/ms177389.aspx + +Clang supports proper mangling of the variables with ``unaligned`` modifier, +but it doesn't affect generated code in any other way. + }]; +} + Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1413,6 +1413,11 @@ if (HasRestrict) Out << 'I'; + + if (!PointeeType.isNull()) + if (auto AT = PointeeType->getAs()) + if (AT->getAttrKind() == AttributedType::attr_unaligned) + Out << 'F'; } void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) { Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -3003,6 +3003,7 @@ case AttributedType::attr_sptr: case AttributedType::attr_uptr: case AttributedType::attr_objc_kindof: + case AttributedType::attr_unaligned: return false; } llvm_unreachable("bad attributed type kind"); @@ -3015,6 +3016,7 @@ case attr_ptr64: case attr_sptr: case attr_uptr: + case attr_unaligned: return true; } llvm_unreachable("invalid attr kind"); @@ -3039,6 +3041,7 @@ case attr_nullable: case attr_null_unspecified: case attr_objc_kindof: + case attr_unaligned: return false; case attr_pcs: Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -1156,6 +1156,7 @@ case AttributedType::attr_ptr64: OS << " __ptr64"; break; case AttributedType::attr_sptr: OS << " __sptr"; break; case AttributedType::attr_uptr: OS << " __uptr"; break; + case AttributedType::attr_unaligned: OS << " __unaligned"; break; } spaceBeforePlaceHolder(OS); } Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -120,7 +120,8 @@ case AttributeList::AT_Ptr32: \ case AttributeList::AT_Ptr64: \ case AttributeList::AT_SPtr: \ - case AttributeList::AT_UPtr + case AttributeList::AT_UPtr: \ + case AttributeList::AT_Unaligned // Nullability qualifiers. #define NULLABILITY_TYPE_ATTRS_CASELIST \ @@ -4538,6 +4539,8 @@ return AttributeList::AT_TypeNullUnspecified; case AttributedType::attr_objc_kindof: return AttributeList::AT_ObjCKindOf; + case AttributedType::attr_unaligned: + return AttributeList::AT_Unaligned; } llvm_unreachable("unexpected attribute kind!"); } @@ -5548,7 +5551,7 @@ // Pointer type qualifiers can only operate on pointer types, but not // pointer-to-member types. - if (!isa(Desugared)) { + if (!isa(Desugared) && (Kind != AttributeList::AT_Unaligned)) { if (Type->isMemberPointerType()) S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) << Attr.getName(); @@ -5565,6 +5568,7 @@ case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break; case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break; case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break; + case AttributeList::AT_Unaligned: TAK = AttributedType::attr_unaligned; break; } Type = S.Context.getAttributedType(TAK, Type, Type); Index: test/CodeGenCXX/mangle-ms-cxx11.cpp =================================================================== --- test/CodeGenCXX/mangle-ms-cxx11.cpp +++ test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -293,3 +293,13 @@ } // CHECK-DAG: @"\01??R@?0??PR26105@@YAHXZ@QBE@H@Z" // CHECK-DAG: @"\01??R@?0???R@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z" + +int __unaligned * unaligned_foo1() { return 0; } +int __unaligned * __unaligned * unaligned_foo2() { return 0; } +__unaligned int unaligned_foo3() { return 0; } +void unaligned_foo4(int __unaligned *p1) {} + +// CHECK-DAG: @"\01?unaligned_foo1@@YAPFAHXZ" +// CHECK-DAG: @"\01?unaligned_foo2@@YAPFAPFAHXZ" +// CHECK-DAG: @"\01?unaligned_foo3@@YAHXZ" +// CHECK-DAG: @"\01?unaligned_foo4@@YAXPFAH@Z" Index: test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- test/SemaCXX/MicrosoftExtensions.cpp +++ test/SemaCXX/MicrosoftExtensions.cpp @@ -80,6 +80,7 @@ // __unaligned handling typedef char __unaligned *aligned_type; typedef struct UnalignedTag { int f; } __unaligned *aligned_type2; +typedef __unaligned char *aligned_type3; template void h1(T (__stdcall M::* const )()) { }