Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-22 Thread Clement Courbet via cfe-commits
courbet added a comment.

I can submit, thanks.


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-22 Thread Haojian Wu via cfe-commits
hokein accepted this revision.
hokein added a comment.

Looks good now. Do you need I submit for you?


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-22 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 65028.
courbet marked an inline comment as done.

https://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Right now this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded.
+This can be misleading especially for member function slicing, for example:
+
+.. code:: c++
+
+	struct B { int a; virtual int f(); };
+	struct D : B { int b; int f() override; };
+	void use(B b) {  // Missing reference, intended ?
+	  b.f();  // Calls B::f.
+	}
+	D d;
+	use(d);  // Slice.
+
+See the relevant CppCoreGuidelines sections for details:
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice

Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-21 Thread Piotr Padlewski via cfe-commits
Prazek added a comment.

Is it in upstream yet?



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.h:19
@@ +18,3 @@
+
+/// Flags slicing of member variables or vtable. See:
+///   -

courbet wrote:
> Prazek wrote:
> > some short description what does this check do?
> There is already a more detialed explanation provided in 
> extra/clang-tidy/checks/cppcoreguidelines-slicing.html, and I feel that the 
> links explain it better than anything short we could put in the comments 
> there. Or should I copy-paste what's in 
> extra/clang-tidy/checks/cppcoreguidelines-slicing.html ?
Well, it would be good to at least say what is slicing :)


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-20 Thread Clement Courbet via cfe-commits
courbet marked an inline comment as done.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.h:19
@@ +18,3 @@
+
+/// Flags slicing of member variables or vtable. See:
+///   -

Prazek wrote:
> some short description what does this check do?
There is already a more detialed explanation provided in 
extra/clang-tidy/checks/cppcoreguidelines-slicing.html, and I feel that the 
links explain it better than anything short we could put in the comments there. 
Or should I copy-paste what's in 
extra/clang-tidy/checks/cppcoreguidelines-slicing.html ?


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-20 Thread Piotr Padlewski via cfe-commits
Prazek added a subscriber: Prazek.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:30
@@ +29,3 @@
+  //   or
+  //   - B does not define any additional members (either variables or
+  //   overrides) wrt A.

What is A and what is B? I guess you are missing very important fact, that A is 
a base class of B


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.h:19
@@ +18,3 @@
+
+/// Flags slicing of member variables or vtable. See:
+///   -

some short description what does this check do?


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-20 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 64642.
courbet added a comment.

rebase


https://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Right now this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded.
+This can be misleading especially for member function slicing, for example:
+
+.. code:: c++
+
+	struct B { int a; virtual int f(); };
+	struct D : B { int b; int f() override; };
+	void use(B b) {  // Missing reference, intended ?
+	  b.f();  // Calls B::f.
+	}
+	D d;
+	use(d);  // Slice.
+
+See the relevant CppCoreGuidelines sections for details:
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice

Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-20 Thread Clement Courbet via cfe-commits
courbet added a comment.

Thanks for the review.



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:86
@@ +85,3 @@
+   "slicing object from type %0 to %1 discards override %2")
+  <<  <<  << Method;
+}

alexfh wrote:
> The "slicing ... discards x bytes of state" message is not going to be 
> repeated for the same location, so it's fine on its own.
> 
> Re: the "discards override" messages, they quite infrequent, IIUC, so the 
> risk of spamming people with diagnostics is rather low. In case it's still 
> problematic, we can change the repeated parts to notes.
Thanks for the insight.


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-20 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 64641.
courbet marked an inline comment as done.
courbet added a comment.

cosmetics


https://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Right now this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded.
+This can be misleading especially for member function slicing, for example:
+
+.. code:: c++
+
+	struct B { int a; virtual int f(); };
+	struct D : B { int b; int f() override; };
+	void use(B b) {  // Missing reference, intended ?
+	  b.f();  // Calls B::f.
+	}
+	D d;
+	use(d);  // Slice.
+
+See the relevant CppCoreGuidelines sections for details:

Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-19 Thread Alexander Kornienko via cfe-commits
alexfh accepted this revision.
alexfh added a comment.
This revision is now accepted and ready to land.

LG with a nit.



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:86
@@ +85,3 @@
+   "slicing object from type %0 to %1 discards override %2")
+  <<  <<  << Method;
+}

The "slicing ... discards x bytes of state" message is not going to be repeated 
for the same location, so it's fine on its own.

