diff options
-rw-r--r-- | clang/include/clang/AST/Type.h | 12 | ||||
-rw-r--r-- | clang/include/clang/Sema/DeclSpec.h | 25 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-ms-cxx11.cpp | 9 | ||||
-rw-r--r-- | clang/test/Sema/MicrosoftExtensions.c | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/MicrosoftExtensions.cpp | 4 |
10 files changed, 47 insertions, 20 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 05650c93ac4..b1773b335be 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/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/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 0c4d94efbbf..1f04c996a14 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/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/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 45205e8b201..2a1fac8509e 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/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/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index a88e2a621ce..b93156cabae 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/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/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index de013afa14d..b9d2843b055 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7365f6cc8d2..4b1be6483c4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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)); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d99d9521f47..113c7c7bf06 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/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/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp index 12bb8c7ee54..8e2577b03e2 100644 --- a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -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" + diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c index 713daf5593f..cdef5dc309d 100644 --- a/clang/test/Sema/MicrosoftExtensions.c +++ b/clang/test/Sema/MicrosoftExtensions.c @@ -178,3 +178,5 @@ void test_unaligned() { __unaligned int *p3 = p2; } +void test_unaligned2(int x[__unaligned 4]) {} + diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index e24e45d871e..e10deadf7c7 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -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 |