RIscRIpt created this revision. Herald added a reviewer: aaron.ballman. Herald added a project: All. RIscRIpt requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D134458 Files: clang/include/clang/AST/Decl.h clang/include/clang/Basic/Attr.td clang/lib/AST/Decl.cpp clang/lib/AST/RecordLayoutBuilder.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CGExprConstant.cpp clang/lib/CodeGen/CGRecordLayoutBuilder.cpp clang/lib/CodeGen/TargetInfo.cpp clang/test/AST/msvc-attrs.cpp
Index: clang/test/AST/msvc-attrs.cpp =================================================================== --- clang/test/AST/msvc-attrs.cpp +++ clang/test/AST/msvc-attrs.cpp @@ -1,6 +1,14 @@ // RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s -// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "1 error generated" +// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "3 errors generated" -// CHECK: msvc-attrs.cpp:[[@LINE+2]]:21, col:61> col:27 constexpr New1 'void *(void *)' +struct Empty {}; + +// CHECK: <line:[[@LINE+2]]:21, col:61> col:27 constexpr New1 'void *(void *)' // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} <col:3, col:9> [[msvc::constexpr]] void *New1(void *where) { return where; } + +struct StructWithNUAField { + [[msvc::no_unique_address]] Empty e; + int f1; +}; +static_assert(sizeof(StructWithNUAField) == sizeof(int)); // expected to fail without -fms-extensions Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -578,8 +578,7 @@ // according to the Itanium ABI. The exception applies only to records, // not arrays of records, so we must also check whether we stripped off an // array type above. - if (isa<CXXRecordDecl>(RT->getDecl()) && - (WasArray || !FD->hasAttr<NoUniqueAddressAttr>())) + if (isa<CXXRecordDecl>(RT->getDecl()) && (WasArray || !FD->hasNoUniqueAddress())) return false; return isEmptyRecord(Context, FT, AllowArrays); @@ -7524,8 +7523,7 @@ // do count. So do anonymous bitfields that aren't zero-sized. // Like isSingleElementStruct(), ignore C++20 empty data members. - if (FD->hasAttr<NoUniqueAddressAttr>() && - isEmptyRecord(getContext(), FD->getType(), true)) + if (FD->hasNoUniqueAddress() && isEmptyRecord(getContext(), FD->getType(), true)) continue; // Unlike isSingleElementStruct(), arrays do not count. Index: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp =================================================================== --- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -744,7 +744,7 @@ Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo( cast<llvm::IntegerType>(Prior->Data)->getIntegerBitWidth(), 8))); else { - assert(Prior->FD->hasAttr<NoUniqueAddressAttr>() && + assert(Prior->FD->hasNoUniqueAddress() && "should not have reused this field's tail padding"); Prior->Data = getByteArrayType( Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width); Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -755,7 +755,7 @@ return false; // After emitting a non-empty field with [[no_unique_address]], we may // need to overwrite its tail padding. - if (Field->hasAttr<NoUniqueAddressAttr>()) + if (Field->hasNoUniqueAddress()) AllowOverwrite = true; } else { // Otherwise we have a bitfield. @@ -856,7 +856,7 @@ return false; // After emitting a non-empty field with [[no_unique_address]], we may // need to overwrite its tail padding. - if (Field->hasAttr<NoUniqueAddressAttr>()) + if (Field->hasNoUniqueAddress()) AllowOverwrite = true; } else { // Otherwise we have a bitfield. Index: clang/lib/CodeGen/CGExprAgg.cpp =================================================================== --- clang/lib/CodeGen/CGExprAgg.cpp +++ clang/lib/CodeGen/CGExprAgg.cpp @@ -2015,7 +2015,7 @@ AggValueSlot::Overlap_t CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) { - if (!FD->hasAttr<NoUniqueAddressAttr>() || !FD->getType()->isRecordType()) + if (!FD->hasNoUniqueAddress() || !FD->getType()->isRecordType()) return AggValueSlot::DoesNotOverlap; // If the field lies entirely within the enclosing class's nvsize, its tail Index: clang/lib/AST/RecordLayoutBuilder.cpp =================================================================== --- clang/lib/AST/RecordLayoutBuilder.cpp +++ clang/lib/AST/RecordLayoutBuilder.cpp @@ -474,7 +474,7 @@ // We are able to place the member variable at this offset. // Make sure to update the empty field subobject map. - UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr<NoUniqueAddressAttr>()); + UpdateEmptyFieldSubobjects(FD, Offset, FD->hasNoUniqueAddress()); return true; } @@ -1853,7 +1853,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, bool InsertExtraPadding) { auto *FieldClass = D->getType()->getAsCXXRecordDecl(); - bool PotentiallyOverlapping = D->hasAttr<NoUniqueAddressAttr>() && FieldClass; + bool PotentiallyOverlapping = D->hasNoUniqueAddress() && FieldClass; bool IsOverlappingEmptyField = PotentiallyOverlapping && FieldClass->isEmpty(); Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -4268,6 +4268,10 @@ nullptr, false, ICIS_NoInit); } +bool FieldDecl::hasNoUniqueAddress() const { + return hasAttr<NoUniqueAddressAttr>() || hasAttr<MSNoUniqueAddressAttr>(); +} + bool FieldDecl::isAnonymousStructOrUnion() const { if (!isImplicit() || getDeclName()) return false; @@ -4295,7 +4299,7 @@ // C++2a [intro.object]p7: // An object has nonzero size if it // -- is not a potentially-overlapping subobject, or - if (!hasAttr<NoUniqueAddressAttr>()) + if (!hasNoUniqueAddress()) return false; // -- is not of class type, or Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -3494,6 +3494,14 @@ let Documentation = [MSConstexprDocs]; } +def MSNoUniqueAddress : InheritableAttr, TargetSpecificAttr<TargetItaniumCXXABI> { + let LangOpts = [MicrosoftExt]; + let Spellings = [CXX11<"msvc", "no_unique_address", 201803>]; + let Subjects = SubjectList<[NonBitField], ErrorDiag>; + let Documentation = [NoUniqueAddressDocs]; + let SimpleHandler = 1; +} + def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -2958,6 +2958,9 @@ /// Determines whether this is an unnamed bitfield. bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); } + /// Determins whether this field has no unique address + bool hasNoUniqueAddress() const; + /// Determines whether this field is a /// representative for an anonymous struct or union. Such fields are /// unnamed and are implicitly generated by the implementation to
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits