From: Andrey Bokhanko Date: Thu, 26 May 2016 10:06:01 +0000 (+0000) Subject: [MSVC] Support for __unaligned qualifier in functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de5174673b83e0bae7f73be2360c32f49e168bca;p=clang [MSVC] Support for __unaligned qualifier in functions This implements support for MS-specific __unaligned qualifier in functions and makes the following test case both compile and mangle correctly: struct S { void f() __unaligned; }; void S::f() __unaligned { } Differential Revision: http://reviews.llvm.org/D20437 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@270834 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 05650c93ac..b1773b335b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -215,6 +215,12 @@ public: 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 @@ public: 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) { @@ -1375,7 +1385,7 @@ protected: /// /// 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. /// diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 0c4d94efbb..1f04c996a1 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -311,12 +311,10 @@ public: 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 DeclaratorChunk { }; 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 DeclaratorChunk { }; 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 @@ struct DeclaratorChunk { /// 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 DeclaratorChunk { 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 { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 45205e8b20..2a1fac8509 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1646,7 +1646,7 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { QualType ClassTy = C.getTypeDeclType(getParent()); ClassTy = C.getQualifiedType(ClassTy, - Qualifiers::fromCVRMask(getTypeQualifiers())); + Qualifiers::fromCVRUMask(getTypeQualifiers())); return C.getPointerType(ClassTy); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index a88e2a621c..b93156caba 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1447,7 +1447,8 @@ void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, if (HasRestrict) Out << 'I'; - if (!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned()) + if (Quals.hasUnaligned() || + (!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned())) Out << 'F'; } @@ -1822,7 +1823,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // 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); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index de013afa14..b9d2843b05 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -796,8 +796,8 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, 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!"); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7365f6cc8d..4b1be6483c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -934,6 +934,8 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, else Record = cast(ContextDecl); + // We care only for CVR qualifiers here, so cut everything else. + CXXThisTypeQuals &= Qualifiers::FastMask; S.CXXThisTypeOverride = S.Context.getPointerType( S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d99d9521f4..113c7c7bf0 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2668,8 +2668,8 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, { "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; diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 12bb8c7ee5..8e2577b03e 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -309,3 +309,12 @@ void unaligned_foo7() { unaligned_foo6(0); unaligned_foo6