36 const auto OfBaseClass = ofClass(cxxRecordDecl().bind(
"BaseDecl"));
37 const auto IsDerivedFromBaseDecl =
38 cxxRecordDecl(isDerivedFrom(equalsBoundNode(
"BaseDecl")))
40 const auto HasTypeDerivedFromBaseDecl =
41 anyOf(hasType(IsDerivedFromBaseDecl),
42 hasType(references(IsDerivedFromBaseDecl)));
43 const auto IsCallToBaseClass = hasParent(cxxConstructorDecl(
44 ofClass(isSameOrDerivedFrom(equalsBoundNode(
"DerivedDecl"))),
45 hasAnyConstructorInitializer(allOf(
46 isBaseInitializer(), withInitializer(equalsBoundNode(
"Call"))))));
49 const auto SlicesObjectInAssignment =
50 callExpr(expr().bind(
"Call"),
51 callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(),
52 isMoveAssignmentOperator()),
54 hasArgument(1, HasTypeDerivedFromBaseDecl));
58 const auto SlicesObjectInCtor = cxxConstructExpr(
60 hasDeclaration(cxxConstructorDecl(
61 anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)),
62 hasArgument(0, HasTypeDerivedFromBaseDecl),
65 unless(IsCallToBaseClass));
68 traverse(TK_AsIs, expr(SlicesObjectInAssignment).bind(
"Call")),
this);
69 Finder->addMatcher(traverse(TK_AsIs, SlicesObjectInCtor),
this);
99 const auto *BaseDecl = Result.Nodes.getNodeAs<CXXRecordDecl>(
"BaseDecl");
100 const auto *DerivedDecl =
101 Result.Nodes.getNodeAs<CXXRecordDecl>(
"DerivedDecl");
102 const auto *Call = Result.Nodes.getNodeAs<Expr>(
"Call");
103 assert(BaseDecl !=
nullptr);
104 assert(DerivedDecl !=
nullptr);
105 assert(Call !=
nullptr);
116 diagnoseSlicedOverriddenMethods(*Call, *DerivedDecl, *BaseDecl);
119 const auto &BaseLayout =
120 BaseDecl->getASTContext().getASTRecordLayout(BaseDecl);
121 const auto &DerivedLayout =
122 DerivedDecl->getASTContext().getASTRecordLayout(DerivedDecl);
123 const CharUnits StateSize =
124 DerivedLayout.getDataSize() - BaseLayout.getDataSize();
125 if (StateSize.isPositive()) {
126 diag(Call->getExprLoc(),
"slicing object from type %0 to %1 discards "
128 << DerivedDecl << BaseDecl << static_cast<int>(StateSize.getQuantity());