Skip to content

Commit 6a1a537

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 b623ed7 commit 6a1a537

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
@@ -617,6 +617,20 @@ class ASTContext : public RefCountedBase<ASTContext> {
617617
using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>;
618618
ParameterIndexTable ParamIndices;
619619

620+
public:
621+
struct CXXRecordDeclRelocationInfo {
622+
unsigned IsRelocatable;
623+
unsigned IsReplaceable;
624+
};
625+
std::optional<CXXRecordDeclRelocationInfo>
626+
getRelocationInfoForCXXRecord(const CXXRecordDecl *) const;
627+
void setRelocationInfoForCXXRecord(const CXXRecordDecl *,
628+
CXXRecordDeclRelocationInfo);
629+
630+
private:
631+
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
632+
RelocatableClasses;
633+
620634
ImportDecl *FirstLocalImport = nullptr;
621635
ImportDecl *LastLocalImport = nullptr;
622636

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
@@ -1133,13 +1133,6 @@ class QualType {
11331133
/// Return true if this is a trivially copyable type
11341134
bool isTriviallyCopyConstructibleType(const ASTContext &Context) const;
11351135

1136-
/// Return true if this is a trivially relocatable type.
1137-
bool isTriviallyRelocatableType(const ASTContext &Context) const;
1138-
1139-
bool isCXXTriviallyRelocatableType(const ASTContext &Context) const;
1140-
1141-
bool isReplaceableType(const ASTContext &Context) const;
1142-
11431136
/// Returns true if it is a class and it might be dynamic.
11441137
bool mayBeDynamicClass() const;
11451138

clang/include/clang/Sema/Sema.h

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

4328-
void CheckCXX2CRelocatableAndReplaceable(CXXRecordDecl *D);
4328+
ASTContext::CXXRecordDeclRelocationInfo
4329+
CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D);
43294330

43304331
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
43314332

@@ -8641,6 +8642,18 @@ class Sema final : public SemaBase {
86418642
ExprResult &LHS, ExprResult &RHS,
86428643
SourceLocation QuestionLoc);
86438644

8645+
//// Determines if a type is trivially relocatable
8646+
/// according to the C++26 rules.
8647+
// FIXME: This is in Sema because it requires
8648+
// overload resolution, can we move to ASTContext?
8649+
bool IsCXXTriviallyRelocatableType(QualType T);
8650+
8651+
//// Determines if a type is replaceable
8652+
/// according to the C++26 rules.
8653+
// FIXME: This is in Sema because it requires
8654+
// overload resolution, can we move to ASTContext?
8655+
bool IsCXXReplaceableType(QualType T);
8656+
86448657
/// Check the operands of ?: under C++ semantics.
86458658
///
86468659
/// 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
@@ -1688,6 +1688,24 @@ void ASTContext::getOverriddenMethods(
16881688
Overridden.append(OverDecls.begin(), OverDecls.end());
16891689
}
16901690

1691+
std::optional<ASTContext::CXXRecordDeclRelocationInfo>
1692+
ASTContext::getRelocationInfoForCXXRecord(const CXXRecordDecl *RD) const {
1693+
assert(RD);
1694+
CXXRecordDecl *D = RD->getDefinition();
1695+
auto it = RelocatableClasses.find(D);
1696+
if (it != RelocatableClasses.end())
1697+
return it->getSecond();
1698+
return std::nullopt;
1699+
}
1700+
1701+
void ASTContext::setRelocationInfoForCXXRecord(
1702+
const CXXRecordDecl *RD, CXXRecordDeclRelocationInfo Info) {
1703+
assert(RD);
1704+
CXXRecordDecl *D = RD->getDefinition();
1705+
assert(RelocatableClasses.find(D) == RelocatableClasses.end());
1706+
RelocatableClasses.insert({D, Info});
1707+
}
1708+
16911709
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
16921710
assert(!Import->getNextLocalImport() &&
16931711
"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

@@ -1559,10 +1556,6 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15591556
if (DD->isNoReturn())
15601557
data().IsAnyDestructorNoReturn = true;
15611558
}
1562-
if (SMKind == SMF_CopyAssignment)
1563-
data().UserProvidedCopyAssignment = MD->isUserProvided();
1564-
else if (SMKind == SMF_MoveAssignment)
1565-
data().UserProvidedMoveAssignment = MD->isUserProvided();
15661559
if (!MD->isImplicit() && !MD->isUserProvided()) {
15671560
// This method is user-declared but not user-provided. We can't work
15681561
// out whether it's trivial yet (not until we get to the end of the
@@ -1584,9 +1577,6 @@ void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD,
15841577
if (!MD->isUserProvided())
15851578
data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
15861579
}
1587-
1588-
if (MD->isDeleted() && SMKind == SMF_MoveAssignment)
1589-
data().ExplicitlyDeletedMoveAssignment = true;
15901580
}
15911581

