<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jul 22, 2016 at 2:42 PM, Clement Courbet via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Author: courbet<br>
Date: Fri Jul 22 07:42:19 2016<br>
New Revision: 276408<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=276408&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=276408&view=rev</a><br>
Log:<br>
[clang-tidy] new cppcoreguidelines-slicing<br>
<br>
Flags slicing of member variables or vtable. See:<br>
<br>
<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice</a><br>
<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references</a><br>
<br>
Differential revision:<br>
<a href="http://reviews.llvm.org/D21974" rel="noreferrer" target="_blank">http://reviews.llvm.org/D21974</a></blockquote><div><br></div><div>I guess, you meant <a href="https://reviews.llvm.org/D21992">https://reviews.llvm.org/D21992</a></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><br>
<br>
Added:<br>
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp<br>
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h<br>
clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst<br>
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp<br>
Modified:<br>
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt<br>
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp<br>
clang-tools-extra/trunk/docs/ReleaseNotes.rst<br>
<br>
Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=276408&r1=276407&r2=276408&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=276408&r1=276407&r2=276408&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt (original)<br>
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt Fri Jul 22 07:42:19 2016<br>
@@ -13,6 +13,7 @@ add_clang_library(clangTidyCppCoreGuidel<br>
ProTypeStaticCastDowncastCheck.cpp<br>
ProTypeUnionAccessCheck.cpp<br>
ProTypeVarargCheck.cpp<br>
+ SlicingCheck.cpp<br>
<br>
LINK_LIBS<br>
clangAST<br>
<br>
Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=276408&r1=276407&r2=276408&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=276408&r1=276407&r2=276408&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp (original)<br>
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp Fri Jul 22 07:42:19 2016<br>
@@ -22,6 +22,7 @@<br>
#include "ProTypeStaticCastDowncastCheck.h"<br>
#include "ProTypeUnionAccessCheck.h"<br>
#include "ProTypeVarargCheck.h"<br>
+#include "SlicingCheck.h"<br>
<br>
namespace clang {<br>
namespace tidy {<br>
@@ -53,6 +54,8 @@ public:<br>
"cppcoreguidelines-pro-type-union-access");<br>
CheckFactories.registerCheck<ProTypeVarargCheck>(<br>
"cppcoreguidelines-pro-type-vararg");<br>
+ CheckFactories.registerCheck<SlicingCheck>(<br>
+ "cppcoreguidelines-slicing");<br>
CheckFactories.registerCheck<misc::UnconventionalAssignOperatorCheck>(<br>
"cppcoreguidelines-c-copy-assignment-signature");<br>
}<br>
<br>
Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp?rev=276408&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp?rev=276408&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp (added)<br>
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.cpp Fri Jul 22 07:42:19 2016<br>
@@ -0,0 +1,135 @@<br>
+//===--- SlicingCheck.cpp - clang-tidy-------------------------------------===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "SlicingCheck.h"<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/RecordLayout.h"<br>
+#include "clang/ASTMatchers/ASTMatchFinder.h"<br>
+#include "clang/ASTMatchers/ASTMatchers.h"<br>
+<br>
+using namespace clang::ast_matchers;<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace cppcoreguidelines {<br>
+<br>
+void SlicingCheck::registerMatchers(MatchFinder *Finder) {<br>
+ // When we see:<br>
+ // class B : public A { ... };<br>
+ // A a;<br>
+ // B b;<br>
+ // a = b;<br>
+ // The assignment is OK if:<br>
+ // - the assignment operator is defined as taking a B as second parameter,<br>
+ // or<br>
+ // - B does not define any additional members (either variables or<br>
+ // overrides) wrt A.<br>
+ //<br>
+ // The same holds for copy ctor calls. This also captures stuff like:<br>
+ // void f(A a);<br>
+ // f(b);<br>
+<br>
+ // Helpers.<br>
+ const auto OfBaseClass = ofClass(cxxRecordDecl().bind("BaseDecl"));<br>
+ const auto IsDerivedFromBaseDecl =<br>
+ cxxRecordDecl(isDerivedFrom(equalsBoundNode("BaseDecl")))<br>
+ .bind("DerivedDecl");<br>
+ const auto HasTypeDerivedFromBaseDecl =<br>
+ anyOf(hasType(IsDerivedFromBaseDecl),<br>
+ hasType(references(IsDerivedFromBaseDecl)));<br>
+ const auto IsWithinDerivedCtor =<br>
+ hasParent(cxxConstructorDecl(ofClass(equalsBoundNode("DerivedDecl"))));<br>
+<br>
+ // Assignement slicing: "a = b;" and "a = std::move(b);" variants.<br>
+ const auto SlicesObjectInAssignment =<br>
+ callExpr(callee(cxxMethodDecl(anyOf(isCopyAssignmentOperator(),<br>
+ isMoveAssignmentOperator()),<br>
+ OfBaseClass)),<br>
+ hasArgument(1, HasTypeDerivedFromBaseDecl));<br>
+<br>
+ // Construction slicing: "A a{b};" and "f(b);" variants. Note that in case of<br>
+ // slicing the letter will create a temporary and therefore call a ctor.<br>
+ const auto SlicesObjectInCtor = cxxConstructExpr(<br>
+ hasDeclaration(cxxConstructorDecl(<br>
+ anyOf(isCopyConstructor(), isMoveConstructor()), OfBaseClass)),<br>
+ hasArgument(0, HasTypeDerivedFromBaseDecl),<br>
+ // We need to disable matching on the call to the base copy/move<br>
+ // constructor in DerivedDecl's constructors.<br>
+ unless(IsWithinDerivedCtor));<br>
+<br>
+ Finder->addMatcher(<br>
+ expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"),<br>
+ this);<br>
+}<br>
+<br>
+/// Warns on methods overridden in DerivedDecl with respect to BaseDecl.<br>
+/// FIXME: this warns on all overrides outside of the sliced path in case of<br>
+/// multiple inheritance.<br>
+void SlicingCheck::DiagnoseSlicedOverriddenMethods(<br>
+ const Expr &Call, const CXXRecordDecl &DerivedDecl,<br>
+ const CXXRecordDecl &BaseDecl) {<br>
+ if (DerivedDecl.getCanonicalDecl() == BaseDecl.getCanonicalDecl())<br>
+ return;<br>
+ for (const auto &Method : DerivedDecl.methods()) {<br>
+ // Virtual destructors are OK. We're ignoring constructors since they are<br>
+ // tagged as overrides.<br>
+ if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))<br>
+ continue;<br>
+ if (Method->size_overridden_methods() > 0) {<br>
+ diag(Call.getExprLoc(),<br>
+ "slicing object from type %0 to %1 discards override %2")<br>
+ << &DerivedDecl << &BaseDecl << Method;<br>
+ }<br>
+ }<br>
+ // Recursively process bases.<br>
+ for (const auto &Base : DerivedDecl.bases()) {<br>
+ if (const auto *BaseRecordType = Base.getType()->getAs<RecordType>()) {<br>
+ if (const auto *BaseRecord = cast_or_null<CXXRecordDecl>(<br>
+ BaseRecordType->getDecl()->getDefinition()))<br>
+ DiagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+void SlicingCheck::check(const MatchFinder::MatchResult &Result) {<br>
+ const auto *BaseDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("BaseDecl");<br>
+ const auto *DerivedDecl =<br>
+ Result.Nodes.getNodeAs<CXXRecordDecl>("DerivedDecl");<br>
+ const auto *Call = Result.Nodes.getNodeAs<Expr>("Call");<br>
+ assert(BaseDecl != nullptr);<br>
+ assert(DerivedDecl != nullptr);<br>
+ assert(Call != nullptr);<br>
+<br>
+ // Warn when slicing the vtable.<br>
+ // We're looking through all the methods in the derived class and see if they<br>
+ // override some methods in the base class.<br>
+ // It's not enough to just test whether the class is polymorphic because we<br>
+ // would be fine slicing B to A if no method in B (or its bases) overrides<br>
+ // anything in A:<br>
+ // class A { virtual void f(); };<br>
+ // class B : public A {};<br>
+ // because in that case calling A::f is the same as calling B::f.<br>
+ DiagnoseSlicedOverriddenMethods(*Call, *DerivedDecl, *BaseDecl);<br>
+<br>
+ // Warn when slicing member variables.<br>
+ const auto &BaseLayout =<br>
+ BaseDecl->getASTContext().getASTRecordLayout(BaseDecl);<br>
+ const auto &DerivedLayout =<br>
+ DerivedDecl->getASTContext().getASTRecordLayout(DerivedDecl);<br>
+ const auto StateSize = DerivedLayout.getDataSize() - BaseLayout.getDataSize();<br>
+ if (StateSize.isPositive()) {<br>
+ diag(Call->getExprLoc(), "slicing object from type %0 to %1 discards "<br>
+ "%2*sizeof(char) bytes of state")<br>
+ << DerivedDecl << BaseDecl << static_cast<int>(StateSize.getQuantity());<br>
+ }<br>
+}<br>
+<br>
+} // namespace cppcoreguidelines<br>
+} // namespace tidy<br>
+} // namespace clang<br>
<br>
Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h?rev=276408&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h?rev=276408&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h (added)<br>
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/SlicingCheck.h Fri Jul 22 07:42:19 2016<br>
@@ -0,0 +1,45 @@<br>
+//===--- SlicingCheck.h - clang-tidy-----------------------------*- C++ -*-===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SLICING_H<br>
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SLICING_H<br>
+<br>
+#include "../ClangTidy.h"<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace cppcoreguidelines {<br>
+<br>
+/// Flags slicing (incomplete copying of an object's state) of member variables<br>
+/// or vtable. See:<br>
+/// - <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice</a><br>
+/// for the former, and<br>
+/// - <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references</a><br>
+/// for the latter<br>
+///<br>
+/// For the user-facing documentation see:<br>
+/// <a href="http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-slicing.html" rel="noreferrer" target="_blank">http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-slicing.html</a><br>
+class SlicingCheck : public ClangTidyCheck {<br>
+public:<br>
+ SlicingCheck(StringRef Name, ClangTidyContext *Context)<br>
+ : ClangTidyCheck(Name, Context) {}<br>
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;<br>
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;<br>
+<br>
+private:<br>
+ void DiagnoseSlicedOverriddenMethods(const Expr &call,<br>
+ const CXXRecordDecl &DerivedDecl,<br>
+ const CXXRecordDecl &BaseDecl);<br>
+};<br>
+<br>
+} // namespace cppcoreguidelines<br>
+} // namespace tidy<br>
+} // namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SLICING_H<br>
<br>
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=276408&r1=276407&r2=276408&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=276408&r1=276407&r2=276408&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)<br>
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Fri Jul 22 07:42:19 2016<br>
@@ -59,7 +59,10 @@ The improvements are...<br>
Improvements to clang-tidy<br>
--------------------------<br>
<br>
-The improvements are...<br>
+- New `cppcoreguidelines-slicing<br>
+ <<a href="http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-slicing.html" rel="noreferrer" target="_blank">http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-slicing.html</a>>`_ check<br>
+<br>
+ Flags slicing of member variables or vtable.<br>
<br>
Improvements to include-fixer<br>
-----------------------------<br>
<br>
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst?rev=276408&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst?rev=276408&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst (added)<br>
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-slicing.rst Fri Jul 22 07:42:19 2016<br>
@@ -0,0 +1,23 @@<br>
+.. title:: clang-tidy - cppcoreguidelines-slicing<br>
+<br>
+cppcoreguidelines-slicing<br>
+=========================<br>
+<br>
+Flags slicing of member variables or vtable. Slicing happens when copying a<br>
+derived object into a base object: the members of the derived object (both<br>
+member variables and virtual member functions) will be discarded.<br>
+This can be misleading especially for member function slicing, for example:<br>
+<br>
+.. code:: c++<br>
+<br>
+ struct B { int a; virtual int f(); };<br>
+ struct D : B { int b; int f() override; };<br>
+ void use(B b) { // Missing reference, intended ?<br>
+ b.f(); // Calls B::f.<br>
+ }<br>
+ D d;<br>
+ use(d); // Slice.<br>
+<br>
+See the relevant CppCoreGuidelines sections for details:<br>
+<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice</a><br>
+<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references" rel="noreferrer" target="_blank">https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references</a><br>
<br>
Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp?rev=276408&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp?rev=276408&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp (added)<br>
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-slicing.cpp Fri Jul 22 07:42:19 2016<br>
@@ -0,0 +1,100 @@<br>
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t<br>
+<br>
+class Base {<br>
+ int i;<br>
+ void f() {}<br>
+ virtual void g() {}<br>
+};<br>
+<br>
+class DerivedWithMemberVariables : public Base {<br>
+ void f();<br>
+ int j;<br>
+};<br>
+<br>
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {<br>
+ void f();<br>
+};<br>
+<br>
+class DerivedWithOverride : public Base {<br>
+ void f();<br>
+ void g() override {}<br>
+};<br>
+<br>
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {<br>
+ void f();<br>
+};<br>
+<br>
+void TakesBaseByValue(Base base);<br>
+<br>
+DerivedWithMemberVariables ReturnsDerived();<br>
+<br>
+void positivesWithMemberVariables() {<br>
+ DerivedWithMemberVariables b;<br>
+ Base a{b};<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]<br>
+ a = b;<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state<br>
+ TakesBaseByValue(b);<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state<br>
+<br>
+ TwiceDerivedWithNoMemberVariables c;<br>
+ a = c;<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state<br>
+<br>
+ a = ReturnsDerived();<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state<br>
+}<br>
+<br>
+void positivesWithOverride() {<br>
+ DerivedWithOverride b;<br>
+ Base a{b};<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'<br>
+ a = b;<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'<br>
+ TakesBaseByValue(b);<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'<br>
+<br>
+ TwiceDerivedWithNoOverride c;<br>
+ a = c;<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'<br>
+}<br>
+<br>
+void TakesBaseByReference(Base &base);<br>
+<br>
+class DerivedThatAddsVirtualH : public Base {<br>
+ virtual void h();<br>
+};<br>
+<br>
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {<br>
+ void h() override;<br>
+};<br>
+<br>
+void negatives() {<br>
+ // OK, simple copying from the same type.<br>
+ Base a;<br>
+ TakesBaseByValue(a);<br>
+ DerivedWithMemberVariables b;<br>
+ DerivedWithMemberVariables c{b};<br>
+ b = c;<br>
+<br>
+ // OK, derived type does not have extra state.<br>
+ TwiceDerivedWithNoMemberVariables d;<br>
+ DerivedWithMemberVariables e{d};<br>
+ e = d;<br>
+<br>
+ // OK, derived does not override any method.<br>
+ TwiceDerivedWithNoOverride f;<br>
+ DerivedWithOverride g{f};<br>
+ g = f;<br>
+<br>
+ // OK, no copying.<br>
+ TakesBaseByReference(d);<br>
+ TakesBaseByReference(f);<br>
+<br>
+ // Derived type overrides methods, but these methods are not in the base type,<br>
+ // so cannot be called accidentally. Right now this triggers, but we might<br>
+ // want to allow it.<br>
+ DerivedThatOverridesH h;<br>
+ a = h;<br>
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>