forked from OSchip/llvm-project
Implement semantic checking for template arguments that correspond to
pointer-to-member-data non-type template parameters. Also, get consistent about what it means to returned a bool from CheckTemplateArgument. llvm-svn: 64305
This commit is contained in:
parent
8527e3a727
commit
0e55853639
|
@ -655,8 +655,8 @@ Sema::ActOnClassTemplateSpecialization(DeclTy *TemplateD,
|
|||
|
||||
// Check that the template argument list is well-formed for this
|
||||
// template.
|
||||
if (!CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
|
||||
TemplateArgs, TemplateArgLocs, RAngleLoc))
|
||||
if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
|
||||
TemplateArgs, TemplateArgLocs, RAngleLoc))
|
||||
return 0;
|
||||
|
||||
// Yes, all class template specializations are just silly sugar for
|
||||
|
@ -730,7 +730,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
|
||||
// Check template type parameters.
|
||||
if (!ArgType.isNull()) {
|
||||
if (!CheckTemplateArgument(TTP, ArgType, ArgLoc))
|
||||
if (CheckTemplateArgument(TTP, ArgType, ArgLoc))
|
||||
Invalid = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -749,7 +749,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
|
||||
// Check non-type template parameters.
|
||||
if (ArgExpr) {
|
||||
if (!CheckTemplateArgument(NTTP, ArgExpr))
|
||||
if (CheckTemplateArgument(NTTP, ArgExpr))
|
||||
Invalid = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -778,7 +778,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
|
||||
if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
|
||||
isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
|
||||
if (!CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
|
||||
if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
|
||||
Invalid = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -1014,7 +1014,25 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
// this.
|
||||
return false;
|
||||
}
|
||||
// FIXME: p5 has a lot more checks to perform!
|
||||
|
||||
// -- For a non-type template-parameter of type pointer to data
|
||||
// member, qualification conversions (4.4) are applied.
|
||||
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
|
||||
|
||||
if (hasSameUnqualifiedType(ParamType, ArgType)) {
|
||||
// Types match exactly: nothing more to do here.
|
||||
} else if (IsQualificationConversion(ArgType, ParamType)) {
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
} else {
|
||||
// We can't perform this conversion.
|
||||
Diag(Arg->getSourceRange().getBegin(),
|
||||
diag::err_template_arg_not_convertible)
|
||||
<< Arg->getType() << Param->getType() << Arg->getSourceRange();
|
||||
Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Check the restrictions in p1.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ template<typename> class X;
|
|||
|
||||
A<int, 0, X> * a1;
|
||||
|
||||
A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}}
|
||||
|
||||
A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}}
|
||||
A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
|
|
|
@ -3,9 +3,11 @@ template<int N> struct A; // expected-note 5{{template parameter is declared her
|
|||
|
||||
A<0> *a0;
|
||||
|
||||
A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int (void)'}}
|
||||
A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int (void)'}} \
|
||||
// FIXME: expected-error{{unqualified-id}}
|
||||
|
||||
A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}}
|
||||
A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}} \
|
||||
// FIXME: expected-error{{unqualified-id}}
|
||||
|
||||
A<1 >> 2> *a3;
|
||||
|
||||
|
@ -15,8 +17,8 @@ A<A> *a4; // expected-error{{must have an integral or enumeration type}} \
|
|||
// FIXME: expected-error{{expected unqualified-id}}
|
||||
|
||||
enum E { Enumerator = 17 };
|
||||
A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}}
|
||||
|
||||
A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}} \
|
||||
// FIXME: expected-error{{unqualified-id}}
|
||||
template<E Value> struct A1; // expected-note{{template parameter is declared here}}
|
||||
A1<Enumerator> *a6; // okay
|
||||
A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'enum E'}} \
|
||||
|
@ -96,9 +98,20 @@ struct Z {
|
|||
float bar(float);
|
||||
int bar(int);
|
||||
double baz(double);
|
||||
|
||||
int int_member;
|
||||
float float_member;
|
||||
};
|
||||
template<int (Z::*pmf)(int)> struct A6; // expected-note{{template parameter is declared here}}
|
||||
A6<&Z::foo> *a17_1;
|
||||
A6<&Z::bar> *a17_2;
|
||||
A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (struct Z::*)(double)' cannot be converted to a value of type 'int (struct Z::*)(int)'}} \
|
||||
// FIXME: expected-error{{expected unqualified-id}}
|
||||
|
||||
|
||||
template<int Z::*pm> struct A7; // expected-note{{template parameter is declared here}}
|
||||
template<int Z::*pm> struct A7c;
|
||||
A7<&Z::int_member> *a18_1;
|
||||
A7c<&Z::int_member> *a18_2;
|
||||
A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float struct Z::*' cannot be converted to a value of type 'int struct Z::*'}} \
|
||||
// FIXME: expected-error{{unqualified-id}}
|
||||
|
|
|
@ -35,7 +35,8 @@ template<typename T> void f(int);
|
|||
// FIXME: we're right to provide an error message, but it should say
|
||||
// that we need a class template. We won't get this right until name
|
||||
// lookup of 'f' returns a TemplateDecl.
|
||||
A<f> *a9; // expected-error{{template argument for template template parameter must be a template}}
|
||||
A<f> *a9; // expected-error{{template argument for template template parameter must be a template}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
|
||||
// FIXME: The code below is ill-formed, because of the evil digraph '<:'.
|
||||
// We should provide a much better error message than we currently do.
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
template<typename T> class A; // expected-note 2 {{template parameter is declared here}}
|
||||
|
||||
// [temp.arg.type]p1
|
||||
A<0> *a1; // expected-error{{template argument for template type parameter must be a type}}
|
||||
A<0> *a1; // expected-error{{template argument for template type parameter must be a type}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
|
||||
A<A> *a2; // expected-error{{template argument for template type parameter must be a type}}
|
||||
A<A> *a2; // expected-error{{template argument for template type parameter must be a type}} \
|
||||
// expected-error{{unqualified-id}}
|
||||
|
||||
A<int> *a3;
|
||||
A<int()> *a4;
|
||||
|
|
Loading…
Reference in New Issue