]> granicus.if.org Git - clang/commitdiff
[MSVC] Support for __unaligned qualifier in functions
authorAndrey Bokhanko <andreybokhanko@gmail.com>
Thu, 26 May 2016 10:06:01 +0000 (10:06 +0000)
committerAndrey Bokhanko <andreybokhanko@gmail.com>
Thu, 26 May 2016 10:06:01 +0000 (10:06 +0000)
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

include/clang/AST/Type.h
include/clang/Sema/DeclSpec.h
lib/AST/DeclCXX.cpp
lib/AST/MicrosoftMangle.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaType.cpp
test/CodeGenCXX/mangle-ms-cxx11.cpp
test/Sema/MicrosoftExtensions.c
test/SemaCXX/MicrosoftExtensions.cpp

index 05650c93ac416b5c32cd5c166156998d2bf8c06f..b1773b335beda6e7568d9a9564122dede010dff4 100644 (file)
@@ -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.
     ///
index 0c4d94efbbf1deab89b27807a2d27626a87a2d3a..1f04c996a147844a89ab306a311cbe1dd393cfd9 100644 (file)
@@ -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 {
index 45205e8b201347bd45f65ee18c7568d0b6cbeb1a..2a1fac8509eb5881c87e09f941c49175dd557d05 100644 (file)
@@ -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);
 }
 
index a88e2a621ce29d424bc97174c98d90bc9396450f..b93156cabae7a58a07705a5b1425d007f8bd383d 100644 (file)
@@ -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);
index de013afa14d1b68ff75bbc6da5fef0e1dbc17a9e..b9d2843b0558c87fefcef52f0e25ed40e2487dcc 100644 (file)
@@ -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!");
index 7365f6cc8d22c27e463305542af5913979346c1c..4b1be6483c4fcb0fe7d1bb022f83c466ea574705 100644 (file)
@@ -934,6 +934,8 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
   else
     Record = cast<CXXRecordDecl>(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));
index d99d9521f47bac165f38d80b1890f69405be6417..113c7c7bf06008e66976c6ad11cda942f5373099 100644 (file)
@@ -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;
index 12bb8c7ee54e8f728f4bf31bfb72bf91c4f5e3b9..8e2577b03e2673bf035529610cea58abf4ebc54d 100644 (file)
@@ -309,3 +309,12 @@ void unaligned_foo7() { unaligned_foo6<int *>(0); unaligned_foo6<int __unaligned
 // 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 713daf5593fd6e6d8001f1f4ead789a4ea8987f0..cdef5dc309daebf312d28318eb1093474a8b5f7a 100644 (file)
@@ -178,3 +178,5 @@ void test_unaligned() {
   __unaligned int *p3 = p2;
 }
 
+void test_unaligned2(int x[__unaligned 4]) {}
+
index e24e45d871ebe2ac0b10081325bd9afe1b816935..e10deadf7c7f52c62609764efd0559bb823c9e24 100644 (file)
@@ -91,6 +91,7 @@ struct aligned_type4 {
 __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) {}
@@ -119,6 +120,9 @@ void test_unaligned() {
   p1_aligned_type4 = p2_aligned_type4;
   p2_aligned_type4 = p1_aligned_type4; // expected-error {{assigning to 'int aligned_type4::*' from incompatible type '__unaligned int aligned_type4::*'}}
   p3_aligned_type4 = p1_aligned_type4;
+
+  __unaligned int a[10];
+  int *b = a; // expected-error {{cannot initialize a variable of type 'int *' with an lvalue of type '__unaligned int [10]'}}
 }
 
 // Test from PR27367