[PATCH] D47108: Add -fforce-emit-vtable

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.
Prazek added reviewers: rjmccall, rsmith, amharc, kuhar.
Herald added a subscriber: llvm-commits.

In many cases we can't devirtualize
because definition of vtable is not present. Most of the
time it is caused by inline virtual function not beeing
emitted. Forcing emitting of vtable adds a reference of these
inline virtual functions


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp
  clang/test/CodeGenCXX/vtable-linkage.cpp

Index: clang/test/CodeGenCXX/vtable-linkage.cpp
===
--- clang/test/CodeGenCXX/vtable-linkage.cpp
+++ clang/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,11 +1,13 @@
 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t
 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++03 -o %t.03
 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.11
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.vtables -fforce-emit-vtables -O3
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-passes -O3 -emit-llvm -o %t.opt
 // RUN: FileCheck %s < %t
 // RUN: FileCheck %s < %t.03
 // RUN: FileCheck %s < %t.11
 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.vtables
 
 namespace {
   struct A {
Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORC

[PATCH] D47108: Add -fforce-emit-vtable

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147672.
Prazek added a comment.

Add release note


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp
  clang/test/CodeGenCXX/vtable-linkage.cpp

Index: clang/test/CodeGenCXX/vtable-linkage.cpp
===
--- clang/test/CodeGenCXX/vtable-linkage.cpp
+++ clang/test/CodeGenCXX/vtable-linkage.cpp
@@ -7,6 +7,7 @@
 // RUN: FileCheck %s < %t.11
 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
 
+
 namespace {
   struct A {
 virtual void f() { }
Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test17

[PATCH] D47108: Add -fforce-emit-vtable

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147673.
Prazek added a comment.

remove empty line


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Fronte

[PATCH] D47108: Add -fforce-emit-vtable

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147675.
Prazek added a comment.

Fixed comment


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Frontend/C

[PATCH] D47108: Add -fforce-emit-vtable

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147679.
Prazek added a comment.

Fixed flag passing


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Front

[PATCH] D47103: Implement strip.invariant.group

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147683.
Prazek added a comment.

introduced mayBeDynamicClass and added more tests


Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/CaptureTracking.cpp
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/test/Analysis/ValueTracking/invariant.group.ll
  llvm/test/CodeGen/Generic/intrinsics.ll
  llvm/test/Other/invariant.group.ll
  llvm/test/Other/launder.invariant.group.ll
  llvm/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/GVN/invariant.group.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/test/Transforms/InstCombine/invariant.group.ll
  llvm/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/test/Transforms/NewGVN/invariant.group.ll
===
--- llvm/test/Transforms/NewGVN/invariant.group.ll
+++ llvm/test/Transforms/NewGVN/invariant.group.ll
@@ -52,6 +52,19 @@
 ret i8 %b
 }
 
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
 ; CHECK-LABEL: define i8 @unoptimizable1() {
 define i8 @unoptimizable1() {
 entry:
Index: llvm/test/Transforms/InstCombine/invariant.group.ll
===
--- llvm/test/Transforms/InstCombine/invariant.group.ll
+++ llvm/test/Transforms/InstCombine/invariant.group.ll
@@ -1,5 +1,6 @@
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
+
 ; CHECK-LABEL: define i8* @simplifyNullLaunder()
 define i8* @simplifyNullLaunder() {
 ; CHECK-NEXT: ret i8* null
@@ -29,6 +30,39 @@
   ret i8 addrspace(42)* %b2
 }
 
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*)
+
+
+; CHECK-LABEL: define i8* @simplifyNullStrip()
+define i8* @simplifyNullStrip() {
+; CHECK-NEXT: ret i8* null
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace()
+define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() {
+; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+; CHECK: ret i8 addrspace(42)* %b2
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+  ret i8 addrspace(42)* %b2
+}
+
+; CHECK-LABEL: define i8* @simplifyUndefStrip()
+define i8* @simplifyUndefStrip() {
+; CHECK-NEXT: ret i8* undef
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2()
+define i8 addrspace(42)* @simplifyUndefStrip2() {
+; CHECK-NEXT: ret i8 addrspace(42)* undef
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef)
+  ret i8 addrspace(42)* %b2
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*)
+
Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll
===
--- llvm/test/Transforms/GlobalOpt/invariant.group.ll
+++ llvm/test/Transforms/GlobalOpt/invariant.group.ll
@@ -27,46 +27,46 @@
 define void @_optimizable() {
 enter:
   %valptr = alloca i32
-  
+
   %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
   store i32 %val, i32* @tmp
   store i32 %val, i32* %valptr
-  
+
   %0 = bitcast i32* %valptr to i8*
   %barr = call i8* @llvm.launder.invariant.group(i8* %0)
   %1 = bitcast i8* %barr to i32*
-  
+
   %val2 = load i32, i32* %1
   store i32 %val2, i32* @tmp2
   ret void
 }
 
 ; We can't step through launder.invariant.group here, because that would change
 ; this load in @usage_of_globals()
-; val = load i32, i32* %ptrVal, !invariant.group !0 
-; into 
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into
 ; %val =

[PATCH] D47103: Implement strip.invariant.group

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147684.
Prazek added a comment.

Changed comments


Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/BasicAliasAnalysis.cpp
  llvm/lib/Analysis/CaptureTracking.cpp
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/test/Analysis/ValueTracking/invariant.group.ll
  llvm/test/CodeGen/Generic/intrinsics.ll
  llvm/test/Other/invariant.group.ll
  llvm/test/Other/launder.invariant.group.ll
  llvm/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/GVN/invariant.group.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/test/Transforms/InstCombine/invariant.group.ll
  llvm/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/test/Transforms/NewGVN/invariant.group.ll
===
--- llvm/test/Transforms/NewGVN/invariant.group.ll
+++ llvm/test/Transforms/NewGVN/invariant.group.ll
@@ -52,6 +52,19 @@
 ret i8 %b
 }
 
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
 ; CHECK-LABEL: define i8 @unoptimizable1() {
 define i8 @unoptimizable1() {
 entry:
Index: llvm/test/Transforms/InstCombine/invariant.group.ll
===
--- llvm/test/Transforms/InstCombine/invariant.group.ll
+++ llvm/test/Transforms/InstCombine/invariant.group.ll
@@ -1,5 +1,6 @@
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
+
 ; CHECK-LABEL: define i8* @simplifyNullLaunder()
 define i8* @simplifyNullLaunder() {
 ; CHECK-NEXT: ret i8* null
@@ -29,6 +30,39 @@
   ret i8 addrspace(42)* %b2
 }
 
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*)
+
+
+; CHECK-LABEL: define i8* @simplifyNullStrip()
+define i8* @simplifyNullStrip() {
+; CHECK-NEXT: ret i8* null
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace()
+define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() {
+; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+; CHECK: ret i8 addrspace(42)* %b2
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+  ret i8 addrspace(42)* %b2
+}
+
+; CHECK-LABEL: define i8* @simplifyUndefStrip()
+define i8* @simplifyUndefStrip() {
+; CHECK-NEXT: ret i8* undef
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2()
+define i8 addrspace(42)* @simplifyUndefStrip2() {
+; CHECK-NEXT: ret i8 addrspace(42)* undef
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef)
+  ret i8 addrspace(42)* %b2
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*)
+
Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll
===
--- llvm/test/Transforms/GlobalOpt/invariant.group.ll
+++ llvm/test/Transforms/GlobalOpt/invariant.group.ll
@@ -27,46 +27,46 @@
 define void @_optimizable() {
 enter:
   %valptr = alloca i32
-  
+
   %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
   store i32 %val, i32* @tmp
   store i32 %val, i32* %valptr
-  
+
   %0 = bitcast i32* %valptr to i8*
   %barr = call i8* @llvm.launder.invariant.group(i8* %0)
   %1 = bitcast i8* %barr to i32*
-  
+
   %val2 = load i32, i32* %1
   store i32 %val2, i32* @tmp2
   ret void
 }
 
 ; We can't step through launder.invariant.group here, because that would change
 ; this load in @usage_of_globals()
-; val = load i32, i32* %ptrVal, !invariant.group !0 
-; into 
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into

[PATCH] D47103: Implement strip.invariant.group

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147688.
Prazek added a comment.

After rebasing


Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/BasicAliasAnalysis.cpp
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/test/Analysis/ValueTracking/invariant.group.ll
  llvm/test/CodeGen/Generic/intrinsics.ll
  llvm/test/Other/invariant.group.ll
  llvm/test/Other/launder.invariant.group.ll
  llvm/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/GVN/invariant.group.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/test/Transforms/InstCombine/invariant.group.ll
  llvm/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/test/Transforms/NewGVN/invariant.group.ll
===
--- llvm/test/Transforms/NewGVN/invariant.group.ll
+++ llvm/test/Transforms/NewGVN/invariant.group.ll
@@ -52,6 +52,19 @@
 ret i8 %b
 }
 
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
 ; CHECK-LABEL: define i8 @unoptimizable1() {
 define i8 @unoptimizable1() {
 entry:
Index: llvm/test/Transforms/InstCombine/invariant.group.ll
===
--- llvm/test/Transforms/InstCombine/invariant.group.ll
+++ llvm/test/Transforms/InstCombine/invariant.group.ll
@@ -1,5 +1,6 @@
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
+
 ; CHECK-LABEL: define i8* @simplifyNullLaunder()
 define i8* @simplifyNullLaunder() {
 ; CHECK-NEXT: ret i8* null
@@ -29,6 +30,39 @@
   ret i8 addrspace(42)* %b2
 }
 
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*)
+
+
+; CHECK-LABEL: define i8* @simplifyNullStrip()
+define i8* @simplifyNullStrip() {
+; CHECK-NEXT: ret i8* null
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace()
+define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() {
+; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+; CHECK: ret i8 addrspace(42)* %b2
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+  ret i8 addrspace(42)* %b2
+}
+
+; CHECK-LABEL: define i8* @simplifyUndefStrip()
+define i8* @simplifyUndefStrip() {
+; CHECK-NEXT: ret i8* undef
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2()
+define i8 addrspace(42)* @simplifyUndefStrip2() {
+; CHECK-NEXT: ret i8 addrspace(42)* undef
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef)
+  ret i8 addrspace(42)* %b2
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*)
+
Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll
===
--- llvm/test/Transforms/GlobalOpt/invariant.group.ll
+++ llvm/test/Transforms/GlobalOpt/invariant.group.ll
@@ -27,46 +27,46 @@
 define void @_optimizable() {
 enter:
   %valptr = alloca i32
-  
+
   %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
   store i32 %val, i32* @tmp
   store i32 %val, i32* %valptr
-  
+
   %0 = bitcast i32* %valptr to i8*
   %barr = call i8* @llvm.launder.invariant.group(i8* %0)
   %1 = bitcast i8* %barr to i32*
-  
+
   %val2 = load i32, i32* %1
   store i32 %val2, i32* @tmp2
   ret void
 }
 
 ; We can't step through launder.invariant.group here, because that would change
 ; this load in @usage_of_globals()
-; val = load i32, i32* %ptrVal, !invariant.group !0 
-; into 
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into
 ; %val = load i32, i32* @tmp3, !invarian

[PATCH] D47103: Implement strip.invariant.group

2018-05-19 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 147691.
Prazek added a comment.

rebase


Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/BasicAliasAnalysis.cpp
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/test/Analysis/ValueTracking/invariant.group.ll
  llvm/test/CodeGen/Generic/intrinsics.ll
  llvm/test/Other/invariant.group.ll
  llvm/test/Other/launder.invariant.group.ll
  llvm/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/GVN/invariant.group.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/test/Transforms/InstCombine/invariant.group.ll
  llvm/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/test/Transforms/NewGVN/invariant.group.ll
===
--- llvm/test/Transforms/NewGVN/invariant.group.ll
+++ llvm/test/Transforms/NewGVN/invariant.group.ll
@@ -52,6 +52,19 @@
 ret i8 %b
 }
 
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
 ; CHECK-LABEL: define i8 @unoptimizable1() {
 define i8 @unoptimizable1() {
 entry:
Index: llvm/test/Transforms/InstCombine/invariant.group.ll
===
--- llvm/test/Transforms/InstCombine/invariant.group.ll
+++ llvm/test/Transforms/InstCombine/invariant.group.ll
@@ -1,5 +1,6 @@
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
+
 ; CHECK-LABEL: define i8* @simplifyNullLaunder()
 define i8* @simplifyNullLaunder() {
 ; CHECK-NEXT: ret i8* null
@@ -29,6 +30,39 @@
   ret i8 addrspace(42)* %b2
 }
 
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*)
+
+
+; CHECK-LABEL: define i8* @simplifyNullStrip()
+define i8* @simplifyNullStrip() {
+; CHECK-NEXT: ret i8* null
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace()
+define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() {
+; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+; CHECK: ret i8 addrspace(42)* %b2
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+  ret i8 addrspace(42)* %b2
+}
+
+; CHECK-LABEL: define i8* @simplifyUndefStrip()
+define i8* @simplifyUndefStrip() {
+; CHECK-NEXT: ret i8* undef
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2()
+define i8 addrspace(42)* @simplifyUndefStrip2() {
+; CHECK-NEXT: ret i8 addrspace(42)* undef
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef)
+  ret i8 addrspace(42)* %b2
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*)
+
Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll
===
--- llvm/test/Transforms/GlobalOpt/invariant.group.ll
+++ llvm/test/Transforms/GlobalOpt/invariant.group.ll
@@ -27,46 +27,46 @@
 define void @_optimizable() {
 enter:
   %valptr = alloca i32
-  
+
   %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
   store i32 %val, i32* @tmp
   store i32 %val, i32* %valptr
-  
+
   %0 = bitcast i32* %valptr to i8*
   %barr = call i8* @llvm.launder.invariant.group(i8* %0)
   %1 = bitcast i8* %barr to i32*
-  
+
   %val2 = load i32, i32* %1
   store i32 %val2, i32* @tmp2
   ret void
 }
 
 ; We can't step through launder.invariant.group here, because that would change
 ; this load in @usage_of_globals()
-; val = load i32, i32* %ptrVal, !invariant.group !0 
-; into 
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into
 ; %val = load i32, i32* @tmp3, !invariant.group 

[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-05-22 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

@rjmccall do you have any thoughts on the best way to solve it?


Repository:
  rL LLVM

https://reviews.llvm.org/D47108



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


[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-05-23 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

In https://reviews.llvm.org/D47108#1109014, @rjmccall wrote:

> I thought we already had places in Sema that marked inline virtual methods as 
> used, instantiated templates, etc. for devirtualization purposes when 
> optimization was enabled.  Did we rip that out?


I only recall the emitting available_externally vtables opportunistically, that 
is emitting it only if all the inline virtual functions are present (and they 
are not hidden).
(https://reviews.llvm.org/D33437)

> The problem we've had over and over with devirtualization is that we have to 
> emit a perfect v-table because LLVM lacks a lot of the key vocabulary for 
> talking about incomplete information.  For example, if something weird 
> happens and we don't have a definition for an inline virtual method, ideally 
> we'd just say "well, you can't devirtualize this slot", then try to fix that 
> as incremental progress; but instead we have to get everything just right or 
> else disable the whole optimization.  Note that vague-linkage v-tables mean 
> that we'd also need to be able to say things like "there is an object with a 
> definition that looks like this, but its symbol is not available and you 
> can't emit it yourself".

That is correcty, my intention was that this flag would cause all inline 
virtual functions to be emitted. Can you give a hint how to achieve this in the 
sane way?


Repository:
  rL LLVM

https://reviews.llvm.org/D47108



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-05-23 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.
Prazek added reviewers: rjmccall, rsmith, amharc, kuhar.
Herald added a subscriber: llvm-commits.

Emmiting new intrinsic that strips invariant.groups to make 
devirtulization sound, as described in RFC: Devirtualization v2.


Repository:
  rL LLVM

https://reviews.llvm.org/D47299

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp

Index: clang/test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- clang/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ clang/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -5,7 +5,8 @@
 // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
 
 typedef __typeof__(sizeof(0)) size_t;
-void *operator new(size_t, void*) throw();
+void *operator new(size_t, void *) throw();
+using uintptr_t = unsigned long long;
 
 struct NotTrivialDtor {
   ~NotTrivialDtor();
@@ -17,7 +18,7 @@
 };
 
 struct DynamicDerived : DynamicBase1 {
-  void foo();
+  void foo() override;
 };
 
 struct DynamicBase2 {
@@ -28,8 +29,8 @@
 };
 
 struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
-  virtual void foo();
-  virtual void bar();
+  void foo() override;
+  void bar() override;
 };
 
 struct StaticBase {
@@ -47,9 +48,8 @@
 struct DynamicFromVirtualStatic2 : virtual StaticBase {
 };
 
-struct DynamicFrom2Virtuals :
-DynamicFromVirtualStatic1,
-DynamicFromVirtualStatic2 {
+struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
+  DynamicFromVirtualStatic2 {
 };
 
 // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
@@ -89,7 +89,6 @@
 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 // CHECK-NEW-LABEL: define void @_Z9Pointers1v()
 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
@@ -134,7 +133,6 @@
 // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 struct DynamicDerived;
 
 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
@@ -164,14 +162,12 @@
 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
 
-
 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
 // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
 // CHECK-CTORS: %[[THIS12:.*]]  = bitcast i8* %[[THIS_ADD]] to i32 (...)***
 
-
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
 // CHECK-CTORS-LABEL: {{^}}}
 
@@ -182,9 +178,10 @@
 
 struct A {
   virtual void foo();
+  int m;
 };
 struct B : A {
-  virtual void foo();
+  void foo() override;
 };
 
 union U {
@@ -209,7 +206,7 @@
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
   g2(&u->b);
-  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* 
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
   changeToA(u);
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // call void @_Z2g2P1A(%struct.A* %a)
@@ -294,21 +291,206 @@
   take(u.v3);
 }
 
+// CHECK-NEW-LABEL: define void @_Z7comparev()
+void compare() {
+  A *a = new A;
+  a->foo();
+  // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
+  A *b = new (a) B;
+
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
+  if (a == b)
+b->foo();
+}
+
+// CHECK-NEW-LABEL: compare2
+bool compare2(A *a, A *a2) {
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]]
+  return a < a2;
+}
+// CHECK-NEW-LABEL: compareIntPointers
+bool compareIntPointers(int *a, int *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+
+struct HoldingOtherVirtuals {
+  B b;
+};
+
+// There is no need to add barriers for comparision of pointer to classes
+// that are not dynamic.
+// CHECK-NEW-LABEL: compare5
+bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+// CHECK-NEW-LABEL

[PATCH] D47103: Implement strip.invariant.group

2018-05-23 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExpr.cpp:3858
+}
+  }
+

rjmccall wrote:
> Please add a comment explaining why this is necessary.  (I'm actually not 
> sure why it is, because surely the invariant groups we generate don't contain 
> assumptions about memory from fields, right?)
Short answer: you can only make virtual calls on a dynamic pointer that carries 
invariant.group and you can't do anything other because it could leak the 
information about this pointer (which when used with comparison could break 
devirtualization). 


Repository:
  rL LLVM

https://reviews.llvm.org/D47103



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


[PATCH] D47103: Implement strip.invariant.group

2018-05-23 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148313.
Prazek marked 2 inline comments as done.
Prazek added a comment.

Slitted commit into defining and using intrinsic


Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/Intrinsics.td
  llvm/lib/Analysis/BasicAliasAnalysis.cpp
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/test/Analysis/ValueTracking/invariant.group.ll
  llvm/test/CodeGen/Generic/intrinsics.ll
  llvm/test/Other/invariant.group.ll
  llvm/test/Other/launder.invariant.group.ll
  llvm/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/GVN/invariant.group.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/test/Transforms/InstCombine/invariant.group.ll
  llvm/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/test/Transforms/NewGVN/invariant.group.ll
===
--- llvm/test/Transforms/NewGVN/invariant.group.ll
+++ llvm/test/Transforms/NewGVN/invariant.group.ll
@@ -52,6 +52,19 @@
 ret i8 %b
 }
 
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
 ; CHECK-LABEL: define i8 @unoptimizable1() {
 define i8 @unoptimizable1() {
 entry:
Index: llvm/test/Transforms/InstCombine/invariant.group.ll
===
--- llvm/test/Transforms/InstCombine/invariant.group.ll
+++ llvm/test/Transforms/InstCombine/invariant.group.ll
@@ -1,5 +1,6 @@
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
+
 ; CHECK-LABEL: define i8* @simplifyNullLaunder()
 define i8* @simplifyNullLaunder() {
 ; CHECK-NEXT: ret i8* null
@@ -29,6 +30,39 @@
   ret i8 addrspace(42)* %b2
 }
 
-
 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
 declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*)
+
+
+; CHECK-LABEL: define i8* @simplifyNullStrip()
+define i8* @simplifyNullStrip() {
+; CHECK-NEXT: ret i8* null
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace()
+define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() {
+; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+; CHECK: ret i8 addrspace(42)* %b2
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null)
+  ret i8 addrspace(42)* %b2
+}
+
+; CHECK-LABEL: define i8* @simplifyUndefStrip()
+define i8* @simplifyUndefStrip() {
+; CHECK-NEXT: ret i8* undef
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef)
+  ret i8* %b2
+}
+
+; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2()
+define i8 addrspace(42)* @simplifyUndefStrip2() {
+; CHECK-NEXT: ret i8 addrspace(42)* undef
+  %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef)
+  ret i8 addrspace(42)* %b2
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*)
+
Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll
===
--- llvm/test/Transforms/GlobalOpt/invariant.group.ll
+++ llvm/test/Transforms/GlobalOpt/invariant.group.ll
@@ -27,46 +27,46 @@
 define void @_optimizable() {
 enter:
   %valptr = alloca i32
-  
+
   %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
   store i32 %val, i32* @tmp
   store i32 %val, i32* %valptr
-  
+
   %0 = bitcast i32* %valptr to i8*
   %barr = call i8* @llvm.launder.invariant.group(i8* %0)
   %1 = bitcast i8* %barr to i32*
-  
+
   %val2 = load i32, i32* %1
   store i32 %val2, i32* @tmp2
   ret void
 }
 
 ; We can't step through launder.invariant.group here, because that would change
 ; this load in @usage_of_globals()
-; val = load i32, i32* %ptrVal, !invariant.group !0 
-; into 
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into
 ; %val = load i32, i32* @tmp3, !invariant.group !0
-; and then we could assume that %val and %val2 to be the same, which

[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-05-25 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1626-1627
+
+  // Casting to pointer that does not carry dynamic information (provided 
by
+  // invariant.group) requires stripping it.
+  Src = Builder.CreateStripInvariantGroup(Src);

rsmith wrote:
> Are there any cases where we need a barrier when the destination type is a 
> dynamic type here?
No, I don't think so. I will also add test for that.


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148745.
Prazek added a comment.
Herald added a subscriber: hiraditya.

  Added launder when going from possiblyNotDynamic to possiblyDynamic
  emitting strip for pointer -> int only if poitner is possiblyDynamic


Repository:
  rL LLVM

https://reviews.llvm.org/D47299

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1205,6 +1205,7 @@
   if (StrippedInvariantGroupsArg == StrippedArg)
 return nullptr;
 
+  return nullptr;
   if (II.getIntrinsicID() == Intrinsic::launder_invariant_group)
 return cast(IC.Builder.CreateLaunderInvariantGroup(StrippedInvariantGroupsArg));
   if (II.getIntrinsicID() == Intrinsic::strip_invariant_group)
Index: clang/test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- clang/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ clang/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -5,7 +5,8 @@
 // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
 
 typedef __typeof__(sizeof(0)) size_t;
-void *operator new(size_t, void*) throw();
+void *operator new(size_t, void *) throw();
+using uintptr_t = unsigned long long;
 
 struct NotTrivialDtor {
   ~NotTrivialDtor();
@@ -17,7 +18,7 @@
 };
 
 struct DynamicDerived : DynamicBase1 {
-  void foo();
+  void foo() override;
 };
 
 struct DynamicBase2 {
@@ -28,8 +29,8 @@
 };
 
 struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
-  virtual void foo();
-  virtual void bar();
+  void foo() override;
+  void bar() override;
 };
 
 struct StaticBase {
@@ -47,9 +48,8 @@
 struct DynamicFromVirtualStatic2 : virtual StaticBase {
 };
 
-struct DynamicFrom2Virtuals :
-DynamicFromVirtualStatic1,
-DynamicFromVirtualStatic2 {
+struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
+  DynamicFromVirtualStatic2 {
 };
 
 // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
@@ -89,7 +89,6 @@
 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 // CHECK-NEW-LABEL: define void @_Z9Pointers1v()
 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
@@ -134,7 +133,6 @@
 // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 struct DynamicDerived;
 
 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
@@ -164,14 +162,12 @@
 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
 
-
 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
 // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
 // CHECK-CTORS: %[[THIS12:.*]]  = bitcast i8* %[[THIS_ADD]] to i32 (...)***
 
-
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
 // CHECK-CTORS-LABEL: {{^}}}
 
@@ -182,9 +178,10 @@
 
 struct A {
   virtual void foo();
+  int m;
 };
 struct B : A {
-  virtual void foo();
+  void foo() override;
 };
 
 union U {
@@ -209,7 +206,7 @@
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
   g2(&u->b);
-  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* 
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
   changeToA(u);
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // call void @_Z2g2P1A(%struct.A* %a)
@@ -294,21 +291,283 @@
   take(u.v3);
 }
 
+// CHECK-NEW-LABEL: define void @_Z7comparev()
+void compare() {
+  A *a = new A;
+  a->foo();
+  // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
+  A *b = new (a) B;
+
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
+  if (a == b)
+b->foo();
+}
+
+// CHECK-NEW-LABEL: compare2
+bool compare2(A *a, A *a2) {
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] =

[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148746.
Prazek marked 3 inline comments as done.
Prazek added a comment.

one more test


Repository:
  rL LLVM

https://reviews.llvm.org/D47299

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp

Index: clang/test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- clang/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ clang/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -5,7 +5,8 @@
 // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
 
 typedef __typeof__(sizeof(0)) size_t;
-void *operator new(size_t, void*) throw();
+void *operator new(size_t, void *) throw();
+using uintptr_t = unsigned long long;
 
 struct NotTrivialDtor {
   ~NotTrivialDtor();
@@ -17,7 +18,7 @@
 };
 
 struct DynamicDerived : DynamicBase1 {
-  void foo();
+  void foo() override;
 };
 
 struct DynamicBase2 {
@@ -28,8 +29,8 @@
 };
 
 struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
-  virtual void foo();
-  virtual void bar();
+  void foo() override;
+  void bar() override;
 };
 
 struct StaticBase {
@@ -47,9 +48,8 @@
 struct DynamicFromVirtualStatic2 : virtual StaticBase {
 };
 
-struct DynamicFrom2Virtuals :
-DynamicFromVirtualStatic1,
-DynamicFromVirtualStatic2 {
+struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
+  DynamicFromVirtualStatic2 {
 };
 
 // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
@@ -89,7 +89,6 @@
 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 // CHECK-NEW-LABEL: define void @_Z9Pointers1v()
 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
@@ -134,7 +133,6 @@
 // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 struct DynamicDerived;
 
 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
@@ -164,14 +162,12 @@
 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
 
-
 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
 // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
 // CHECK-CTORS: %[[THIS12:.*]]  = bitcast i8* %[[THIS_ADD]] to i32 (...)***
 
-
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
 // CHECK-CTORS-LABEL: {{^}}}
 
@@ -182,9 +178,10 @@
 
 struct A {
   virtual void foo();
+  int m;
 };
 struct B : A {
-  virtual void foo();
+  void foo() override;
 };
 
 union U {
@@ -209,7 +206,7 @@
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
   g2(&u->b);
-  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* 
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
   changeToA(u);
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // call void @_Z2g2P1A(%struct.A* %a)
@@ -294,21 +291,287 @@
   take(u.v3);
 }
 
+// CHECK-NEW-LABEL: define void @_Z7comparev()
+void compare() {
+  A *a = new A;
+  a->foo();
+  // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
+  A *b = new (a) B;
+
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
+  if (a == b)
+b->foo();
+}
+
+// CHECK-NEW-LABEL: compare2
+bool compare2(A *a, A *a2) {
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]]
+  return a < a2;
+}
+// CHECK-NEW-LABEL: compareIntPointers
+bool compareIntPointers(int *a, int *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+
+struct HoldingOtherVirtuals {
+  B b;
+};
+
+// There is no need to add barriers for comparision of pointer to classes
+// that are not dynamic.
+// CHECK-NEW-LABEL: compare5
+bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+// CHECK-NEW-LABEL: compareNull
+bool compareNull(A *a) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+
+  if (a != nullptr)
+retu

[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148762.
Prazek added a comment.

Fixed missing vtable commponents


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
@@ -418,3 +438,27 @@

[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148764.
Prazek added a comment.

small update


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
@@ -418,3 +438,27 @@
 }
 
 } // namespac

[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-05-28 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 148839.
Prazek marked an inline comment as done.
Prazek added a comment.

fixed test


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
  

[PATCH] D33470: [clang-tidy] Add misc-default-numerics

2017-05-24 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: docs/clang-tidy/checks/misc-default-numerics.rst:11
+Consider scenario:
+1. Have `typedef long long BigInt` in source code
+2. Use `std::numeric_limits::min()`

Eugene.Zelenko wrote:
> May be code-block will be better?
Right, I was looking for something like an inline code block, but I guess I 
will just change it to code block with comments


https://reviews.llvm.org/D33470



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


[PATCH] D33470: [clang-tidy] Add misc-default-numerics

2017-05-24 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100070.
Prazek added a comment.

- fixed docs


https://reviews.llvm.org/D33470

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/DefaultNumericsCheck.cpp
  clang-tidy/misc/DefaultNumericsCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-default-numerics.rst
  test/clang-tidy/misc-default-numerics.cpp

Index: test/clang-tidy/misc-default-numerics.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-default-numerics.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s misc-default-numerics %t
+
+namespace std {
+
+template 
+struct numeric_limit {
+  static T min() { return T(); }
+  static T max() { return T(); }
+};
+
+template <>
+struct numeric_limit {
+  static int min() { return -1; }
+  static int max() { return 1; }
+};
+
+} // namespace std
+
+class MyType {};
+template 
+class MyTemplate {};
+
+void test() {
+  auto x = std::numeric_limit::min();
+
+  auto y = std::numeric_limit::min();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: called std::numeric_limit method on not specialized type
+
+  auto z = std::numeric_limit>::max();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: called std::numeric_limit method on not specialized type
+}
+
+template 
+void fun() {
+  auto x = std::numeric_limit::min();
+}
+
+void testTemplate() {
+  fun();
+  // FIXME: This should generate warning with backtrace.
+  fun;
+}
Index: docs/clang-tidy/checks/misc-default-numerics.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-default-numerics.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - misc-default-numerics
+
+misc-default-numerics
+=
+
+This check flags usages of ``std::numeric_limits::{min,max}()`` for
+unspecialized types. It is dangerous because returns T(), which might is rarely
+minimum or maximum for this type.
+
+Consider scenario:
+.. code-block:: c++
+
+  // 1. Have a:
+  typedef long long BigInt
+
+  // 2. Use
+  std::numeric_limits::min()
+
+
+  // 3. Replace the BigInt typedef with class implementing BigIntegers
+  class BigInt { ;;; };
+
+  // 4. Your code compiles silently and you a few years later you find an
+  // of by 9223372036854775808 error.
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -75,6 +75,7 @@
misc-assert-side-effect
misc-bool-pointer-implicit-conversion
misc-dangling-handle
+   misc-default-numerics
misc-definitions-in-headers
misc-fold-init-type
misc-forward-declaration-namespace
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -71,7 +71,11 @@
   `_ check
 
   Allow custom memory management functions to be considered as well.
-  
+
+- New `misc-default-numerics
+  `_ check
+  Finds uses of ``std::numeric_limit`` for unspecialized types
+
 - New `misc-forwarding-reference-overload
   `_ check
 
Index: clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "AssertSideEffectCheck.h"
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DanglingHandleCheck.h"
+#include "DefaultNumericsCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
@@ -66,6 +67,7 @@
 CheckFactories.registerCheck("misc-argument-comment");
 CheckFactories.registerCheck(
 "misc-assert-side-effect");
+CheckFactories.registerCheck("misc-default-numerics");
 CheckFactories.registerCheck(
 "misc-forwarding-reference-overload");
 CheckFactories.registerCheck("misc-misplaced-const");
Index: clang-tidy/misc/DefaultNumericsCheck.h
===
--- /dev/null
+++ clang-tidy/misc/DefaultNumericsCheck.h
@@ -0,0 +1,37 @@
+//===--- DefaultNumericsCheck.h - clang-tidy-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+names

[PATCH] D33470: [clang-tidy] Add misc-default-numerics

2017-05-25 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100216.
Prazek marked 8 inline comments as done.
Prazek added a comment.

- Thanks for the review Aaron, that is much better.


https://reviews.llvm.org/D33470

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/DefaultNumericsCheck.cpp
  clang-tidy/misc/DefaultNumericsCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-default-numerics.rst
  test/clang-tidy/misc-default-numerics.cpp

Index: test/clang-tidy/misc-default-numerics.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-default-numerics.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s misc-default-numerics %t
+
+namespace std {
+
+template 
+struct numeric_limit {
+  static T min() { return T(); }
+  static T max() { return T(); }
+};
+
+template <>
+struct numeric_limit {
+  static int min() { return -1; }
+  static int max() { return 1; }
+};
+
+} // namespace std
+
+class MyType {};
+template 
+class MyTemplate {};
+
+void test() {
+  auto x = std::numeric_limit::min();
+
+  auto y = std::numeric_limit::min();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'std::numeric_limits::min' called with type 'MyType'; no such specialization exists, so the default value for that type is returned
+
+  auto z = std::numeric_limit>::max();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'std::numeric_limits::max' called with type 'MyTemplate';
+}
+
+template 
+void fun() {
+  auto x = std::numeric_limit::min();
+}
+
+void testTemplate() {
+  fun();
+  // FIXME: This should generate warning with backtrace.
+  fun;
+}
Index: docs/clang-tidy/checks/misc-default-numerics.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-default-numerics.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - misc-default-numerics
+
+misc-default-numerics
+=
+
+This check flags usages of ``std::numeric_limits::{min,max}()`` for
+unspecialized types. It is dangerous because the calls return ``T()``
+in this case, which is unlikely to represent the minimum or maximum value for
+the type.
+
+Consider scenario:
+.. code-block:: c++
+
+  // 1. Have a:
+  typedef long long BigInt
+
+  // 2. Use
+  std::numeric_limits::min()
+
+  // 3. Replace the BigInt typedef with class implementing BigIntegers
+  class BigInt { ;;; };
+
+  // 4. Your code continues to compile, but the call to min() returns BigInt{}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -75,6 +75,7 @@
misc-assert-side-effect
misc-bool-pointer-implicit-conversion
misc-dangling-handle
+   misc-default-numerics
misc-definitions-in-headers
misc-fold-init-type
misc-forward-declaration-namespace
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -71,7 +71,11 @@
   `_ check
 
   Allow custom memory management functions to be considered as well.
-  
+
+- New `misc-default-numerics
+  `_ check
+  Finds uses of ``std::numeric_limit`` for unspecialized types
+
 - New `misc-forwarding-reference-overload
   `_ check
 
Index: clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "AssertSideEffectCheck.h"
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DanglingHandleCheck.h"
+#include "DefaultNumericsCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
@@ -66,6 +67,7 @@
 CheckFactories.registerCheck("misc-argument-comment");
 CheckFactories.registerCheck(
 "misc-assert-side-effect");
+CheckFactories.registerCheck("misc-default-numerics");
 CheckFactories.registerCheck(
 "misc-forwarding-reference-overload");
 CheckFactories.registerCheck("misc-misplaced-const");
Index: clang-tidy/misc/DefaultNumericsCheck.h
===
--- /dev/null
+++ clang-tidy/misc/DefaultNumericsCheck.h
@@ -0,0 +1,37 @@
+//===--- DefaultNumericsCheck.h - clang-tidy-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS

[PATCH] D33537: [clang-tidy] Exception Escape Checker

2017-05-25 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

How is that compared to https://reviews.llvm.org/D19201 and the clang patch 
mentioned in this patch?


Repository:
  rL LLVM

https://reviews.llvm.org/D33537



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


[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100530.
Prazek marked 3 inline comments as done.
Prazek added a comment.

- Addressing John's comments


https://reviews.llvm.org/D33437

Files:
  include/clang/AST/VTableBuilder.h
  lib/CodeGen/CGVTables.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  lib/CodeGen/ItaniumCXXABI.cpp
  test/CodeGenCXX/vtable-available-externally.cpp
  test/CodeGenCXX/vtable-linkage.cpp

Index: test/CodeGenCXX/vtable-linkage.cpp
===
--- test/CodeGenCXX/vtable-linkage.cpp
+++ test/CodeGenCXX/vtable-linkage.cpp
@@ -145,12 +145,14 @@
 // F is an explicit template instantiation declaration without a
 // key function, so its vtable should have external linkage.
 // CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant
-// CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr constant
 
 // E is an explicit template instantiation declaration. It has a
 // key function is not instantiated, so we know that vtable definition
 // will be generated in TU where key function will be defined
-// so we can mark it as available_externally (only with optimizations)
+// so we can mark it as external (without optimizations) and
+// available_externally (with optimizations) because all of the inline
+// virtual functions have been emitted.
 // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant
 // CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant
 
Index: test/CodeGenCXX/vtable-available-externally.cpp
===
--- test/CodeGenCXX/vtable-available-externally.cpp
+++ test/CodeGenCXX/vtable-available-externally.cpp
@@ -12,6 +12,7 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
 
 #include 
 
@@ -274,8 +275,8 @@
   virtual D& operator=(const D&);
 };
 
-// Cannot emit B's vtable available_externally, because we cannot create
-// a reference to the inline virtual B::operator= function.
+// Cannot emit D's vtable available_externally, because we cannot create
+// a reference to the inline virtual D::operator= function.
 // CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant
 struct D : C {
   virtual void key();
@@ -391,3 +392,30 @@
 }
 }
 
+namespace Test17 {
+// This test checks if we emit vtables opportunistically.
+// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+
+struct A {
+  virtual void key();
+  virtual void bar() {}
+};
+
+// We won't gonna use deleting destructor for this type, which will disallow
+// emitting vtable as available_externally
+struct B {
+  virtual void key();
+  virtual ~B() {}
+};
+
+void testcaseA() {
+  A a;
+  a.bar(); // this forces to emit definition of bar
+}
+
+void testcaseB() {
+  B b; // This only forces emitting of complete object destructor
+}
+
+} // namespace Test17
Index: lib/CodeGen/ItaniumCXXABI.cpp
===
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -366,20 +366,30 @@
   void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
 
  private:
-   bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
-const auto &VtableLayout =
-CGM.getItaniumVTableContext().getVTableLayout(RD);
-
-for (const auto &VtableComponent : VtableLayout.vtable_components()) {
-  // Skip empty slot.
-  if (!VtableComponent.isUsedFunctionPointerKind())
-continue;
-
-  const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
-  if (Method->getCanonicalDecl()->isInlined())
-return true;
-}
-return false;
+   bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+   // Skip empty slot.
+   if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+   const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+   if (!Method->getCanonicalDecl()->isInlined())
+ continue;
+
+   StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
+   auto *Entry = CGM.GetGlobalValue(Name);
+   // This checks if virtual inline function has already been emitted.
+   // Note that it is possible that this inline function would be emitted
+   // after trying to emit vtable speculatively. Because of this we do
+   // an extra pass after emitting all deferred vtables to find and emit
+   // these vtables opportunistically.
+   if (!Entry || Entry->isDeclaration())
+ r

[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

Thanks for the comments :)




Comment at: include/clang/AST/VTableBuilder.h:160
+   "GlobalDecl can be created only from virtual function");
+if (getKind() == CK_FunctionPointer)
+  return GlobalDecl(getFunctionDecl());

rjmccall wrote:
> Please use an exhaustive switch.  You can put llvm_unreachable in the other 
> cases.
Should I implement this for RTTI fields? Or maybe leave a fixme comment that it 
could also work for some other fields in vtable, but is not currently used?


https://reviews.llvm.org/D33437



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


[PATCH] D31830: Emit invariant.group.barrier when using union field

2017-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100533.
Prazek added a comment.

- changed to QualType, now it is much cleaner


https://reviews.llvm.org/D31830

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenCXX/strict-vtable-pointers.cpp

Index: test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- test/CodeGenCXX/strict-vtable-pointers.cpp
+++ test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
 // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@@ -180,6 +180,82 @@
 // CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
 // CHECK-CTORS-LABEL: {{^}}}
 
+struct A {
+  virtual void foo();
+};
+struct B : A {
+  virtual void foo();
+};
+
+union U {
+  A a;
+  B b;
+};
+
+void changeToB(U *u);
+void changeToA(U *u);
+
+void g2(A *a) {
+  a->foo();
+}
+// We have to guard access to union fields with invariant.group, because
+// it is very easy to skip the barrier with unions. In this example the inlined
+// g2 will produce loads with the same !invariant.group metadata, and
+// u->a and u->b would use the same pointer.
+// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U
+void UnionsBarriers(U *u) {
+  // CHECK-NEW: call void @_Z9changeToBP1U(
+  changeToB(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
+  g2(&u->b);
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* %6)
+  changeToA(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // call void @_Z2g2P1A(%struct.A* %a)
+  g2(&u->a);
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+}
+
+struct HoldingVirtuals {
+  A a;
+};
+
+struct Empty {};
+struct AnotherEmpty {
+  Empty e;
+};
+union NoVptrs {
+  int a;
+  AnotherEmpty empty;
+};
+void take(AnotherEmpty &);
+
+// CHECK-NEW-LABEL: noBarriers
+void noBarriers(NoVptrs &noVptrs) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  noVptrs.a += 42;
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
+  take(noVptrs.empty);
+}
+
+union U2 {
+  HoldingVirtuals h;
+  int z;
+};
+void take(HoldingVirtuals &);
+
+// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
+void UnionsBarriers2(U2 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
+  take(u.h);
+}
 
 /** DTORS **/
 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3528,6 +3528,25 @@
   return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
 }
 
+static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
+  const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
+  if (!RD)
+return false;
+
+  if (RD->isDynamicClass())
+return true;
+
+  for (const auto &Base : RD->bases())
+if (hasAnyVptr(Base.getType(), Context))
+  return true;
+
+  for (const FieldDecl *Field : RD->fields())
+if (hasAnyVptr(Field->getType(), Context))
+  return true;
+
+  return false;
+}
+
 LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
   LValueBaseInfo BaseInfo = base.getBaseInfo();
@@ -3569,6 +3588,14 @@
 assert(!type->isReferenceType() && "union has reference member");
 // TODO: handle path-aware TBAA for union.
 TBAAPath = false;
+
+const auto FieldType = field->getType();
+if (CGM.getCodeGenOpts().StrictVTablePointers &&
+hasAnyVptr(FieldType, getContext()))
+  // Because unions can easily skip invariant.barriers, we need to add
+  // a barrier every time CXXRecord field with vptr is referenced.
+  addr = Address(Builder.CreateInvariantGroupBarrier(addr.getPointer()),
+ addr.getAlignment());
   } else {
 // For structs, we GEP to the field that the record layout suggests.
 addr = emitAddrOfFieldStorage(*this, addr, field);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31830: Emit invariant.group.barrier when using union field

2017-05-27 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 2 inline comments as done.
Prazek added inline comments.



Comment at: lib/CodeGen/CGExpr.cpp:3530
+  return false;
+}
+

rjmccall wrote:
> You need to recurse into base classes (to check their fields), and if you 
> write this to take a QualType you won't have to eagerly extract RD below.
Cool, thanks for the tip


https://reviews.llvm.org/D31830



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


[PATCH] D31830: Emit invariant.group.barrier when using union field

2017-05-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100621.
Prazek added a comment.

Add test


https://reviews.llvm.org/D31830

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenCXX/strict-vtable-pointers.cpp

Index: test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- test/CodeGenCXX/strict-vtable-pointers.cpp
+++ test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
 // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@@ -180,6 +180,112 @@
 // CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
 // CHECK-CTORS-LABEL: {{^}}}
 
+struct A {
+  virtual void foo();
+};
+struct B : A {
+  virtual void foo();
+};
+
+union U {
+  A a;
+  B b;
+};
+
+void changeToB(U *u);
+void changeToA(U *u);
+
+void g2(A *a) {
+  a->foo();
+}
+// We have to guard access to union fields with invariant.group, because
+// it is very easy to skip the barrier with unions. In this example the inlined
+// g2 will produce loads with the same !invariant.group metadata, and
+// u->a and u->b would use the same pointer.
+// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U
+void UnionsBarriers(U *u) {
+  // CHECK-NEW: call void @_Z9changeToBP1U(
+  changeToB(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
+  g2(&u->b);
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* %6)
+  changeToA(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // call void @_Z2g2P1A(%struct.A* %a)
+  g2(&u->a);
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+}
+
+struct HoldingVirtuals {
+  A a;
+};
+
+struct Empty {};
+struct AnotherEmpty {
+  Empty e;
+};
+union NoVptrs {
+  int a;
+  AnotherEmpty empty;
+};
+void take(AnotherEmpty &);
+
+// CHECK-NEW-LABEL: noBarriers
+void noBarriers(NoVptrs &noVptrs) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  noVptrs.a += 42;
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
+  take(noVptrs.empty);
+}
+
+union U2 {
+  HoldingVirtuals h;
+  int z;
+};
+void take(HoldingVirtuals &);
+
+// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
+void UnionsBarriers2(U2 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
+  take(u.h);
+}
+
+struct VirtualInBase : HoldingVirtuals, Empty {
+};
+
+struct VirtualInVBase : virtual Empty, HoldingVirtuals {
+};
+
+union U3 {
+  VirtualInBase v1;
+  VirtualInBase v2;
+  int z;
+};
+
+void take(VirtualInBase &);
+void take(VirtualInVBase &);
+
+void UnionsBarrier3(U3 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v1);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v2);
+}
+
+
+
 
 /** DTORS **/
 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3528,6 +3528,25 @@
   return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
 }
 
+static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
+  const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
+  if (!RD)
+return false;
+
+  if (RD->isDynamicClass())
+return true;
+
+  for (const auto &Base : RD->bases())
+if (hasAnyVptr(Base.getType(), Context))
+  return true;
+
+  for (const FieldDecl *Field : RD->fields())
+if (hasAnyVptr(Field->getType(), Context))
+  return true;
+
+  return false;
+}
+
 LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
   LValueBaseInfo BaseInfo = base.getBaseInfo();
@@ -3569,6 +3588,14 @@
 assert(!type->isReferenceType() && "union has reference member");
 // TODO: handle path-aware TBAA for union.
 TBAAPath = false;
+
+const auto FieldType = field->getType();
+if (CGM.getCodeGenOpts().StrictVTablePointers &&
+hasAnyVptr(FieldType, getContext()))
+  // Because unions can easily skip invariant.barriers, we need to add
+  // a barrier every time CXXRecord field with vptr is referenced.
+  addr = Address(Builder.CreateInvariantGroupB

[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked an inline comment as done.
Prazek added inline comments.



Comment at: include/clang/AST/VTableBuilder.h:169
+  return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
+default:
+  llvm_unreachable("Only function pointers kinds");

rjmccall wrote:
> By "exhaustive" I mean that you should list out all the cases instead of 
> using default.  It means that someone who adds a new kind of v-table entry 
> will get alerted to fix this switch.  There's only five other cases, it's not 
> too bad.
Oh right, that make sense


https://reviews.llvm.org/D33437



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


[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 4 inline comments as done.
Prazek added inline comments.



Comment at: include/clang/AST/VTableBuilder.h:160
+   "GlobalDecl can be created only from virtual function");
+if (getKind() == CK_FunctionPointer)
+  return GlobalDecl(getFunctionDecl());

rjmccall wrote:
> Prazek wrote:
> > rjmccall wrote:
> > > Please use an exhaustive switch.  You can put llvm_unreachable in the 
> > > other cases.
> > Should I implement this for RTTI fields? Or maybe leave a fixme comment 
> > that it could also work for some other fields in vtable, but is not 
> > currently used?
> I think your precondition of isUsedFunctionPointerKind() is fine, you don't 
> need to handle RTTI in this function.
> 
> This does raise the interesting question, though, of whether this approach is 
> safe for lazily-emitted RTTI.  I guess it currently works because IRGen 
> doesn't use the normal deferred-emission mechanism for RTTI objects, so if 
> the RTTI object is lazily-emitted, we'll just eagerly emit it instead of 
> potentially ending up with an illegal reference to external RTTI.  You should 
> add a comment to the appropriate place in CGRTTI (i.e. where we fill in the 
> global definition) saying that this optimization may need adjustment if we 
> ever switch to using deferred emission for some reason.
I couldn't find CGRTTI, so I added comment in Itanium and Microsoft ABI where 
we create RTTI fields, but maybe the CodeGenModule::GetAddrOfRTTIDescriptor 
would be a better place instead?

I also added small note to the EmitVTablesOpportunistically about this.


https://reviews.llvm.org/D33437



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


[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100623.
Prazek marked an inline comment as done.
Prazek added a comment.

- Final changes


https://reviews.llvm.org/D33437

Files:
  include/clang/AST/VTableBuilder.h
  lib/CodeGen/CGVTables.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  test/CodeGenCXX/vtable-available-externally.cpp
  test/CodeGenCXX/vtable-linkage.cpp

Index: test/CodeGenCXX/vtable-linkage.cpp
===
--- test/CodeGenCXX/vtable-linkage.cpp
+++ test/CodeGenCXX/vtable-linkage.cpp
@@ -145,12 +145,14 @@
 // F is an explicit template instantiation declaration without a
 // key function, so its vtable should have external linkage.
 // CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant
-// CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr constant
 
 // E is an explicit template instantiation declaration. It has a
 // key function is not instantiated, so we know that vtable definition
 // will be generated in TU where key function will be defined
-// so we can mark it as available_externally (only with optimizations)
+// so we can mark it as external (without optimizations) and
+// available_externally (with optimizations) because all of the inline
+// virtual functions have been emitted.
 // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant
 // CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant
 
Index: test/CodeGenCXX/vtable-available-externally.cpp
===
--- test/CodeGenCXX/vtable-available-externally.cpp
+++ test/CodeGenCXX/vtable-available-externally.cpp
@@ -12,6 +12,7 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
 
 #include 
 
@@ -274,8 +275,8 @@
   virtual D& operator=(const D&);
 };
 
-// Cannot emit B's vtable available_externally, because we cannot create
-// a reference to the inline virtual B::operator= function.
+// Cannot emit D's vtable available_externally, because we cannot create
+// a reference to the inline virtual D::operator= function.
 // CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant
 struct D : C {
   virtual void key();
@@ -391,3 +392,30 @@
 }
 }
 
+namespace Test17 {
+// This test checks if we emit vtables opportunistically.
+// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+
+struct A {
+  virtual void key();
+  virtual void bar() {}
+};
+
+// We won't gonna use deleting destructor for this type, which will disallow
+// emitting vtable as available_externally
+struct B {
+  virtual void key();
+  virtual ~B() {}
+};
+
+void testcaseA() {
+  A a;
+  a.bar(); // this forces to emit definition of bar
+}
+
+void testcaseB() {
+  B b; // This only forces emitting of complete object destructor
+}
+
+} // namespace Test17
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -3756,6 +3756,9 @@
   if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
 return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
 
+  // Note for the future: If we would ever like to do deferred emission of
+  // RTTI, check if emitting vtables opportunistically need any adjustment.
+
   // Compute the fields for the TypeDescriptor.
   SmallString<256> TypeInfoString;
   {
Index: lib/CodeGen/ItaniumCXXABI.cpp
===
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -366,20 +366,30 @@
   void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
 
  private:
-   bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
-const auto &VtableLayout =
-CGM.getItaniumVTableContext().getVTableLayout(RD);
-
-for (const auto &VtableComponent : VtableLayout.vtable_components()) {
-  // Skip empty slot.
-  if (!VtableComponent.isUsedFunctionPointerKind())
-continue;
-
-  const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
-  if (Method->getCanonicalDecl()->isInlined())
-return true;
-}
-return false;
+   bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+   // Skip empty slot.
+   if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+   const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+

[PATCH] D33437: Emit available_externally vtables opportunistically

2017-05-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100641.
Prazek added a comment.

changed assert


https://reviews.llvm.org/D33437

Files:
  include/clang/AST/VTableBuilder.h
  lib/CodeGen/CGVTables.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  test/CodeGenCXX/vtable-available-externally.cpp
  test/CodeGenCXX/vtable-linkage.cpp

Index: test/CodeGenCXX/vtable-linkage.cpp
===
--- test/CodeGenCXX/vtable-linkage.cpp
+++ test/CodeGenCXX/vtable-linkage.cpp
@@ -145,12 +145,14 @@
 // F is an explicit template instantiation declaration without a
 // key function, so its vtable should have external linkage.
 // CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant
-// CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr constant
 
 // E is an explicit template instantiation declaration. It has a
 // key function is not instantiated, so we know that vtable definition
 // will be generated in TU where key function will be defined
-// so we can mark it as available_externally (only with optimizations)
+// so we can mark it as external (without optimizations) and
+// available_externally (with optimizations) because all of the inline
+// virtual functions have been emitted.
 // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant
 // CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant
 
Index: test/CodeGenCXX/vtable-available-externally.cpp
===
--- test/CodeGenCXX/vtable-available-externally.cpp
+++ test/CodeGenCXX/vtable-available-externally.cpp
@@ -12,6 +12,7 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
 
 #include 
 
@@ -274,8 +275,8 @@
   virtual D& operator=(const D&);
 };
 
-// Cannot emit B's vtable available_externally, because we cannot create
-// a reference to the inline virtual B::operator= function.
+// Cannot emit D's vtable available_externally, because we cannot create
+// a reference to the inline virtual D::operator= function.
 // CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant
 struct D : C {
   virtual void key();
@@ -391,3 +392,30 @@
 }
 }
 
+namespace Test17 {
+// This test checks if we emit vtables opportunistically.
+// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+
+struct A {
+  virtual void key();
+  virtual void bar() {}
+};
+
+// We won't gonna use deleting destructor for this type, which will disallow
+// emitting vtable as available_externally
+struct B {
+  virtual void key();
+  virtual ~B() {}
+};
+
+void testcaseA() {
+  A a;
+  a.bar(); // this forces to emit definition of bar
+}
+
+void testcaseB() {
+  B b; // This only forces emitting of complete object destructor
+}
+
+} // namespace Test17
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -3756,6 +3756,9 @@
   if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
 return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
 
+  // Note for the future: If we would ever like to do deferred emission of
+  // RTTI, check if emitting vtables opportunistically need any adjustment.
+
   // Compute the fields for the TypeDescriptor.
   SmallString<256> TypeInfoString;
   {
Index: lib/CodeGen/ItaniumCXXABI.cpp
===
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -366,20 +366,30 @@
   void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
 
  private:
-   bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
-const auto &VtableLayout =
-CGM.getItaniumVTableContext().getVTableLayout(RD);
-
-for (const auto &VtableComponent : VtableLayout.vtable_components()) {
-  // Skip empty slot.
-  if (!VtableComponent.isUsedFunctionPointerKind())
-continue;
-
-  const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
-  if (Method->getCanonicalDecl()->isInlined())
-return true;
-}
-return false;
+   bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+   // Skip empty slot.
+   if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+   const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+   if (!Method->getCanonicalDecl()->is

[PATCH] D33437: Emit available_externally vtables opportunistically

2017-06-01 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL304394: Emit available_externally vtables opportunistically 
(authored by Prazek).

Changed prior to commit:
  https://reviews.llvm.org/D33437?vs=100641&id=100976#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D33437

Files:
  cfe/trunk/include/clang/AST/VTableBuilder.h
  cfe/trunk/lib/CodeGen/CGVTables.cpp
  cfe/trunk/lib/CodeGen/CodeGenModule.cpp
  cfe/trunk/lib/CodeGen/CodeGenModule.h
  cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
  cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
  cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp
  cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp

Index: cfe/trunk/lib/CodeGen/CodeGenModule.h
===
--- cfe/trunk/lib/CodeGen/CodeGenModule.h
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h
@@ -341,6 +341,9 @@
   /// A queue of (optional) vtables to consider emitting.
   std::vector DeferredVTables;
 
+  /// A queue of (optional) vtables that may be emitted opportunistically.
+  std::vector OpportunisticVTables;
+
   /// List of global values which are required to be present in the object file;
   /// bitcast to i8*. This is used for forcing visibility of symbols which may
   /// otherwise be optimized out.
@@ -450,7 +453,7 @@
 
   bool isTriviallyRecursive(const FunctionDecl *F);
   bool shouldEmitFunction(GlobalDecl GD);
-
+  bool shouldOpportunisticallyEmitVTables();
   /// Map used to be sure we don't emit the same CompoundLiteral twice.
   llvm::DenseMap
   EmittedCompoundLiterals;
@@ -1278,6 +1281,12 @@
   /// Emit any needed decls for which code generation was deferred.
   void EmitDeferred();
 
+  /// Try to emit external vtables as available_externally if they have emitted
+  /// all inlined virtual functions.  It runs after EmitDeferred() and therefore
+  /// is not allowed to create new references to things that need to be emitted
+  /// lazily.
+  void EmitVTablesOpportunistically();
+
   /// Call replaceAllUsesWith on all pairs in Replacements.
   void applyReplacements();
 
Index: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
===
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
@@ -366,20 +366,30 @@
   void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
 
  private:
-   bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
-const auto &VtableLayout =
-CGM.getItaniumVTableContext().getVTableLayout(RD);
-
-for (const auto &VtableComponent : VtableLayout.vtable_components()) {
-  // Skip empty slot.
-  if (!VtableComponent.isUsedFunctionPointerKind())
-continue;
-
-  const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
-  if (Method->getCanonicalDecl()->isInlined())
-return true;
-}
-return false;
+   bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+   // Skip empty slot.
+   if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+   const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+   if (!Method->getCanonicalDecl()->isInlined())
+ continue;
+
+   StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
+   auto *Entry = CGM.GetGlobalValue(Name);
+   // This checks if virtual inline function has already been emitted.
+   // Note that it is possible that this inline function would be emitted
+   // after trying to emit vtable speculatively. Because of this we do
+   // an extra pass after emitting all deferred vtables to find and emit
+   // these vtables opportunistically.
+   if (!Entry || Entry->isDeclaration())
+ return true;
+ }
+ return false;
   }
 
   bool isVTableHidden(const CXXRecordDecl *RD) const {
@@ -1687,11 +1697,11 @@
   if (CGM.getLangOpts().AppleKext)
 return false;
 
-  // If we don't have any inline virtual functions, and if vtable is not hidden,
-  // then we are safe to emit available_externally copy of vtable.
+  // If we don't have any not emitted inline virtual function, and if vtable is
+  // not hidden, then we are safe to emit available_externally copy of vtable.
   // FIXME we can still emit a copy of the vtable if we
   // can emit definition of the inline functions.
-  return !hasAnyVirtualInlineFunction(RD) && !isVTableHidden(RD);
+  return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD);
 }
 static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
   Address InitialPtr,
@@ -2576,6 +2586,9 @@
 
   if (!GV) {
 // Create a new global variable.
+// Note for the future: If we would ever like to do deferred em

[PATCH] D31830: Emit invariant.group.barrier when using union field

2017-06-01 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 100977.
Prazek marked an inline comment as done.
Prazek added a comment.

Extra test


https://reviews.llvm.org/D31830

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGenCXX/strict-vtable-pointers.cpp

Index: test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- test/CodeGenCXX/strict-vtable-pointers.cpp
+++ test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
 // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@@ -180,6 +180,119 @@
 // CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
 // CHECK-CTORS-LABEL: {{^}}}
 
+struct A {
+  virtual void foo();
+};
+struct B : A {
+  virtual void foo();
+};
+
+union U {
+  A a;
+  B b;
+};
+
+void changeToB(U *u);
+void changeToA(U *u);
+
+void g2(A *a) {
+  a->foo();
+}
+// We have to guard access to union fields with invariant.group, because
+// it is very easy to skip the barrier with unions. In this example the inlined
+// g2 will produce loads with the same !invariant.group metadata, and
+// u->a and u->b would use the same pointer.
+// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U
+void UnionsBarriers(U *u) {
+  // CHECK-NEW: call void @_Z9changeToBP1U(
+  changeToB(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
+  g2(&u->b);
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* %6)
+  changeToA(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // call void @_Z2g2P1A(%struct.A* %a)
+  g2(&u->a);
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+}
+
+struct HoldingVirtuals {
+  A a;
+};
+
+struct Empty {};
+struct AnotherEmpty {
+  Empty e;
+};
+union NoVptrs {
+  int a;
+  AnotherEmpty empty;
+};
+void take(AnotherEmpty &);
+
+// CHECK-NEW-LABEL: noBarriers
+void noBarriers(NoVptrs &noVptrs) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  noVptrs.a += 42;
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
+  take(noVptrs.empty);
+}
+
+union U2 {
+  HoldingVirtuals h;
+  int z;
+};
+void take(HoldingVirtuals &);
+
+// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
+void UnionsBarriers2(U2 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
+  take(u.h);
+}
+
+struct VirtualInBase : HoldingVirtuals, Empty {
+};
+
+struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals {
+};
+
+// It has vtable by virtual inheritance.
+struct VirtualInheritance : virtual Empty {
+};
+
+union U3 {
+  VirtualInBase v1;
+  VirtualInBase v2;
+  VirtualInheritance v3;
+  int z;
+};
+
+void take(VirtualInBase &);
+void take(VirtualInVBase &);
+void take(VirtualInheritance &);
+
+void UnionsBarrier3(U3 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v1);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v2);
+
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
+  take(u.v3);
+}
 
 /** DTORS **/
 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3530,6 +3530,25 @@
   return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
 }
 