15921582
void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
@@ -1614,11 +1604,8 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
16141604
data().HasIrrelevantDestructor = false;
16151605
} else if (D->isCopyAssignmentOperator())
16161606
SMKind |= SMF_CopyAssignment;
1617-
else if (D->isMoveAssignmentOperator()) {
1607+
else if (D->isMoveAssignmentOperator())
16181608
SMKind |= SMF_MoveAssignment;
1619-
if (!D->isIneligibleOrNotSelected() && D->isDeleted())
1620-
data().ExplicitlyDeletedMoveAssignment = true;
1621-
}
16221609

16231610
// Update which trivial / non-trivial special members we have.
16241611
// 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
@@ -2896,59 +2896,6 @@ bool QualType::isTriviallyCopyConstructibleType(
28962896
/*IsCopyConstructible=*/true);
28972897
}
28982898

2899-
bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
2900-
QualType BaseElementType = Context.getBaseElementType(*this);
2901-
2902-
if (BaseElementType->isIncompleteType()) {
2903-
return false;
2904-
} else if (!BaseElementType->isObjectType()) {
2905-
return false;
2906-
} else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
2907-
return RD->canPassInRegisters();
2908-
} else if (BaseElementType.isCXXTriviallyRelocatableType(Context)) {
2909-
return true;
2910-
} else {
2911-
switch (isNonTrivialToPrimitiveDestructiveMove()) {
2912-
case PCK_Trivial:
2913-
return !isDestructedType();
2914-
case PCK_ARCStrong:
2915-
return true;
2916-
default:
2917-
return false;
2918-
}
2919-
}
2920-
}
2921-
2922-
bool QualType::isCXXTriviallyRelocatableType(const ASTContext &Context) const {
2923-
QualType BaseElementType = Context.getBaseElementType(*this);
2924-
2925-
if (hasNonTrivialObjCLifetime())
2926-
return false;
2927-
2928-
if (BaseElementType->isIncompleteType())
2929-
return false;
2930-
2931-
if (BaseElementType->isScalarType() || BaseElementType->isVectorType())
2932-
return true;
2933-
2934-
if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
2935-
return RD->isTriviallyRelocatable();
2936-
return false;
2937-
}
2938-
2939-
bool QualType::isReplaceableType(const ASTContext &Context) const {
2940-
if (isConstQualified() || isVolatileQualified())
2941-
return false;
2942-
QualType BaseElementType = Context.getBaseElementType(getUnqualifiedType());
2943-
if (BaseElementType->isIncompleteType())
2944-
return false;
2945-
if (BaseElementType->isScalarType())
2946-
return true;
2947-
if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
2948-
return RD->isReplaceable();
2949-
return false;
2950-
}
2951-
29522899
bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
29532900
return !Context.getLangOpts().ObjCAutoRefCount &&
29542901
Context.getLangOpts().ObjCWeak &&

clang/lib/Sema/SemaChecking.cpp

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

1942-
if (T.isConstQualified() ||
1943-
!T.isCXXTriviallyRelocatableType(S.getASTContext()) ||
1942+
if (T.isConstQualified() || !S.IsCXXTriviallyRelocatableType(T) ||
19441943
T->isIncompleteArrayType()) {
19451944
S.Diag(TheCall->getArg(0)->getExprLoc(),
19461945
diag::err_builtin_trivially_relocate_invalid_arg_type)

0 commit comments

Comments
 (0)