<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>