+static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
+  const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
+  if (!RD)
+return false;
+
+  if (RD->isDynamicClass())
+return true;
+
+  for (const auto &Base : RD->bases())
+if (hasAnyVptr(Base.getType(), Context))
+  return true;
+
+  for (const FieldDecl *Field : RD->fields())
+if (hasAnyVptr(Field->getType(), Context))
+  return true;
+
+  return false;
+}
+
 LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
   LValueBaseInfo BaseInfo = base.getBaseInfo();
@@ -3572,6 +3591,14 @@
 assert(!type->isReferenceType() && "union has reference member");
 // TODO: handle path-aware TBAA for union.
 TBAAPath = false;
+
+const a

[PATCH] D31830: Emit invariant.group.barrier when using union field

2017-06-01 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL304448: Emit invariant.group.barrier when using union field 
(authored by Prazek).

Changed prior to commit:
  https://reviews.llvm.org/D31830?vs=100977&id=101058#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D31830

Files:
  cfe/trunk/lib/CodeGen/CGExpr.cpp
  cfe/trunk/test/CodeGenCXX/strict-vtable-pointers.cpp

Index: cfe/trunk/test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- cfe/trunk/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ cfe/trunk/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
 // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
 // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@@ -180,6 +180,119 @@
 // CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
 // CHECK-CTORS-LABEL: {{^}}}
 
