Skip to content

Commit fd884f1

Browse files
committed
Defer the computation of relocatability/replaceability to
when the trait is queried, in order to avoid a performance regression. Unfortunately, this move the queries from ASTContext to Sema.
1 parent 94eb978 commit fd884f1

File tree

12 files changed

+170
-172
lines changed

12 files changed

+170
-172
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,20 @@ class ASTContext : public RefCountedBase<ASTContext> {
624624
using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>;
625625
ParameterIndexTable ParamIndices;
626626

627+
public:
628+
struct CXXRecordDeclRelocationInfo {
629+
unsigned IsRelocatable;
630+
unsigned IsReplaceable;
631+
};
632+
std::optional<CXXRecordDeclRelocationInfo>
633+
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
634+
void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
635+
CXXRecordDeclRelocationInfo);
636+
637+
private:
638+
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
639+
RelocatableClasses;
640+
627641
ImportDecl *FirstLocalImport = nullptr;
628642
ImportDecl *LastLocalImport = nullptr;
629643

clang/include/clang/AST/CXXRecordDeclDefinitionBits.def

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,6 @@ FIELD(StructuralIfLiteral, 1, NO_MERGE)
224224
/// explicitly deleted or defaulted).
225225
FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE)
226226

227-
FIELD(UserProvidedMoveAssignment, 1, NO_MERGE)
228-
FIELD(UserProvidedCopyAssignment, 1, NO_MERGE)
229-
FIELD(ExplicitlyDeletedMoveAssignment, 1, NO_MERGE)
230-
231227
/// The special members which have been declared for this class,
232228
/// either by the user or implicitly.
233229
FIELD(DeclaredSpecialMembers, 6, MERGE_OR)
@@ -257,8 +253,4 @@ FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
257253
/// type that is intangible). HLSL only.
258254
FIELD(IsHLSLIntangible, 1, NO_MERGE)
259255

260-
FIELD(IsTriviallyRelocatable, 1, NO_MERGE)
261-
262-
FIELD(IsReplaceable, 1, NO_MERGE)
263-
264256
#undef FIELD

clang/include/clang/AST/DeclCXX.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -820,18 +820,6 @@ class CXXRecordDecl : public RecordDecl {
820820
return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
821821
}
822822

