diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bb8d204f33dc5..21a3b5226623c 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1798,24 +1798,11 @@ def ArmMveStrictPolymorphism : TypeAttr, TargetSpecificAttr { let Documentation = [ArmMveStrictPolymorphismDocs]; } -def NoUniqueAddress : InheritableAttr { - let Subjects = SubjectList<[NonBitField], ErrorDiag>; - // No spellings because instances of this attribute are created by - // MSNoUniqueAddress and ItaniumNoUniqueAddress - let Spellings = []; - let Documentation = [NoUniqueAddressDocs]; -} - -def MSNoUniqueAddress : InheritableAttr, TargetSpecificAttr { - let Subjects = SubjectList<[NonBitField], ErrorDiag>; - let Spellings = [CXX11<"msvc", "no_unique_address", 201803>]; - let Documentation = [NoUniqueAddressDocs]; -} - -def ItaniumNoUniqueAddress : InheritableAttr, TargetSpecificAttr { - let Subjects = SubjectList<[NonBitField], ErrorDiag>; +def NoUniqueAddress : InheritableAttr, TargetSpecificAttr { let Spellings = [CXX11<"", "no_unique_address", 201803>]; + let Subjects = SubjectList<[NonBitField], ErrorDiag>; let Documentation = [NoUniqueAddressDocs]; + let SimpleHandler = 1; } def ReturnsTwice : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 18428d26b5dc8..b13baa46754cf 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1405,10 +1405,6 @@ Example usage: ``[[no_unique_address]]`` is a standard C++20 attribute. Clang supports its use in C++11 onwards. - -On MSVC targets, ``[[no_unique_address]]`` is ignored; use -``[[msvc::no_unique_address]]`` instead. Currently there is no guarantee of ABI -compatibility or stability. }]; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 07aee0d87c835..08ae2087cfe70 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4507,14 +4507,9 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { // Otherwise, [...] the circumstances under which the object has zero size // are implementation-defined. - if (!Ctx.getTargetInfo().getCXXABI().isMicrosoft()) - return true; - - // MS ABI: has nonzero size if it is a class type with class type fields, - // whether or not they have nonzero size - return !llvm::any_of(CXXRD->fields(), [](const FieldDecl *Field) { - return Field->getType()->getAs(); - }); + // FIXME: This might be Itanium ABI specific; we don't yet know what the MS + // ABI will do. + return true; } bool FieldDecl::isPotentiallyOverlapping() const { diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f1f2275da44dc..8afd88ae7be27 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2545,10 +2545,7 @@ struct MicrosoftRecordLayoutBuilder { CharUnits Alignment; }; typedef llvm::DenseMap BaseOffsetsMapTy; - MicrosoftRecordLayoutBuilder(const ASTContext &Context, - EmptySubobjectMap *EmptySubobjects) - : Context(Context), EmptySubobjects(EmptySubobjects) {} - + MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {} private: MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete; void operator=(const MicrosoftRecordLayoutBuilder &) = delete; @@ -2598,8 +2595,6 @@ struct MicrosoftRecordLayoutBuilder { llvm::SmallPtrSetImpl &HasVtorDispSet, const CXXRecordDecl *RD) const; const ASTContext &Context; - EmptySubobjectMap *EmptySubobjects; - /// The size of the record being laid out. CharUnits Size; /// The non-virtual size of the record layout. @@ -2913,7 +2908,8 @@ static bool recordUsesEBO(const RecordDecl *RD) { } void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( - const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl, + const CXXRecordDecl *RD, + const CXXRecordDecl *BaseDecl, const ASTRecordLayout &BaseLayout, const ASTRecordLayout *&PreviousBaseLayout) { // Insert padding between two bases if the left first one is zero sized or @@ -2946,7 +2942,6 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( } Bases.insert(std::make_pair(BaseDecl, BaseOffset)); Size += BaseLayout.getNonVirtualSize(); - DataSize = Size; PreviousBaseLayout = &BaseLayout; } @@ -2964,43 +2959,15 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { LastFieldIsNonZeroWidthBitfield = false; ElementInfo Info = getAdjustedElementInfo(FD); Alignment = std::max(Alignment, Info.Alignment); - - const CXXRecordDecl *FieldClass = FD->getType()->getAsCXXRecordDecl(); - bool IsOverlappingEmptyField = FD->isPotentiallyOverlapping() && - FieldClass->isEmpty() && - FieldClass->fields().empty(); - CharUnits FieldOffset = CharUnits::Zero(); - - if (UseExternalLayout) { + CharUnits FieldOffset; + if (UseExternalLayout) FieldOffset = Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD)); - } else if (IsUnion) { + else if (IsUnion) FieldOffset = CharUnits::Zero(); - } else if (EmptySubobjects) { - if (!IsOverlappingEmptyField) - FieldOffset = DataSize.alignTo(Info.Alignment); - - while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) { - const CXXRecordDecl *ParentClass = cast(FD->getParent()); - bool HasBases = ParentClass && (!ParentClass->bases().empty() || - !ParentClass->vbases().empty()); - if (FieldOffset == CharUnits::Zero() && DataSize != CharUnits::Zero() && - HasBases) { - // MSVC appears to only do this when there are base classes; - // otherwise it overlaps no_unique_address fields in non-zero offsets. - FieldOffset = DataSize.alignTo(Info.Alignment); - } else { - FieldOffset += Info.Alignment; - } - } - } else { + else FieldOffset = Size.alignTo(Info.Alignment); - } placeFieldAtOffset(FieldOffset); - - if (!IsOverlappingEmptyField) - DataSize = std::max(DataSize, FieldOffset + Info.Size); - Size = std::max(Size, FieldOffset + Info.Size); } @@ -3046,7 +3013,6 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { Alignment = std::max(Alignment, Info.Alignment); RemainingBitsInField = Context.toBits(Info.Size) - Width; } - DataSize = Size; } void @@ -3072,7 +3038,6 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { Size = FieldOffset; Alignment = std::max(Alignment, Info.Alignment); } - DataSize = Size; } void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { @@ -3339,9 +3304,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; if (isMsLayout(*this)) { + MicrosoftRecordLayoutBuilder Builder(*this); if (const auto *RD = dyn_cast(D)) { - EmptySubobjectMap EmptySubobjects(*this, RD); - MicrosoftRecordLayoutBuilder Builder(*this, &EmptySubobjects); Builder.cxxLayout(RD); NewEntry = new (*this) ASTRecordLayout( *this, Builder.Size, Builder.Alignment, Builder.Alignment, @@ -3353,7 +3317,6 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase, Builder.Bases, Builder.VBases); } else { - MicrosoftRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); Builder.layout(D); NewEntry = new (*this) ASTRecordLayout( *this, Builder.Size, Builder.Alignment, Builder.Alignment, diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index cc93fe7d54619..5a6b5efbf6c12 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4374,8 +4374,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, case ParsedAttr::AT_Deprecated: case ParsedAttr::AT_FallThrough: case ParsedAttr::AT_CXX11NoReturn: - case ParsedAttr::AT_MSNoUniqueAddress: - case ParsedAttr::AT_ItaniumNoUniqueAddress: + case ParsedAttr::AT_NoUniqueAddress: case ParsedAttr::AT_Likely: case ParsedAttr::AT_Unlikely: return true; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f3839b2c59e0d..090a54eedaa07 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8372,10 +8372,6 @@ static void handleNoMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(NoMergeAttr::Create(S.Context, AL)); } -static void handleNoUniqueAddressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - D->addAttr(NoUniqueAddressAttr::Create(S.Context, AL)); -} - static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // The 'sycl_kernel' attribute applies only to function templates. const auto *FD = cast(D); @@ -9281,12 +9277,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_NoMerge: handleNoMergeAttr(S, D, AL); break; - case ParsedAttr::AT_MSNoUniqueAddress: - handleNoUniqueAddressAttr(S, D, AL); - break; - case ParsedAttr::AT_ItaniumNoUniqueAddress: - handleNoUniqueAddressAttr(S, D, AL); - break; case ParsedAttr::AT_AvailableOnlyInDefaultEvalMethod: handleAvailableOnlyInDefaultEvalMethod(S, D, AL); diff --git a/clang/test/Layout/ms-no-unique-address.cpp b/clang/test/Layout/ms-no-unique-address.cpp deleted file mode 100644 index 51cfd9a6ae3b7..0000000000000 --- a/clang/test/Layout/ms-no-unique-address.cpp +++ /dev/null @@ -1,381 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-windows-msvc -fms-compatibility -fdump-record-layouts %s | FileCheck %s - -namespace Empty { - struct A {}; - struct A2 {}; - struct A3 { [[msvc::no_unique_address]] A a; }; - struct alignas(8) A4 {}; - - struct B { - [[msvc::no_unique_address]] A a; - char b; - }; - static_assert(sizeof(B) == 1); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::B - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 0 | char b - // CHECK-NEXT: | [sizeof=1, align=1, - // CHECK-NEXT: | nvsize=1, nvalign=1] - - struct C { - [[msvc::no_unique_address]] A a; - [[msvc::no_unique_address]] A2 a2; - char c; - }; - static_assert(sizeof(C) == 1); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::C - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 0 | struct Empty::A2 a2 (empty) - // CHECK-NEXT: 0 | char c - // CHECK-NEXT: | [sizeof=1, align=1, - // CHECK-NEXT: | nvsize=1, nvalign=1] - - struct D { - [[msvc::no_unique_address]] A3 a; - int i; - }; - static_assert(sizeof(D) == 8); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::D - // CHECK-NEXT: 0 | struct Empty::A3 a (empty) - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 4 | int i - // CHECK-NEXT: | [sizeof=8, align=4, - // CHECK-NEXT: | nvsize=8, nvalign=4] - - struct E { - [[msvc::no_unique_address]] A a1; - [[msvc::no_unique_address]] A a2; - char e; - }; - static_assert(sizeof(E) == 2); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::E - // CHECK-NEXT: 0 | struct Empty::A a1 (empty) - // CHECK-NEXT: 1 | struct Empty::A a2 (empty) - // CHECK-NEXT: 0 | char e - // CHECK-NEXT: | [sizeof=2, align=1, - // CHECK-NEXT: | nvsize=2, nvalign=1] - - struct F { - ~F(); - [[msvc::no_unique_address]] A a1; - [[msvc::no_unique_address]] A a2; - char f; - }; - static_assert(sizeof(F) == 2); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::F - // CHECK-NEXT: 0 | struct Empty::A a1 (empty) - // CHECK-NEXT: 1 | struct Empty::A a2 (empty) - // CHECK-NEXT: 0 | char f - // CHECK-NEXT: | [sizeof=2, align=1, - // CHECK-NEXT: | nvsize=2, nvalign=1] - - struct G { [[msvc::no_unique_address]] A a; ~G(); }; - static_assert(sizeof(G) == 1); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::G - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: | [sizeof=1, align=1, - // CHECK-NEXT: | nvsize=1, nvalign=1] - - struct H { - [[msvc::no_unique_address]] A a; - [[msvc::no_unique_address]] A b; - ~H(); - }; - static_assert(sizeof(H) == 2); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::H - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 1 | struct Empty::A b (empty) - // CHECK-NEXT: | [sizeof=2, align=1, - // CHECK-NEXT: | nvsize=2, nvalign=1] - - struct I { - [[msvc::no_unique_address]] A4 a; - [[msvc::no_unique_address]] A4 b; - }; - static_assert(sizeof(I) == 16); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::I - // CHECK-NEXT: 0 | struct Empty::A4 a (empty) - // CHECK-NEXT: 8 | struct Empty::A4 b (empty) - // CHECK-NEXT: | [sizeof=16, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct J { - [[msvc::no_unique_address]] A4 a; - A4 b; - }; - static_assert(sizeof(J) == 16); - - // MSVC puts a and b at the same offset. - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::J - // CHECK-NEXT: 0 | struct Empty::A4 a (empty) - // CHECK-NEXT: 8 | struct Empty::A4 b (empty) - // CHECK-NEXT: | [sizeof=16, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct K { - [[msvc::no_unique_address]] A4 a; - [[msvc::no_unique_address]] char c; - [[msvc::no_unique_address]] A4 b; - }; - static_assert(sizeof(K) == 16); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::K - // CHECK-NEXT: 0 | struct Empty::A4 a (empty) - // CHECK-NEXT: 0 | char c - // CHECK-NEXT: 8 | struct Empty::A4 b (empty) - // CHECK-NEXT: | [sizeof=16, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct OversizedEmpty : A { - ~OversizedEmpty(); - [[msvc::no_unique_address]] A a; - }; - static_assert(sizeof(OversizedEmpty) == 1); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::OversizedEmpty - // CHECK-NEXT: 0 | struct Empty::A (base) (empty) - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: | [sizeof=1, align=1, - // CHECK-NEXT: | nvsize=1, nvalign=1] - - struct HasOversizedEmpty { - [[msvc::no_unique_address]] OversizedEmpty m; - }; - static_assert(sizeof(HasOversizedEmpty) == 1); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::HasOversizedEmpty - // CHECK-NEXT: 0 | struct Empty::OversizedEmpty m (empty) - // CHECK-NEXT: 0 | struct Empty::A (base) (empty) - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: | [sizeof=1, align=1, - // CHECK-NEXT: | nvsize=1, nvalign=1] - - struct EmptyWithNonzeroDSize { - [[msvc::no_unique_address]] A a; - int x; - [[msvc::no_unique_address]] A b; - int y; - [[msvc::no_unique_address]] A c; - }; - static_assert(sizeof(EmptyWithNonzeroDSize) == 8); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::EmptyWithNonzeroDSize - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 0 | int x - // CHECK-NEXT: 1 | struct Empty::A b (empty) - // CHECK-NEXT: 4 | int y - // CHECK-NEXT: 2 | struct Empty::A c (empty) - // CHECK-NEXT: | [sizeof=8, align=4, - // CHECK-NEXT: | nvsize=8, nvalign=4] - - struct EmptyWithNonzeroDSizeNonPOD { - ~EmptyWithNonzeroDSizeNonPOD(); - [[msvc::no_unique_address]] A a; - int x; - [[msvc::no_unique_address]] A b; - int y; - [[msvc::no_unique_address]] A c; - }; - static_assert(sizeof(EmptyWithNonzeroDSizeNonPOD) == 8); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct Empty::EmptyWithNonzeroDSizeNonPOD - // CHECK-NEXT: 0 | struct Empty::A a (empty) - // CHECK-NEXT: 0 | int x - // CHECK-NEXT: 1 | struct Empty::A b (empty) - // CHECK-NEXT: 4 | int y - // CHECK-NEXT: 2 | struct Empty::A c (empty) - // CHECK-NEXT: | [sizeof=8, align=4, - // CHECK-NEXT: | nvsize=8, nvalign=4] -} - -namespace POD { - struct A { int n; char c[3]; }; - struct B { [[msvc::no_unique_address]] A a; char d; }; - static_assert(sizeof(B) == 12); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct POD::B - // CHECK-NEXT: 0 | struct POD::A a - // CHECK-NEXT: 0 | int n - // CHECK-NEXT: 4 | char[3] c - // CHECK-NEXT: 8 | char d - // CHECK-NEXT: | [sizeof=12, align=4, - // CHECK-NEXT: | nvsize=12, nvalign=4] -} - -namespace NonPOD { - struct A { int n; char c[3]; ~A(); }; - struct B { [[msvc::no_unique_address]] A a; char d; }; - static_assert(sizeof(B) == 12); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct NonPOD::B - // CHECK-NEXT: 0 | struct NonPOD::A a - // CHECK-NEXT: 0 | int n - // CHECK-NEXT: 4 | char[3] c - // CHECK-NEXT: 8 | char d - // CHECK-NEXT: | [sizeof=12, align=4, - // CHECK-NEXT: | nvsize=12, nvalign=4] -} - -namespace VBases { - // The nvsize of an object includes the complete size of its empty subobjects - // (although it's unclear why). Ensure this corner case is handled properly. - struct Empty {}; - struct alignas(8) A {}; // dsize 0, nvsize 0, size 8 - struct B : A { char c; }; // dsize 1, nvsize 8, size 8 - static_assert(sizeof(B) == 8); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::B - // CHECK-NEXT: 0 | struct VBases::A (base) (empty) - // CHECK-NEXT: 0 | char c - // CHECK-NEXT: | [sizeof=8, align=8, - // CHECK-NEXT: | nvsize=8, nvalign=8] - - struct V { int n; }; - - struct C : B, virtual V {}; - static_assert(sizeof(C) == 24); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::C - // CHECK-NEXT: 0 | struct VBases::B (base) - // CHECK-NEXT: 0 | struct VBases::A (base) (empty) - // CHECK-NEXT: 0 | char c - // CHECK-NEXT: 8 | (C vbtable pointer) - // CHECK-NEXT: 16 | struct VBases::V (virtual base) - // CHECK-NEXT: 16 | int n - // CHECK-NEXT: | [sizeof=24, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct D : virtual Empty { - [[msvc::no_unique_address]] Empty a; - }; - static_assert(sizeof(D) == 16); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::D - // CHECK-NEXT: 0 | (D vbtable pointer) - // CHECK-NEXT: 8 | struct VBases::Empty a - // CHECK-NEXT: 16 | struct VBases::Empty (virtual base) (empty) - // CHECK-NEXT: | [sizeof=16, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct E : virtual V { - [[msvc::no_unique_address]] B b; - }; - static_assert(sizeof(E) == 24); - - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::E - // CHECK-NEXT: 0 | (E vbtable pointer) - // CHECK-NEXT: 8 | struct VBases::B b - // CHECK-NEXT: 8 | struct VBases::A (base) (empty) - // CHECK-NEXT: 8 | char c - // CHECK-NEXT: 16 | struct VBases::V (virtual base) - // CHECK-NEXT: 16 | int n - // CHECK-NEXT: | [sizeof=24, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] - - struct X : virtual A { [[msvc::no_unique_address]] A a; }; - struct F : virtual A { - [[msvc::no_unique_address]] A a; - [[msvc::no_unique_address]] X x; - }; - static_assert(sizeof(F) == 24); - - // MSVC places x after a and the total size is 48. - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::F - // CHECK-NEXT: 0 | (F vbtable pointer) - // CHECK-NEXT: 8 | struct VBases::A a (empty) - // CHECK-NEXT: 8 | struct VBases::X x - // CHECK-NEXT: 8 | (X vbtable pointer) - // CHECK-NEXT: 16 | struct VBases::A a (empty) - // CHECK-NEXT: 24 | struct VBases::A (virtual base) (empty) - // CHECK-NEXT: 24 | struct VBases::A (virtual base) (empty) - // CHECK-NEXT: | [sizeof=24, align=8, - // CHECK-NEXT: | nvsize=24, nvalign=8] - - struct G : virtual Empty { - int i; - [[msvc::no_unique_address]] A a; - }; - static_assert(sizeof(G) == 16); - - // MSVC places a at offset 12. - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct VBases::G - // CHECK-NEXT: 0 | (G vbtable pointer) - // CHECK-NEXT: 8 | int i - // CHECK-NEXT: 8 | struct VBases::A a (empty) - // CHECK-NEXT: 16 | struct VBases::Empty (virtual base) (empty) - // CHECK-NEXT: | [sizeof=16, align=8, - // CHECK-NEXT: | nvsize=16, nvalign=8] -} - -namespace ZeroSize { - struct empty {}; - - union empty_union {}; - - struct empty_union_container { - [[msvc::no_unique_address]] empty_union x; - }; - - union union_of_empty { - [[msvc::no_unique_address]] empty x; - }; - - struct struct_of_empty { - [[msvc::no_unique_address]] empty x; - }; - - struct union_of_empty_container { - [[msvc::no_unique_address]] union_of_empty x; - }; - static_assert(sizeof(union_of_empty_container) == 1); - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct ZeroSize::union_of_empty_container - // CHECK-NOT: (empty) - // CHECK: 0 | union ZeroSize::union_of_empty x (empty) - // CHECK: 0 | struct ZeroSize::empty x (empty) - // CHECK: | [sizeof=1, align=1, - // CHECK: | nvsize=1, nvalign=1] - - struct struct_of_empty_container { - [[msvc::no_unique_address]] struct_of_empty x; - }; - static_assert(sizeof(struct_of_empty_container) == 1); - // CHECK:*** Dumping AST Record Layout - // CHECK: 0 | struct ZeroSize::struct_of_empty_container - // CHECK-NOT: (empty) - // CHECK: 0 | struct ZeroSize::struct_of_empty x (empty) - // CHECK: 0 | struct ZeroSize::empty x (empty) - // CHECK: | [sizeof=1, align=1, - // CHECK: | nvsize=1, nvalign=1] - -} diff --git a/clang/test/Preprocessor/has_attribute.cpp b/clang/test/Preprocessor/has_attribute.cpp index 3fb99eda699b3..bf0f9b3bc4a8f 100644 --- a/clang/test/Preprocessor/has_attribute.cpp +++ b/clang/test/Preprocessor/has_attribute.cpp @@ -43,7 +43,6 @@ CXX11(fallthrough) CXX11(likely) CXX11(maybe_unused) CXX11(no_unique_address) -CXX11(msvc::no_unique_address) CXX11(nodiscard) CXX11(noreturn) CXX11(unlikely) @@ -56,9 +55,7 @@ CXX11(unlikely) // CHECK: likely: 201803L // CHECK: maybe_unused: 201603L // ITANIUM: no_unique_address: 201803L -// WINDOWS: no_unique_address: 0 -// ITANIUM: msvc::no_unique_address: 0 -// WINDOWS: msvc::no_unique_address: 201803L +// WINDOWS: no_unique_address: 0 // CHECK: nodiscard: 201907L // CHECK: noreturn: 200809L // CHECK: unlikely: 201803L diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp deleted file mode 100644 index 42058559a087a..0000000000000 --- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu -// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility - -[[msvc::no_unique_address]] int a; // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} -[[msvc::no_unique_address]] void f(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} -struct [[msvc::no_unique_address]] S { // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} - [[msvc::no_unique_address]] int a; // unsupported-warning {{unknown}} - [[msvc::no_unique_address]] void f(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} - [[msvc::no_unique_address]] static int sa;// expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} - [[msvc::no_unique_address]] static void sf(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} - [[msvc::no_unique_address]] int b : 3; // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}} - - [[msvc::no_unique_address, msvc::no_unique_address]] int duplicated; // ok - // unsupported-warning@-1 2{{unknown}} - [[msvc::no_unique_address]] [[msvc::no_unique_address]] int duplicated2; // unsupported-warning 2{{unknown}} - [[msvc::no_unique_address()]] int arglist; // expected-error {{cannot have an argument list}} unsupported-warning {{unknown}} - - int [[msvc::no_unique_address]] c; // expected-error {{cannot be applied to types}} unsupported-error {{cannot be applied to types}} -};