+struct A {
+  virtual void foo();
+};
+struct B : A {
+  virtual void foo();
+};
+
+union U {
+  A a;
+  B b;
+};
+
+void changeToB(U *u);
+void changeToA(U *u);
+
+void g2(A *a) {
+  a->foo();
+}
+// We have to guard access to union fields with invariant.group, because
+// it is very easy to skip the barrier with unions. In this example the inlined
+// g2 will produce loads with the same !invariant.group metadata, and
+// u->a and u->b would use the same pointer.
+// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U
+void UnionsBarriers(U *u) {
+  // CHECK-NEW: call void @_Z9changeToBP1U(
+  changeToB(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
+  g2(&u->b);
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* %6)
+  changeToA(u);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // call void @_Z2g2P1A(%struct.A* %a)
+  g2(&u->a);
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+}
+
+struct HoldingVirtuals {
+  A a;
+};
+
+struct Empty {};
+struct AnotherEmpty {
+  Empty e;
+};
+union NoVptrs {
+  int a;
+  AnotherEmpty empty;
+};
+void take(AnotherEmpty &);
+
+// CHECK-NEW-LABEL: noBarriers
+void noBarriers(NoVptrs &noVptrs) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  noVptrs.a += 42;
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
+  take(noVptrs.empty);
+}
+
+union U2 {
+  HoldingVirtuals h;
+  int z;
+};
+void take(HoldingVirtuals &);
+
+// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
+void UnionsBarriers2(U2 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
+  take(u.h);
+}
+
+struct VirtualInBase : HoldingVirtuals, Empty {
+};
+
+struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals {
+};
+
+// It has vtable by virtual inheritance.
+struct VirtualInheritance : virtual Empty {
+};
+
+union U3 {
+  VirtualInBase v1;
+  VirtualInBase v2;
+  VirtualInheritance v3;
+  int z;
+};
+
+void take(VirtualInBase &);
+void take(VirtualInVBase &);
+void take(VirtualInheritance &);
+
+void UnionsBarrier3(U3 &u) {
+  // CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: 42
+  u.z += 42;
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v1);
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
+  take(u.v2);
+
+  // CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
+  // CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
+  take(u.v3);
+}
 
 /** DTORS **/
 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
Index: cfe/trunk/lib/CodeGen/CGExpr.cpp
===
--- cfe/trunk/lib/CodeGen/CGExpr.cpp
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp
@@ -3530,6 +3530,25 @@
   return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
 }
 
+static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
+  const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
+  if (!RD)
+return false;
+
+  if (RD->isDynamicClass())
+return true;
+
+  for (const auto &Base : RD->bases())
+if (hasAnyVptr(Base.getType(), Context))
+  return true;
+
+  for (const FieldDecl *Field : RD->fields())
+if (hasAnyVptr(Field->getType(), Context))
+  return true;
+
+  return false;
+}
+
 LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDec

[PATCH] D33852: Enable __declspec(selectany) on linux)

2017-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.

This feature was disabled probably by mistake in 
https://reviews.llvm.org/rL300562
This fixes bug https://bugs.llvm.org/show_bug.cgi?id=33285


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fms-extensions %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2413,7 +2413,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fms-extensions %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2413,7 +2413,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33841: [clang-tidy] redundant keyword check

2017-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

Feature request: removing "void" from int main(void)


Repository:
  rL LLVM

https://reviews.llvm.org/D33841



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


[PATCH] D33841: [clang-tidy] redundant keyword check

2017-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

extern on function definition is also redundant, right?

Also, what about:
inline extern void foo();
(you check if it startswith extern)


Repository:
  rL LLVM

https://reviews.llvm.org/D33841



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

OK, I will try to make it work on linux and windows only


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-03 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

It seems that this is separate issue - we don't generate comdat for MachO. 
Indeed we should warn on not supported declspec for macho.


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-04 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 101352.
Prazek added a comment.

- Fixes


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  test/Sema/attr-selectany-not-supported.c
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp
  utils/TableGen/ClangAttrEmitter.cpp


Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2659,6 +2659,23 @@
 }
 Test += ")";
   }
+
+  // If one or more CXX ABIs are specified, check those as well.
+  if (!R->isValueUnset("ObjectFormats")) {
+Test += " && (";
+std::vector ObjectFormats =
+R->getValueAsListOfStrings("ObjectFormats");
+for (auto I = ObjectFormats.begin(), E = ObjectFormats.end(); I != E; ++I) 
{
+  StringRef Part = *I;
+  Test += "T.getObjectFormat() == llvm::Triple::";
+  Test += Part;
+  if (I + 1 != E)
+Test += " || ";
+  if (FnName)
+*FnName += Part;
+}
+Test += ")";
+  }
 }
 
 static void GenerateHasAttrSpellingStringSwitch(
Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: test/Sema/attr-selectany-not-supported.c
===
--- /dev/null
+++ test/Sema/attr-selectany-not-supported.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
+
+// selectany is not supported for macho object files.
+__declspec(selectany) int x1; // expected-warning{{__declspec attribute 
'selectany' is not supported}}
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -261,6 +261,7 @@
   list Arches = arches;
   list OSes;
   list CXXABIs;
+  list ObjectFormats;
 }
 def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
 def TargetAVR : TargetArch<["avr"]>;
@@ -274,6 +275,10 @@
 def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
   let CXXABIs = ["Microsoft"];
 }
+def TargetWindowsAndLinux : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+  let OSes = ["Win32", "Linux"];
+  let ObjectFormats = ["COFF", "ELF"];
+}
 
 // Attribute subject match rules that are used for #pragma clang attribute.
 //
@@ -2413,7 +2418,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr, TargetSpecificAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }


Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2659,6 +2659,23 @@
 }
 Test += ")";
   }
+
+  // If one or more CXX ABIs are specified, check those as well.
+  if (!R->isValueUnset("ObjectFormats")) {
+Test += " && (";
+std::vector ObjectFormats =
+R->getValueAsListOfStrings("ObjectFormats");
+for (auto I = ObjectFormats.begin(), E = ObjectFormats.end(); I != E; ++I) {
+  StringRef Part = *I;
+  Test += "T.getObjectFormat() == llvm::Triple::";
+  Test += Part;
+  if (I + 1 != E)
+Test += " || ";
+  if (FnName)
+*FnName += Part;
+}
+Test += ")";
+  }
 }
 
 static void GenerateHasAttrSpellingStringSwitch(
Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-err

[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-04 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

I fired bug about the crash: https://bugs.llvm.org/show_bug.cgi?id=33300


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-05 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: include/clang/Basic/Attr.td:2421
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr, TargetSpecificAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];

majnemer wrote:
> selectany should work on targets other than "x86", "x86_64", "arm", "thumb", 
> etc. I think it is only necessary to require that it be a COFF or ELF target.
Should we allow other OSes than Win32 and Linux?


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-06-13 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: include/clang/Basic/Attr.td:2421
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr, TargetSpecificAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];

rnk wrote:
> davide wrote:
> > Prazek wrote:
> > > majnemer wrote:
> > > > selectany should work on targets other than "x86", "x86_64", "arm", 
> > > > "thumb", etc. I think it is only necessary to require that it be a COFF 
> > > > or ELF target.
> > > Should we allow other OSes than Win32 and Linux?
> > I guess everything ELF should be allowed.
> Why not use weak_odr / linkonce_odr on MachO? Microsoft builds Office for Mac 
> and I suspect they use `__declspec(selectany)`.
I think this is what would happen right now. The question is - should we warn 
about using declspec on macho? Beause not using comdat looks like "not 
supporting" it, but I am not sure about it.


https://reviews.llvm.org/D33852



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


[PATCH] D33470: [clang-tidy] Add misc-default-numerics

2017-06-24 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 103837.
Prazek marked 4 inline comments as done.
Prazek added a comment.

- fixed docs
- fixes


https://reviews.llvm.org/D33470

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/DefaultNumericsCheck.cpp
  clang-tidy/misc/DefaultNumericsCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-default-numerics.rst
  test/clang-tidy/misc-default-numerics.cpp

Index: test/clang-tidy/misc-default-numerics.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-default-numerics.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s misc-default-numerics %t
+
+namespace std {
+
+template 
+struct numeric_limits {
+  static T min() { return T(); }
+  static T max() { return T(); }
+};
+
+template <>
+struct numeric_limits {
+  static int min() { return -1; }
+  static int max() { return 1; }
+};
+
+} // namespace std
+
+class MyType {};
+template 
+class MyTemplate {};
+
+void test() {
+  auto x = std::numeric_limits::min();
+
+  auto y = std::numeric_limits::min();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'std::numeric_limits::min' called with type 'MyType'; no such specialization exists, so the default value for that type is returned
+
+  auto z = std::numeric_limits>::max();
+  // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'std::numeric_limits::max' called with type 'MyTemplate';
+}
+
+template 
+void fun() {
+  auto x = std::numeric_limits::min();
+}
+
+void testTemplate() {
+  fun();
+  // FIXME: This should generate warning with backtrace.
+  fun;
+}
Index: docs/clang-tidy/checks/misc-default-numerics.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-default-numerics.rst
@@ -0,0 +1,23 @@
+.. title:: clang-tidy - misc-default-numerics
+
+misc-default-numerics
+=
+
+This check flags usages of ``std::numeric_limits::{min,max}()`` for
+unspecialized types. It is dangerous because the calls return ``T()``
+in this case, which is unlikely to represent the minimum or maximum value for
+the type.
+
+Consider scenario:
+.. code-block:: c++
+
+  // 1. Have a:
+  typedef long long BigInt
+
+  // 2. Use
+  std::numeric_limits::min()
+
+  // 3. Replace the BigInt typedef with class implementing BigIntegers
+  class BigInt { ;;; };
+
+  // 4. Your code continues to compile, but the call to min() returns BigInt{}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -75,6 +75,7 @@
misc-assert-side-effect
misc-bool-pointer-implicit-conversion
misc-dangling-handle
+   misc-default-numerics
misc-definitions-in-headers
misc-fold-init-type
misc-forward-declaration-namespace
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -72,6 +72,10 @@
 
   Allow custom memory management functions to be considered as well.
 
+- New `misc-default-numerics
+  `_ check
+  Finds uses of ``std::numeric_limits`` for unspecialized types
+
 - New `misc-forwarding-reference-overload
   `_ check
 
Index: clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "AssertSideEffectCheck.h"
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DanglingHandleCheck.h"
+#include "DefaultNumericsCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
@@ -67,6 +68,7 @@
 CheckFactories.registerCheck("misc-argument-comment");
 CheckFactories.registerCheck(
 "misc-assert-side-effect");
+CheckFactories.registerCheck("misc-default-numerics");
 CheckFactories.registerCheck(
 "misc-forwarding-reference-overload");
 CheckFactories.registerCheck(
Index: clang-tidy/misc/DefaultNumericsCheck.h
===
--- /dev/null
+++ clang-tidy/misc/DefaultNumericsCheck.h
@@ -0,0 +1,37 @@
+//===--- DefaultNumericsCheck.h - clang-tidy-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DEFAULT_NUMERICS_H
+
+#include "../ClangTidy.h"
+
+nam

[PATCH] D33470: [clang-tidy] Add misc-default-numerics

2017-06-24 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

In https://reviews.llvm.org/D33470#764846, @aaron.ballman wrote:

> Once you fix the typo in the check, can you run it over some large C++ code 
> bases to see if it finds any results?


I tried it on LLVM code base (after fixing bug with the numeric_limits name) 
and it didn't find anything suspisious.
Unfortunatelly I don't have enough time to try it on different codebases, but I 
am weiling to fix any bug with this check if it would happen in the future.
The release 5.0 is near, so I would like to push it upstream. Does it sound 
good to you?


https://reviews.llvm.org/D33470



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


[PATCH] D47103: Implement strip.invariant.group

2018-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

friendly ping


Repository:
  rL LLVM

https://reviews.llvm.org/D47103



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-02 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

@rjmccall @rsmith friendly ping


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-06-11 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 150735.
Prazek added a comment.

- Fixed templates


Repository:
  rL LLVM

https://reviews.llvm.org/D47108

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/CodeGenOptions.def
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CodeGenCXX/vtable-available-externally.cpp

Index: clang/test/CodeGenCXX/vtable-available-externally.cpp
===
--- clang/test/CodeGenCXX/vtable-available-externally.cpp
+++ clang/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases
 // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
@@ -13,10 +14,13 @@
 // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable
+
 
 #include 
 
 // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant
 namespace Test1 {
 
 struct A {
@@ -213,14 +217,16 @@
 
 // because A's key function is defined here, vtable is generated in this TU
 // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 struct A {
   virtual void foo();
   virtual void bar();
 };
 void A::foo() {}
 
 // Because key function is inline we will generate vtable as linkonce_odr.
 // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 struct D : A {
   void bar();
 };
@@ -237,14 +243,17 @@
 // can't guarantee that we will be able to refer to bar from name
 // so (at the moment) we can't emit vtable available_externally.
 // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant
 struct C : A {
   void bar() {}   // defined in body - not key function
   virtual inline void gar();  // inline in body - not key function
   virtual void car();
 };
 
 // no key function, vtable will be generated everywhere it will be used
 // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
+
 struct E : A {};
 
 void g(A& a) {
@@ -298,11 +307,13 @@
 namespace Test12 {
 
 // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant
 struct A {
   virtual void foo();
   virtual ~A() {}
 };
 // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant
 struct B : A {
   void foo();
 };
@@ -319,6 +330,9 @@
 
 // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant
+
 struct A {
   virtual ~A();
 };
@@ -371,6 +385,8 @@
 // generate available_externally vtable for it.
 // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally
 
 struct S {
   __attribute__((visibility("hidden"))) virtual void doStuff();
@@ -395,6 +411,10 @@
 // This test checks if we emit vtables opportunistically.
 // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
 // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally
+// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev(
+// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev(
 
 struct A {
   virtual void key();
@@ -418,3 +43

[PATCH] D47103: Implement strip.invariant.group

2018-06-13 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

Friendly ping @hfinkel @rsmith


Repository:
  rL LLVM

https://reviews.llvm.org/D47103



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


[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables

2018-06-13 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Prazek marked an inline comment as done.
Closed by commit rC334600: Add -fforce-emit-vtables (authored by Prazek, 
committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D47108?vs=150735&id=151154#toc

Repository:
  rC Clang

https://reviews.llvm.org/D47108

Files:
  docs/ClangCommandLineReference.rst
  docs/ReleaseNotes.rst
  docs/UsersManual.rst
  include/clang/Basic/LangOptions.def
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGenCXX/vtable-available-externally.cpp

Index: docs/ClangCommandLineReference.rst
===
--- docs/ClangCommandLineReference.rst
+++ docs/ClangCommandLineReference.rst
@@ -1934,6 +1934,12 @@
 
 Enables whole-program vtable optimization. Requires -flto
 
+.. option:: -fforce-emit-vtables, -fno-force-emit-vtables
+
+In order to improve devirtualization, forces emitting of vtables even in
+modules where it isn't necessary. It causes more inline virtual functions
+to be emitted.
+
 .. option:: -fwrapv, -fno-wrapv
 
 Treat signed integer overflow as two's complement
Index: docs/UsersManual.rst
===
--- docs/UsersManual.rst
+++ docs/UsersManual.rst
@@ -1269,6 +1269,12 @@
devirtualization and virtual constant propagation, for classes with
:doc:`hidden LTO visibility `. Requires ``-flto``.
 
+.. option:: -fforce-emit-vtables
+
+   In order to improve devirtualization, forces emitting of vtables even in
+   modules where it isn't necessary. It causes more inline virtual functions
+   to be emitted.
+
 .. option:: -fno-assume-sane-operator-new
 
Don't assume that the C++'s new operator is sane.
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -112,6 +112,12 @@
   'no-strict' option, Clang attempts to match the overflowing behavior of the
   target's native float-to-int conversion instructions.
 
+- :option: `-fforce-emit-vtables` and `-fno-force-emit-vtables`.
+
+   In order to improve devirtualization, forces emitting of vtables even in
+   modules where it isn't necessary. It causes more inline virtual functions
+   to be emitted.
+
 - ...
 
 Deprecated Compiler Flags
Index: include/clang/Basic/LangOptions.def
===
--- include/clang/Basic/LangOptions.def
+++ include/clang/Basic/LangOptions.def
@@ -293,6 +293,8 @@
 "controls whether to always emit intrinsic calls to "
 "__xray_typedevent(...) builtin.")
 
+LANGOPT(ForceEmitVTables, 1, 0, "whether to emit all vtables")
+
 BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0,
"allow editor placeholders in source")
 
Index: include/clang/Frontend/CodeGenOptions.def
===
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -332,6 +332,10 @@
 /// Whether to embed source in DWARF debug line section.
 CODEGENOPT(EmbedSource, 1, 0)
 
+/// Whether to emit all vtables
+CODEGENOPT(ForceEmitVTables, 1, 0)
+
+
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
 #undef VALUE_CODEGENOPT
Index: include/clang/Driver/Options.td
===
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1688,6 +1688,11 @@
   HelpText<"Enables whole-program vtable optimization. Requires -flto">;
 def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group,
   Flags<[CoreOption]>;
+def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group,
+Flags<[CC1Option]>,
+HelpText<"Emits more virtual tables to improve devirtualization">;
+def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group,
+  Flags<[CoreOption]>;
 def fwrapv : Flag<["-"], "fwrapv">, Group, Flags<[CC1Option]>,
   HelpText<"Treat signed integer overflow as two's complement">;
 def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags<[CC1Option]>,
Index: test/CodeGenCXX/vtable-available-externally.cpp
===
--- test/CodeGenCXX/vtable-available-externally.cpp
+++ test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases
 // RUN: FileCheck --check-pref

[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 5 inline comments as done.
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1623
+  const CXXRecordDecl *SourceClassDecl =
+  E->getType().getTypePtr()->getPointeeCXXRecordDecl();
+  const CXXRecordDecl *DstClassDecl = DestTy->getPointeeCXXRecordDecl();

rjmccall wrote:
> Unnecessary `getTypePtr()`.
getType returns QualType and it does not have getPointeeCXXRecordDecl. Am I 
missing something?



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1647
+  }
+}
+

rjmccall wrote:
> Incidentally, how do you protect against code like this?
> 
>   A *ptr;
>   reinterpret_cast(ptr) = new B();
>   ptr->foo();
> 
> Presumably there needs to be a launder/strip here, but I guess it would have 
> to be introduced by the middle-end when forwarding the store?  The way I've 
> written this is an aliasing violation, but (1) I assume your pass isn't 
> disabled whenever strict-aliasing is disabled and (2) you can do this with a 
> memcpy and still pretty reliably expect that LLVM will be able to eventually 
> forward the store.
Can you add more info on what is A and B so I can make sure I understand it 
correctly?
Is the prefix of the layout the same for both, but they are not in the 
hierarchy?

I haven't thought about the strict aliasing. I think the only sane way would be 
to require strict aliasing for the strict vtable pointers.


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 151575.
Prazek added a comment.

Refactor


Repository:
  rL LLVM

https://reviews.llvm.org/D47299

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/AST/Type.h
  clang/lib/AST/Type.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/test/CodeGenCXX/strict-vtable-pointers.cpp

Index: clang/test/CodeGenCXX/strict-vtable-pointers.cpp
===
--- clang/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ clang/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -5,7 +5,8 @@
 // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
 
 typedef __typeof__(sizeof(0)) size_t;
-void *operator new(size_t, void*) throw();
+void *operator new(size_t, void *) throw();
+using uintptr_t = unsigned long long;
 
 struct NotTrivialDtor {
   ~NotTrivialDtor();
@@ -17,7 +18,7 @@
 };
 
 struct DynamicDerived : DynamicBase1 {
-  void foo();
+  void foo() override;
 };
 
 struct DynamicBase2 {
@@ -28,8 +29,8 @@
 };
 
 struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
-  virtual void foo();
-  virtual void bar();
+  void foo() override;
+  void bar() override;
 };
 
 struct StaticBase {
@@ -47,9 +48,8 @@
 struct DynamicFromVirtualStatic2 : virtual StaticBase {
 };
 
-struct DynamicFrom2Virtuals :
-DynamicFromVirtualStatic1,
-DynamicFromVirtualStatic2 {
+struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
+  DynamicFromVirtualStatic2 {
 };
 
 // CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
@@ -89,7 +89,6 @@
 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 // CHECK-NEW-LABEL: define void @_Z9Pointers1v()
 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
@@ -134,7 +133,6 @@
 // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
 // CHECK-CTORS-LABEL: {{^}}}
 
-
 struct DynamicDerived;
 
 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
@@ -164,14 +162,12 @@
 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
 
-
 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
 // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
 // CHECK-CTORS: %[[THIS12:.*]]  = bitcast i8* %[[THIS_ADD]] to i32 (...)***
 
-
 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
 // CHECK-CTORS-LABEL: {{^}}}
 
@@ -182,9 +178,10 @@
 
 struct A {
   virtual void foo();
+  int m;
 };
 struct B : A {
-  virtual void foo();
+  void foo() override;
 };
 
 union U {
@@ -209,7 +206,7 @@
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
   g2(&u->b);
-  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U* 
+  // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
   changeToA(u);
   // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
   // call void @_Z2g2P1A(%struct.A* %a)
@@ -294,21 +291,287 @@
   take(u.v3);
 }
 
+// CHECK-NEW-LABEL: define void @_Z7comparev()
+void compare() {
+  A *a = new A;
+  a->foo();
+  // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
+  A *b = new (a) B;
+
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
+  if (a == b)
+b->foo();
+}
+
+// CHECK-NEW-LABEL: compare2
+bool compare2(A *a, A *a2) {
+  // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
+  // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
+  // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
+  // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]]
+  return a < a2;
+}
+// CHECK-NEW-LABEL: compareIntPointers
+bool compareIntPointers(int *a, int *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+
+struct HoldingOtherVirtuals {
+  B b;
+};
+
+// There is no need to add barriers for comparision of pointer to classes
+// that are not dynamic.
+// CHECK-NEW-LABEL: compare5
+bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+  return a == b;
+}
+// CHECK-NEW-LABEL: compareNull
+bool compareNull(A *a) {
+  // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
+
+  if (a != nullpt

[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1633
+  bool DstMayNotBeDynamic =
+  !DstClassDecl || DstClassDecl->mayBeNotDynamicClass();
+  if (SourceMayBeNotDynamic && DstMayBeDynamic) {

rjmccall wrote:
> If you made a couple of tiny helper functions here that you could invoke on 
> either `SourceClassDecl` or `DstClassDecl`, you could avoid some redundant 
> logic and also make the calls self-documenting enough to legibly inline into 
> the `if`-conditions.
> 
> ...in fact, since you start from a QualType in every case, maybe you should 
> just define the helper as a method there.
oh yea, it is definitely better!


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked an inline comment as done.
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1624
+  E->getType().getTypePtr()->getPointeeCXXRecordDecl();
+  const CXXRecordDecl *DstClassDecl = DestTy->getPointeeCXXRecordDecl();
+

rjmccall wrote:
> The opposite of `Dst` is `Src`.  Alternatively, the opposite of `Source` is 
> `Destination` (or `Result`).  Please pick.
Not sure if it still holds (if the DestTy should be DstTy, but I haven't 
declared it myself)


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-06-16 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1647
+  }
+}
+

rjmccall wrote:
> Prazek wrote:
> > rjmccall wrote:
> > > Incidentally, how do you protect against code like this?
> > > 
> > >   A *ptr;
> > >   reinterpret_cast(ptr) = new B();
> > >   ptr->foo();
> > > 
> > > Presumably there needs to be a launder/strip here, but I guess it would 
> > > have to be introduced by the middle-end when forwarding the store?  The 
> > > way I've written this is an aliasing violation, but (1) I assume your 
> > > pass isn't disabled whenever strict-aliasing is disabled and (2) you can 
> > > do this with a memcpy and still pretty reliably expect that LLVM will be 
> > > able to eventually forward the store.
> > Can you add more info on what is A and B so I can make sure I understand it 
> > correctly?
> > Is the prefix of the layout the same for both, but they are not in the 
> > hierarchy?
> > 
> > I haven't thought about the strict aliasing. I think the only sane way 
> > would be to require strict aliasing for the strict vtable pointers.
> It's whatever case you're worried about such that you have to launder member 
> accesses and bitcasts.
> 
> And like I mentioned, relying on strict aliasing isn't enough because you can 
> do it legally with memcpy.  Maybe it's okay to consider it UB?  I'm not sure 
> about that.
AFAIK reinterpreting one class as another is UB if they are not in hierarchy 
(especially calling virtual function on reinterpreted class), not sure if 
strict aliasing should allow it anyway (if it would be a hand written custom 
vptr then it should be ok with strict aliasing turned off, but with vptr I 
don't think it is legal).
@rsmith Can you comment on that?


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-26 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 9 inline comments as done.
Prazek added a comment.

Sorry for so late fixes, but it would be good to put it in 5.0


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-26 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 112805.
Prazek added a comment.

remove empty line


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,7 +2472,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,7 +2472,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-26 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 112804.
Prazek added a comment.

Enable it on every platform


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp
  utils/TableGen/ClangAttrEmitter.cpp


Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2680,6 +2680,7 @@
 }
 Test += ")";
   }
+
 }
 
 static void GenerateHasAttrSpellingStringSwitch(
Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,7 +2472,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }


Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2680,6 +2680,7 @@
 }
 Test += ")";
   }
+
 }
 
 static void GenerateHasAttrSpellingStringSwitch(
Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,7 +2472,7 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-28 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

In https://reviews.llvm.org/D33852#853982, @aaron.ballman wrote:

> In https://reviews.llvm.org/D33852#853410, @Prazek wrote:
>
> > Sorry for so late fixes, but it would be good to put it in 5.0
>
>
> I do not think this should be in 5.0, as I believe we're only accepting 
> regression fixes at this point.


This is a regression. __declspec(selectany) works completely fine on linux with 
4.0. Without it clang-5.0 will be useless for any major windows project 
compiled on linux.


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

In https://reviews.llvm.org/D33852#854213, @aaron.ballman wrote:

> In https://reviews.llvm.org/D33852#854176, @Prazek wrote:
>
> > In https://reviews.llvm.org/D33852#853982, @aaron.ballman wrote:
> >
> > > In https://reviews.llvm.org/D33852#853410, @Prazek wrote:
> > >
> > > > Sorry for so late fixes, but it would be good to put it in 5.0
> > >
> > >
> > > I do not think this should be in 5.0, as I believe we're only accepting 
> > > regression fixes at this point.
> >
> >
> > This is a regression. __declspec(selectany) works completely fine on linux 
> > with 4.0. Without it clang-5.0 will be useless for any major windows 
> > project compiled on linux.
> >
> > edit:
> >  here is a regression: https://reviews.llvm.org/D32083
>
>
> This is also adding new functionality that has had zero testing because it 
> removes *all* target-specific checking for the attribute. Under the previous 
> functionality (changed in https://reviews.llvm.org/D32083), this still 
> required some mention of microsoft something (it went from requiring 
> microsoft extensions to be enabled to instead require a Windows target) -- 
> that's been entirely removed from this patch so now you can use this 
> attribute for all target architectures, so it's not purely fixing a 
> regression. Given how late we are in the release cycle, I am uncomfortable 
> with this going in to 5.0, but I'd have no problems letting it bake for a bit 
> and putting it into 5.1 (or 5.0.1, however we're naming bug releases these 
> days).


I don't think this is the case - @rnk said that

> I guess so. I think __declspec spellings are controlled by 
> -fdeclspec-extensions, which is off by default except on Windows & PS4. If we 
> remove this constraint, __attribute__((selectany)) will become available 
> everywhere. I guess that's OK.

So we went from requiring ms extension to not requiring ms extension but only 
working on windows and now 
we require -fdeclspec-extensions or -fms-extensions on every platform other 
than windows and ps4.


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-29 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 113189.
Prazek added a comment.

- Add documentation


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,10 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = ["This makes global symbol have a weak definition,
+meaning that the linker can select any definition."];
 }
 
 def Thread : Attr {


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,10 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = ["This makes global symbol have a weak definition,
+meaning that the linker can select any definition."];
 }
 
 def Thread : Attr {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-30 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: include/clang/Basic/Attr.td:2477
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
   let Documentation = [Undocumented];
 }

aaron.ballman wrote:
> aaron.ballman wrote:
> > Since we're drastically modifying what platforms this is supported on, can 
> > you please add documentation for this attribute?
> This documentation isn't correct. Please see the other attributes (and 
> AttrDocs.td) for an example of how to add the documentation.
Yes, sorry for that. I haven't compile it before sending patch. Is the 
documentation string good at least?


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-30 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 113357.
Prazek added a comment.

- docs fixes


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,9 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition
+   (link-once), meaning that the linker can select any definition.}];
+}
\ No newline at end of file
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,9 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition
+   (link-once), meaning that the linker can select any definition.}];
+}
\ No newline at end of file
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-30 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 113359.
Prazek added a comment.

- docs fixes


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,12 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition
+   (link-once), meaning that the linker can select any definition.
+   For more information see:
+   
https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
+   }];
+}
\ No newline at end of file
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,12 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition
+   (link-once), meaning that the linker can select any definition.
+   For more information see:
+   https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
+   }];
+}
\ No newline at end of file
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {
_

[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-31 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: include/clang/Basic/AttrDocs.td:3154
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition

aaron.ballman wrote:
> I think you need to set the `Category` as well.
> 
> To test this you should run something like (replacing  and fixing up 
> path separators as needed):
> ```
> clang-tblgen -gen-attr-docs -I \llvm\tools\clang\include 
> \llvm\tools\clang\include\clang\Basic\Attr.td -o 
> \llvm\tools\clang\docs\AttributeReference.rst
> ```
Thanks for the testing command. Should I do anything in order to check if docs 
build?
I enabled docs with -DLLVM_BUILD_DOCS=ON, and I have sphinx. Everything builds, 
but I don't see docs anywhere.

the docs looks like this:
+selectany (gnu::selectany)
+--
+.. csv-table:: Supported Syntaxes
+   :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma", "Pragma clang 
attribute"
+
+   "X","X","X","", "", ""
+
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+.. _`linkonce`: https://llvm.org/docs/LangRef.html#linkage-types
+), allowing the linker to select any definition.
+
+For more information see
+.. `gcc documentation`: 
https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
+


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-08-31 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 113507.
Prazek marked 4 inline comments as done.
Prazek added a comment.

- docs fixes


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,17 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+.. _`linkonce`: https://llvm.org/docs/LangRef.html#linkage-types
+), allowing the linker to select any definition.
+
+For more information see
+.. `gcc documentation`: 
https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
+   }];
+}
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,17 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+.. _`linkonce`: https://llvm.org/docs/LangRef.html#linkage-types
+), allowing the linker to select any definition.
+
+For more information see
+.. `gcc documentation`: https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
+   }];
+}
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+d

[PATCH] D33852: Enable __declspec(selectany) on linux

2017-09-05 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked an inline comment as done.
Prazek added inline comments.



Comment at: include/clang/Basic/AttrDocs.td:3154
+
+def SelectAnyDocs : Documentation {
+   let Content = [{This attribute makes global symbol have a weak definition

aaron.ballman wrote:
> Prazek wrote:
> > aaron.ballman wrote:
> > > I think you need to set the `Category` as well.
> > > 
> > > To test this you should run something like (replacing  and fixing 
> > > up path separators as needed):
> > > ```
> > > clang-tblgen -gen-attr-docs -I \llvm\tools\clang\include 
> > > \llvm\tools\clang\include\clang\Basic\Attr.td -o 
> > > \llvm\tools\clang\docs\AttributeReference.rst
> > > ```
> > Thanks for the testing command. Should I do anything in order to check if 
> > docs build?
> > I enabled docs with -DLLVM_BUILD_DOCS=ON, and I have sphinx. Everything 
> > builds, but I don't see docs anywhere.
> > 
> > the docs looks like this:
> > +selectany (gnu::selectany)
> > +--
> > +.. csv-table:: Supported Syntaxes
> > +   :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma", "Pragma 
> > clang attribute"
> > +
> > +   "X","X","X","", "", ""
> > +
> > +This attribute appertains to a global symbol, causing it to have a weak
> > +definition (
> > +.. _`linkonce`: https://llvm.org/docs/LangRef.html#linkage-types
> > +), allowing the linker to select any definition.
> > +
> > +For more information see
> > +.. `gcc documentation`: 
> > https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Microsoft-Windows-Variable-Attributes.html
> > +
> > Thanks for the testing command. Should I do anything in order to check if 
> > docs build?
> 
> On Windows, I use `make html` within the clang\docs directory to generate the 
> actual sphinx docs -- that will tell you if there are sphinx issues. Be sure 
> you do *not* commit the AttributeReference.rst file that it generates, 
> however.
I tried building docs but it doesn't seem that there is any target like "html". 
Do you know if there is documentation on how to build docs? I couldn't find any.


https://reviews.llvm.org/D33852



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


[PATCH] D33852: Enable __declspec(selectany) on linux

2017-09-14 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 115243.
Prazek marked 8 inline comments as done.
Prazek added a comment.

Fixed links


https://reviews.llvm.org/D33852

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  test/Sema/attr-selectany.c
  test/SemaCXX/attr-selectany.cpp


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,18 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+`linkonce `_
+), allowing the linker to select any definition.
+
+For more information see
+`gcc documentation 
`_
+or `msvc documentation `_.
+}];
+}
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {


Index: test/SemaCXX/attr-selectany.cpp
===
--- test/SemaCXX/attr-selectany.cpp
+++ test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility -fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
Index: test/Sema/attr-selectany.c
===
--- test/Sema/attr-selectany.c
+++ test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: include/clang/Basic/AttrDocs.td
===
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -3149,3 +3149,18 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+`linkonce `_
+), allowing the linker to select any definition.
+
+For more information see
+`gcc documentation `_
+or `msvc documentation `_.
+}];
+}
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ inclu

[PATCH] D33852: Enable __declspec(selectany) on linux

2017-09-14 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL313278: Enable __declspec(selectany) on any platform 
(authored by Prazek).

Repository:
  rL LLVM

https://reviews.llvm.org/D33852

Files:
  cfe/trunk/include/clang/Basic/Attr.td
  cfe/trunk/include/clang/Basic/AttrDocs.td
  cfe/trunk/test/Sema/attr-selectany.c
  cfe/trunk/test/SemaCXX/attr-selectany.cpp


Index: cfe/trunk/include/clang/Basic/AttrDocs.td
===
--- cfe/trunk/include/clang/Basic/AttrDocs.td
+++ cfe/trunk/include/clang/Basic/AttrDocs.td
@@ -3192,3 +3192,18 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+`linkonce `_
+), allowing the linker to select any definition.
+
+For more information see
+`gcc documentation 
`_
+or `msvc documentation `_.
+}];
+}
Index: cfe/trunk/include/clang/Basic/Attr.td
===
--- cfe/trunk/include/clang/Basic/Attr.td
+++ cfe/trunk/include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {
Index: cfe/trunk/test/Sema/attr-selectany.c
===
--- cfe/trunk/test/Sema/attr-selectany.c
+++ cfe/trunk/test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we 
need extern in C++
 
Index: cfe/trunk/test/SemaCXX/attr-selectany.cpp
===
--- cfe/trunk/test/SemaCXX/attr-selectany.cpp
+++ cfe/trunk/test/SemaCXX/attr-selectany.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-compatibility -fms-extensions 
-fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -fms-compatibility 
-fms-extensions -fsyntax-only -verify -std=c++11 %s
+
 // MSVC produces similar diagnostics.
 
 __declspec(selectany) void foo() { } // expected-error{{'selectany' can only 
be applied to data items with external linkage}}


Index: cfe/trunk/include/clang/Basic/AttrDocs.td
===
--- cfe/trunk/include/clang/Basic/AttrDocs.td
+++ cfe/trunk/include/clang/Basic/AttrDocs.td
@@ -3192,3 +3192,18 @@
 ensure that this class cannot be subclassed.
   }];
 }
+
+
+def SelectAnyDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+This attribute appertains to a global symbol, causing it to have a weak
+definition (
+`linkonce `_
+), allowing the linker to select any definition.
+
+For more information see
+`gcc documentation `_
+or `msvc documentation `_.
+}];
+}
Index: cfe/trunk/include/clang/Basic/Attr.td
===
--- cfe/trunk/include/clang/Basic/Attr.td
+++ cfe/trunk/include/clang/Basic/Attr.td
@@ -2472,9 +2472,9 @@
   let Documentation = [DLLImportDocs];
 }
 
-def SelectAny : InheritableAttr, TargetSpecificAttr {
+def SelectAny : InheritableAttr {
   let Spellings = [Declspec<"selectany">, GCC<"selectany">];
-  let Documentation = [Undocumented];
+  let Documentation = [SelectAnyDocs];
 }
 
 def Thread : Attr {
Index: cfe/trunk/test/Sema/attr-selectany.c
===
--- cfe/trunk/test/Sema/attr-selectany.c
+++ cfe/trunk/test/Sema/attr-selectany.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -triple x86_64-win32 -fdeclspec -verify %s
 // RUN: %clang_cc1 -triple x86_64-mingw32 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -verify -fdeclspec %s
+// RUN: %clang_cc1 -triple x86_64-win32-macho -verify -fdeclspec %s
 
 extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
 
Index: cfe/trunk/test/SemaCXX/attr-selectany.cpp
=

[PATCH] D33852: Enable __declspec(selectany) on linux

2017-09-14 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 3 inline comments as done.
Prazek added a comment.

Thanks for help. I checked and docs build and looks legit. Sorry that it took 
so long.


Repository:
  rL LLVM

https://reviews.llvm.org/D33852



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


[PATCH] D53295: Mark store and load of block invoke function as invariant.group

2019-06-14 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: lib/CodeGen/CGBlocks.cpp:1318
+CGM.getModule().getMDKindID("invariant.load"),
+llvm::MDNode::get(getLLVMContext(), None));
+

rjmccall wrote:
> yaxunl wrote:
> > rjmccall wrote:
> > > OpenCL blocks are still potentially function-local, right?  I don't think 
> > > you're allowed to put `invariant.load` on something that's visibly 
> > > initialized, even if it's visibly initialized to the same thing every 
> > > time.  The problem is that `invariant.load` could allow the load to be 
> > > hoisted above the initialization.
> > > 
> > > If you can solve that problem, you can make this non-OpenCL-specific.
> > It seems that invariant.load implies the pointer is invariant in the whole 
> > module, disregarding the store to it, which is not suitable for this case.
> > 
> > In this case what I need is that after the first store to the pointer, 
> > every load does not change.
> > 
> > It seems invariant.group can be used for this.
> Hmm.  I guess `invariant.group` does what you need because LLVM will probably 
> unify the GEPs to extract the function-pointer field if they appear in the 
> same function, and there are no launderings of that pointer.
> 
> CC'ing Piotr to get his opinion about whether this is a correct use of 
> `invariant.group`.  Piotr, we have a struct-typed alloca that we initialize 
> in a probably-dominating position.  A pointer to the struct can be passed off 
> to other contexts which we can't necessarily analyze, blocking normal 
> optimization; however, we know that this struct can (mostly) not be legally 
> modified after initialization.  We're marking one of the initializing stores 
> as well as the load of the corresponding field when it's used.  These two 
> places are completely separate and will perform their own GEPs, but because 
> we don't emit any `launder`s on the struct, LLVM will likely unify the GEPs 
> if they appear in the same function, allowing `invariant.group`-based 
> optimizations to apply.  Does this seem reasonable?
Yep, seems totally reasonable. Sorry for such a late response, I just have open 
reviews and saw that.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53295/new/

https://reviews.llvm.org/D53295



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


[PATCH] D47103: Implement strip.invariant.group

2018-07-01 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Prazek marked an inline comment as done.
Closed by commit rL336073: Implement strip.invariant.group (authored by Prazek, 
committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D47103?vs=148313&id=153664#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D47103

Files:
  llvm/trunk/docs/LangRef.rst
  llvm/trunk/include/llvm/IR/IRBuilder.h
  llvm/trunk/include/llvm/IR/Intrinsics.td
  llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
  llvm/trunk/lib/Analysis/ConstantFolding.cpp
  llvm/trunk/lib/Analysis/ValueTracking.cpp
  llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
  llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
  llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/trunk/lib/IR/Value.cpp
  llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
  llvm/trunk/test/Analysis/ValueTracking/invariant.group.ll
  llvm/trunk/test/CodeGen/Generic/intrinsics.ll
  llvm/trunk/test/Other/invariant.group.ll
  llvm/trunk/test/Other/launder.invariant.group.ll
  llvm/trunk/test/Transforms/CodeGenPrepare/invariant.group.ll
  llvm/trunk/test/Transforms/DeadStoreElimination/launder.invariant.group.ll
  llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/trunk/test/Transforms/GVN/invariant.group.ll
  llvm/trunk/test/Transforms/GlobalOpt/invariant.group.barrier.ll
  llvm/trunk/test/Transforms/GlobalOpt/invariant.group.ll
  llvm/trunk/test/Transforms/InstCombine/invariant.group.ll
  llvm/trunk/test/Transforms/NewGVN/invariant.group.ll

Index: llvm/trunk/lib/IR/Value.cpp
===
--- llvm/trunk/lib/IR/Value.cpp
+++ llvm/trunk/lib/IR/Value.cpp
@@ -521,7 +521,8 @@
 // but it can't be marked with returned attribute, that's why it needs
 // special case.
 if (StripKind == PSK_ZeroIndicesAndAliasesAndInvariantGroups &&
-CS.getIntrinsicID() == Intrinsic::launder_invariant_group) {
+(CS.getIntrinsicID() == Intrinsic::launder_invariant_group ||
+ CS.getIntrinsicID() == Intrinsic::strip_invariant_group)) {
   V = CS.getArgOperand(0);
   continue;
 }
Index: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
===
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1437,6 +1437,7 @@
 return true;
   }
   case Intrinsic::launder_invariant_group:
+  case Intrinsic::strip_invariant_group:
   case Intrinsic::expect: {
 unsigned ResultReg = getRegForValue(II->getArgOperand(0));
 if (!ResultReg)
Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5768,6 +5768,7 @@
   case Intrinsic::annotation:
   case Intrinsic::ptr_annotation:
   case Intrinsic::launder_invariant_group:
+  case Intrinsic::strip_invariant_group:
 // Drop the intrinsic, but forward the value
 setValue(&I, getValue(I.getOperand(0)));
 return nullptr;
Index: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
===
--- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
+++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
@@ -1702,6 +1702,7 @@
   return true;
 }
 case Intrinsic::launder_invariant_group:
+case Intrinsic::strip_invariant_group:
   II->replaceAllUsesWith(II->getArgOperand(0));
   II->eraseFromParent();
   return true;
Index: llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
===
--- llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -457,6 +457,7 @@
   case Intrinsic::invariant_start:
   case Intrinsic::invariant_end:
   case Intrinsic::launder_invariant_group:
+  case Intrinsic::strip_invariant_group:
   case Intrinsic::objectsize:
 return true;
   default:
@@ -882,6 +883,7 @@
 case Intrinsic::invariant_start:
 case Intrinsic::invariant_end:
 case Intrinsic::launder_invariant_group:
+case Intrinsic::strip_invariant_group:
   Intr->eraseFromParent();
   // FIXME: I think the invariant marker should still theoretically apply,
   // but the intrinsics need to be changed to accept pointers with any
Index: llvm/trunk/lib/Analysis/ValueTracking.cpp
===
--- llvm/trunk/lib/Analysis/ValueTracking.cpp
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp
@@ -3404,8 +3404,9 @@
 }
 
 bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
-  ImmutableCallSite CS) {
-  return CS.getIntrinsicID() == Intrinsic::launder_invariant_group;
+ImmutableCallSite CS) {
+  return CS.getIntrinsicID(

[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-07-01 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 10 inline comments as done.
Prazek added inline comments.



Comment at: clang/lib/CodeGen/CGExprScalar.cpp:1647
+  }
+}
+

rsmith wrote:
> Prazek wrote:
> > rjmccall wrote:
> > > Prazek wrote:
> > > > rjmccall wrote:
> > > > > Incidentally, how do you protect against code like this?
> > > > > 
> > > > >   A *ptr;
> > > > >   reinterpret_cast(ptr) = new B();
> > > > >   ptr->foo();
> > > > > 
> > > > > Presumably there needs to be a launder/strip here, but I guess it 
> > > > > would have to be introduced by the middle-end when forwarding the 
> > > > > store?  The way I've written this is an aliasing violation, but (1) I 
> > > > > assume your pass isn't disabled whenever strict-aliasing is disabled 
> > > > > and (2) you can do this with a memcpy and still pretty reliably 
> > > > > expect that LLVM will be able to eventually forward the store.
> > > > Can you add more info on what is A and B so I can make sure I 
> > > > understand it correctly?
> > > > Is the prefix of the layout the same for both, but they are not in the 
> > > > hierarchy?
> > > > 
> > > > I haven't thought about the strict aliasing. I think the only sane way 
> > > > would be to require strict aliasing for the strict vtable pointers.
> > > It's whatever case you're worried about such that you have to launder 
> > > member accesses and bitcasts.
> > > 
> > > And like I mentioned, relying on strict aliasing isn't enough because you 
> > > can do it legally with memcpy.  Maybe it's okay to consider it UB?  I'm 
> > > not sure about that.
> > AFAIK reinterpreting one class as another is UB if they are not in 
> > hierarchy (especially calling virtual function on reinterpreted class), not 
> > sure if strict aliasing should allow it anyway (if it would be a hand 
> > written custom vptr then it should be ok with strict aliasing turned off, 
> > but with vptr I don't think it is legal).
> > @rsmith Can you comment on that?
> OK, here's how I think about what we're doing here:
> 
> We view the IR-level pointer value for a pointer to a dynamic class type as 
> being a fat pointer, containing the actual pointer value and also a tag 
> indicating the dynamic type of the object (only notionally, though -- the 
> actual bit representation of the pointer doesn't include the extra 
> information, but we don't ever emit IR that inspects the bit representation 
> of the fat pointer to avoid exposing that fact). In that model, if you try to 
> type pun between a pointer to a dynamic class type and a pointer to a 
> non-dynamic-class type, that can't be expected to work because the (notional) 
> value is different, much as type punning between a derived and base class 
> pointer wouldn't work for a pointer to something other than a base class at 
> offset zero.
> 
> I think @rjmccall's example is OK, because both `A` and `B` would need to be 
> dynamic class types in a hierarchy to work, and that means we'd be using the 
> same notional pointer representation. A slight variation of that example:
> 
> ```
> struct A {};
> struct B : A { virtual void f(); };
> struct C : B { void f(); } c;
> A *p = &c;
> B *q;
> memcpy(&q, &p, sizeof(B*)); // or q = std::bit_cast(p);
> q->f();
> ```
> 
> ... would be UB, because the representation of an `A*` and a `B*` are 
> different (a `B*` contains a tag and an `A*` does not).
Does this answer satisfy you John? Can I push it to trunk?


Repository:
  rL LLVM

https://reviews.llvm.org/D47299



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


[PATCH] D47299: [CodeGenCXX] Emit strip.invariant.group with -fstrict-vtable-pointers

2018-07-02 Thread Piotr Padlewski via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rC336137: [CodeGenCXX] Emit strip.invariant.group with 
-fstrict-vtable-pointers (authored by Prazek, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D47299?vs=151575&id=153767#toc

Repository:
  rC Clang

https://reviews.llvm.org/D47299

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/Type.h
  lib/AST/Type.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/CodeGenCXX/strict-vtable-pointers.cpp

Index: lib/CodeGen/CGExpr.cpp
===
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3870,6 +3870,18 @@
   }
 
   Address addr = base.getAddress();
+  if (auto *ClassDef = dyn_cast(rec)) {
+if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ClassDef->isDynamicClass()) {
+  // Getting to any field of dynamic object requires stripping dynamic
+  // information provided by invariant.group.  This is because accessing
+  // fields may leak the real address of dynamic object, which could result
+  // in miscompilation when leaked pointer would be compared.
+  auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer());
+  addr = Address(stripped, addr.getAlignment());
+}
+  }
+
   unsigned RecordCVR = base.getVRQualifiers();
   if (rec->isUnion()) {
 // For unions, there is no pointer adjustment.
Index: lib/CodeGen/CGExprScalar.cpp
===
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -1621,6 +1621,24 @@
   CE->getLocStart());
 }
 
+if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+  const QualType SrcType = E->getType();
+
+  if (SrcType.mayBeNotDynamicClass() && DestTy.mayBeDynamicClass()) {
+// Casting to pointer that could carry dynamic information (provided by
+// invariant.group) requires launder.
+Src = Builder.CreateLaunderInvariantGroup(Src);
+  } else if (SrcType.mayBeDynamicClass() && DestTy.mayBeNotDynamicClass()) {
+// Casting to pointer that does not carry dynamic information (provided
+// by invariant.group) requires stripping it.  Note that we don't do it
+// if the source could not be dynamic type and destination could be
+// dynamic because dynamic information is already laundered.  It is
+// because launder(strip(src)) == launder(src), so there is no need to
+// add extra strip before launder.
+Src = Builder.CreateStripInvariantGroup(Src);
+  }
+}
+
 return Builder.CreateBitCast(Src, DstTy);
   }
   case CK_AddressSpaceConversion: {
@@ -1757,12 +1775,31 @@
 llvm::Value* IntResult =
   Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
 
-return Builder.CreateIntToPtr(IntResult, DestLLVMTy);
+auto *IntToPtr = Builder.CreateIntToPtr(IntResult, DestLLVMTy);
+
+if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+  // Going from integer to pointer that could be dynamic requires reloading
+  // dynamic information from invariant.group.
+  if (DestTy.mayBeDynamicClass())
+IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr);
+}
+return IntToPtr;
   }
-  case CK_PointerToIntegral:
+  case CK_PointerToIntegral: {
 assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
-return Builder.CreatePtrToInt(Visit(E), ConvertType(DestTy));
+auto *PtrExpr = Visit(E);
+
+if (CGF.CGM.getCodeGenOpts().StrictVTablePointers) {
+  const QualType SrcType = E->getType();
 
+  // Casting to integer requires stripping dynamic information as it does
+  // not carries it.
+  if (SrcType.mayBeDynamicClass())
+PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr);
+}
+
+return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy));
+  }
   case CK_ToVoid: {
 CGF.EmitIgnoredExpr(E);
 return nullptr;
@@ -3241,6 +3278,23 @@
   Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp");
 } else {
   // Unsigned integers and pointers.
+
+  if (CGF.CGM.getCodeGenOpts().StrictVTablePointers &&
+  !isa(LHS) &&
+  !isa(RHS)) {
+
+// Dynamic information is required to be stripped for comparisons,
+// because it could leak the dynamic information.  Based on comparisons
+// of pointers to dynamic objects, the optimizer can replace one pointer
+// with another, which might be incorrect in presence of invariant
+// groups. Comparison with null is safe because null does not carry any
+// dynamic information.
+if (LHSTy.mayBeDynamicClass())
+  LHS = Builder.CreateStripInvariantGroup(LHS);
+if (RHSTy.mayBeDynamicClass())
+  RHS = Builder.CreateStripInv

[PATCH] D40062: Update tests for llvm.invariant.group.barrier becoming mangled

2017-11-16 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek accepted this revision.
Prazek added a comment.

LGTM


https://reviews.llvm.org/D40062



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


[PATCH] D27166: [clang-tidy] Enhance modernize-use-auto to templated function casts

2016-12-14 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek accepted this revision.
Prazek added a comment.
This revision is now accepted and ready to land.

LGTM, thanks for all the fixes.
Can you leave FIXIT comment somewhere in the code near the FixitHint about the 
function pointers?


https://reviews.llvm.org/D27166



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


[PATCH] D21298: [Clang-tidy] delete null check

2016-12-14 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: clang-tidy/readability/DeleteNullPointerCheck.cpp:33
+  Finder->addMatcher(
+  ifStmt(allOf(hasCondition(
+   anyOf(PointerCondition, BinaryPointerCheckCondition)),

I think allOf matcher is redundant here because ifStmt takes variadic number of 
arguments and matches only if all of them matches.


https://reviews.llvm.org/D21298



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


[PATCH] D27806: [clang-tidy] Add misc-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.
Prazek added reviewers: alexfh, malcolm.parsons.
Prazek added a subscriber: cfe-commits.
Herald added subscribers: JDevlieghere, mgorny.

Warns if algorithm is used with ``.begin()`` and ``.end()`` from
different variables.


https://reviews.llvm.org/D27806

Files:
  clang-tidy/ClangTidy.cpp
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/InvalidRangeCheck.cpp
  clang-tidy/misc/InvalidRangeCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-invalid-range.rst
  test/clang-tidy/misc-invalid-range.cpp

Index: test/clang-tidy/misc-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/misc-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - misc-invalid-range
+
+misc-invalid-range
+==
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -81,6 +81,12 @@
   Warns if an object is used after it has been moved, without an intervening
   reinitialization.
 
+- New `misc-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - `modernize-make-unique
   `_
   and `modernize-make-shared
Index: clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -20,6 +20,7 @@
 #include "InaccurateEraseCheck.h"
 #include "IncorrectRoundings.h"
 #include "InefficientAlgorithmCheck.h"
+#include "InvalidRangeCheck.h"
 #include "MacroParenthesesCheck.h"
 #include "MacroRepeatedSideEffectsCheck.h"
 #include "MisplacedConstCheck.h"
@@ -63,6 +64,7 @@
 CheckFactories.registerCheck("misc-argument-comment");
 CheckFactories.registerCheck(
 "misc-assert-side-effect");
+CheckFactories.registerCheck("misc-invalid-range");
 CheckFactories.registerCheck("misc-misplaced-const");
 CheckFactories.registerCheck(
 "misc-unconventional-assign-operator");
Index: clang-tidy/misc/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/misc/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-

[PATCH] D27813: [clang-tidy] fix missing anchor for MPI Module

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.
Prazek added reviewers: alexfh, Alexander_Droste, hokein.
Prazek added a subscriber: cfe-commits.
Herald added a subscriber: JDevlieghere.

MPIModule was not linked to plugins


https://reviews.llvm.org/D27813

Files:
  clang-tidy/plugin/ClangTidyPlugin.cpp


Index: clang-tidy/plugin/ClangTidyPlugin.cpp
===
--- clang-tidy/plugin/ClangTidyPlugin.cpp
+++ clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -108,6 +108,11 @@
 static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
 ModernizeModuleAnchorSource;
 
+// This anchor is used to force the linker to link the MPIModule.
+extern volatile int MPIModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
+  MPIModuleAnchorSource;
+
 // This anchor is used to force the linker to link the PerformanceModule.
 extern volatile int PerformanceModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =


Index: clang-tidy/plugin/ClangTidyPlugin.cpp
===
--- clang-tidy/plugin/ClangTidyPlugin.cpp
+++ clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -108,6 +108,11 @@
 static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
 ModernizeModuleAnchorSource;
 
+// This anchor is used to force the linker to link the MPIModule.
+extern volatile int MPIModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
+  MPIModuleAnchorSource;
+
 // This anchor is used to force the linker to link the PerformanceModule.
 extern volatile int PerformanceModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24487: [Clang] Fix some Clang-tidy modernize-use-bool-literals and Include What You Use warnings in AST; other minor fixes

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: lib/ASTMatchers/Dynamic/Parser.cpp:617
 
-}  // namespace dynamic
-}  // namespace ast_matchers
-}  // namespace clang
+} // end namespace dynamic
+} // end namespace ast_matchers

