Skip to content

Commit b4f4d51

Browse files
committed
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
1 parent de214e2 commit b4f4d51

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,29 +3501,46 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
35013501
return ExprError();
35023502
}
35033503

3504+
// Add the value of this argument to the list of converted
3505+
// arguments. We use the bitwidth and signedness of the template
3506+
// parameter.
3507+
if (Arg->isValueDependent()) {
3508+
// The argument is value-dependent. Create a new
3509+
// TemplateArgument with the converted expression.
3510+
Converted = TemplateArgument(Arg);
3511+
return Owned(Arg);
3512+
}
3513+
35043514
QualType IntegerType = Context.getCanonicalType(ParamType);
35053515
if (const EnumType *Enum = IntegerType->getAs<EnumType>())
35063516
IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
35073517

3508-
if (!Arg->isValueDependent()) {
3518+
if (ParamType->isBooleanType()) {
3519+
// Value must be zero or one.
3520+
Value = Value != 0;
3521+
unsigned AllowedBits = Context.getTypeSize(IntegerType);
3522+
if (Value.getBitWidth() != AllowedBits)
3523+
Value = Value.extOrTrunc(AllowedBits);
3524+
Value.setIsSigned(IntegerType->isSignedIntegerType());
3525+
} else {
35093526
llvm::APSInt OldValue = Value;
3510-
3527+
35113528
// Coerce the template argument's value to the value it will have
35123529
// based on the template parameter's type.
35133530
unsigned AllowedBits = Context.getTypeSize(IntegerType);
35143531
if (Value.getBitWidth() != AllowedBits)
35153532
Value = Value.extOrTrunc(AllowedBits);
35163533
Value.setIsSigned(IntegerType->isSignedIntegerType());
3517-
3534+
35183535
// Complain if an unsigned parameter received a negative value.
35193536
if (IntegerType->isUnsignedIntegerType()
3520-
&& (OldValue.isSigned() && OldValue.isNegative())) {
3537+
&& (OldValue.isSigned() && OldValue.isNegative())) {
35213538
Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)
35223539
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
35233540
<< Arg->getSourceRange();
35243541
Diag(Param->getLocation(), diag::note_template_param_here);
35253542
}
3526-
3543+
35273544
// Complain if we overflowed the template parameter's type.
35283545
unsigned RequiredBits;
35293546
if (IntegerType->isUnsignedIntegerType())
@@ -3541,16 +3558,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
35413558
}
35423559
}
35433560

3544-
// Add the value of this argument to the list of converted
3545-
// arguments. We use the bitwidth and signedness of the template
3546-
// parameter.
3547-
if (Arg->isValueDependent()) {
3548-
// The argument is value-dependent. Create a new
3549-
// TemplateArgument with the converted expression.
3550-
Converted = TemplateArgument(Arg);
3551-
return Owned(Arg);
3552-
}
3553-
35543561
Converted = TemplateArgument(Value,
35553562
ParamType->isEnumeralType() ? ParamType
35563563
: IntegerType);

clang/test/SemaTemplate/partial-spec-instantiate.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,13 @@ namespace WonkyAccess {
3838
return y.m + y2.m;
3939
}
4040
}
41+
42+
// <rdar://problem/9169404>
43+
namespace rdar9169404 {
44+
template<typename T, T N> struct X { };
45+
template<bool C> struct X<bool, C> {
46+
typedef int type;
47+
};
48+
49+
X<bool, -1>::type value;
50+
}

0 commit comments

Comments
 (0)