diff options
Diffstat (limited to 'clang/test/Modules')
| -rw-r--r-- | clang/test/Modules/Inputs/cxx-templates-common.h | 17 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/cxx-templates-unimported.h | 43 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/module.map | 2 | ||||
| -rw-r--r-- | clang/test/Modules/cxx-templates.cpp | 70 |
4 files changed, 126 insertions, 6 deletions
diff --git a/clang/test/Modules/Inputs/cxx-templates-common.h b/clang/test/Modules/Inputs/cxx-templates-common.h index a9ca6244867..8e730c8a852 100644 --- a/clang/test/Modules/Inputs/cxx-templates-common.h +++ b/clang/test/Modules/Inputs/cxx-templates-common.h @@ -53,4 +53,21 @@ template<typename T> struct WithAnonymousDecls { typedef int X; }; +namespace hidden_specializations { + template<typename T> void fn() {} + + template<typename T> struct cls { + static void nested_fn() {} + struct nested_cls {}; + static int nested_var; + enum class nested_enum {}; + + template<typename U> static void nested_fn_t() {} + template<typename U> struct nested_cls_t {}; + template<typename U> static int nested_var_t; + }; + + template<typename T> int var; +} + #include "cxx-templates-textual.h" diff --git a/clang/test/Modules/Inputs/cxx-templates-unimported.h b/clang/test/Modules/Inputs/cxx-templates-unimported.h new file mode 100644 index 00000000000..c2b6b915924 --- /dev/null +++ b/clang/test/Modules/Inputs/cxx-templates-unimported.h @@ -0,0 +1,43 @@ +#include "cxx-templates-common.h" + +namespace hidden_specializations { + // explicit specializations + template<> void fn<int>() {} + template<> struct cls<int> { + void nested_fn(); + struct nested_cls; + static int nested_var; + enum nested_enum : int; + }; + template<> int var<int>; + + // partial specializations + template<typename T> struct cls<T*> { + void nested_fn(); + struct nested_cls; + static int nested_var; + enum nested_enum : int; + }; + template<typename T> int var<T*>; + + // member specializations + template<> void cls<void>::nested_fn() {} + template<> struct cls<void>::nested_cls {}; + template<> int cls<void>::nested_var; + template<> enum class cls<void>::nested_enum { e }; + template<> template<typename U> void cls<void>::nested_fn_t() {} + template<> template<typename U> struct cls<void>::nested_cls_t {}; + template<> template<typename U> int cls<void>::nested_var_t; + + // specializations instantiated here are ok if their pattern is + inline void use_stuff() { + fn<char>(); + cls<char>(); + (void)var<char>; + cls<char*>(); + (void)var<char*>; + cls<void>::nested_fn_t<char>(); + cls<void>::nested_cls_t<char>(); + (void)cls<void>::nested_var_t<char>; + } +} diff --git a/clang/test/Modules/Inputs/module.map b/clang/test/Modules/Inputs/module.map index 66b52e9105e..4db1cca925c 100644 --- a/clang/test/Modules/Inputs/module.map +++ b/clang/test/Modules/Inputs/module.map @@ -215,6 +215,8 @@ module cxx_linkage_cache { module cxx_templates_common { header "cxx-templates-common.h" + + explicit module unimported { header "cxx-templates-unimported.h" } } module cxx_templates_a { diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp index ef4e4e420d0..eea90774aa8 100644 --- a/clang/test/Modules/cxx-templates.cpp +++ b/clang/test/Modules/cxx-templates.cpp @@ -1,9 +1,9 @@ // RUN: rm -rf %t -// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump-lookups | FileCheck %s --check-prefix=CHECK-GLOBAL -// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N -// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-filter SomeTemplate | FileCheck %s --check-prefix=CHECK-DUMP -// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 -// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 -DEARLY_IMPORT +// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++14 -ast-dump-lookups | FileCheck %s --check-prefix=CHECK-GLOBAL +// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++14 -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N +// RUN: not %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++14 -ast-dump -ast-dump-filter SomeTemplate | FileCheck %s --check-prefix=CHECK-DUMP +// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++14 +// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++14 -DEARLY_IMPORT #ifdef EARLY_IMPORT #include "cxx-templates-textual.h" @@ -105,7 +105,8 @@ void g() { TemplateInstantiationVisibility<char[1]> tiv1; TemplateInstantiationVisibility<char[2]> tiv2; - TemplateInstantiationVisibility<char[3]> tiv3; // expected-error 2{{must be imported from module 'cxx_templates_b_impl'}} + TemplateInstantiationVisibility<char[3]> tiv3; // expected-error 5{{must be imported from module 'cxx_templates_b_impl'}} + // expected-note@cxx-templates-b-impl.h:10 3{{explicit specialization declared here}} // expected-note@cxx-templates-b-impl.h:10 2{{previous definition is here}} TemplateInstantiationVisibility<char[4]> tiv4; @@ -172,6 +173,63 @@ bool testFriendInClassTemplate(Std::WithFriend<int> wfi) { return wfi != wfi; } +namespace hidden_specializations { + // expected-note@cxx-templates-unimported.h:* 1+{{here}} + void test() { + // For functions, uses that would trigger instantiations of definitions are + // not allowed. + fn<void>(); // ok + fn<char>(); // ok + fn<int>(); // expected-error 1+{{explicit specialization of 'fn<int>' must be imported}} + cls<void>::nested_fn(); // expected-error 1+{{explicit specialization of 'nested_fn' must be imported}} + cls<void>::nested_fn_t<int>(); // expected-error 1+{{explicit specialization of 'nested_fn_t' must be imported}} + cls<void>::nested_fn_t<char>(); // expected-error 1+{{explicit specialization of 'nested_fn_t' must be imported}} + + // For classes, uses that would trigger instantiations of definitions are + // not allowed. + cls<void> *k0; // ok + cls<char> *k1; // ok + cls<int> *k2; // ok + cls<int*> *k3; // ok + cls<void>::nested_cls *nk1; // ok + cls<void>::nested_cls_t<int> *nk2; // ok + cls<void>::nested_cls_t<char> *nk3; // ok + cls<int> uk1; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}} + cls<int*> uk3; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}} + cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}} + cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}} + cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}} + cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} + + // For enums, uses that would trigger instantiations of definitions are not + // allowed. + cls<void>::nested_enum e; // ok + (void)cls<void>::nested_enum::e; // expected-error 1+{{definition of 'nested_enum' must be imported}} expected-error 1+{{declaration of 'e'}} + + // For variable template specializations, no uses are allowed because + // specializations can change the type. + (void)sizeof(var<void>); // ok + (void)sizeof(var<char>); // ok + (void)sizeof(var<int>); // expected-error 1+{{explicit specialization of 'var<int>' must be imported}} + (void)sizeof(var<int*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}} + (void)sizeof(var<char*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}} + (void)sizeof(cls<void>::nested_var); // ok + (void)cls<void>::nested_var; // expected-error 1+{{explicit specialization of 'nested_var' must be imported}} + (void)sizeof(cls<void>::nested_var_t<int>); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}} + (void)sizeof(cls<void>::nested_var_t<char>); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}} + } + + void cls<int>::nested_fn() {} // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}} + struct cls<int>::nested_cls {}; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}} + int cls<int>::nested_var; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}} + enum cls<int>::nested_enum : int {}; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}} + + template<typename T> void cls<T*>::nested_fn() {} // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} + template<typename T> struct cls<T*>::nested_cls {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} + template<typename T> int cls<T*>::nested_var; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} + template<typename T> enum cls<T*>::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} +} + namespace Std { void g(); // expected-error {{functions that differ only in their return type cannot be overloaded}} // expected-note@cxx-templates-common.h:21 {{previous}} |