I think check should not warn in these cases.


Repository:
  rL LLVM

https://reviews.llvm.org/D24487



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


[PATCH] D27767: NFC Changes from modernize-use-auto

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp:106
 
   if (Optional P = Succ->getLocationAs())
+if (const auto *BO = P->getStmtAs()) {

malcolm.parsons wrote:
> The check missed this one.
I don't think it is miss if getLocationAs returns Optional, because that 
would suggest that it returns T


https://reviews.llvm.org/D27767



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


[PATCH] D27806: [clang-tidy] Add misc-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked an inline comment as done.
Prazek added inline comments.



Comment at: clang-tidy/ClangTidy.cpp:296
   const auto &RegisteredCheckers =
-  AnalyzerOptions::getRegisteredCheckers(/*IncludeExperimental=*/false);
+  AnalyzerOptions::getRegisteredCheckers(/*IncludeExperimental=*/true);
   bool AnalyzerChecksEnabled = false;

malcolm.parsons wrote:
> Is this intentional?
actually not, good catch. I was testing alpha checks



Comment at: docs/clang-tidy/checks/misc-invalid-range.rst:12
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).

malcolm.parsons wrote:
> What about the parallel versions of algorithms?
parallel version won't take iterator as first argument, so it won't gonna match.
I don't think it makes sense to support parallel algorithms now because they 
don't have that many users yet.


https://reviews.llvm.org/D27806



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


[PATCH] D27815: [clang-tidy] Add obvious module for obvious bugs

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek created this revision.
Prazek added reviewers: alexfh, malcolm.parsons.
Prazek added a subscriber: cfe-commits.
Herald added subscribers: JDevlieghere, mgorny.

Module for checks for obvious bugs that probably won't be found
in working code, but can be found while looking for an
obvious bug in broken code.


https://reviews.llvm.org/D27815

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/ObviousTidyModule.cpp
  clang-tidy/plugin/CMakeLists.txt
  clang-tidy/plugin/ClangTidyPlugin.cpp
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  docs/clang-tidy/index.rst

Index: docs/clang-tidy/index.rst
===
--- docs/clang-tidy/index.rst
+++ docs/clang-tidy/index.rst
@@ -65,6 +65,9 @@
 ``modernize-`` Checks that advocate usage of modern (currently "modern"
means "C++11") language constructs.
 ``mpi-``   Checks related to MPI (Message Passing Interface).
+``obvious-``   Checks for obvious bugs that probably won't be found
+   in working code, but can be found while looking for an
+   obvious bug in broken code.
 ``performance-``   Checks that target performance-related issues.
 ``readability-``   Checks that target readability-related issues that don't
relate to any particular coding style.
Index: clang-tidy/tool/ClangTidyMain.cpp
===
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -465,6 +465,11 @@
 static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
 MPIModuleAnchorSource;
 
+// This anchor is used to force the linker to link the ObviousModule.
+extern volatile int ObviousModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ObviousModuleAnchorDestination =
+  ObviousModuleAnchorSource;
+
 // This anchor is used to force the linker to link the PerformanceModule.
 extern volatile int PerformanceModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
Index: clang-tidy/tool/CMakeLists.txt
===
--- clang-tidy/tool/CMakeLists.txt
+++ clang-tidy/tool/CMakeLists.txt
@@ -21,6 +21,7 @@
   clangTidyMiscModule
   clangTidyModernizeModule
   clangTidyMPIModule
+  clangTidyObviousModule
   clangTidyPerformanceModule
   clangTidyReadabilityModule
   clangTooling
Index: clang-tidy/plugin/ClangTidyPlugin.cpp
===
--- clang-tidy/plugin/ClangTidyPlugin.cpp
+++ clang-tidy/plugin/ClangTidyPlugin.cpp
@@ -108,6 +108,11 @@
 static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
 ModernizeModuleAnchorSource;
 
+// This anchor is used to force the linker to link the ObviousModule.
+extern volatile int ObviousModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ObviousModuleAnchorDestination =
+ObviousModuleAnchorSource;
+
 // This anchor is used to force the linker to link the PerformanceModule.
 extern volatile int PerformanceModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
Index: clang-tidy/plugin/CMakeLists.txt
===
--- clang-tidy/plugin/CMakeLists.txt
+++ clang-tidy/plugin/CMakeLists.txt
@@ -15,6 +15,7 @@
   clangTidyLLVMModule
   clangTidyMiscModule
   clangTidyModernizeModule
+  clangTidyObviousModule
   clangTidyMPIModule
   clangTidyPerformanceModule
   clangTidyReadabilityModule
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- /dev/null
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -0,0 +1,38 @@
+//===--- ObviousTidyModule.cpp - clang-tidy ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace obvious {
+
+class ObviousModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+// Add obvious checks here.
+  }
+};
+
+// Register the ObviousModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add X("obvious-module",
+ "Add obvious checks.");
+
+} // namespace obvious
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ObviousModule.
+volatile int ObviousModuleAnchorSource = 0;
+
+} //

[PATCH] D27806: [clang-tidy] Add misc-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81597.
Prazek added a comment.

- Moved to obvious


https://reviews.llvm.org/D27806

Files:
  clang-tidy/ClangTidy.cpp
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-invalid-range.rst
  test/clang-tidy/misc-invalid-range.cpp

Index: test/clang-tidy/misc-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/misc-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - misc-invalid-range
+
+misc-invalid-range
+==
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -81,6 +81,12 @@
   Warns if an object is used after it has been moved, without an intervening
   reinitialization.
 
+- New `misc-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - `modernize-make-unique
   `_
   and `modernize-make-shared
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("misc-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+
+#include "../ClangTidy.h"
+#include 
+#include 
+
+namespace clang {
+namespace tidy {
+namespace obvious {
+
+/// F

[PATCH] D27806: [clang-tidy] Add misc-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 2 inline comments as done.
Prazek added inline comments.



Comment at: docs/ReleaseNotes.rst:84
 
+- New `misc-invalid-range
+  `_ 
check

malcolm.parsons wrote:
> "invalid" < "use"
You mean to change "invalid" to "use"?
It is not about using range, it is about finding broken range.


https://reviews.llvm.org/D27806



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


[PATCH] D27806: [clang-tidy] Add misc-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81600.
Prazek added a comment.

- Small fixes


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-invalid-range.rst
  test/clang-tidy/misc-invalid-range.cpp

Index: test/clang-tidy/misc-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/misc-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - misc-invalid-range
+
+misc-invalid-range
+==
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("misc-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked 3 inline comments as done.
Prazek added inline comments.



Comment at: docs/ReleaseNotes.rst:84
 
+- New `misc-invalid-range
+  `_ 
check

malcolm.parsons wrote:
> Prazek wrote:
> > malcolm.parsons wrote:
> > > "invalid" < "use"
> > You mean to change "invalid" to "use"?
> > It is not about using range, it is about finding broken range.
> The release notes should be in alphabetical order.
oh sure, fixed that.


https://reviews.llvm.org/D27806



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


[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81603.
Prazek marked 2 inline comments as done.
Prazek added a comment.

- Small fixes


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-invalid-range.rst
  test/clang-tidy/misc-invalid-range.cpp

Index: test/clang-tidy/misc-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/misc-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - misc-invalid-range
+
+misc-invalid-range
+==
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("obvious-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RA

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek marked an inline comment as done.
Prazek added a comment.

In https://reviews.llvm.org/D27806#623838, @malcolm.parsons wrote:

> What about arguments 3 and 4 of `std::list::splice(It, list, It, It)`?


I am aware of that, but I wanted to make a bunch of simple checks to fill 
obvious module without taking too much time.
So does FIXIT comment satisfies you for this patch?


https://reviews.llvm.org/D27806



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


[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81604.
Prazek added a comment.

- Small fixes


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-invalid-range.rst
  test/clang-tidy/misc-invalid-range.cpp

Index: test/clang-tidy/misc-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [misc-invalid-range]
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/misc-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/misc-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - misc-invalid-range
+
+misc-invalid-range
+==
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("obvious-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLA

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81606.
Prazek added a comment.

- Small fixes


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/obvious-invalid-range.rst
  test/clang-tidy/obvious-invalid-range.cpp

Index: test/clang-tidy/obvious-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/obvious-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s obvious-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [obvious-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/obvious-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/obvious-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - obvious-invalid-range
+
+obvious-invalid-range
+=
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@
misc-inaccurate-erase
misc-incorrect-roundings
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses
misc-macro-repeated-side-effects
misc-misplaced-const
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("obvious-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H
+#define LLVM_CLANG_TOO

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: test/clang-tidy/misc-invalid-range.cpp:41
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin 
and end from different objects [misc-invalid-range]

malcolm.parsons wrote:
> They're the same object...
Yep, but this type of code stinks, so it is probably a bug


https://reviews.llvm.org/D27806



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


[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added inline comments.



Comment at: docs/clang-tidy/checks/list.rst:68
misc-inefficient-algorithm
+   misc-invalid-range
misc-macro-parentheses

malcolm.parsons wrote:
> misc.
> add_new_check.py can fix it.
How? I added new check with this script, but unfortunatelly rename_check 
doesn't move check from module to module, so I have to make all the changes by 
hand.


https://reviews.llvm.org/D27806



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


[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81616.
Prazek marked an inline comment as done.
Prazek added a comment.

- removed misc


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/obvious-invalid-range.rst
  test/clang-tidy/obvious-invalid-range.cpp

Index: test/clang-tidy/obvious-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/obvious-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s obvious-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [obvious-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/obvious-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/obvious-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - obvious-invalid-range
+
+obvious-invalid-range
+=
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -118,6 +118,7 @@
modernize-use-using
mpi-buffer-deref
mpi-type-mismatch
+   obvious-invalid-range
performance-faster-string-find
performance-for-range-copy
performance-implicit-cast-in-loop
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  variables.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("obvious-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_O

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek updated this revision to Diff 81617.
Prazek marked an inline comment as done.
Prazek added a comment.

- Small fixes


https://reviews.llvm.org/D27806

Files:
  clang-tidy/obvious/CMakeLists.txt
  clang-tidy/obvious/InvalidRangeCheck.cpp
  clang-tidy/obvious/InvalidRangeCheck.h
  clang-tidy/obvious/ObviousTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/obvious-invalid-range.rst
  test/clang-tidy/obvious-invalid-range.cpp

Index: test/clang-tidy/obvious-invalid-range.cpp
===
--- /dev/null
+++ test/clang-tidy/obvious-invalid-range.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s obvious-invalid-range %t
+
+namespace std {
+
+template 
+OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+OutputIterator move(InputIterator first, InputIterator last, OutputIterator result) {
+  return result;
+}
+
+template 
+T move(T &&) { return T(); }
+
+template 
+void fill(InputIterator first, InputIterator last, const Val &v) {
+}
+
+template 
+class vector {
+public:
+  T *begin();
+  T *end();
+};
+}
+
+void test_copy() {
+  std::vector v, v2;
+  std::copy(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects [obvious-invalid-range]
+
+  std::copy(v.begin(), v.end(), v2.begin());
+}
+
+void test_move() {
+  std::vector v;
+  auto &v2 = v;
+  std::move(v.begin(), v2.end(), v2.begin());
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: call to algorithm with begin and end from different objects
+
+  std::move(v.begin(), v.end(), v2.begin());
+  std::move(v.begin());
+  test_copy();
+}
Index: docs/clang-tidy/checks/obvious-invalid-range.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/obvious-invalid-range.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - obvious-invalid-range
+
+obvious-invalid-range
+=
+
+This check finds invalid calls to algorithms with obviously invalid range of
+iterators like:
+
+.. code-block:: c++
+std::fill(v.begin(), v2.end(), it);
+
+It checks if first and second argument of call is method call to ``begin()``
+and ``end()``, but on different objects (having different name).
+
+By default it looks for all algorithms from . This can be
+changed by using ``AlgorithmNames`` option, where empty list means that any
+function name will be accepted.
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -118,6 +118,7 @@
modernize-use-using
mpi-buffer-deref
mpi-type-mismatch
+   obvious-invalid-range
performance-faster-string-find
performance-for-range-copy
performance-implicit-cast-in-loop
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@
 
   Flags MPI function calls with a buffer type and MPI data type mismatch.
 
+- New obvious module with checks for obvious bugs that probably won't be found
+  in working code, but can be found while looking for an obvious bug in broken
+  code.
+- New `obvious-invalid-range
+  `_ check
+
+  Warns if algorithm is used with ``.begin()`` and ``.end()`` from different
+  container.
+
 - New `performance-inefficient-string-concatenation
   `_ check
 
Index: clang-tidy/obvious/ObviousTidyModule.cpp
===
--- clang-tidy/obvious/ObviousTidyModule.cpp
+++ clang-tidy/obvious/ObviousTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 
+#include "InvalidRangeCheck.h"
 using namespace clang::ast_matchers;
 
 namespace clang {
@@ -20,7 +21,7 @@
 class ObviousModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
-// Add obvious checks here.
+CheckFactories.registerCheck("obvious-invalid-range");
   }
 };
 
Index: clang-tidy/obvious/InvalidRangeCheck.h
===
--- /dev/null
+++ clang-tidy/obvious/InvalidRangeCheck.h
@@ -0,0 +1,40 @@
+//===--- InvalidRangeCheck.h - clang-tidy*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBVIOUS_INVALID_RANGE_H

[PATCH] D27806: [clang-tidy] Add obvious-invalid-range

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

Also please review https://reviews.llvm.org/D27815 to make it happen


https://reviews.llvm.org/D27806



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


[PATCH] D24487: [Clang] Fix some Clang-tidy modernize-use-bool-literals and Include What You Use warnings in AST; other minor fixes

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

I would say that as long as most of the people don't see big difference between 
"end namespace X" and "namespace X" or even "X" then we should not be so 
strict. For me "end" is redundant. 
Even checks added by add_new_check uses "namespace clang" instead of "end 
namespace clang"


Repository:
  rL LLVM

https://reviews.llvm.org/D24487



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


[PATCH] D27813: [clang-tidy] fix missing anchor for MPI Module

2016-12-15 Thread Piotr Padlewski via Phabricator via cfe-commits
Prazek added a comment.

In https://reviews.llvm.org/D27813#623978, @Alexander_Droste wrote:

> Thanks for adding!


I also forgot about that one once. It is simple bugfix so I guess I need small 
LGTM to push it


https://reviews.llvm.org/D27813



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


  1   2   3   >