Re: the "discards override" messages, they quite infrequent, IIUC, so the risk 
of spamming people with diagnostics is rather low. In case it's still 
problematic, we can change the repeated parts to notes.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:91
@@ +90,3 @@
+  for (const auto  : DerivedDecl.bases()) {
+const auto *BaseRecordType = Base.getType()->getAs();
+if (!BaseRecordType)

Let's make the code more consistent:

```
if (const auto *BaseRecordType = Base.getType()->getAs()) {
  if (const auto *BaseRecord =
cast_or_null(BaseRecordType->getDecl()->getDefinition()))
  DiagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl);
}
```


https://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-18 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 64302.
courbet marked 3 inline comments as done.
courbet added a comment.

Cosmetics.


https://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Right now this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded.
+This can be misleading especially for member function slicing, for example:
+
+.. code:: c++
+
+	struct B { int a; virtual int f(); };
+	struct D : B { int b; int f() override; };
+	void use(B b) {  // Missing reference, intended ?
+	  b.f();  // Calls B::f.
+	}
+	D d;
+	use(d);  // Slice.
+
+See the relevant CppCoreGuidelines sections for details:

Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-12 Thread Haojian Wu via cfe-commits
hokein added inline comments.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:48
@@ +47,3 @@
+
+  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
+  const auto SlicesObjectInAssignment =

courbet wrote:
> hokein wrote:
> > Looks like you are missing some cases here, like assigning a Subclass 
> > object from a function call to a Baseclass object, passing a Subclass 
> > object to a function whose parameter is a BaseClass.
> > 
> > But I think it's fine to implement in a separate patch, but you'd better to 
> > add a TODO here.
> > 
> > ```
> > SubClass f1();
> > BaseClass a = f1();
> > 
> > void f1(BaseClass a);
> > SubClass sc;
> > f1(sc);
> > ```
> Actually these will still create a CXXConstructExpr in the AST, e.g for case 
> (2):
> 
> ```
> CallExpr 0x3d6e560  
> 'void'
> |-ImplicitCastExpr 0x3d6e548  'void (*)(class A)' 
> 
> | `-DeclRefExpr 0x3d6e4f8  'void (class A)' lvalue Function 0x3d66550 
> 'g' 'void (class A)'
> `-CXXConstructExpr 0x3d6e5c8  'class A' 'void (const class A &) 
> throw()'
>   `-ImplicitCastExpr 0x3d6e5b0  'const class A' lvalue 
> `-ImplicitCastExpr 0x3d6e590  'class A' lvalue 
>   `-DeclRefExpr 0x3d6e4d0  'class B' lvalue Var 0x3d6e300 'b' 
> 'class B'
> ```
> 
> I alreagy have a test to case (2) and I've added one for case (1).
> 
Oh, I see it now. Sorry for missing them and thanks for explanation.  It'd be 
more clear to if you can update comments at `SlicesObjectInCtor`.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:85
@@ +84,3 @@
+   "slicing object from type %0 to %1 discards override %2")
+  <<  <<  << Method;
+}

Maybe alexfh@ has idea about this. Output multiple warning messages in a same 
location is not the pattern of clang-tidy message. I think we should combine 
three message into exact one, something like `"slicing object from type 'B' to 
'A' discards override 'f', 'g', 4*sizeof(char) bytes of state"`.




Comment at: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst:24
@@ +23,2 @@
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references
+

There is an extra blank line at the bottom.


Comment at: test/clang-tidy/cppcoreguidelines-slicing.cpp:95
@@ +94,3 @@
+  // Derived type overrides methods, but these methods are not in the base 
type,
+  // so cannot be called accidentally. Righ tnow this triggers, but we might
+  // want to allow it.

s/tnow/now


http://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-11 Thread Clement Courbet via cfe-commits
courbet added a comment.

I've ran this check on llvm. There are 0 instances of virtual function slicing 
(which is not surprising since these usually result in actual bugs) and 71 
instances of member varaible slicing:

- 'FullSourceLoc' to 'SourceLocation': 57
- 'APSInt' to 'APInt': 5
- 'DeducedTemplateArgument' to 'TemplateArgument': 3
- 'SemaDiagnosticBuilder' to 'DiagnosticBuilder': 2
- 'RegHalf' to 'RegisterRef': 2
- 'PathDiagnosticRange' to 'SourceRange': 2

Most are harmless (but still true positives). The 'SemaDiagnosticBuilder' and 
'APSInt' are actually interesting:

llvm/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp:3555
``DiagnosticBuilder DiagB = …`` should be: ``SemaDiagnosticBuilder DiagB = …``
DiagB is then passed by reference to a function, so there really is no reason 
to slice it.

AST/ExprConstant.cpp:3150
``explicit APSInt(APInt I, bool isUnsigned = true)``
Here it’s easy to write: ``APSInt MyInt(MyOtherInt);`` and think it’s a copy, 
but it’s not (it just changed the signedness). ``APSInt 
MyInt(MyOtherInt.toAPInt());`` would make it clear what’s happening.


http://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-11 Thread Clement Courbet via cfe-commits
courbet added a comment.

Thanks for the comments.



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:48
@@ +47,3 @@
+
+  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
+  const auto SlicesObjectInAssignment =

hokein wrote:
> Looks like you are missing some cases here, like assigning a Subclass object 
> from a function call to a Baseclass object, passing a Subclass object to a 
> function whose parameter is a BaseClass.
> 
> But I think it's fine to implement in a separate patch, but you'd better to 
> add a TODO here.
> 
> ```
> SubClass f1();
> BaseClass a = f1();
> 
> void f1(BaseClass a);
> SubClass sc;
> f1(sc);
> ```
Actually these will still create a CXXConstructExpr in the AST, e.g for case 
(2):

```
CallExpr 0x3d6e560  'void'
|-ImplicitCastExpr 0x3d6e548  'void (*)(class A)' 

| `-DeclRefExpr 0x3d6e4f8  'void (class A)' lvalue Function 0x3d66550 
'g' 'void (class A)'
`-CXXConstructExpr 0x3d6e5c8  'class A' 'void (const class A &) throw()'
  `-ImplicitCastExpr 0x3d6e5b0  'const class A' lvalue 
`-ImplicitCastExpr 0x3d6e590  'class A' lvalue 
  `-DeclRefExpr 0x3d6e4d0  'class B' lvalue Var 0x3d6e300 'b' 'class 
B'
```

I alreagy have a test to case (2) and I've added one for case (1).



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:84
@@ +83,3 @@
+  diag(Call.getExprLoc(),
+   "slicing object from type %0 to %1 discards override %2")
+  <<  <<  << Method;

hokein wrote:
> There are two diagnostic messages in the code. For subclasses with override 
> base class methods and extra member, this will print two messages, which is a 
> bit of redundant.
I think we still want to point out to the user which overrides are going to be 
discarded:

class A { virtual void f();  virtual void g(); }
class B : public A { void f() override;  void g() override; int a; }

The messages will be:
"slicing object from type 'B' to 'A' discards override 'f' "
"slicing object from type 'B' to 'A' discards override 'g' "
"slicing object from type 'B' to 'A' discards 4*sizeof(char) bytes of state"





http://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-11 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 63477.
courbet marked 4 inline comments as done.
courbet added a comment.

- Add a test case following comments.
- Add more comments in tests.
- Add examples in doc.
- Simplify code a bit.


http://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+DerivedWithMemberVariables ReturnsDerived();
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  a = ReturnsDerived();
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards 4*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // Derived type overrides methods, but these methods are not in the base type,
+  // so cannot be called accidentally. Righ tnow this triggers, but we might
+  // want to allow it.
+  DerivedThatOverridesH h;
+  a = h;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedThatOverridesH' to 'Base' discards override 'h'
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. Slicing happens when copying a
+derived object into a base object: the members of the derived object (both
+member variables and virtual member functions) will be discarded.
+This can be misleading especially for member function slicing, for example:
+
+.. code:: c++
+
+	struct B { int a; virtual int f(); };
+	struct D : B { int b; int f() override; };
+	void use(B b) {  // Missing reference, intended ?
+	  b.f();  // Calls B::f.
+	}
+	D d;
+	use(d);  // Slice.
+
+See the relevant 

Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-11 Thread Haojian Wu via cfe-commits
hokein added inline comments.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:48
@@ +47,3 @@
+
+  // Assignement slicing: "a = b;" and "a = std::move(b);" variants.
+  const auto SlicesObjectInAssignment =

Looks like you are missing some cases here, like assigning a Subclass object 
from a function call to a Baseclass object, passing a Subclass object to a 
function whose parameter is a BaseClass.

But I think it's fine to implement in a separate patch, but you'd better to add 
a TODO here.

```
SubClass f1();
BaseClass a = f1();

void f1(BaseClass a);
SubClass sc;
f1(sc);
```


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:84
@@ +83,3 @@
+  diag(Call.getExprLoc(),
+   "slicing object from type %0 to %1 discards override %2")
+  <<  <<  << Method;

There are two diagnostic messages in the code. For subclasses with override 
base class methods and extra member, this will print two messages, which is a 
bit of redundant.


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:94
@@ +93,3 @@
+CXXRecordDecl *BaseRecord =
+
cast_or_null(BaseRecordType->getDecl()->getDefinition());
+if (!BaseRecord)

The code can be simplified like:

```
if (const auto *BR = 
cast_or_null(BaseRecordType->getDecl()->getDefinition())) {
  DiagnoseSlicedOverriddenMethods(Call, *BR, BaseDecl); 
}
```


Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:112
@@ +111,3 @@
+  // We're looking through all the methods in the derived class and see if they
+  // override some method in the base class.
+  // It's not enough to just test whether the class is polymorphic because we

s/method/methods


http://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-07 Thread Alexander Kornienko via cfe-commits
alexfh added a comment.

Thanks for the new awesome check!

Please run the check on LLVM and include your analysis of the results in the 
patch description. Another couple of comments below.



Comment at: clang-tidy/cppcoreguidelines/SlicingCheck.cpp:93
@@ +92,3 @@
+  continue;
+CXXRecordDecl *BaseRecord =
+
cast_or_null(BaseRecordType->getDecl()->getDefinition());

Please use `auto *`


Comment at: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst:7
@@ +6,3 @@
+Flags slicing of member variables or vtable. See the relevant CppCoreGuidelines
+sections for details:
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice

Links to the C++ Core Guidelines are good, but a few words of explanation and 
an example here wouldn't hurt either.


http://reviews.llvm.org/D21992



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21992: [clang-tidy] new cppcoreguidelines-slicing

2016-07-06 Thread Clement Courbet via cfe-commits
courbet updated this revision to Diff 62845.
courbet added a comment.

Update release notes.


http://reviews.llvm.org/D21992

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.cpp
  clang-tidy/cppcoreguidelines/SlicingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
  test/clang-tidy/cppcoreguidelines-slicing.cpp

Index: test/clang-tidy/cppcoreguidelines-slicing.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-slicing.cpp
@@ -0,0 +1,93 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-slicing %t
+
+class Base {
+  int i;
+  void f() {}
+  virtual void g() {}
+};
+
+class DerivedWithMemberVariables : public Base {
+  void f();
+  int j;
+};
+
+class TwiceDerivedWithNoMemberVariables : public DerivedWithMemberVariables {
+  void f();
+};
+
+class DerivedWithOverride : public Base {
+  void f();
+  void g() override {}
+};
+
+class TwiceDerivedWithNoOverride : public DerivedWithOverride {
+  void f();
+};
+
+void TakesBaseByValue(Base base);
+
+void positivesWithMemberVariables() {
+  DerivedWithMemberVariables b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state [cppcoreguidelines-slicing]
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+
+  TwiceDerivedWithNoMemberVariables c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'TwiceDerivedWithNoMemberVariables' to 'Base' discards {{[0-9]*}}*sizeof(char) bytes of state
+}
+
+void positivesWithOverride() {
+  DerivedWithOverride b;
+  Base a{b};
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  a = b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+  TakesBaseByValue(b);
+  // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+
+  TwiceDerivedWithNoOverride c;
+  a = c;
+  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: slicing object from type 'DerivedWithOverride' to 'Base' discards override 'g'
+}
+
+void TakesBaseByReference(Base );
+
+class DerivedThatAddsVirtualH : public Base {
+  virtual void h();
+};
+
+class DerivedThatOverridesH : public DerivedThatAddsVirtualH {
+  void h() override;
+};
+
+void negatives() {
+  // OK, simple copying from the same type.
+  Base a;
+  TakesBaseByValue(a);
+  DerivedWithMemberVariables b;
+  DerivedWithMemberVariables c{b};
+  b = c;
+
+  // OK, derived type does not have extra state.
+  TwiceDerivedWithNoMemberVariables d;
+  DerivedWithMemberVariables e{d};
+  e = d;
+
+  // OK, derived does not override any method.
+  TwiceDerivedWithNoOverride f;
+  DerivedWithOverride g{f};
+  g = f;
+
+  // OK, no copying.
+  TakesBaseByReference(d);
+  TakesBaseByReference(f);
+
+  // OK, derived type overrides methods, but these methods are not in the base
+  // type, so cannot be called accidentally.
+  DerivedThatOverridesH h;
+  a = h;
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/cppcoreguidelines-slicing.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - cppcoreguidelines-slicing
+
+cppcoreguidelines-slicing
+=
+
+Flags slicing of member variables or vtable. See the relevant CppCoreGuidelines
+sections for details:
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es63-dont-slice
+https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c145-access-polymorphic-objects-through-pointers-and-references
+
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -101,6 +101,11 @@
   Flags user-defined constructor definitions that do not initialize all builtin
   and pointer fields which leaves their memory in an undefined state.
 
+- New `cppcoreguidelines-slicing
+  `_ check
+
+  Flags slicing of member variables or vtable.
+
 - New `google-default-arguments
   `_ check
 
Index: clang-tidy/cppcoreguidelines/SlicingCheck.h
===
---