Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -215,6 +215,12 @@ return Qs; } + static Qualifiers fromCVRUMask(unsigned CVRU) { + Qualifiers Qs; + Qs.addCVRUQualifiers(CVRU); + return Qs; + } + // Deserialize qualifiers from an opaque representation. static Qualifiers fromOpaqueValue(unsigned opaque) { Qualifiers Qs; @@ -265,6 +271,10 @@ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); Mask |= mask; } + void addCVRUQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask & ~UMask) && "bitmask contains non-CVRU bits"); + Mask |= mask; + } bool hasUnaligned() const { return Mask & UMask; } void setUnaligned(bool flag) { @@ -1372,7 +1382,7 @@ /// /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. - unsigned TypeQuals : 3; + unsigned TypeQuals : 4; /// \brief The ref-qualifier associated with a \c FunctionProtoType. /// Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -311,12 +311,10 @@ TQ_const = 1, TQ_restrict = 2, TQ_volatile = 4, + TQ_unaligned = 8, // This has no corresponding Qualifiers::TQ value, because it's not treated // as a qualifier in our type system. - TQ_atomic = 8, - // There is no corresponding Qualifiers::TQ value, but it's kept separately - // in a dedicated Qualifiers::Mask bit. - TQ_unaligned = 16 + TQ_atomic = 16 }; /// ParsedSpecifiers - Flags to query which specifiers were applied. This is @@ -1120,7 +1118,7 @@ }; struct PointerTypeInfo : TypeInfoCommon { - /// The type qualifiers: const/volatile/restrict/atomic/unaligned. + /// The type qualifiers: const/volatile/restrict/unaligned/atomic. unsigned TypeQuals : 5; /// The location of the const-qualifier, if any. @@ -1152,8 +1150,9 @@ }; struct ArrayTypeInfo : TypeInfoCommon { - /// The type qualifiers for the array: const/volatile/restrict/_Atomic. - unsigned TypeQuals : 4; + /// The type qualifiers for the array: + /// const/volatile/restrict/__unaligned/_Atomic. + unsigned TypeQuals : 5; /// True if this dimension included the 'static' keyword. bool hasStatic : 1; @@ -1219,9 +1218,9 @@ /// Otherwise, it's an rvalue reference. unsigned RefQualifierIsLValueRef : 1; - /// The type qualifiers: const/volatile/restrict. + /// The type qualifiers: const/volatile/restrict/__unaligned /// The qualifier bitmask values are the same as in QualType. - unsigned TypeQuals : 3; + unsigned TypeQuals : 4; /// ExceptionSpecType - An ExceptionSpecificationType value. unsigned ExceptionSpecType : 4; @@ -1405,16 +1404,16 @@ struct BlockPointerTypeInfo : TypeInfoCommon { /// For now, sema will catch these as invalid. - /// The type qualifiers: const/volatile/restrict/_Atomic. - unsigned TypeQuals : 4; + /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. + unsigned TypeQuals : 5; void destroy() { } }; struct MemberPointerTypeInfo : TypeInfoCommon { - /// The type qualifiers: const/volatile/restrict/_Atomic. - unsigned TypeQuals : 4; + /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. + unsigned TypeQuals : 5; // CXXScopeSpec has a constructor, so it can't be a direct member. // So we need some pointer-aligned storage and a bit of trickery. union { Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1643,7 +1643,7 @@ QualType ClassTy = C.getTypeDeclType(getParent()); ClassTy = C.getQualifiedType(ClassTy, - Qualifiers::fromCVRMask(getTypeQualifiers())); + Qualifiers::fromCVRUMask(getTypeQualifiers())); return C.getPointerType(ClassTy); } Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1447,7 +1447,8 @@ if (HasRestrict) Out << 'I'; - if (!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned()) + if (Quals.hasUnaligned() || + (!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned())) Out << 'F'; } @@ -1822,7 +1823,7 @@ // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { - Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); + Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals()); manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -796,8 +796,8 @@ case TQ_const: TQ_constLoc = Loc; return false; case TQ_restrict: TQ_restrictLoc = Loc; return false; case TQ_volatile: TQ_volatileLoc = Loc; return false; - case TQ_atomic: TQ_atomicLoc = Loc; return false; case TQ_unaligned: TQ_unalignedLoc = Loc; return false; + case TQ_atomic: TQ_atomicLoc = Loc; return false; } llvm_unreachable("Unknown type qualifier!"); Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -934,6 +934,7 @@ else Record = cast(ContextDecl); + CXXThisTypeQuals &= Qualifiers::FastMask; S.CXXThisTypeOverride = S.Context.getPointerType( S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -2668,8 +2668,8 @@ { "const", DeclSpec::TQ_const, ConstQualLoc }, { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc }, { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc }, - { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }, - { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc } + { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc }, + { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc } }; SmallString<32> QualStr; Index: test/CodeGenCXX/mangle-ms-cxx11.cpp =================================================================== --- test/CodeGenCXX/mangle-ms-cxx11.cpp +++ test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -309,3 +309,12 @@ // CHECK-DAG: @"\01?unaligned_foo5@@YAXPIFAH@Z" // CHECK-DAG: @"\01??$unaligned_foo6@PAH@@YAPAHPAH@Z" // CHECK-DAG: @"\01??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z" + +// __unaligned qualifier for function types +struct unaligned_foo8_S { + void unaligned_foo8() volatile __unaligned; +}; +void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {} + +// CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ" + Index: test/Sema/MicrosoftExtensions.c =================================================================== --- test/Sema/MicrosoftExtensions.c +++ test/Sema/MicrosoftExtensions.c @@ -178,3 +178,5 @@ __unaligned int *p3 = p2; } +void test_unaligned2(int x[__unaligned 4]) {} + Index: test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- test/SemaCXX/MicrosoftExtensions.cpp +++ test/SemaCXX/MicrosoftExtensions.cpp @@ -91,6 +91,7 @@ __unaligned int aligned_type4::*p1_aligned_type4 = &aligned_type4::i; int aligned_type4::* __unaligned p2_aligned_type4 = &aligned_type4::i; __unaligned int aligned_type4::* __unaligned p3_aligned_type4 = &aligned_type4::i; +void (aligned_type4::*__unaligned p4_aligned_type4)(); // Check that __unaligned qualifier can be used for overloading void foo_unaligned(int *arg) {}