[PATCH] D51789: [WIP][clang] Add the no_extern_template attribute

2018-09-14 Thread Louis Dionne via Phabricator via cfe-commits
ldionne updated this revision to Diff 165507.
ldionne added a comment.

Fix the tests and remove some warnings that I wasn't able to generate properly
(to avoid false positives).


Repository:
  rC Clang

https://reviews.llvm.org/D51789

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  
clang/test/CodeGenCXX/attr-no_extern_template.dont_assume_extern_instantiation.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/attr-no_extern_template.diagnose_on_undefined_entity.cpp
  clang/test/SemaCXX/attr-no_extern_template.explicit_instantiation.cpp
  clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp
  clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp

Index: clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/attr-no_extern_template.merge_redeclarations.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Test that we properly merge the no_extern_template attribute on
+// redeclarations.
+
+#define NO_EXTERN_TEMPLATE __attribute__((no_extern_template))
+
+template 
+struct Foo {
+  // Declaration without the attribute, definition with the attribute.
+  void func1();
+
+  // Declaration with the attribute, definition without the attribute.
+  NO_EXTERN_TEMPLATE void func2();
+
+  // Declaration with the attribute, definition with the attribute.
+  NO_EXTERN_TEMPLATE void func3();
+};
+
+template 
+NO_EXTERN_TEMPLATE void Foo::func1() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+void Foo::func2() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+NO_EXTERN_TEMPLATE void Foo::func3() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+struct Empty { };
+extern template struct Foo;
+
+int main() {
+  Foo foo;
+  foo.func1(); // expected-note{{in instantiation of}}
+  foo.func2(); // expected-note{{in instantiation of}}
+  foo.func3(); // expected-note{{in instantiation of}}
+}
Index: clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/attr-no_extern_template.extern_declaration.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s
+
+// Test that extern instantiation declarations cause members marked with
+// no_extern_template to be instantiated in the current TU.
+
+#define NO_EXTERN_TEMPLATE __attribute__((no_extern_template))
+
+template 
+struct Foo {
+  NO_EXTERN_TEMPLATE inline void non_static_member_function1();
+
+  NO_EXTERN_TEMPLATE void non_static_member_function2();
+
+  NO_EXTERN_TEMPLATE static inline void static_member_function1();
+
+  NO_EXTERN_TEMPLATE static void static_member_function2();
+
+  NO_EXTERN_TEMPLATE static int static_data_member;
+
+  struct NO_EXTERN_TEMPLATE member_class1 {
+static void static_member_function() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+  };
+
+  struct member_class2 {
+NO_EXTERN_TEMPLATE static void static_member_function() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+  };
+};
+
+template 
+inline void Foo::non_static_member_function1() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+void Foo::non_static_member_function2() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+inline void Foo::static_member_function1() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+void Foo::static_member_function2() {
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
+}
+
+template 
+int Foo::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}}
+
+struct Empty { };
+extern template struct Foo;
+
+int main() {
+  Foo foo;
+  foo.non_static_member_function1();   // expected-note{{in instantiation of}}
+  foo.non_static_member_function2();   // expected-note{{in instantiation of}}
+  Foo::static_member_function1();   // expected-note{{in instantiation of}}
+  Foo::static_member_function2();   // expected-note{{in instantiation of}}
+  (void)foo.static_data_member;// expected-note{{in instantiation of}}
+  Foo::member_class1::static_member_function(); // expected-note{{in instantiation of}}
+  Foo::member_class2::

[PATCH] D51789: [WIP][clang] Add the no_extern_template attribute

2018-09-07 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

It'd be good to test that `[[no_extern_template]]` affects instantiation, not 
just code generation (eg, put something in the body of the entity that will 
trigger an error if instantiated, and check that the diagnostic is produced at 
the right times).


Repository:
  rL LLVM

https://reviews.llvm.org/D51789



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


[PATCH] D51789: [WIP][clang] Add the no_extern_template attribute

2018-09-07 Thread Duncan P. N. Exon Smith via Phabricator via cfe-commits
dexonsmith edited subscribers, added: cfe-commits; removed: llvm-commits.
dexonsmith added a comment.

+cfe-commits
-llvm-commits


Repository:
  rL LLVM

https://reviews.llvm.org/D51789



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