From 8ecbed3b1a3fe7702c59b4e703beacabbd08e898 Mon Sep 17 00:00:00 2001 From: Andrey Bokhanko Date: Wed, 11 May 2016 18:38:21 +0000 Subject: [MSVC] Implementation of __unaligned as a proper type qualifier This patch implements __unaligned (MS extension) as a proper type qualifier (before that, it was implemented as an ignored attribute). It also fixes PR27367 and PR27666. Differential Revision: http://reviews.llvm.org/D20103 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269220 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 49 +++++++++----- include/clang/Basic/AddressSpaces.h | 2 +- include/clang/Basic/Attr.td | 4 -- include/clang/Basic/DiagnosticSemaKinds.td | 10 +++ include/clang/Sema/DeclSpec.h | 23 +++++-- include/clang/Sema/Sema.h | 3 +- lib/AST/MicrosoftMangle.cpp | 5 ++ lib/AST/TypePrinter.cpp | 6 ++ lib/Parse/ParseDecl.cpp | 15 +++-- lib/Parse/ParseTentative.cpp | 2 +- lib/Sema/DeclSpec.cpp | 6 +- lib/Sema/SemaCodeComplete.cpp | 3 + lib/Sema/SemaDecl.cpp | 7 ++ lib/Sema/SemaDeclObjC.cpp | 1 + lib/Sema/SemaExpr.cpp | 2 +- lib/Sema/SemaOverload.cpp | 22 +++++- lib/Sema/SemaType.cpp | 37 +++++----- test/CodeGenCXX/mangle-ms-cxx11.cpp | 16 +++++ test/CodeGenCXX/mangle-ms-cxx14.cpp | 5 ++ test/Sema/MicrosoftExtensions.c | 8 +++ test/Sema/address_spaces.c | 4 +- .../invalid-assignment-constant-address-space.c | 2 +- test/SemaCXX/MicrosoftExtensions.cpp | 78 +++++++++++++++++++++- 23 files changed, 255 insertions(+), 55 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 71004fc572..09b3fc79b8 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -111,6 +111,7 @@ namespace clang { /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict +/// * MS: __unaligned /// * Embedded C (TR18037): address spaces /// * Objective C: the GC attributes (none, weak, or strong) class Qualifiers { @@ -152,8 +153,8 @@ public: enum { /// The maximum supported address space number. - /// 24 bits should be enough for anyone. - MaxAddressSpace = 0xffffffu, + /// 23 bits should be enough for anyone. + MaxAddressSpace = 0x7fffffu, /// The width of the "fast" qualifier mask. FastWidth = 3, @@ -265,6 +266,13 @@ public: Mask |= mask; } + bool hasUnaligned() const { return Mask & UMask; } + void setUnaligned(bool flag) { + Mask = (Mask & ~UMask) | (flag ? UMask : 0); + } + void removeUnaligned() { Mask &= ~UMask; } + void addUnaligned() { Mask |= UMask; } + bool hasObjCGCAttr() const { return Mask & GCAttrMask; } GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); } void setObjCGCAttr(GC type) { @@ -433,7 +441,9 @@ public: // ObjC lifetime qualifiers must match exactly. getObjCLifetime() == other.getObjCLifetime() && // CVR qualifiers may subset. - (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); + (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)) && + // U qualifier may superset. + (!other.hasUnaligned() || hasUnaligned()); } /// \brief Determines if these qualifiers compatibly include another set of @@ -501,16 +511,19 @@ public: private: - // bits: |0 1 2|3 .. 4|5 .. 7|8 ... 31| - // |C R V|GCAttr|Lifetime|AddressSpace| + // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| + // |C R V|U|GCAttr|Lifetime|AddressSpace| uint32_t Mask; - static const uint32_t GCAttrMask = 0x18; - static const uint32_t GCAttrShift = 3; - static const uint32_t LifetimeMask = 0xE0; - static const uint32_t LifetimeShift = 5; - static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask); - static const uint32_t AddressSpaceShift = 8; + static const uint32_t UMask = 0x8; + static const uint32_t UShift = 3; + static const uint32_t GCAttrMask = 0x30; + static const uint32_t GCAttrShift = 4; + static const uint32_t LifetimeMask = 0x1C0; + static const uint32_t LifetimeShift = 6; + static const uint32_t AddressSpaceMask = + ~(CVRMask | UMask | GCAttrMask | LifetimeMask); + static const uint32_t AddressSpaceShift = 9; }; /// A std::pair-like structure for storing a qualified type split @@ -5367,9 +5380,9 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { /// "int". However, it is not more qualified than "const volatile /// int". inline bool QualType::isMoreQualifiedThan(QualType other) const { - Qualifiers myQuals = getQualifiers(); - Qualifiers otherQuals = other.getQualifiers(); - return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals)); + Qualifiers MyQuals = getQualifiers(); + Qualifiers OtherQuals = other.getQualifiers(); + return (MyQuals != OtherQuals && MyQuals.compatiblyIncludes(OtherQuals)); } /// Determine whether this type is at last @@ -5377,7 +5390,13 @@ inline bool QualType::isMoreQualifiedThan(QualType other) const { /// int" is at least as qualified as "const int", "volatile int", /// "int", and "const volatile int". inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { - return getQualifiers().compatiblyIncludes(other.getQualifiers()); + Qualifiers OtherQuals = other.getQualifiers(); + + // Ignore __unaligned qualifier if this type is a void. + if (getUnqualifiedType()->isVoidType()) + OtherQuals.removeUnaligned(); + + return getQualifiers().compatiblyIncludes(OtherQuals); } /// If Type is a reference type (e.g., const diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 8dd75660c6..63df61bedb 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -25,7 +25,7 @@ namespace LangAS { /// This uses a high starting offset so as not to conflict with any address /// space used by a target. enum ID { - Offset = 0xFFFF00, + Offset = 0x7FFF00, opencl_global = Offset, opencl_local, diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index e3c5e44265..8bc5dfcadc 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -2157,10 +2157,6 @@ def InitSeg : Attr { }]; } -def Unaligned : IgnoredAttr { - let Spellings = [Keyword<"__unaligned">]; -} - def LoopHint : Attr { /// #pragma clang loop