Skip to content

Commit 5b5f261

Browse files
committed
[CIR] Add move ctor and move/copy assignment to CXXSpecialMemberAttr
1 parent 96efab1 commit 5b5f261

File tree

6 files changed

+85
-10
lines changed

6 files changed

+85
-10
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ def CIR_CtorKind : CIR_I32EnumAttr<"CtorKind", "CXX Constructor Kind", [
12791279
I32EnumAttrCase<"Custom", 0, "custom">,
12801280
I32EnumAttrCase<"Default", 1, "default">,
12811281
I32EnumAttrCase<"Copy", 2, "copy">,
1282+
I32EnumAttrCase<"Move", 3, "move">,
12821283
]> {
12831284
let genSpecializedAttr = 0;
12841285
}
@@ -1290,6 +1291,7 @@ def CIR_CXXCtorAttr : CIR_Attr<"CXXCtor", "cxx_ctor"> {
12901291
The `custom` kind is used if the constructor is a custom constructor.
12911292
The `default` kind is used if the constructor is a default constructor.
12921293
The `copy` kind is used if the constructor is a copy constructor.
1294+
The `move` kind is used if the constructor is a move constructor.
12931295
}];
12941296
let parameters = (ins "mlir::Type":$type,
12951297
EnumParameter<CIR_CtorKind>:$ctorKind);
@@ -1324,9 +1326,39 @@ def CIR_CXXDtorAttr : CIR_Attr<"CXXDtor", "cxx_dtor"> {
13241326
];
13251327
}
13261328

1329+
def CIR_AssignKind : CIR_I32EnumAttr<"AssignKind", "CXX Assignment Operator Kind", [
1330+
I32EnumAttrCase<"Copy", 0, "copy">,
1331+
I32EnumAttrCase<"Move", 1, "move">,
1332+
]> {
1333+
let genSpecializedAttr = 0;
1334+
}
1335+
1336+
def CIR_CXXAssignAttr : CIR_Attr<"CXXAssign", "cxx_assign"> {
1337+
let summary = "Marks a function as a CXX assignment operator";
1338+
let description = [{
1339+
Functions with this attribute are CXX assignment operators.
1340+
The `copy` kind is used if the assignment operator is a copy assignment operator.
1341+
The `move` kind is used if the assignment operator is a move assignment operator.
1342+
}];
1343+
let parameters = (ins "mlir::Type":$type,
1344+
EnumParameter<CIR_AssignKind>:$assignKind);
1345+
1346+
let assemblyFormat = [{
1347+
`<` $type `,` $assignKind `>`
1348+
}];
1349+
1350+
let builders = [
1351+
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
1352+
CArg<"AssignKind">:$assignKind), [{
1353+
return $_get(type.getContext(), type, assignKind);
1354+
}]>
1355+
];
1356+
}
1357+
13271358
def CIR_CXXSpecialMemberAttr : AnyAttrOf<[
13281359
CIR_CXXCtorAttr,
1329-
CIR_CXXDtorAttr
1360+
CIR_CXXDtorAttr,
1361+
CIR_CXXAssignAttr
13301362
]>;
13311363

13321364
def CIR_BitfieldInfoAttr : CIR_Attr<"BitfieldInfo", "bitfield_info"> {

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,8 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
774774
ctorKind = cir::CtorKind::Default;
775775
if (ctor->isCopyConstructor())
776776
ctorKind = cir::CtorKind::Copy;
777+
if (ctor->isMoveConstructor())
778+
ctorKind = cir::CtorKind::Move;
777779

778780
auto cxxCtor = cir::CXXCtorAttr::get(
779781
convertType(getContext().getRecordType(ctor->getParent())), ctorKind);
@@ -792,6 +794,19 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
792794
} else if (fd->isDefaulted() && isa<CXXMethodDecl>(fd) &&
793795
(cast<CXXMethodDecl>(fd)->isCopyAssignmentOperator() ||
794796
cast<CXXMethodDecl>(fd)->isMoveAssignmentOperator())) {
797+
// Attach the special member attribute to the assignment operator.
798+
auto method = cast<CXXMethodDecl>(fd);
799+
cir::AssignKind assignKind;
800+
if (method->isCopyAssignmentOperator())
801+
assignKind = cir::AssignKind::Copy;
802+
if (method->isMoveAssignmentOperator())
803+
assignKind = cir::AssignKind::Move;
804+
805+
auto cxxAssign = cir::CXXAssignAttr::get(
806+
convertType(getContext().getRecordType(method->getParent())),
807+
assignKind);
808+
fn.setCxxSpecialMemberAttr(cxxAssign);
809+
795810
// Implicit copy-assignment gets the same special treatment as implicit
796811
// copy-constructors.
797812
emitImplicitAssignmentOperatorBody(args);

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2760,12 +2760,29 @@ cir::FuncOp CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
27602760
ctorKind = cir::CtorKind::Default;
27612761
if (ctor->isCopyConstructor())
27622762
ctorKind = cir::CtorKind::Copy;
2763+
if (ctor->isMoveConstructor())
2764+
ctorKind = cir::CtorKind::Move;
27632765

27642766
auto cxxCtor = cir::CXXCtorAttr::get(
27652767
convertType(getASTContext().getRecordType(ctor->getParent())),
27662768
ctorKind);
27672769
f.setCxxSpecialMemberAttr(cxxCtor);
27682770
}
2771+
2772+
auto method = dyn_cast<CXXMethodDecl>(fd);
2773+
if (method && (method->isCopyAssignmentOperator() ||
2774+
method->isMoveAssignmentOperator())) {
2775+
cir::AssignKind assignKind;
2776+
if (method->isCopyAssignmentOperator())
2777+
assignKind = cir::AssignKind::Copy;
2778+
if (method->isMoveAssignmentOperator())
2779+
assignKind = cir::AssignKind::Move;
2780+
2781+
auto cxxAssign = cir::CXXAssignAttr::get(
2782+
convertType(getASTContext().getRecordType(method->getParent())),
2783+
assignKind);
2784+
f.setCxxSpecialMemberAttr(cxxAssign);
2785+
}
27692786
}
27702787