823-
bool hasUserProvidedCopyAssignment() const {
824-
return data().UserProvidedCopyAssignment;
825-
}
826-
827-
bool hasUserProvidedMoveAssignment() const {
828-
return data().UserProvidedCopyAssignment;
829-
}
830-
831-
bool hasExplicitlyDeletedMoveAssignment() const {
832-
return data().ExplicitlyDeletedMoveAssignment;
833-
}
834-
835823
/// Determine whether this class needs an implicit copy
836824
/// constructor to be lazily declared.
837825
bool needsImplicitCopyConstructor() const {
@@ -1497,16 +1485,6 @@ class CXXRecordDecl : public RecordDecl {
14971485
return isLiteral() && data().StructuralIfLiteral;
14981486
}
14991487

1500-
bool isTriviallyRelocatable() const { return data().IsTriviallyRelocatable; }
1501-
1502-
void setIsTriviallyRelocatable(bool Set) {
1503-
data().IsTriviallyRelocatable = Set;
1504-
}
1505-
1506-
bool isReplaceable() const { return data().IsReplaceable; }
1507-
1508-
void setIsReplaceable(bool Set) { data().IsReplaceable = Set; }
1509-
15101488
/// Notify the class that this destructor is now selected.
15111489
///
15121490
/// Important properties of the class depend on destructor properties. Since

clang/include/clang/AST/Type.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,13 +1126,6 @@ class QualType {
11261126
/// Return true if this is a trivially copyable type
11271127
bool isTriviallyCopyConstructibleType(const ASTContext &Context) const;
11281128

1129-
/// Return true if this is a trivially relocatable type.
1130-
bool isTriviallyRelocatableType(const ASTContext &Context) const;
1131-
1132-
bool isCXXTriviallyRelocatableType(const ASTContext &Context) const;
1133-
1134-
bool isReplaceableType(const ASTContext &Context) const;
1135-
11361129
/// Returns true if it is a class and it might be dynamic.
11371130
bool mayBeDynamicClass() const;
11381131

clang/include/clang/Sema/Sema.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4024,7 +4024,8 @@ class Sema final : public SemaBase {
40244024
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
40254025
SourceRange BraceRange);
40264026

4027-
void CheckCXX2CRelocatableAndReplaceable(CXXRecordDecl *D);
4027+
ASTContext::CXXRecordDeclRelocationInfo
4028+
CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D);
40284029

40294030
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
40304031

@@ -8439,6 +8440,18 @@ class Sema final : public SemaBase {
84398440
ExprResult &LHS, ExprResult &RHS,
84408441
SourceLocation QuestionLoc);
84418442

8443+
//// Determines if a type is trivially relocatable
8444+
/// according to the C++26 rules.
8445+
// FIXME: This is in Sema because it requires
8446+
// overload resolution, can we move to ASTContext?
8447+
bool IsCXXTriviallyRelocatableType(QualType T);
8448+
8449+
//// Determines if a type is replaceable
8450+
/// according to the C++26 rules.
8451+
// FIXME: This is in Sema because it requires
8452+
// overload resolution, can we move to ASTContext?
8453+
bool IsCXXReplaceableType(QualType T);
8454+
84428455
/// Check the operands of ?: under C++ semantics.
84438456
///
84448457
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y

clang/lib/AST/ASTContext.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,24 @@ void ASTContext::getOverriddenMethods(
16811681
Overridden.append(OverDecls.begin(), OverDecls.end());
16821682
}
16831683

1684+
std::optional<ASTContext::CXXRecordDeclRelocationInfo>
1685+
ASTContext::getRelocationInfoForCXXRecord(const CXXRecordDecl *RD) const {
1686+
assert(RD);
1687+
CXXRecordDecl *D = RD->getDefinition();
1688+
auto it = RelocatableClasses.find(D);
1689+
if (it != RelocatableClasses.end())
1690+
return it->getSecond();
1691+
return std::nullopt;
1692+
}
1693+
1694+
void ASTContext::setRelocationInfoForCXXRecord(
1695+
const CXXRecordDecl *RD, CXXRecordDeclRelocationInfo Info) {
1696+
assert(RD);
1697+
CXXRecordDecl *D = RD->getDefinition();
1698+
assert(RelocatableClasses.find(D) == RelocatableClasses.end());
1699+
RelocatableClasses.insert({D, Info});
1700+
}
1701+
16841702
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
16851703
assert(!Import->getNextLocalImport() &&
16861704
"Import declaration already in the chain");

clang/lib/AST/DeclCXX.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,13 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
103103
HasConstexprDefaultConstructor(false),
104104
DefaultedDestructorIsConstexpr(true),
105105
HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true),
106-
UserProvidedDefaultConstructor(false), UserProvidedMoveAssignment(false),
107-
UserProvidedCopyAssignment(false), ExplicitlyDeletedMoveAssignment(false),
108-
DeclaredSpecialMembers(0),
106+
UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
109107
ImplicitCopyConstructorCanHaveConstParamForVBase(true),
110108
ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
111109
ImplicitCopyAssignmentHasConstParam(true),
112110
HasDeclaredCopyConstructorWithConstParam(false),
113111
HasDeclaredCopyAssignmentWithConstParam(false),
114-
IsAnyDestructorNoReturn(false), IsHLSLIntangible(false),
115-
IsTriviallyRelocatable(false), IsReplaceable(false), IsLambda(false),
112+
IsAnyDestructorNoReturn(false), IsHLSLIntangible(false), IsLambda(false),
116113
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
117114
HasODRHash(false), Definition(D) {}
118115

