[clang] [Clang] Implement the core language parts of P2786 - Trivial relocation (PR #127636)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 20 09:49:12 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clang
Author: cor3ntin (cor3ntin)
<details>
<summary>Changes</summary>
This adds
- The parsing of `trivially_relocatable_if_eligible`, `replaceable_if_eligible` keywords
- `__builtin_trivially_relocate`, implemented in terms of memmove. In the future this should
- Add the appropriate start/end lifetime markers that llvm does not have (`start_lifetime_as`)
- Add support for ptrauth when that's upstreamed
- the `__builtin_is_cpp_trivially_relocatable` and `__builtin_is_replaceable` traits
---
Patch is 52.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/127636.diff
25 Files Affected:
- (modified) clang/docs/LanguageExtensions.rst (+21)
- (modified) clang/include/clang/AST/CXXRecordDeclDefinitionBits.def (+8)
- (modified) clang/include/clang/AST/DeclCXX.h (+77-2)
- (modified) clang/include/clang/AST/Type.h (+4)
- (modified) clang/include/clang/Basic/Builtins.td (+6)
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+3)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5)
- (modified) clang/include/clang/Basic/TokenKinds.def (+2)
- (modified) clang/include/clang/Parse/Parser.h (+13)
- (modified) clang/include/clang/Sema/Sema.h (+14-5)
- (modified) clang/lib/AST/Decl.cpp (+1)
- (modified) clang/lib/AST/DeclCXX.cpp (+16-4)
- (modified) clang/lib/AST/Type.cpp (+24)
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+1)
- (modified) clang/lib/Frontend/InitPreprocessor.cpp (+2-1)
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+97-24)
- (modified) clang/lib/Parse/Parser.cpp (+2)
- (modified) clang/lib/Sema/SemaChecking.cpp (+51)
- (modified) clang/lib/Sema/SemaDecl.cpp (+20-5)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+214)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+6)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+4)
- (added) clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp (+16)
- (added) clang/test/Parser/cxx2c-trivially-relocatable.cpp (+8)
- (added) clang/test/SemaCXX/cxx2c-trivially-relocatable.cpp (+272)
``````````diff
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 2a956ad5b2909..7e4e71299eb80 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1825,6 +1825,12 @@ The following type trait primitives are supported by Clang. Those traits marked
functionally equivalent to copying the underlying bytes and then dropping the
source object on the floor. This is true of trivial types and types which
were made trivially relocatable via the ``clang::trivial_abi`` attribute.
+* ``__builtin_is_cpp_trivially_relocatable`` (C++): Returns true if and object
+ is trivially relocatable, as defined by the C++26 standard.
+ Note that the caller code should ensure that if the object is polymorphic,
+ the dynamic type is of the most derived type.
+* ``__builtin_is_replaceable`` (C++): Returns true if and object
+ is replaceable, as defined by the C++26 standard.
* ``__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
@@ -3624,6 +3630,21 @@ Query for this feature with ``__has_builtin(__builtin_operator_new)`` or
replaceable global (de)allocation functions, but do support calling at least
``::operator new(size_t)`` and ``::operator delete(void*)``.
+
+``__builtin_trivially_relocate``
+-----------------------------------
+
+**Syntax**:
+
+.. code-block:: c
+
+ T* __builtin_trivially_relocate(T* dest, T* src, size_t count)
+
+Trivially relocates ``count`` objects of relocatable, complete type ``T``
+from ``src`` to ``dest`` and returns ``dest``.
+This builtin is used to implement ``std::trivially_relocate``.
+
+
``__builtin_preserve_access_index``
-----------------------------------
diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
index 6620840df0ced..7633a987673e9 100644
--- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -224,6 +224,10 @@ FIELD(StructuralIfLiteral, 1, NO_MERGE)
/// explicitly deleted or defaulted).
FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE)
+FIELD(UserProvidedMoveAssignment, 1, NO_MERGE)
+FIELD(UserProvidedCopyAssignment, 1, NO_MERGE)
+FIELD(ExplicitlyDeletedMoveAssignment, 1, NO_MERGE)
+
/// The special members which have been declared for this class,
/// either by the user or implicitly.
FIELD(DeclaredSpecialMembers, 6, MERGE_OR)
@@ -253,4 +257,8 @@ FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
/// type that is intangible). HLSL only.
FIELD(IsHLSLIntangible, 1, NO_MERGE)
+FIELD(IsTriviallyRelocatable, 1, NO_MERGE)
+
+FIELD(IsReplaceable, 1, NO_MERGE)
+
#undef FIELD
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 266b93a64a390..4d578e3401456 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -127,6 +127,33 @@ class AccessSpecDecl : public Decl {
static bool classofKind(Kind K) { return K == AccessSpec; }
};
+enum class RelocatableOrReplaceableClassSpecifierKind {
+ Relocatable,
+ Replaceable
+};
+
+template <RelocatableOrReplaceableClassSpecifierKind MK>
+class BasicRelocatableOrReplaceableClassSpecifier {
+public:
+ BasicRelocatableOrReplaceableClassSpecifier() = default;
+ BasicRelocatableOrReplaceableClassSpecifier(SourceLocation Begin)
+ : Loc(Begin) {}
+ void Set(SourceLocation Begin) { Loc = Begin; }
+
+ bool isSet() const { return !Loc.isInvalid(); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+private:
+ SourceLocation Loc;
+};
+
+using TriviallyRelocatableSpecifier =
+ BasicRelocatableOrReplaceableClassSpecifier<
+ RelocatableOrReplaceableClassSpecifierKind::Relocatable>;
+using ReplaceableSpecifier = BasicRelocatableOrReplaceableClassSpecifier<
+ RelocatableOrReplaceableClassSpecifierKind::Replaceable>;
+
/// Represents a base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
@@ -349,6 +376,10 @@ class CXXRecordDecl : public RecordDecl {
/// This is actually currently stored in reverse order.
LazyDeclPtr FirstFriend;
+ TriviallyRelocatableSpecifier TriviallyRelocatableSpecifier;
+
+ ReplaceableSpecifier ReplaceableSpecifier;
+
DefinitionData(CXXRecordDecl *D);
/// Retrieve the set of direct base classes.
@@ -717,11 +748,18 @@ class CXXRecordDecl : public RecordDecl {
/// deleted.
bool defaultedMoveConstructorIsDeleted() const {
assert((!needsOverloadResolutionForMoveConstructor() ||
- (data().DeclaredSpecialMembers & SMF_MoveConstructor)) &&
- "this property has not yet been computed by Sema");
+ (data().DeclaredSpecialMembers & SMF_MoveConstructor)) &&
+ "this property has not yet been computed by Sema");
return data().DefaultedMoveConstructorIsDeleted;
}
+ bool defaultedMoveAssignmentIsDeleted() const {
+ assert((!needsOverloadResolutionForMoveAssignment() ||
+ (data().DeclaredSpecialMembers & SMF_MoveAssignment)) &&
+ "this property has not yet been computed by Sema");
+ return data().DefaultedMoveAssignmentIsDeleted;
+ }
+
/// \c true if a defaulted destructor for this class would be deleted.
bool defaultedDestructorIsDeleted() const {
assert((!needsOverloadResolutionForDestructor() ||
@@ -806,6 +844,18 @@ class CXXRecordDecl : public RecordDecl {
return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
}
+ bool hasUserProvidedCopyAssignment() const {
+ return data().UserProvidedCopyAssignment;
+ }
+
+ bool hasUserProvidedMoveAssignment() const {
+ return data().UserProvidedCopyAssignment;
+ }
+
+ bool hasExplicitlyDeletedMoveAssignment() const {
+ return data().ExplicitlyDeletedMoveAssignment;
+ }
+
/// Determine whether this class needs an implicit copy
/// constructor to be lazily declared.
bool needsImplicitCopyConstructor() const {
@@ -1471,6 +1521,24 @@ class CXXRecordDecl : public RecordDecl {
return isLiteral() && data().StructuralIfLiteral;
}
+ TriviallyRelocatableSpecifier getTriviallyRelocatableSpecifier() const {
+ return data().TriviallyRelocatableSpecifier;
+ }
+
+ ReplaceableSpecifier getReplaceableSpecifier() const {
+ return data().ReplaceableSpecifier;
+ }
+
+ bool isTriviallyRelocatable() const { return data().IsTriviallyRelocatable; }
+
+ void setIsTriviallyRelocatable(bool Set) {
+ data().IsTriviallyRelocatable = Set;
+ }
+
+ bool isReplaceable() const { return data().IsReplaceable; }
+
+ void setIsReplaceable(bool Set) { data().IsReplaceable = Set; }
+
/// Notify the class that this destructor is now selected.
///
/// Important properties of the class depend on destructor properties. Since
@@ -1905,6 +1973,13 @@ class CXXRecordDecl : public RecordDecl {
return K >= firstCXXRecord && K <= lastCXXRecord;
}
void markAbstract() { data().Abstract = true; }
+
+ void setTriviallyRelocatableSpecifier(TriviallyRelocatableSpecifier TRS) {
+ data().TriviallyRelocatableSpecifier = TRS;
+ }
+ void setReplaceableSpecifier(ReplaceableSpecifier MRS) {
+ data().ReplaceableSpecifier = MRS;
+ }
};
/// Store information needed for an explicit specifier.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1d9743520654e..8eb373cdd942a 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1129,6 +1129,10 @@ class QualType {
/// Return true if this is a trivially relocatable type.
bool isTriviallyRelocatableType(const ASTContext &Context) const;
+ bool isCppTriviallyRelocatableType(const ASTContext &Context) const;
+
+ bool isReplaceableType(const ASTContext &Context) const;
+
/// Returns true if it is a class and it might be dynamic.
bool mayBeDynamicClass() const;
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0e5df338dd2e5..237fa3a46f8c8 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2823,6 +2823,12 @@ def MemMove : LibBuiltin<"string.h"> {
let AddBuiltinPrefixedAlias = 1;
}
+def BuiltinTriviallyRelocate : Builtin {
+ let Spellings = ["__builtin_trivially_relocate"];
+ let Attributes = [FunctionWithBuiltinPrefix, CustomTypeChecking, NoThrow];
+ let Prototype = "void*(void*, void*, size_t)";
+}
+
def StrCpy : LibBuiltin<"string.h"> {
let Spellings = ["strcpy"];
let Attributes = [NoThrow];
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c513dab810d1f..84ee963e48ff6 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1063,6 +1063,9 @@ 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_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 f10af8f5bd6b2..2292afe5f9ecb 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12427,6 +12427,11 @@ def err_builtin_invalid_arg_type: Error <
"an 'int'|"
"a vector of floating points}1 (was %2)">;
+def err_builtin_trivially_relocate_invalid_arg_type: Error <
+ "first%select{||| and second}0 argument%select{|||s}0 to "
+ "'__builtin_trivially_relocate' must be"
+ " %select{a pointer|non-const|relocatable|of the same type}0">;
+
def err_builtin_matrix_disabled: Error<
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;
def err_matrix_index_not_integer: Error<
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 397a5d95709fb..5846acff120fc 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -555,6 +555,8 @@ TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary
TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX)
TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL)
+TYPE_TRAIT_1(__builtin_is_cpp_trivially_relocatable, IsCppTriviallyRelocatable, KEYCXX)
+TYPE_TRAIT_1(__builtin_is_replaceable, IsReplaceable, KEYCXX)
// Embarcadero Expression Traits
EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 335258d597028..304ad6dd25476 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -164,6 +164,8 @@ class Parser : public CodeCompletionHandler {
mutable IdentifierInfo *Ident_final;
mutable IdentifierInfo *Ident_GNU_final;
mutable IdentifierInfo *Ident_override;
+ mutable IdentifierInfo *Ident_trivially_relocatable_if_eligible;
+ mutable IdentifierInfo *Ident_replaceable_if_eligible;
// C++2a contextual keywords.
mutable IdentifierInfo *Ident_import;
@@ -3169,6 +3171,17 @@ class Parser : public CodeCompletionHandler {
SourceLocation FriendLoc);
bool isCXX11FinalKeyword() const;
+
+ bool isCXX2CTriviallyRelocatableKeyword(Token Tok) const;
+ bool isCXX2CTriviallyRelocatableKeyword() const;
+ void ParseOptionalCXX2CTriviallyRelocatableSpecifier(
+ TriviallyRelocatableSpecifier &TRS);
+
+ bool isCXX2CReplaceableKeyword(Token Tok) const;
+ bool isCXX2CReplaceableKeyword() const;
+ void ParseOptionalCXX2CReplaceableSpecifier(ReplaceableSpecifier &MRS);
+
+ bool isClassCompatibleKeyword(Token Tok) const;
bool isClassCompatibleKeyword() const;
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c55b964650323..4fd14d2b93636 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3960,20 +3960,29 @@ class Sema final : public SemaBase {
/// Invoked when we enter a tag definition that we're skipping.
SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
+ TriviallyRelocatableSpecifier
+ ActOnTriviallyRelocatableSpecifier(SourceLocation Loc);
+
+ ReplaceableSpecifier ActOnReplaceableSpecifier(SourceLocation Loc);
+
/// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
/// C++ record definition's base-specifiers clause and are starting its
/// member declarations.
- void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
- SourceLocation FinalLoc,
- bool IsFinalSpelledSealed,
- bool IsAbstract,
- SourceLocation LBraceLoc);
+ void ActOnStartCXXMemberDeclarations(
+ Scope *S, Decl *TagDecl, SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed, bool IsAbstract,
+ TriviallyRelocatableSpecifier TriviallyRelocatable,
+ ReplaceableSpecifier Replaceable, SourceLocation LBraceLoc);
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
/// the definition of a tag (enumeration, class, struct, or union).
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
SourceRange BraceRange);
+ void CheckCXX2CTriviallyRelocatable(CXXRecordDecl *D);
+
+ void CheckCXX2CReplaceable(CXXRecordDecl *D);
+
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
/// ActOnTagDefinitionError - Invoked when there was an unrecoverable
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 610207cf8b9a4..dd45aa9c8d5dc 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4445,6 +4445,7 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
case Builtin::BImempcpy:
return Builtin::BImempcpy;
+ case Builtin::BI__builtin_trivially_relocate:
case Builtin::BI__builtin_memmove:
case Builtin::BI__builtin___memmove_chk:
case Builtin::BImemmove:
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 7eff776882629..b80c8827ee839 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -103,13 +103,16 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
HasConstexprDefaultConstructor(false),
DefaultedDestructorIsConstexpr(true),
HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true),
- UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
+ UserProvidedDefaultConstructor(false), UserProvidedMoveAssignment(false),
+ UserProvidedCopyAssignment(false), ExplicitlyDeletedMoveAssignment(false),
+ DeclaredSpecialMembers(0),
ImplicitCopyConstructorCanHaveConstParamForVBase(true),
ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false),
- IsAnyDestructorNoReturn(false), IsHLSLIntangible(false), IsLambda(false),
+ IsAnyDestructorNoReturn(false), IsHLSLIntangible(false),
+ IsTriviallyRelocatable(false), IsReplaceable(false), IsLambda(false),
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
HasODRHash(false), Definition(D) {}
@@ -1529,7 +1532,10 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
if (DD->isNoReturn())
data().IsAnyDestructorNoReturn = true;
}
-
+ if (SMKind == SMF_CopyAssignment)
+ data().UserProvidedCopyAssignment = MD->isUserProvided();
+ else if (SMKind == SMF_MoveAssignment)
+ data().UserProvidedMoveAssignment = MD->isUserProvided();
if (!MD->isImplicit() && !MD->isUserProvided()) {
// This method is user-declared but not user-provided. We can't work
// out whether it's trivial yet (not until we get to the end of the
@@ -1551,6 +1557,9 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
if (!MD->isUserProvided())
data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
}
+
+ if (MD->isDeleted() && SMKind == SMF_MoveAssignment)
+ data().ExplicitlyDeletedMoveAssignment = true;
}
void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
@@ -1578,8 +1587,11 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
data().HasIrrelevantDestructor = false;
} else if (D->isCopyAssignmentOperator())
SMKind |= SMF_CopyAssignment;
- else if (D->isMoveAssignmentOperator())
+ else if (D->isMoveAssignmentOperator()) {
SMKind |= SMF_MoveAssignment;
+ if (!D->isIneligibleOrNotSelected() && D->isDeleted())
+ data().ExplicitlyDeletedMoveAssignment = true;
+ }
// Update which trivial / non-trivial special members we have.
// addedMember will have skipped this step for this member.
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 8c11ec2e1fe24..77700056d8952 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2862,6 +2862,30 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
}
}
+bool QualType::isCppTriviallyRelocatableType(const ASTContext &Context) const {
+ QualType BaseElementType = Context.getBaseElementType(*this);
+ if (BaseElementType->isIncompleteType())
+ return false;
+ else if (BaseElementType->isScalarType())
+ return true;
+ else if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
+ return RD->isTriviallyRelocatable();
+ return false;
+}
+
+bool QualType::isReplaceableType(const ASTContext &Context) const {
+ if (isConstQualified())
+ return false;
+ QualType BaseElementType = Context.getBaseElementType(getUnqualifiedType());
+ if (BaseElementType->isIncompleteType())
+ return false;
+ if (BaseElementType->isScalarType())
+ return true;
+ if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
+ return RD->isReplaceable();
+ return false;
+}
+
bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
return !Context.getLangOpts().ObjCAutoRefCount &&
Context.getLangOpts().ObjCWeak &&
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index d57f491a20c8e..8e7e714960321 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4762,6 +4762,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Dest, *this);
}
+ case Builtin::BI__builtin_trivially_relocate:
case Builtin::BImemmove:
case Builtin::BI__builtin_memmove: {
Address Dest = EmitPointerWithAlignment(E->getArg(0));
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 77833f5d1defb..48140a6375eb0 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -757,7 +757,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_explicit_this_parameter", "202110L");
}
- // We provide those C++23 features as extensions in earlier language modes, so
+ // We provide those C++2b features as extensions in earlier language modes, so
// we also define their feature test macros.
if (LangOpts.CPlusPlus11)
Builder.defineMacro("__cpp_static_call_operator", "202207L");
@@ -768,6 +768,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_pack_indexing", "202311L");
Builder.defineMacro("__cpp_deleted_function", "202403L");
Builder.defineMacro("__cpp_variadic_friend", "202403L");
+ Builder.defineMacro("__cpp_trivial_relocatability", "202502L");
if (LangOpts.Char8)
Builder.defineMacro("__cpp_char8_t", "202207L");
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 43db715ac6d70..3...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/127636
More information about the cfe-commits
mailing list