27712788
if (!curCGF)

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2595,12 +2595,15 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
25952595
if (parser.parseOptionalKeyword("special_member").succeeded()) {
25962596
cir::CXXCtorAttr ctorAttr;
25972597
cir::CXXDtorAttr dtorAttr;
2598+
cir::CXXAssignAttr assignAttr;
25982599
if (parser.parseLess().failed())
25992600
return failure();
26002601
if (parser.parseOptionalAttribute(ctorAttr).has_value())
26012602
state.addAttribute(cxxSpecialMemberAttr, ctorAttr);
26022603
if (parser.parseOptionalAttribute(dtorAttr).has_value())
26032604
state.addAttribute(cxxSpecialMemberAttr, dtorAttr);
2605+
if (parser.parseOptionalAttribute(assignAttr).has_value())
2606+
state.addAttribute(cxxSpecialMemberAttr, assignAttr);
26042607
if (parser.parseGreater().failed())
26052608
return failure();
26062609
}
@@ -2786,7 +2789,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
27862789
}
27872790

27882791
if (auto specialMemberAttr = getCxxSpecialMember()) {
2789-
assert((mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr>(*specialMemberAttr)));
2792+
assert((mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr>(
2793+
*specialMemberAttr)));
27902794
p << " special_member<";
27912795
p.printAttribute(*specialMemberAttr);
27922796
p << '>';

clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,16 +1793,21 @@ void LifetimeCheckPass::checkCall(CallOp callOp) {
17931793
// From this point on only owner and pointer class methods handling,
17941794
// starting from special methods.
17951795
if (auto fnName = callOp.getCallee()) {
1796-
auto calleeFuncOp = getCalleeFromSymbol(theModule, *fnName);
1797-
if (calleeFuncOp && calleeFuncOp.getCxxSpecialMember())
1798-
if (auto cxxCtor =
1799-
dyn_cast<cir::CXXCtorAttr>(*calleeFuncOp.getCxxSpecialMember()))
1796+
if (calleeFuncOp && calleeFuncOp.getCxxSpecialMember()) {
1797+
auto cxxSpecialMember = *calleeFuncOp.getCxxSpecialMember();
1798+
if (auto cxxCtor = dyn_cast<cir::CXXCtorAttr>(cxxSpecialMember))
18001799
return checkCtor(callOp, cxxCtor);
1800+
1801+
if (auto cxxAssign = dyn_cast<cir::CXXAssignAttr>(cxxSpecialMember)) {
1802+
switch (cxxAssign.getAssignKind()) {
1803+
case cir::AssignKind::Move:
1804+
return checkMoveAssignment(callOp, methodDecl);
1805+
case cir::AssignKind::Copy:
1806+
return checkCopyAssignment(callOp, methodDecl);
1807+
}
1808+
}
1809+
}
18011810
}
1802-
if (methodDecl.isMoveAssignmentOperator())
1803-
return checkMoveAssignment(callOp, methodDecl);
1804-
if (methodDecl.isCopyAssignmentOperator())
1805-
return checkCopyAssignment(callOp, methodDecl);
18061811
if (methodDecl.isOverloadedOperator())
18071812
return checkOperators(callOp, methodDecl);
18081813

clang/test/CIR/IR/cxx-special-member.cir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
!rec_S = !cir.record<struct "S" {!s32i}>
66
module {
77
cir.func private @_ZN1SC1ERKS_(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, copy>>
8+
cir.func private @_ZN1SC1EOS_(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, move>>
89
cir.func private @_ZN1SC2Ei(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>)
910
cir.func private @_ZN1SC2Ev(!cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, default>>
1011
cir.func private @_ZN1SD2Ev(!cir.ptr<!rec_S>) special_member<#cir.cxx_dtor<!rec_S>>
@@ -14,6 +15,7 @@ module {
1415
// CHECK: !rec_S = !cir.record<struct "S" {!s32i}>
1516
// CHECK: module {
1617
// CHECK: cir.func private @_ZN1SC1ERKS_(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, copy>>
18+
// CHECK: cir.func private @_ZN1SC1EOS_(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, move>>
1719
// CHECK: cir.func private @_ZN1SC2Ei(!cir.ptr<!rec_S>, !cir.ptr<!rec_S>)
1820
// CHECK: cir.func private @_ZN1SC2Ev(!cir.ptr<!rec_S>) special_member<#cir.cxx_ctor<!rec_S, default>>
1921
// CHECK: cir.func private @_ZN1SD2Ev(!cir.ptr<!rec_S>) special_member<#cir.cxx_dtor<!rec_S>>

0 commit comments

Comments
 (0)