forked from OSchip/llvm-project
Template argument deduction for member pointers.
Also, introduced some of the framework for performing instantiation as part of template argument deduction. llvm-svn: 73175
This commit is contained in:
parent
96c9dea4a0
commit
637d9984f0
|
@ -772,6 +772,9 @@ def note_template_member_function_here : Note<
|
|||
"in instantiation of member function %q0 requested here">;
|
||||
def note_default_arg_instantiation_here : Note<
|
||||
"in instantiation of default argument for '%0' required here">;
|
||||
def note_partial_spec_deduct_instantiation_here : Note<
|
||||
"during template argument deduction for class template partial "
|
||||
"specialization %0, here">;
|
||||
def err_field_instantiates_to_function : Error<
|
||||
"data member instantiated with function type %0">;
|
||||
def err_nested_name_spec_non_tag : Error<
|
||||
|
|
|
@ -2056,7 +2056,16 @@ public:
|
|||
/// parameter. The Entity is the template, and
|
||||
/// TemplateArgs/NumTemplateArguments provides the template
|
||||
/// arguments as specified.
|
||||
DefaultTemplateArgumentInstantiation
|
||||
/// FIXME: Use a TemplateArgumentList
|
||||
DefaultTemplateArgumentInstantiation,
|
||||
|
||||
/// We are performing template argument deduction for a class
|
||||
/// template partial specialization. The Entity is the class
|
||||
/// template partial specialization, and
|
||||
/// TemplateArgs/NumTemplateArgs provides the deduced template
|
||||
/// arguments.
|
||||
/// FIXME: Use a TemplateArgumentList
|
||||
PartialSpecDeductionInstantiation
|
||||
} Kind;
|
||||
|
||||
/// \brief The point of instantiation within the source code.
|
||||
|
@ -2090,6 +2099,7 @@ public:
|
|||
return true;
|
||||
|
||||
case DefaultTemplateArgumentInstantiation:
|
||||
case PartialSpecDeductionInstantiation:
|
||||
return X.TemplateArgs == Y.TemplateArgs;
|
||||
}
|
||||
|
||||
|
@ -2146,6 +2156,15 @@ public:
|
|||
unsigned NumTemplateArgs,
|
||||
SourceRange InstantiationRange = SourceRange());
|
||||
|
||||
/// \brief Note that we are instantiating as part of template
|
||||
/// argument deduction for a class template partial
|
||||
/// specialization.
|
||||
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
||||
ClassTemplatePartialSpecializationDecl *PartialSpec,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceRange InstantiationRange = SourceRange());
|
||||
|
||||
/// \brief Note that we have finished instantiating this template.
|
||||
void Clear();
|
||||
|
||||
|
|
|
@ -408,6 +408,37 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
|
|||
return true;
|
||||
}
|
||||
|
||||
// T type::*
|
||||
// T T::*
|
||||
// T (type::*)()
|
||||
// type (T::*)()
|
||||
// type (type::*)(T)
|
||||
// type (T::*)(T)
|
||||
// T (type::*)(T)
|
||||
// T (T::*)()
|
||||
// T (T::*)(T)
|
||||
case Type::MemberPointer: {
|
||||
const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
|
||||
const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
|
||||
if (!MemPtrArg)
|
||||
return false;
|
||||
|
||||
return DeduceTemplateArguments(Context,
|
||||
MemPtrParam->getPointeeType(),
|
||||
MemPtrArg->getPointeeType(),
|
||||
Deduced) &&
|
||||
DeduceTemplateArguments(Context,
|
||||
QualType(MemPtrParam->getClass(), 0),
|
||||
QualType(MemPtrArg->getClass(), 0),
|
||||
Deduced);
|
||||
}
|
||||
|
||||
case Type::TypeOfExpr:
|
||||
case Type::TypeOf:
|
||||
case Type::Typename:
|
||||
// No template argument deduction for these types
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -492,6 +523,14 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
|
|||
if (! ::DeduceTemplateArguments(Context, Partial->getTemplateArgs(),
|
||||
TemplateArgs, Deduced))
|
||||
return 0;
|
||||
|
||||
// FIXME: It isn't clear whether we want the diagnostic to point at
|
||||
// the partial specialization itself or at the actual point of
|
||||
// instantiation.
|
||||
InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
|
||||
Deduced.data(), Deduced.size());
|
||||
if (Inst)
|
||||
return 0;
|
||||
|
||||
// FIXME: Substitute the deduced template arguments into the template
|
||||
// arguments of the class template partial specialization; the resulting
|
||||
|
|
|
@ -90,6 +90,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
|||
}
|
||||
}
|
||||
|
||||
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
||||
SourceLocation PointOfInstantiation,
|
||||
ClassTemplatePartialSpecializationDecl *PartialSpec,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceRange InstantiationRange)
|
||||
: SemaRef(SemaRef) {
|
||||
|
||||
Invalid = CheckInstantiationDepth(PointOfInstantiation,
|
||||
InstantiationRange);
|
||||
if (!Invalid) {
|
||||
ActiveTemplateInstantiation Inst;
|
||||
Inst.Kind
|
||||
= ActiveTemplateInstantiation::PartialSpecDeductionInstantiation;
|
||||
Inst.PointOfInstantiation = PointOfInstantiation;
|
||||
Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
|
||||
Inst.TemplateArgs = TemplateArgs;
|
||||
Inst.NumTemplateArgs = NumTemplateArgs;
|
||||
Inst.InstantiationRange = InstantiationRange;
|
||||
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
|
||||
Invalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Sema::InstantiatingTemplate::Clear() {
|
||||
if (!Invalid) {
|
||||
SemaRef.ActiveTemplateInstantiations.pop_back();
|
||||
|
@ -157,6 +181,26 @@ void Sema::PrintInstantiationStack() {
|
|||
<< Active->InstantiationRange;
|
||||
break;
|
||||
}
|
||||
|
||||
case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: {
|
||||
ClassTemplatePartialSpecializationDecl *PartialSpec
|
||||
= cast<ClassTemplatePartialSpecializationDecl>((Decl *)Active->Entity);
|
||||
std::string TemplateArgsStr
|
||||
= TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
PartialSpec->getTemplateArgs().getFlatArgumentList(),
|
||||
PartialSpec->getTemplateArgs().flat_size(),
|
||||
Context.PrintingPolicy);
|
||||
// FIXME: The active template instantiation's template arguments
|
||||
// are interesting, too. We should add something like [with T =
|
||||
// foo, U = bar, etc.] to the string.
|
||||
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
||||
diag::note_partial_spec_deduct_instantiation_here)
|
||||
<< (PartialSpec->getSpecializedTemplate()->getNameAsString() +
|
||||
TemplateArgsStr)
|
||||
<< Active->InstantiationRange;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,3 +158,98 @@ template<typename T, typename Class>
|
|||
struct is_member_pointer<T Class::*> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
struct X { };
|
||||
|
||||
int is_member_pointer0[is_member_pointer<int X::*>::value? 1 : -1];
|
||||
int is_member_pointer1[is_member_pointer<const int X::*>::value? 1 : -1];
|
||||
int is_member_pointer2[is_member_pointer<int (X::*)()>::value? 1 : -1];
|
||||
int is_member_pointer3[is_member_pointer<int (X::*)(int) const>::value? 1 : -1];
|
||||
int is_member_pointer4[is_member_pointer<int (X::**)(int) const>::value? -1 : 1];
|
||||
int is_member_pointer5[is_member_pointer<int>::value? -1 : 1];
|
||||
|
||||
template<typename T>
|
||||
struct is_member_function_pointer {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T, typename Class>
|
||||
struct is_member_function_pointer<T (Class::*)()> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class>
|
||||
struct is_member_function_pointer<T (Class::*)() const> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class>
|
||||
struct is_member_function_pointer<T (Class::*)() volatile> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class>
|
||||
struct is_member_function_pointer<T (Class::*)() const volatile> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class, typename A1>
|
||||
struct is_member_function_pointer<T (Class::*)(A1)> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class, typename A1>
|
||||
struct is_member_function_pointer<T (Class::*)(A1) const> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class, typename A1>
|
||||
struct is_member_function_pointer<T (Class::*)(A1) volatile> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Class, typename A1>
|
||||
struct is_member_function_pointer<T (Class::*)(A1) const volatile> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
int is_member_function_pointer0[
|
||||
is_member_function_pointer<int X::*>::value? -1 : 1];
|
||||
int is_member_function_pointer1[
|
||||
is_member_function_pointer<int (X::*)()>::value? 1 : -1];
|
||||
int is_member_function_pointer2[
|
||||
is_member_function_pointer<X (X::*)(X&)>::value? 1 : -1];
|
||||
int is_member_function_pointer3[
|
||||
is_member_function_pointer<int (X::*)() const>::value? 1 : -1];
|
||||
int is_member_function_pointer4[
|
||||
is_member_function_pointer<int (X::*)(float) const>::value? 1 : -1];
|
||||
|
||||
template<typename T, typename ValueType = T>
|
||||
struct is_nested_value_type_identity {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_nested_value_type_identity<T, typename T::value_type> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct HasValueType {
|
||||
typedef T value_type;
|
||||
};
|
||||
|
||||
struct HasIdentityValueType {
|
||||
typedef HasIdentityValueType value_type;
|
||||
};
|
||||
|
||||
struct NoValueType { };
|
||||
|
||||
// FIXME: Need substitution into the template arguments of the partial spec
|
||||
//int is_nested_value_type_identity0[
|
||||
// is_nested_value_type_identity<HasValueType<int> >::value? -1 : 1];
|
||||
int is_nested_value_type_identity1[
|
||||
is_nested_value_type_identity<HasIdentityValueType>::value? 1 : -1];
|
||||
// FIXME: Enable when we have SFINAE support
|
||||
//int is_nested_value_type_identity0[
|
||||
// is_nested_value_type_identity<NoValueType>::value? -1 : 1];
|
||||
|
|
Loading…
Reference in New Issue