forked from OSchip/llvm-project
[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 llvm-svn: 270834
This commit is contained in:
parent
57446efaa9
commit
67a4186ee6
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -178,3 +178,5 @@ void test_unaligned() {
|
|||
__unaligned int *p3 = p2;
|
||||
}
|
||||
|
||||
void test_unaligned2(int x[__unaligned 4]) {}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue