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);
101 const auto *BaseDecl = Result.Nodes.getNodeAs<CXXRecordDecl>(
"BaseDecl");
102 const auto *DerivedDecl =
103 Result.Nodes.getNodeAs<CXXRecordDecl>(
"DerivedDecl");
104 const auto *Call = Result.Nodes.getNodeAs<Expr>(
"Call");
105 assert(BaseDecl !=
nullptr);
106 assert(DerivedDecl !=
nullptr);
107 assert(Call !=
nullptr);
118 diagnoseSlicedOverriddenMethods(*Call, *DerivedDecl, *BaseDecl);
121 const auto &BaseLayout =
122 BaseDecl->getASTContext().getASTRecordLayout(BaseDecl);
123 const auto &DerivedLayout =
124 DerivedDecl->getASTContext().getASTRecordLayout(DerivedDecl);
125 const CharUnits StateSize =
126 DerivedLayout.getDataSize() - BaseLayout.getDataSize();
127 if (StateSize.isPositive()) {
128 diag(Call->getExprLoc(),
"slicing object from type %0 to %1 discards "
130 << DerivedDecl << BaseDecl << static_cast<int>(StateSize.getQuantity());