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