Add type-checking and implicit conversions for template parameters of
integral or enumeration type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64256 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5eb2b21..7aab4a5 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -827,7 +827,75 @@
/// This routine implements the semantics of C++ [temp.arg.nontype].
/// It returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
- Expr *Arg) {
+ Expr *&Arg) {
+ // If either the parameter has a dependent type or the argument is
+ // type-dependent, there's nothing we can check now.
+ if (Param->getType()->isDependentType() || Arg->isTypeDependent())
+ return false;
+
+ // C++ [temp.arg.nontype]p5:
+ // The following conversions are performed on each expression used
+ // as a non-type template-argument. If a non-type
+ // template-argument cannot be converted to the type of the
+ // corresponding template-parameter then the program is
+ // ill-formed.
+ //
+ // -- for a non-type template-parameter of integral or
+ // enumeration type, integral promotions (4.5) and integral
+ // conversions (4.7) are applied.
+ QualType ParamType = Param->getType();
+ if (ParamType->isIntegralType() || ParamType->isEnumeralType()) {
+ QualType ArgType = Arg->getType();
+
+ // C++ [temp.arg.nontype]p1:
+ // A template-argument for a non-type, non-template
+ // template-parameter shall be one of:
+ //
+ // -- an integral constant-expression of integral or enumeration
+ // type; or
+ // -- the name of a non-type template-parameter; or
+ SourceLocation NonConstantLoc;
+ if (!ArgType->isIntegralType() && !ArgType->isEnumeralType()) {
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_integral_or_enumeral)
+ << ArgType << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ } else if (!Arg->isValueDependent() &&
+ !Arg->isIntegerConstantExpr(Context, &NonConstantLoc)) {
+ Diag(NonConstantLoc, diag::err_template_arg_not_ice)
+ << ArgType << Arg->getSourceRange();
+ return true;
+ }
+
+ // FIXME: We need some way to more easily get the unqualified form
+ // of the types without going all the way to the
+ // canonical type.
+ if (Context.getCanonicalType(ParamType).getCVRQualifiers())
+ ParamType = Context.getCanonicalType(ParamType).getUnqualifiedType();
+ if (Context.getCanonicalType(ArgType).getCVRQualifiers())
+ ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType();
+
+ // Try to convert the argument to the parameter's type.
+ if (ParamType == ArgType) {
+ // Okay: no conversion necessary
+ } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
+ !ParamType->isEnumeralType()) {
+ // This is an integral promotion or conversion.
+ 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;
+ }
+
+ return false;
+ }
+ // FIXME: p5 has a lot more checks to perform!
+
return false;
}