@@ -1532,10 +1529,6 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15321529
if (DD->isNoReturn())
15331530
data().IsAnyDestructorNoReturn = true;
15341531
}
1535-
if (SMKind == SMF_CopyAssignment)
1536-
data().UserProvidedCopyAssignment = MD->isUserProvided();
1537-
else if (SMKind == SMF_MoveAssignment)
1538-
data().UserProvidedMoveAssignment = MD->isUserProvided();
15391532
if (!MD->isImplicit() && !MD->isUserProvided()) {
15401533
// This method is user-declared but not user-provided. We can't work
15411534
// out whether it's trivial yet (not until we get to the end of the
@@ -1557,9 +1550,6 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15571550
if (!MD->isUserProvided())
15581551
data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
15591552
}
1560-
1561-
if (MD->isDeleted() && SMKind == SMF_MoveAssignment)
1562-
data().ExplicitlyDeletedMoveAssignment = true;
15631553
}
15641554

15651555
void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
@@ -1587,11 +1577,8 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
15871577
data().HasIrrelevantDestructor = false;
15881578
} else if (D->isCopyAssignmentOperator())
15891579
SMKind |= SMF_CopyAssignment;
1590-
else if (D->isMoveAssignmentOperator()) {
1580+
else if (D->isMoveAssignmentOperator())
15911581
SMKind |= SMF_MoveAssignment;
1592-
if (!D->isIneligibleOrNotSelected() && D->isDeleted())
1593-
data().ExplicitlyDeletedMoveAssignment = true;
1594-
}
15951582

15961583
// Update which trivial / non-trivial special members we have.
15971584
// addedMember will have skipped this step for this member.

clang/lib/AST/Type.cpp

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,59 +2839,6 @@ bool QualType::isTriviallyCopyConstructibleType(
28392839
/*IsCopyConstructible=*/true);
28402840
}
28412841

2842-
bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
2843-
QualType BaseElementType = Context.getBaseElementType(*this);
2844-
2845-
if (BaseElementType->isIncompleteType()) {
2846-
return false;
2847-
} else if (!BaseElementType->isObjectType()) {
2848-
return false;
2849-
} else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
2850-
return RD->canPassInRegisters();
2851-
} else if (BaseElementType.isCXXTriviallyRelocatableType(Context)) {
2852-
return true;
2853-
} else {
2854-
switch (isNonTrivialToPrimitiveDestructiveMove()) {
2855-
case PCK_Trivial:
2856-
return !isDestructedType();
2857-
case PCK_ARCStrong:
2858-
return true;
2859-
default:
2860-
return false;
2861-
}
2862-
}
2863-
}
2864-
2865-
bool QualType::isCXXTriviallyRelocatableType(const ASTContext &Context) const {
2866-
QualType BaseElementType = Context.getBaseElementType(*this);
2867-
2868-
if (hasNonTrivialObjCLifetime())
2869-
return false;
2870-
2871-
if (BaseElementType->isIncompleteType())
2872-
return false;
2873-
2874-
if (BaseElementType->isScalarType() || BaseElementType->isVectorType())
2875-
return true;
2876-
2877-
if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
2878-
return RD->isTriviallyRelocatable();
2879-
return false;
2880-
}
2881-
2882-
bool QualType::isReplaceableType(const ASTContext &Context) const {
2883-
if (isConstQualified() || isVolatileQualified())
2884-
return false;
2885-
QualType BaseElementType = Context.getBaseElementType(getUnqualifiedType());
2886-
if (BaseElementType->isIncompleteType())
2887-
return false;
2888-
if (BaseElementType->isScalarType())
2889-
return true;
2890-
if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
2891-
return RD->isReplaceable();
2892-
return false;
2893-
}
2894-
28952842
bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
28962843
return !Context.getLangOpts().ObjCAutoRefCount &&
28972844
Context.getLangOpts().ObjCWeak &&

clang/lib/Sema/SemaChecking.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,8 +1895,7 @@ static ExprResult BuiltinTriviallyRelocate(Sema &S, CallExpr *TheCall) {
18951895
diag::err_incomplete_type))
18961896
return ExprError();
18971897

1898-
if (T.isConstQualified() ||
1899-
!T.isCXXTriviallyRelocatableType(S.getASTContext()) ||
1898+
if (T.isConstQualified() || !S.IsCXXTriviallyRelocatableType(T) ||
19001899
T->isIncompleteArrayType()) {
19011900
S.Diag(TheCall->getArg(0)->getExprLoc(),
19021901
diag::err_builtin_trivially_relocate_invalid_arg_type)

0 commit comments

Comments
 (0)