llvm-project/clang/test/Modules/Inputs/cxx-templates-b.h

96 lines
2.8 KiB
C
Raw Normal View History

@import cxx_templates_common;
template<typename T> T f();
template<typename T> T f(T t) { return t; }
namespace N {
template<typename T> T f();
template<typename T> T f(T t) { return t; }
}
template<typename> int template_param_kinds_1();
template<template<typename, int, int...> class> int template_param_kinds_2();
template<template<typename T, typename U, U> class> int template_param_kinds_3();
template<typename T> struct SomeTemplate<T&> {};
template<typename T> struct SomeTemplate<T&>;
typedef SomeTemplate<int&> SomeTemplateIntRef;
When we perform dependent name lookup during template instantiation, it's not sufficient to only consider names visible at the point of instantiation, because that may not include names that were visible when the template was defined. More generally, if the instantiation backtrace goes through a module M, then every declaration visible within M should be available to the instantiation. Any of those declarations might be part of the interface that M intended to export to a template that it instantiates. The fix here has two parts: 1) If we find a non-visible declaration during name lookup during template instantiation, check whether the declaration was visible from the defining module of all entities on the active template instantiation stack. The defining module is not the owning module in all cases: we look at the module in which a template was defined, not the module in which it was first instantiated. 2) Perform pending instantiations at the end of a module, not at the end of the translation unit. This is general goodness, since it significantly cuts down the amount of redundant work that is performed in every TU importing a module, and also implicitly adds the module containing the point of instantiation to the set of modules checked for declarations in a lookup within a template instantiation. There's a known issue here with template instantiations performed while building a module, if additional imports are added later on. I'll fix that in a subsequent commit. llvm-svn: 187167
2013-07-26 07:08:39 +08:00
extern DefinedInCommon &defined_in_common;
template<int> struct MergeTemplates;
MergeTemplates<0> *merge_templates_b;
template<typename T> template<typename U>
constexpr int Outer<T>::Inner<U>::g() { return 2; }
static_assert(Outer<int>::Inner<int>::g() == 2, "");
namespace TestInjectedClassName {
template<typename T> struct X { X(); };
typedef X<char[2]> B;
}
When we perform dependent name lookup during template instantiation, it's not sufficient to only consider names visible at the point of instantiation, because that may not include names that were visible when the template was defined. More generally, if the instantiation backtrace goes through a module M, then every declaration visible within M should be available to the instantiation. Any of those declarations might be part of the interface that M intended to export to a template that it instantiates. The fix here has two parts: 1) If we find a non-visible declaration during name lookup during template instantiation, check whether the declaration was visible from the defining module of all entities on the active template instantiation stack. The defining module is not the owning module in all cases: we look at the module in which a template was defined, not the module in which it was first instantiated. 2) Perform pending instantiations at the end of a module, not at the end of the translation unit. This is general goodness, since it significantly cuts down the amount of redundant work that is performed in every TU importing a module, and also implicitly adds the module containing the point of instantiation to the set of modules checked for declarations in a lookup within a template instantiation. There's a known issue here with template instantiations performed while building a module, if additional imports are added later on. I'll fix that in a subsequent commit. llvm-svn: 187167
2013-07-26 07:08:39 +08:00
@import cxx_templates_b_impl;
template<typename T, typename> struct Identity { typedef T type; };
template<typename T> void UseDefinedInBImpl() {
typename Identity<DefinedInBImpl, T>::type dependent;
FoundByADL(dependent);
typename Identity<DefinedInBImpl, T>::type::Inner inner;
dependent.f();
}
extern DefinedInBImpl &defined_in_b_impl;
template<typename T>
struct RedeclareTemplateAsFriend {
template<typename U>
friend struct RedeclaredAsFriend;
};
void use_some_template_b() {
SomeTemplate<char[1]> a;
SomeTemplate<char[2]> b, c;
b = c;
WithImplicitSpecialMembers<int> wism1, wism2(wism1);
}
auto enum_b_from_b = CommonTemplate<int>::b;
const auto enum_c_from_b = CommonTemplate<int>::c;
template<int> struct UseInt;
template<typename T> void UseRedeclaredEnum(UseInt<T() + CommonTemplate<char>::a>);
constexpr void (*UseRedeclaredEnumB)(UseInt<1>) = UseRedeclaredEnum<int>;
typedef WithPartialSpecialization<void(int)>::type WithPartialSpecializationInstantiate3;
template<typename> struct MergeSpecializations;
template<typename T> struct MergeSpecializations<T&> {
typedef int partially_specialized_in_b;
};
template<> struct MergeSpecializations<double> {
typedef int explicitly_specialized_in_b;
};
template<typename U> using AliasTemplate = U;
void InstantiateWithAliasTemplate(WithAliasTemplate<int>::X<char>);
inline int InstantiateWithAnonymousDeclsB(WithAnonymousDecls<int> x) {
return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d) + x.e;
}
inline int InstantiateWithAnonymousDeclsB2(WithAnonymousDecls<char> x) {
return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d) + x.e;
}
When we perform dependent name lookup during template instantiation, it's not sufficient to only consider names visible at the point of instantiation, because that may not include names that were visible when the template was defined. More generally, if the instantiation backtrace goes through a module M, then every declaration visible within M should be available to the instantiation. Any of those declarations might be part of the interface that M intended to export to a template that it instantiates. The fix here has two parts: 1) If we find a non-visible declaration during name lookup during template instantiation, check whether the declaration was visible from the defining module of all entities on the active template instantiation stack. The defining module is not the owning module in all cases: we look at the module in which a template was defined, not the module in which it was first instantiated. 2) Perform pending instantiations at the end of a module, not at the end of the translation unit. This is general goodness, since it significantly cuts down the amount of redundant work that is performed in every TU importing a module, and also implicitly adds the module containing the point of instantiation to the set of modules checked for declarations in a lookup within a template instantiation. There's a known issue here with template instantiations performed while building a module, if additional imports are added later on. I'll fix that in a subsequent commit. llvm-svn: 187167
2013-07-26 07:08:39 +08:00
@import cxx_templates_a;
template<typename T> void UseDefinedInBImplIndirectly(T &v) {
PerformDelayedLookup(v);
}
void TriggerInstantiation() {
UseDefinedInBImpl<void>();
Std::f<int>();
PartiallyInstantiatePartialSpec<int*>::foo();
WithPartialSpecialization<void(int)>::type x;
When we perform dependent name lookup during template instantiation, it's not sufficient to only consider names visible at the point of instantiation, because that may not include names that were visible when the template was defined. More generally, if the instantiation backtrace goes through a module M, then every declaration visible within M should be available to the instantiation. Any of those declarations might be part of the interface that M intended to export to a template that it instantiates. The fix here has two parts: 1) If we find a non-visible declaration during name lookup during template instantiation, check whether the declaration was visible from the defining module of all entities on the active template instantiation stack. The defining module is not the owning module in all cases: we look at the module in which a template was defined, not the module in which it was first instantiated. 2) Perform pending instantiations at the end of a module, not at the end of the translation unit. This is general goodness, since it significantly cuts down the amount of redundant work that is performed in every TU importing a module, and also implicitly adds the module containing the point of instantiation to the set of modules checked for declarations in a lookup within a template instantiation. There's a known issue here with template instantiations performed while building a module, if additional imports are added later on. I'll fix that in a subsequent commit. llvm-svn: 187167
2013-07-26 07:08:39 +08:00
}