When converting an integral template argument value to a non-type

template parameter of type 'bool', force the value to be zero or
one. Fixes <rdar://problem/9169404>.

llvm-svn: 130873
This commit is contained in:
Douglas Gregor 2011-05-04 21:55:00 +00:00
parent de214e29df
commit b4f4d512ad
2 changed files with 32 additions and 15 deletions

View File

@ -3501,29 +3501,46 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return ExprError();
}
// Add the value of this argument to the list of converted
// arguments. We use the bitwidth and signedness of the template
// parameter.
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
return Owned(Arg);
}
QualType IntegerType = Context.getCanonicalType(ParamType);
if (const EnumType *Enum = IntegerType->getAs<EnumType>())
IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
if (!Arg->isValueDependent()) {
if (ParamType->isBooleanType()) {
// Value must be zero or one.
Value = Value != 0;
unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerType());
} else {
llvm::APSInt OldValue = Value;
// Coerce the template argument's value to the value it will have
// based on the template parameter's type.
unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerType());
// Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerType()
&& (OldValue.isSigned() && OldValue.isNegative())) {
&& (OldValue.isSigned() && OldValue.isNegative())) {
Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
// Complain if we overflowed the template parameter's type.
unsigned RequiredBits;
if (IntegerType->isUnsignedIntegerType())
@ -3541,16 +3558,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
}
// Add the value of this argument to the list of converted
// arguments. We use the bitwidth and signedness of the template
// parameter.
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
return Owned(Arg);
}
Converted = TemplateArgument(Value,
ParamType->isEnumeralType() ? ParamType
: IntegerType);

View File

@ -38,3 +38,13 @@ namespace WonkyAccess {
return y.m + y2.m;
}
}
// <rdar://problem/9169404>
namespace rdar9169404 {
template<typename T, T N> struct X { };
template<bool C> struct X<bool, C> {
typedef int type;
};
X<bool, -1>::type value;
}