From: Douglas Gregor Date: Wed, 4 May 2011 21:55:00 +0000 (+0000) Subject: When converting an integral template argument value to a non-type X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c7469374548b06e50aa8b4d41bf1a35338e9b358;p=clang 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130873 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ef0912485b..7a4e54de0f 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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()) 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); diff --git a/test/SemaTemplate/partial-spec-instantiate.cpp b/test/SemaTemplate/partial-spec-instantiate.cpp index 68b4964816..a93af5026d 100644 --- a/test/SemaTemplate/partial-spec-instantiate.cpp +++ b/test/SemaTemplate/partial-spec-instantiate.cpp @@ -38,3 +38,13 @@ namespace WonkyAccess { return y.m + y2.m; } } + +// +namespace rdar9169404 { + template struct X { }; + template struct X { + typedef int type; + }; + + X::type value; +}