// 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++14 -ast-dump-lookups 2>/dev/null | 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 2>/dev/null | 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 2>/dev/null | 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" #endif @import cxx_templates_a; @import cxx_templates_b; @import cxx_templates_c; @import cxx_templates_d; @import cxx_templates_common; template struct Tmpl_T_C {}; template struct Tmpl_T_I_I {}; template struct Tmpl_T_T_A {}; template struct Tmpl_T_T_B {}; template struct UseInt {}; void g() { f(0); f(1.0); f(); f(); // expected-error {{no matching function}} // expected-note@Inputs/cxx-templates-a.h:3 {{couldn't infer template argument}} // expected-note@Inputs/cxx-templates-a.h:4 {{requires 1 argument}} N::f(0); N::f(1.0); N::f(); N::f(); // expected-error {{no matching function}} // expected-note@Inputs/cxx-templates-b.h:6 {{couldn't infer template argument}} // expected-note@Inputs/cxx-templates-b.h:7 {{requires single argument}} template_param_kinds_1<0>(); // ok, from cxx-templates-a.h template_param_kinds_1(); // ok, from cxx-templates-b.h template_param_kinds_2(); // expected-error {{no matching function}} // expected-note@Inputs/cxx-templates-a.h:11 {{invalid explicitly-specified argument}} // expected-note@Inputs/cxx-templates-b.h:11 {{invalid explicitly-specified argument}} template_param_kinds_2(); // expected-error {{ambiguous}} // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}} // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}} // FIXME: This should be valid, but we incorrectly match the template template // argument against both template template parameters. template_param_kinds_3(); // expected-error {{ambiguous}} // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} template_param_kinds_3(); // expected-error {{ambiguous}} // expected-note@Inputs/cxx-templates-a.h:12 {{candidate}} // expected-note@Inputs/cxx-templates-b.h:12 {{candidate}} // Trigger the instantiation of a template in 'a' that uses a type defined in // 'common'. That type is not visible here. PerformDelayedLookup(defined_in_common); // Likewise, but via a default argument. PerformDelayedLookupInDefaultArgument(defined_in_common); // Trigger the instantiation of a template in 'b' that uses a type defined in // 'b_impl'. That type is not visible here. UseDefinedInBImpl(); // Trigger the instantiation of a template in 'a' that uses a type defined in // 'b_impl', via a template defined in 'b'. Since the type is visible from // within 'b', the instantiation succeeds. UseDefinedInBImplIndirectly(defined_in_b_impl); // Trigger the instantiation of a template in 'a' that uses a type defined in // 'b_impl'. That type is not visible here, nor in 'a'. This fails; there is // no reason why DefinedInBImpl should be visible here. // // We turn off error recovery for modules in this test (so we don't get an // implicit import of cxx_templates_b_impl), and that results in us producing // a big spew of errors here. // // expected-error@Inputs/cxx-templates-a.h:19 {{definition of 'DefinedInBImpl' must be imported}} // expected-note@Inputs/cxx-templates-b-impl.h:1 +{{definition here is not reachable}} // expected-error@Inputs/cxx-templates-a.h:19 +{{}} // expected-error@Inputs/cxx-templates-a.h:20 +{{}} PerformDelayedLookup(defined_in_b_impl); // expected-note {{in instantiation of}} merge_templates_a = merge_templates_b; // ok, same type using T = decltype(enum_a_from_a); using T = decltype(enum_b_from_b); T e = true ? enum_a_from_a : enum_b_from_b; UseRedeclaredEnum(UseInt<1>()); // FIXME: Reintroduce this once we merge function template specializations. //static_assert(UseRedeclaredEnumA == UseRedeclaredEnumB, ""); //static_assert(UseRedeclaredEnumA == UseRedeclaredEnum, ""); //static_assert(UseRedeclaredEnumB == UseRedeclaredEnum, ""); static_assert(enum_c_from_a == enum_c_from_b, ""); CommonTemplate cti; CommonTemplate::E eee = CommonTemplate::c; TemplateInstantiationVisibility tiv1; TemplateInstantiationVisibility tiv2; TemplateInstantiationVisibility 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 is not reachable}} // expected-note@cxx-templates-b-impl.h:10 2{{definition here is not reachable}} TemplateInstantiationVisibility tiv4; int &p = WithPartialSpecializationUse().f(); int &q = WithExplicitSpecializationUse().inner_template(); int *r = PartiallyInstantiatePartialSpec::bar(); (void)&WithImplicitSpecialMembers::n; MergeClassTemplateSpecializations_string s; extern TestInjectedClassName::A *use_a; extern TestInjectedClassName::C *use_c; TestInjectedClassName::UseD(); } static_assert(Outer::Inner::f() == 1, ""); static_assert(Outer::Inner::g() == 2, ""); static_assert(MergeTemplateDefinitions::f() == 1, ""); static_assert(MergeTemplateDefinitions::g() == 2, ""); RedeclaredAsFriend raf1; RedeclareTemplateAsFriend rtaf; RedeclaredAsFriend raf2; MergeSpecializations::partially_specialized_in_a spec_in_a_1; MergeSpecializations::partially_specialized_in_b spec_in_b_1; MergeSpecializations::partially_specialized_in_c spec_in_c_1; MergeSpecializations::explicitly_specialized_in_a spec_in_a_2; MergeSpecializations::explicitly_specialized_in_b spec_in_b_2; MergeSpecializations::explicitly_specialized_in_c spec_in_c_2; MergeAnonUnionMember<> maum_main; typedef DontWalkPreviousDeclAfterMerging dwpdam_typedef_2; dwpdam_typedef::type dwpdam_typedef_use; DontWalkPreviousDeclAfterMerging::Inner::type dwpdam; using AliasTemplateMergingTest = WithAliasTemplate::X; int AnonymousDeclsMergingTest(WithAnonymousDecls WAD, WithAnonymousDecls WADC) { return InstantiateWithAnonymousDeclsA(WAD) + InstantiateWithAnonymousDeclsB(WAD) + InstantiateWithAnonymousDeclsB2(WADC) + InstantiateWithAnonymousDeclsD(WADC); } @import cxx_templates_common; typedef SomeTemplate SomeTemplateIntPtr; typedef SomeTemplate SomeTemplateIntRef; SomeTemplate some_template_char_ptr; SomeTemplate some_template_char_ref; void testImplicitSpecialMembers(SomeTemplate &a, const SomeTemplate &b, SomeTemplate &c, const SomeTemplate &d) { a = b; c = d; } bool testFriendInClassTemplate(Std::WithFriend 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(); // ok fn(); // ok fn(); // expected-error 1+{{explicit specialization of 'fn' must be imported}} cls::nested_fn(); // expected-error 1+{{explicit specialization of 'nested_fn' must be imported}} cls::nested_fn_t(); // expected-error 1+{{explicit specialization of 'nested_fn_t' must be imported}} cls::nested_fn_t(); // 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 *k0; // ok cls *k1; // ok cls *k2; // ok cls *k3; // ok cls::nested_cls *nk1; // ok cls::nested_cls_t *nk2; // ok cls::nested_cls_t *nk3; // ok cls uk1; // expected-error 1+{{explicit specialization of 'cls' must be imported}} expected-error 1+{{definition of}} cls uk3; // expected-error 1+{{partial specialization of 'cls' must be imported}} expected-error 1+{{definition of}} cls uk4; // expected-error 1+{{partial specialization of 'cls' must be imported}} expected-error 1+{{definition of}} cls::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}} cls::nested_cls_t unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}} // expected-error@cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}} // expected-note@-2 {{in evaluation of exception specification}} cls::nested_cls_t 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::nested_enum e; // ok (void)cls::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); // ok (void)sizeof(var); // ok (void)sizeof(var); // expected-error 1+{{explicit specialization of 'var' must be imported}} (void)sizeof(var); // expected-error 1+{{partial specialization of 'var' must be imported}} (void)sizeof(var); // expected-error 1+{{partial specialization of 'var' must be imported}} (void)sizeof(cls::nested_var); // ok (void)cls::nested_var; // expected-error 1+{{explicit specialization of 'nested_var' must be imported}} (void)sizeof(cls::nested_var_t); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}} (void)sizeof(cls::nested_var_t); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}} } void cls::nested_fn() {} // expected-error 1+{{explicit specialization of 'cls' must be imported}} expected-error 1+{{definition of}} struct cls::nested_cls {}; // expected-error 1+{{explicit specialization of 'cls' must be imported}} expected-error 1+{{definition of}} int cls::nested_var; // expected-error 1+{{explicit specialization of 'cls' must be imported}} expected-error 1+{{definition of}} enum cls::nested_enum : int {}; // expected-error 1+{{explicit specialization of 'cls' must be imported}} expected-error 1+{{definition of}} template void cls::nested_fn() {} // expected-error 1+{{partial specialization of 'cls' must be imported}} template struct cls::nested_cls {}; // expected-error 1+{{partial specialization of 'cls' must be imported}} template int cls::nested_var; // expected-error 1+{{partial specialization of 'cls' must be imported}} template enum cls::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls' 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}} } // CHECK-GLOBAL: DeclarationName 'f' // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-GLOBAL-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-GLOBAL-NEXT: `-FunctionTemplate {{.*}} 'f' // CHECK-NAMESPACE-N: DeclarationName 'f' // CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f' // CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f' // CHECK-DUMP: ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}> col:{{.*}} in cxx_templates_common SomeTemplate // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate // CHECK-DUMP-NEXT: TemplateArgument type 'char [2]' // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition // CHECK-DUMP-NEXT: DefinitionData // CHECK-DUMP-NEXT: DefaultConstructor // CHECK-DUMP-NEXT: CopyConstructor // CHECK-DUMP-NEXT: MoveConstructor // CHECK-DUMP-NEXT: CopyAssignment // CHECK-DUMP-NEXT: MoveAssignment // CHECK-DUMP-NEXT: Destructor // CHECK-DUMP-NEXT: TemplateArgument type 'char [2]' // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate // CHECK-DUMP-NEXT: TemplateArgument type 'char [1]' // CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition // CHECK-DUMP-NEXT: DefinitionData // CHECK-DUMP-NEXT: DefaultConstructor // CHECK-DUMP-NEXT: CopyConstructor // CHECK-DUMP-NEXT: MoveConstructor // CHECK-DUMP-NEXT: CopyAssignment // CHECK-DUMP-NEXT: MoveAssignment // CHECK-DUMP-NEXT: Destructor // CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'