diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 06982b8698e0c..66a6f07efd7bb 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -83,7 +83,6 @@ static const llvm::StringSet<> ValueTraits = { "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", - "is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 87d38e7d99e50..0270d3e07bf76 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2044,8 +2044,6 @@ The following type trait primitives are supported by Clang. Those traits marked is trivially relocatable, as defined by the C++26 standard [meta.unary.prop]. Note that when relocating the caller code should ensure that if the object is polymorphic, the dynamic type is of the most derived type. Padding bytes should not be copied. -* ``__builtin_is_replaceable`` (C++): Returns true if an object - is replaceable, as defined by the C++26 standard [meta.unary.prop]. * ``__is_trivially_equality_comparable`` (Clang): Returns true if comparing two objects of the provided type is known to be equivalent to comparing their object representations. Note that types containing padding bytes are never diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index f64e29be3205f..1484ead2d9bfd 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -666,7 +666,6 @@ class ASTContext : public RefCountedBase { public: struct CXXRecordDeclRelocationInfo { unsigned IsRelocatable; - unsigned IsReplaceable; }; std::optional getRelocationInfoForCXXRecord(const CXXRecordDecl *) const; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d8d1675f245a1..4a5f0ea73f518 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1952,14 +1952,6 @@ def TriviallyRelocatable : InheritableAttr { let Documentation = [InternalOnly]; } -def Replaceable : InheritableAttr { - let Spellings = [CustomKeyword<"replaceable_if_eligible">]; - let SemaHandler = 0; - // Omitted from docs, since this is language syntax, not an attribute, as far - // as users are concerned. - let Documentation = [InternalOnly]; -} - def MinSize : InheritableAttr { let Spellings = [Clang<"minsize">]; let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 9401377002223..bbaa9db2723ed 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1077,14 +1077,15 @@ def ext_ms_abstract_keyword : ExtWarn< "'abstract' keyword is a Microsoft extension">, InGroup; -def ext_relocatable_keyword : ExtWarn< - "'%select{trivially_relocatable_if_eligible|replaceable_if_eligible}0' " - "keyword is a C++2c extension">, - InGroup; -def warn_relocatable_keyword : Warning< - "'%select{trivially_relocatable|replaceable}0_if_eligible' " - "keyword is incompatible with standards before C++2c">, - DefaultIgnore, InGroup; +def ext_relocatable_keyword + : ExtWarn< + "'trivially_relocatable_if_eligible' keyword is a C++2c extension">, + InGroup; +def warn_relocatable_keyword + : Warning<"'trivially_relocatable_if_eligible' keyword is incompatible " + "with standards before C++2c">, + DefaultIgnore, + InGroup; def err_access_specifier_interface : Error< "interface types cannot specify '%select{private|protected}0' access">; @@ -1092,8 +1093,8 @@ def err_access_specifier_interface : Error< def err_duplicate_class_virt_specifier : Error< "class already marked '%0'">; -def err_duplicate_class_relocation_specifier : Error< - "class already marked '%select{trivially_relocatable_if_eligible|replaceable_if_eligible}0'">; +def err_duplicate_class_relocation_specifier + : Error<"class already marked 'trivially_relocatable_if_eligible'">; def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9147b6a041c70..9a75ab3b1b3c3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1770,7 +1770,6 @@ def err_user_defined_msg_constexpr : Error< def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" - "%Replaceable{replaceable}|" "%TriviallyCopyable{trivially copyable}|" "%Empty{empty}|" "%StandardLayout{standard-layout}|" @@ -1792,8 +1791,6 @@ def note_unsatisfied_trait_reason "class type}|" "%NTRBase{has a non-trivially-relocatable base %1}|" "%NTRField{has a non-trivially-relocatable member %1 of type %2}|" - "%NonReplaceableBase{has a non-replaceable base %1}|" - "%NonReplaceableField{has a non-replaceable member %1 of type %2}|" "%NTCBase{has a non-trivially-copyable base %1}|" "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%NonEmptyMember{has a non-static data member %1 of type %2}|" diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 564d6010181cc..235ffbaa874a6 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -564,7 +564,6 @@ TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) TYPE_TRAIT_1(__builtin_is_cpp_trivially_relocatable, IsCppTriviallyRelocatable, KEYCXX) TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX) TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL) -TYPE_TRAIT_1(__builtin_is_replaceable, IsReplaceable, KEYCXX) TYPE_TRAIT_1(__builtin_structured_binding_size, StructuredBindingSize, KEYCXX) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 58eb1c0a7c114..c67fb32af1eef 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2835,7 +2835,6 @@ class Parser : public CodeCompletionHandler { mutable IdentifierInfo *Ident_GNU_final; mutable IdentifierInfo *Ident_override; mutable IdentifierInfo *Ident_trivially_relocatable_if_eligible; - mutable IdentifierInfo *Ident_replaceable_if_eligible; /// Representation of a class that has been parsed, including /// any member function declarations or definitions that need to be @@ -3129,7 +3128,7 @@ class Parser : public CodeCompletionHandler { /// isClassCompatibleKeyword - Determine whether the next token is a C++11 /// 'final', a C++26 'trivially_relocatable_if_eligible', - /// 'replaceable_if_eligible', or Microsoft 'sealed' or 'abstract' contextual + /// or Microsoft 'sealed' or 'abstract' contextual /// keyword. bool isClassCompatibleKeyword() const; @@ -3603,12 +3602,8 @@ class Parser : public CodeCompletionHandler { bool isCXX2CTriviallyRelocatableKeyword() const; void ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS); - bool isCXX2CReplaceableKeyword(Token Tok) const; - bool isCXX2CReplaceableKeyword() const; - void ParseCXX2CReplaceableSpecifier(SourceLocation &MRS); - /// 'final', a C++26 'trivially_relocatable_if_eligible', - /// 'replaceable_if_eligible', or Microsoft 'sealed' or 'abstract' contextual + /// or Microsoft 'sealed' or 'abstract' contextual /// keyword. bool isClassCompatibleKeyword(Token Tok) const; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d14b5dc5ffaa4..1ddfae54b4b4b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4366,7 +4366,6 @@ class Sema final : public SemaBase { bool IsFinalSpelledSealed, bool IsAbstract, SourceLocation TriviallyRelocatable, - SourceLocation Replaceable, SourceLocation LBraceLoc); /// ActOnTagFinishDefinition - Invoked once we have finished parsing @@ -4375,7 +4374,7 @@ class Sema final : public SemaBase { SourceRange BraceRange); ASTContext::CXXRecordDeclRelocationInfo - CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D); + CheckCXX2CRelocatable(const clang::CXXRecordDecl *D); void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); @@ -8733,12 +8732,6 @@ class Sema final : public SemaBase { bool IsCXXTriviallyRelocatableType(QualType T); bool IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD); - //// Determines if a type is replaceable - /// according to the C++26 rules. - // FIXME: This is in Sema because it requires - // overload resolution, can we move to ASTContext? - bool IsCXXReplaceableType(QualType T); - /// Check the operands of ?: under C++ semantics. /// /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d8ed7e3ff96bd..6b67a2aa99cc7 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2498,40 +2498,13 @@ void Parser::ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS) { Diag(Tok.getLocation(), getLangOpts().CPlusPlus26 ? diag::warn_relocatable_keyword - : diag::ext_relocatable_keyword) - << /*relocatable*/ 0; + : diag::ext_relocatable_keyword); TRS = ConsumeToken(); } -bool Parser::isCXX2CReplaceableKeyword(Token Tok) const { - if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier)) - return false; - if (!Ident_replaceable_if_eligible) - Ident_replaceable_if_eligible = - &PP.getIdentifierTable().get("replaceable_if_eligible"); - IdentifierInfo *II = Tok.getIdentifierInfo(); - return II == Ident_replaceable_if_eligible; -} - -bool Parser::isCXX2CReplaceableKeyword() const { - return isCXX2CReplaceableKeyword(Tok); -} - -void Parser::ParseCXX2CReplaceableSpecifier(SourceLocation &MRS) { - assert(isCXX2CReplaceableKeyword() && - "expected a replaceable_if_eligible specifier"); - - Diag(Tok.getLocation(), getLangOpts().CPlusPlus26 - ? diag::warn_relocatable_keyword - : diag::ext_relocatable_keyword) - << /*replaceable*/ 1; - - MRS = ConsumeToken(); -} - bool Parser::isClassCompatibleKeyword(Token Tok) const { - if (isCXX2CTriviallyRelocatableKeyword(Tok) || isCXX2CReplaceableKeyword(Tok)) + if (isCXX2CTriviallyRelocatableKeyword(Tok)) return true; VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok); return Specifier == VirtSpecifiers::VS_Final || @@ -3587,7 +3560,6 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, bool IsFinalSpelledSealed = false; bool IsAbstract = false; SourceLocation TriviallyRelocatable; - SourceLocation Replaceable; // Parse the optional 'final' keyword. if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { @@ -3599,23 +3571,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, auto Skipped = Tok; ConsumeToken(); Diag(Skipped, diag::err_duplicate_class_relocation_specifier) - << /*trivial_relocatable*/ 0 << TriviallyRelocatable; + << TriviallyRelocatable; } else { ParseCXX2CTriviallyRelocatableSpecifier(TriviallyRelocatable); } continue; } - if (isCXX2CReplaceableKeyword(Tok)) { - if (Replaceable.isValid()) { - auto Skipped = Tok; - ConsumeToken(); - Diag(Skipped, diag::err_duplicate_class_relocation_specifier) - << /*replaceable*/ 1 << Replaceable; - } else { - ParseCXX2CReplaceableSpecifier(Replaceable); - } - continue; - } break; } if (isCXX11FinalKeyword()) { @@ -3654,7 +3615,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, Diag(FinalLoc, diag::ext_warn_gnu_final); } assert((FinalLoc.isValid() || AbstractLoc.isValid() || - TriviallyRelocatable.isValid() || Replaceable.isValid()) && + TriviallyRelocatable.isValid()) && "not a class definition"); // Parse any C++11 attributes after 'final' keyword. @@ -3729,7 +3690,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnStartCXXMemberDeclarations( getCurScope(), TagDecl, FinalLoc, IsFinalSpelledSealed, IsAbstract, - TriviallyRelocatable, Replaceable, T.getOpenLocation()); + TriviallyRelocatable, T.getOpenLocation()); // C++ 11p3: Members of a class defined with the keyword class are private // by default. Members of a class defined with the keywords struct or union diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 7b425dd3dda43..1f32bf8009ded 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -515,7 +515,6 @@ void Parser::Initialize() { Ident_abstract = nullptr; Ident_override = nullptr; Ident_trivially_relocatable_if_eligible = nullptr; - Ident_replaceable_if_eligible = nullptr; Ident_GNU_final = nullptr; Ident_import = nullptr; Ident_module = nullptr; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 47bd7295e93f6..9285238e4dfb9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18794,10 +18794,12 @@ bool Sema::ActOnDuplicateDefinition(Scope *S, Decl *Prev, return true; } -void Sema::ActOnStartCXXMemberDeclarations( - Scope *S, Decl *TagD, SourceLocation FinalLoc, bool IsFinalSpelledSealed, - bool IsAbstract, SourceLocation TriviallyRelocatable, - SourceLocation Replaceable, SourceLocation LBraceLoc) { +void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, + SourceLocation FinalLoc, + bool IsFinalSpelledSealed, + bool IsAbstract, + SourceLocation TriviallyRelocatable, + SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast(TagD); @@ -18820,9 +18822,6 @@ void Sema::ActOnStartCXXMemberDeclarations( Record->addAttr( TriviallyRelocatableAttr::Create(Context, TriviallyRelocatable)); - if (Replaceable.isValid()) - Record->addAttr(ReplaceableAttr::Create(Context, Replaceable)); - // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 38877967af05e..f9d223a67e393 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -211,49 +211,15 @@ static bool IsEligibleForTrivialRelocation(Sema &SemaRef, return !D->hasDeletedDestructor(); } -// [C++26][class.prop] -// A class C is eligible for replacement unless -static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) { - - for (const CXXBaseSpecifier &B : D->bases()) { - const auto *BaseDecl = B.getType()->getAsCXXRecordDecl(); - if (!BaseDecl) - continue; - // it has a base class that is not a replaceable class - if (!BaseDecl->isDependentType() && - !SemaRef.IsCXXReplaceableType(B.getType())) - return false; - } - - for (const FieldDecl *Field : D->fields()) { - if (Field->getType()->isDependentType()) - continue; - - // it has a non-static data member that is not of a replaceable type, - if (!SemaRef.IsCXXReplaceableType(Field->getType())) - return false; - } - return !D->hasDeletedDestructor(); -} - ASTContext::CXXRecordDeclRelocationInfo -Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) { - ASTContext::CXXRecordDeclRelocationInfo Info{false, false}; +Sema::CheckCXX2CRelocatable(const CXXRecordDecl *D) { + ASTContext::CXXRecordDeclRelocationInfo Info{false}; if (!getLangOpts().CPlusPlus || D->isInvalidDecl()) return Info; assert(D->hasDefinition()); - // This is part of "eligible for replacement", however we defer it - // to avoid extraneous computations. - auto HasSuitableSMP = [&] { - return hasSuitableConstructorForRelocation(*this, D, - /*AllowUserDefined=*/true) && - hasSuitableMoveAssignmentOperatorForRelocation( - *this, D, /*AllowUserDefined=*/true); - }; - auto IsUnion = [&, Is = std::optional{}]() mutable { if (!Is.has_value()) Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() && @@ -289,26 +255,6 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) { return IsDefaultMovable(); }(); - Info.IsReplaceable = [&] { - if (D->isDependentType()) - return false; - - // A class C is a replaceable class if it is eligible for replacement - if (!IsEligibleForReplacement(*this, D)) - return false; - - // has the replaceable_if_eligible class-property-specifier - if (D->hasAttr()) - return HasSuitableSMP(); - - // is a union with no user-declared special member functions, or - if (IsUnion()) - return HasSuitableSMP(); - - // is default-movable. - return IsDefaultMovable(); - }(); - return Info; } @@ -316,8 +262,7 @@ bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) { if (std::optional Info = getASTContext().getRelocationInfoForCXXRecord(&RD)) return Info->IsRelocatable; - ASTContext::CXXRecordDeclRelocationInfo Info = - CheckCXX2CRelocatableAndReplaceable(&RD); + ASTContext::CXXRecordDeclRelocationInfo Info = CheckCXX2CRelocatable(&RD); getASTContext().setRelocationInfoForCXXRecord(&RD, Info); return Info.IsRelocatable; } @@ -346,34 +291,6 @@ bool Sema::IsCXXTriviallyRelocatableType(QualType Type) { return false; } -static bool IsCXXReplaceableType(Sema &S, const CXXRecordDecl *RD) { - if (std::optional Info = - S.getASTContext().getRelocationInfoForCXXRecord(RD)) - return Info->IsReplaceable; - ASTContext::CXXRecordDeclRelocationInfo Info = - S.CheckCXX2CRelocatableAndReplaceable(RD); - S.getASTContext().setRelocationInfoForCXXRecord(RD, Info); - return Info.IsReplaceable; -} - -bool Sema::IsCXXReplaceableType(QualType Type) { - if (Type.isConstQualified() || Type.isVolatileQualified()) - return false; - - if (Type->isVariableArrayType()) - return false; - - QualType BaseElementType = - getASTContext().getBaseElementType(Type.getUnqualifiedType()); - if (BaseElementType->isIncompleteType()) - return false; - if (BaseElementType->isScalarType()) - return true; - if (const auto *RD = BaseElementType->getAsCXXRecordDecl()) - return ::IsCXXReplaceableType(*this, RD); - return false; -} - /// Checks that type T is not a VLA. /// /// @returns @c true if @p T is VLA and a diagnostic was emitted, @@ -526,7 +443,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsTriviallyRelocatable: case UTT_IsTriviallyEqualityComparable: case UTT_IsCppTriviallyRelocatable: - case UTT_IsReplaceable: case UTT_CanPassInRegs: // Per the GCC type traits documentation, T shall be a complete type, cv void, // or an array of unknown bound. But GCC actually imposes the same constraints @@ -1128,8 +1044,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return T.isBitwiseCloneableType(C); case UTT_IsCppTriviallyRelocatable: return Self.IsCXXTriviallyRelocatableType(T); - case UTT_IsReplaceable: - return Self.IsCXXReplaceableType(T); case UTT_CanPassInRegs: if (CXXRecordDecl *RD = T->getAsCXXRecordDecl(); RD && !T.hasQualifiers()) return RD->canPassInRegisters(); @@ -2019,7 +1933,6 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) - .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Case("is_assignable", TypeTrait::BTT_IsAssignable) .Case("is_empty", TypeTrait::UTT_IsEmpty) @@ -2202,92 +2115,6 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } -static void DiagnoseNonReplaceableReason(Sema &SemaRef, SourceLocation Loc, - const CXXRecordDecl *D) { - for (const CXXBaseSpecifier &B : D->bases()) { - assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); - if (!SemaRef.IsCXXReplaceableType(B.getType())) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::NonReplaceableBase << B.getType() - << B.getSourceRange(); - } - for (const FieldDecl *Field : D->fields()) { - if (!SemaRef.IsCXXReplaceableType(Field->getType())) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::NonReplaceableField << Field - << Field->getType() << Field->getSourceRange(); - } - if (D->hasDeletedDestructor()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::DeletedDtr << /*Deleted*/ 0 - << D->getDestructor()->getSourceRange(); - - if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) { - const auto *Decl = cast( - LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false)); - if (Decl && Decl->isDeleted()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::DeletedCtr - << Decl->isMoveConstructor() << Decl->getSourceRange(); - } - if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) { - CXXMethodDecl *Decl = - LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true); - if (Decl && Decl->isDeleted()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::DeletedAssign - << Decl->isMoveAssignmentOperator() << Decl->getSourceRange(); - } - - if (D->hasAttr()) - return; - DiagnoseNonDefaultMovable(SemaRef, Loc, D); -} - -static void DiagnoseNonReplaceableReason(Sema &SemaRef, SourceLocation Loc, - QualType T) { - SemaRef.Diag(Loc, diag::note_unsatisfied_trait) - << T << diag::TraitName::Replaceable; - - if (T->isVariablyModifiedType()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::VLA; - - if (T->isReferenceType()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::Ref; - T = T.getNonReferenceType(); - - if (T.isConstQualified()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::Const; - - if (T.isVolatileQualified()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::Volatile; - - bool IsArray = T->isArrayType(); - T = SemaRef.getASTContext().getBaseElementType(T.getUnqualifiedType()); - - if (T->isScalarType()) - return; - - const CXXRecordDecl *D = T->getAsCXXRecordDecl(); - if (!D) { - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::NotScalarOrClass << IsArray; - return; - } - - if (D->isInvalidDecl()) - return; - - if (D->hasDefinition()) - DiagnoseNonReplaceableReason(SemaRef, Loc, D); - - SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; -} - static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D) { @@ -2871,9 +2698,6 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsCppTriviallyRelocatable: DiagnoseNonTriviallyRelocatableReason(*this, E->getBeginLoc(), Args[0]); break; - case UTT_IsReplaceable: - DiagnoseNonReplaceableReason(*this, E->getBeginLoc(), Args[0]); - break; case UTT_IsTriviallyCopyable: DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); break; diff --git a/clang/test/Parser/cxx2c-trivially-relocatable.cpp b/clang/test/Parser/cxx2c-trivially-relocatable.cpp index 255e3e4f4460d..e47fe2a32972c 100644 --- a/clang/test/Parser/cxx2c-trivially-relocatable.cpp +++ b/clang/test/Parser/cxx2c-trivially-relocatable.cpp @@ -17,26 +17,15 @@ class I trivially_relocatable_if_eligible trivially_relocatable_if_eligible fina // cxx03-warning@-3 {{'final' keyword is a C++11 extension}} class trivially_relocatable_if_eligible trivially_relocatable_if_eligible {}; // cxx11-warning@-1 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} -class J replaceable_if_eligible{}; -// cxx11-warning@-1 {{'replaceable_if_eligible' keyword is a C++2c extension}} -class K replaceable_if_eligible replaceable_if_eligible {}; -// expected-error@-1 {{class already marked 'replaceable_if_eligible'}} -// cxx11-warning@-2 {{'replaceable_if_eligible' keyword is a C++2c extension}} -class replaceable_if_eligible replaceable_if_eligible {}; -// cxx11-warning@-1 {{'replaceable_if_eligible' keyword is a C++2c extension}} -class L replaceable_if_eligible trivially_relocatable_if_eligible final {}; -// cxx11-warning@-1 {{'replaceable_if_eligible' keyword is a C++2c extension}} -// cxx11-warning@-2 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} -// cxx03-warning@-3 {{'final' keyword is a C++11 extension}} -class M replaceable_if_eligible final trivially_relocatable_if_eligible {}; +class L trivially_relocatable_if_eligible final {}; // cxx11-warning@-1 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} -// cxx11-warning@-2 {{'replaceable_if_eligible' keyword is a C++2c extension}} -// cxx03-warning@-3 {{'final' keyword is a C++11 extension}} -class N final trivially_relocatable_if_eligible replaceable_if_eligible {}; +// cxx03-warning@-2 {{'final' keyword is a C++11 extension}} +class M final trivially_relocatable_if_eligible {}; // cxx11-warning@-1 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} -// cxx11-warning@-2 {{'replaceable_if_eligible' keyword is a C++2c extension}} -// cxx03-warning@-3 {{'final' keyword is a C++11 extension}} -class O trivially_relocatable_if_eligible replaceable_if_eligible final {}; +// cxx03-warning@-2 {{'final' keyword is a C++11 extension}} +class N final trivially_relocatable_if_eligible {}; // cxx11-warning@-1 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} -// cxx11-warning@-2 {{'replaceable_if_eligible' keyword is a C++2c extension}} -// cxx03-warning@-3 {{'final' keyword is a C++11 extension}} +// cxx03-warning@-2 {{'final' keyword is a C++11 extension}} +class O trivially_relocatable_if_eligible final {}; +// cxx11-warning@-1 {{'trivially_relocatable_if_eligible' keyword is a C++2c extension}} +// cxx03-warning@-2 {{'final' keyword is a C++11 extension}} diff --git a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp index c6919447798da..1fdce9cf2ec0b 100644 --- a/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp +++ b/clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp @@ -227,31 +227,12 @@ struct UserProvidedMoveAssign { }; struct Empty{}; -static_assert(__builtin_is_replaceable(Empty)); -struct S1 replaceable_if_eligible{}; -static_assert(__builtin_is_replaceable(S1)); - -static_assert(__builtin_is_replaceable(DefaultedMove)); -static_assert(__builtin_is_replaceable(DefaultedCopy)); -static_assert(__builtin_is_replaceable(DefaultedMoveAssign)); - -static_assert(!__builtin_is_replaceable(DeletedMove)); -static_assert(!__builtin_is_replaceable(DeletedCopy)); -static_assert(!__builtin_is_replaceable(DeletedMoveAssign)); -static_assert(!__builtin_is_replaceable(DeletedDtr)); - -static_assert(!__builtin_is_replaceable(UserProvidedMove)); -static_assert(!__builtin_is_replaceable(UserProvidedCopy)); -static_assert(!__builtin_is_replaceable(UserProvidedMoveAssign)); struct DeletedCopyTpl { template DeletedCopyTpl(const U&) = delete; }; -static_assert(__builtin_is_replaceable(DeletedCopyTpl)); - -using NotReplaceable = DeletedMove; template struct WithBase : T{}; @@ -265,59 +246,23 @@ struct WithVirtual { WithVirtual& operator=(WithVirtual&&) = default; }; -static_assert(__builtin_is_replaceable(S)); -static_assert(!__builtin_is_replaceable(S)); -static_assert(!__builtin_is_replaceable(S)); -static_assert(!__builtin_is_replaceable(S)); -static_assert(!__builtin_is_replaceable(S)); -static_assert(__builtin_is_replaceable(S)); -static_assert(!__builtin_is_replaceable(S)); -static_assert(__builtin_is_replaceable(WithBase>)); -static_assert(!__builtin_is_replaceable(WithBase>)); -static_assert(!__builtin_is_replaceable(WithBase)); -static_assert(__builtin_is_replaceable(WithVBase>)); -static_assert(!__builtin_is_replaceable(WithVBase>)); -static_assert(!__builtin_is_replaceable(WithVBase)); -static_assert(__builtin_is_replaceable(WithVirtual)); - -int n = 4; // expected-note 2{{declared here}} +int n = 4; // expected-note {{declared here}} static_assert(!__builtin_is_cpp_trivially_relocatable(int[n])); // expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} // expected-note@-2 {{read of non-const variable 'n' is not allowed in a constant expression}} -static_assert(!__builtin_is_replaceable(int[n])); -// expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} -// expected-note@-2 {{read of non-const variable 'n' is not allowed in a constant expression}} -struct U1 replaceable_if_eligible { - ~U1() = delete; - U1(U1&&) = default; - U1& operator=(U1&&) = default; - -}; -static_assert(!__builtin_is_replaceable(U1)); - -struct U2 replaceable_if_eligible { - U2(const U2&) = delete; -}; -static_assert(!__builtin_is_replaceable(U2)); - - -template -struct WithVBaseExplicit replaceable_if_eligible : virtual T{}; -static_assert(__builtin_is_replaceable(WithVBaseExplicit>)); - -struct S42 trivially_relocatable_if_eligible replaceable_if_eligible { +struct S42 trivially_relocatable_if_eligible { S42(S42&&); S42& operator=(S42&&) = default; }; -struct S43 trivially_relocatable_if_eligible replaceable_if_eligible { +struct S43 trivially_relocatable_if_eligible { S43(S43&&) = default; S43& operator=(S43&&); }; -struct Copyable1Explicit replaceable_if_eligible { +struct Copyable1Explicit { Copyable1Explicit(Copyable1Explicit const &) = default; }; @@ -326,7 +271,7 @@ struct Copyable1 { }; -struct CopyAssign1Explicit replaceable_if_eligible { +struct CopyAssign1Explicit { CopyAssign1Explicit & operator=(const CopyAssign1Explicit&) = default; }; @@ -338,26 +283,22 @@ struct UserDeleted1 { UserDeleted1(const UserDeleted1&) = delete; }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted1)); -static_assert(!__builtin_is_replaceable(UserDeleted1)); struct UserDeleted2 { UserDeleted2(UserDeleted2&&) = delete; }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted2)); -static_assert(!__builtin_is_replaceable(UserDeleted2)); struct UserDeleted3 { UserDeleted3 operator=(UserDeleted3); }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted3)); -static_assert(!__builtin_is_replaceable(UserDeleted3)); struct UserDeleted4 { UserDeleted4 operator=(UserDeleted4&&); }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted4)); -static_assert(!__builtin_is_replaceable(UserDeleted4)); } @@ -396,53 +337,43 @@ struct A { ~A (); }; A::~A () = default; static_assert (!__builtin_is_cpp_trivially_relocatable(A)); -static_assert (!__builtin_is_replaceable(A)); struct B { B(const B&); }; B::B (const B&) = default; static_assert (!__builtin_is_cpp_trivially_relocatable(B)); -static_assert (!__builtin_is_replaceable(B)); struct C { C& operator=(const C&); }; C& C::operator=(const C&) = default; static_assert (!__builtin_is_cpp_trivially_relocatable(C)); -static_assert (!__builtin_is_replaceable(C)); } namespace GH144232 { -struct E trivially_relocatable_if_eligible replaceable_if_eligible { +struct E trivially_relocatable_if_eligible { E (E &&); E &operator= (E &&) = default; }; -struct F trivially_relocatable_if_eligible replaceable_if_eligible { +struct F trivially_relocatable_if_eligible { F (F &&) = default; F &operator= (F &&); }; -struct G trivially_relocatable_if_eligible replaceable_if_eligible { G (G const &) = default; }; - -struct I trivially_relocatable_if_eligible replaceable_if_eligible { I &operator= (const I &) = default; }; +struct G trivially_relocatable_if_eligible { G (G const &) = default; }; -struct J trivially_relocatable_if_eligible replaceable_if_eligible { J (J const &); }; -struct K trivially_relocatable_if_eligible replaceable_if_eligible { K (K const &); }; +struct I trivially_relocatable_if_eligible { I &operator= (const I &) = default; }; +struct J trivially_relocatable_if_eligible { J (J const &); }; +struct K trivially_relocatable_if_eligible { K (K const &); }; -static_assert (__builtin_is_replaceable (E)); static_assert (__builtin_is_cpp_trivially_relocatable(E)); -static_assert (__builtin_is_replaceable (F)); static_assert (__builtin_is_cpp_trivially_relocatable(F)); -static_assert (__builtin_is_replaceable (G)); static_assert (__builtin_is_cpp_trivially_relocatable(G)); -static_assert (__builtin_is_replaceable (I)); static_assert (__builtin_is_cpp_trivially_relocatable(I)); -static_assert (__builtin_is_replaceable (J)); static_assert (__builtin_is_cpp_trivially_relocatable(J)); -static_assert (__builtin_is_replaceable (K)); static_assert (__builtin_is_cpp_trivially_relocatable(K)); } diff --git a/clang/test/SemaCXX/ptrauth-type-traits.cpp b/clang/test/SemaCXX/ptrauth-type-traits.cpp index a81ef1cce25b6..be4e17aa81ceb 100644 --- a/clang/test/SemaCXX/ptrauth-type-traits.cpp +++ b/clang/test/SemaCXX/ptrauth-type-traits.cpp @@ -320,26 +320,6 @@ static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableAddressDiscrimi static_assert(!__builtin_is_cpp_trivially_relocatable(EmbdeddedAddressDiscriminatedPolymorphicClass)); static_assert(!__builtin_is_cpp_trivially_relocatable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); -static_assert( __builtin_is_replaceable(AddressDiscriminatedPtr)); -static_assert( __builtin_is_replaceable(AddressDiscriminatedInt64)); -static_assert( __builtin_is_replaceable(AddressDiscriminatedFields)); -static_assert( __builtin_is_replaceable(RelocatableAddressDiscriminatedFields)); -static_assert( __builtin_is_replaceable(AddressDiscriminatedFieldInBaseClass)); -static_assert(!__builtin_is_replaceable(NonAddressDiscriminatedVTablePtr)); -static_assert(!__builtin_is_replaceable(NonAddressDiscriminatedVTablePtr2)); -static_assert(!__builtin_is_replaceable(RelocatableNonAddressDiscriminatedVTablePtr)); -static_assert(!__builtin_is_replaceable(RelocatableNonAddressDiscriminatedVTablePtr2)); -static_assert(!__builtin_is_replaceable(AddressDiscriminatedVTablePtr)); -static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedVTablePtr)); -static_assert(!__builtin_is_replaceable(NoAddressDiscriminatedBaseClasses)); -static_assert(!__builtin_is_replaceable(RelocatableNoAddressDiscriminatedBaseClasses)); -static_assert(!__builtin_is_replaceable(AddressDiscriminatedPrimaryBase)); -static_assert(!__builtin_is_replaceable(AddressDiscriminatedSecondaryBase)); -static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedPrimaryBase)); -static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedSecondaryBase)); -static_assert(!__builtin_is_replaceable(EmbdeddedAddressDiscriminatedPolymorphicClass)); -static_assert(!__builtin_is_replaceable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); - static_assert( __is_bitwise_cloneable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); static_assert( __is_bitwise_cloneable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); static_assert( __is_bitwise_cloneable(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 3e03a79275232..8a9f3bc400d20 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp @@ -591,24 +591,3 @@ void test() { // expected-note@#concept10 {{because it is a cv void type}} } } - - -namespace std { -template -struct is_replaceable { - static constexpr bool value = __builtin_is_replaceable(T); -}; - -template -constexpr bool is_replaceable_v = __builtin_is_replaceable(T); - -} - -static_assert(std::is_replaceable::value); -// expected-error@-1 {{static assertion failed due to requirement 'std::is_replaceable::value'}} \ -// expected-note@-1 {{'int &' is not replaceable}} \ -// expected-note@-1 {{because it is a reference type}} -static_assert(std::is_replaceable_v); -// expected-error@-1 {{static assertion failed due to requirement 'std::is_replaceable_v'}} \ -// expected-note@-1 {{'int &' is not replaceable}} \ -// expected-note@-1 {{because it is a reference type}} diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp index 22740418f09f5..2ab5b6ec372ed 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp @@ -144,138 +144,6 @@ static_assert(__builtin_is_cpp_trivially_relocatable(U2)); // expected-note@#tr-U2 {{'U2' defined here}} } -namespace replaceable { - -extern int vla_size; -static_assert(__builtin_is_replaceable(int[vla_size])); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(int[vla_size])'}} \ -// expected-note@-1 {{'int[vla_size]' is not replaceable}} \ -// expected-note@-1 {{because it is a variably-modified type}} - -struct S; // expected-note {{forward declaration of 'replaceable::S'}} -static_assert(__builtin_is_replaceable(S)); -// expected-error@-1 {{incomplete type 'S' used in type trait expression}} - -static_assert(__builtin_is_replaceable(const volatile int)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(const volatile int)}} \ -// expected-note@-1 {{'const volatile int' is not replaceable}} \ -// expected-note@-1 {{because it is const}} \ -// expected-note@-1 {{because it is volatile}} - - -static_assert(__builtin_is_replaceable(void())); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(void ())}} \ -// expected-note@-1 {{'void ()' is not replaceable}} \ -// expected-note@-1 {{because it is not a scalar or class type}} - -struct B { - virtual ~B(); -}; -struct S : virtual B { // #replaceable-S - S(); - int & a; - const int ci; - B & b; - B c; - ~S(); -}; -static_assert(__builtin_is_replaceable(S)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::S)'}} \ -// expected-note@-1 {{'S' is not replaceable}} \ -// expected-note@-1 {{because it has a non-replaceable base 'B'}} \ -// expected-note@-1 {{because it has a non-replaceable member 'a' of type 'int &'}} \ -// expected-note@-1 {{because it has a non-replaceable member 'ci' of type 'const int'}} \ -// expected-note@-1 {{because it has a non-replaceable member 'b' of type 'B &'}} \ -// expected-note@-1 {{because it has a non-replaceable member 'c' of type 'B'}} \ -// expected-note@-1 {{because it has a user-provided destructor}} \ -// expected-note@-1 {{because it has a deleted copy assignment operator}} -// expected-note@#replaceable-S {{'S' defined here}} - -struct S2 { // #replaceable-S2 - S2(S2&&); - S2& operator=(const S2&); -}; -static_assert(__builtin_is_replaceable(S2)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::S2)'}} \ -// expected-note@-1 {{'S2' is not replaceable}} \ -// expected-note@-1 {{because it has a user provided move constructor}} \ -// expected-note@-1 {{because it has a user provided copy assignment operator}} \ -// expected-note@#replaceable-S2 {{'S2' defined here}} - - -struct S3 { // #replaceable-S3 - ~S3() = delete; -}; -static_assert(__builtin_is_replaceable(S3)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::S3)'}} \ -// expected-note@-1 {{'S3' is not replaceable}} \ -// expected-note@-1 {{because it has a deleted destructor}} \ -// expected-note@#replaceable-S3 {{'S3' defined here}} - - -union U { // #replaceable-U - U(const U&); - U(U&&); - U& operator=(const U&); - U& operator=(U&&); -}; -static_assert(__builtin_is_replaceable(U)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::U)'}} \ -// expected-note@-1 {{'U' is not replaceable}} \ -// expected-note@-1 {{because it is a union with a user-declared copy constructor}} \ -// expected-note@-1 {{because it is a union with a user-declared copy assignment operator}} \ -// expected-note@-1 {{because it is a union with a user-declared move constructor}} \ -// expected-note@-1 {{because it is a union with a user-declared move assignment operator}} -// expected-note@#replaceable-U {{'U' defined here}} -struct S4 replaceable_if_eligible { // #replaceable-S4 - ~S4(); - B b; -}; -static_assert(__builtin_is_replaceable(S4)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::S4)'}} \ -// expected-note@-1 {{'S4' is not replaceable}} \ -// expected-note@-1 {{because it has a non-replaceable member 'b' of type 'B'}} \ -// expected-note@#replaceable-S4 {{'S4' defined here}} - -union U2 replaceable_if_eligible { // #replaceable-U2 - U2(const U2&); - U2(U2&&); - B b; -}; -static_assert(__builtin_is_replaceable(U2)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::U2)'}} \ -// expected-note@-1 {{'U2' is not replaceable}} \ -// expected-note@-1 {{because it has a deleted destructor}} \ -// expected-note@-1 {{because it has a non-replaceable member 'b' of type 'B'}} \ -// expected-note@-1 {{because it has a deleted copy assignment operator}} \ -// expected-note@#replaceable-U2 {{'U2' defined here}} - -struct UD1 { // #replaceable-UD1 - UD1(const UD1&) = delete; - UD1 & operator=(const UD1&) = delete; - -}; -static_assert(__builtin_is_replaceable(UD1)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::UD1)'}} \ -// expected-note@-1 {{'UD1' is not replaceable}} \ -// expected-note@-1 {{because it has a deleted copy constructor}} \ -// expected-note@-1 {{because it has a deleted copy assignment operator}} \ -// expected-note@#replaceable-UD1 {{'UD1' defined here}} - - -struct UD2 { // #replaceable-UD2 - UD2(UD2&&) = delete; - UD2 & operator=(UD2&&) = delete; -}; -static_assert(__builtin_is_replaceable(UD2)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(replaceable::UD2)'}} \ -// expected-note@-1 {{'UD2' is not replaceable}} \ -// expected-note@-1 {{because it has a deleted move constructor}} \ -// expected-note@-1 {{because it has a deleted move assignment operator}} \ -// expected-note@#replaceable-UD2 {{'UD2' defined here}} - -} - namespace GH143325 { struct Foo { // expected-note {{previous definition is here}} @@ -320,7 +188,7 @@ static_assert(__builtin_is_cpp_trivially_relocatable(UnionOfPolymorphic)); } -struct GH143599 { // expected-note 2 {{'GH143599' defined here}} +struct GH143599 { // expected-note {{'GH143599' defined here}} ~GH143599 (); GH143599(const GH143599&); GH143599& operator=(const GH143599&); @@ -336,13 +204,6 @@ static_assert (__builtin_is_cpp_trivially_relocatable(GH143599)); // expected-note@-1 {{because it has a user provided copy assignment operator}} \ // expected-note@-1 {{because it has a user-provided destructor}} -static_assert (__builtin_is_replaceable(GH143599)); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_is_replaceable(GH143599)'}} \ -// expected-note@-1 {{'GH143599' is not replaceable}} \ -// expected-note@-1 {{because it has a user provided copy constructor}} \ -// expected-note@-1 {{because it has a user provided copy assignment operator}} \ -// expected-note@-1 {{because it has a user-provided destructor}} - namespace trivially_copyable { struct B { virtual ~B(); @@ -663,7 +524,7 @@ namespace is_empty_tests { // expected-error@-1 {{static assertion failed due to requirement '__is_empty(is_empty_tests::Derived)'}} \ // expected-note@-1 {{'Derived' is not empty}} \ // expected-note@-1 {{because it has a base class 'Base' that is not empty}} \ - // expected-note@#e-Derived {{'Derived' defined here}} + // expected-note@#e-Derived {{'Derived' defined here}} // Combination of the above. struct Multi : Base, virtual EB { // #e-Multi @@ -681,15 +542,15 @@ namespace is_empty_tests { // Zero-width bit-field. struct BitField { int : 0; }; // #e-BitField - static_assert(__is_empty(BitField)); // no diagnostics + static_assert(__is_empty(BitField)); // no diagnostics - // Dependent bit-field width. + // Dependent bit-field width. template struct DependentBitField { int : N; }; // #e-DependentBitField static_assert(__is_empty(DependentBitField<0>)); // no diagnostics - static_assert(__is_empty(DependentBitField<2>)); + static_assert(__is_empty(DependentBitField<2>)); // expected-error@-1 {{static assertion failed due to requirement '__is_empty(is_empty_tests::DependentBitField<2>)'}} \ // expected-note@-1 {{'DependentBitField<2>' is not empty}} \ // expected-note@-1 {{because it field '' is a non-zero-length bit-field}} \ @@ -738,7 +599,7 @@ union U { // #sl-U int x; // #sl-UF1 private: int y; // #sl-UF2 -}; +}; static_assert(__is_standard_layout(U)); // expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::U)'}} \ // expected-note@-1 {{'U' is not standard-layout}} \ @@ -750,7 +611,7 @@ static_assert(__is_standard_layout(U)); // Single base class is OK struct BaseClass{ int a; }; // #sl-BaseClass struct DerivedOK : BaseClass {}; // #sl-DerivedOK -static_assert(__is_standard_layout(DerivedOK)); +static_assert(__is_standard_layout(DerivedOK)); // Primitive types should be standard layout static_assert(__is_standard_layout(int)); // #sl-Int @@ -760,11 +621,11 @@ static_assert(__is_standard_layout(float)); // #sl-Float struct Base1 { int a; }; // #sl-Base1 struct Base2 { int b; }; // #sl-Base2 struct DerivedClass : Base1, Base2 {}; // #sl-DerivedClass -static_assert(__is_standard_layout(DerivedClass)); +static_assert(__is_standard_layout(DerivedClass)); // expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::DerivedClass)'}} \ // expected-note@-1 {{'DerivedClass' is not standard-layout}} \ // expected-note@-1 {{because it has multiple base classes with data members}} \ -// expected-note@#sl-DerivedClass {{'DerivedClass' defined here}} +// expected-note@#sl-DerivedClass {{'DerivedClass' defined here}} // Inheritance hierarchy with multiple classes having data members struct BaseA { int a; }; // #sl-BaseA @@ -809,7 +670,7 @@ static_assert(__is_standard_layout(E)); // expected-note@#sl-E {{'E' defined here}} // F inherits D but only an unnamed bitfield -// This should still fail because F ends up with a +// This should still fail because F ends up with a // base class with a data member and its own unnamed bitfield // which is not allowed in standard layout struct F : D { int : 0; }; // #sl-F