When deducing an integral template argument for a non-type template

parameter, keep the integral value exactly as it was in the source
code rather than trying to convert it to the type of the non-type
template parameter (which may still be dependent!). The value will
then be converted to the appropriate type once we check the resulting
template arguments. Fixes PR6707.

llvm-svn: 99611
This commit is contained in:
Douglas Gregor 2010-03-26 05:50:28 +00:00
parent e0b2ddb492
commit 0a29a05f02
1 changed files with 35 additions and 32 deletions

View File

@ -48,6 +48,27 @@ namespace clang {
using namespace clang;
/// \brief Compare two APSInts, extending and switching the sign as
/// necessary to compare their values regardless of underlying type.
static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
if (Y.getBitWidth() > X.getBitWidth())
X.extend(Y.getBitWidth());
else if (Y.getBitWidth() < X.getBitWidth())
Y.extend(X.getBitWidth());
// If there is a signedness mismatch, correct it.
if (X.isSigned() != Y.isSigned()) {
// If the signed value is negative, then the values cannot be the same.
if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative()))
return false;
Y.setIsSigned(true);
X.setIsSigned(true);
}
return X == Y;
}
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
@ -74,47 +95,30 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value,
llvm::APSInt Value, QualType ValueType,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
if (Deduced[NTTP->getIndex()].isNull()) {
QualType T = NTTP->getType();
// FIXME: Make sure we didn't overflow our data type!
unsigned AllowedBits = S.Context.getTypeSize(T);
if (Value.getBitWidth() != AllowedBits)
Value.extOrTrunc(AllowedBits);
Value.setIsSigned(T->isSignedIntegerType());
Deduced[NTTP->getIndex()] = TemplateArgument(Value, T);
Deduced[NTTP->getIndex()] = TemplateArgument(Value, ValueType);
return Sema::TDK_Success;
}
assert(Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral);
// If the template argument was previously deduced to a negative value,
// then our deduction fails.
const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
if (PrevValuePtr->isNegative()) {
if (Deduced[NTTP->getIndex()].getKind() != TemplateArgument::Integral) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
Info.SecondArg = TemplateArgument(Value, NTTP->getType());
Info.SecondArg = TemplateArgument(Value, ValueType);
return Sema::TDK_Inconsistent;
}
llvm::APSInt PrevValue = *PrevValuePtr;
if (Value.getBitWidth() > PrevValue.getBitWidth())
PrevValue.zext(Value.getBitWidth());
else if (Value.getBitWidth() < PrevValue.getBitWidth())
Value.zext(PrevValue.getBitWidth());
if (Value != PrevValue) {
// Extent the smaller of the two values.
llvm::APSInt PrevValue = *Deduced[NTTP->getIndex()].getAsIntegral();
if (!hasSameExtendedValue(PrevValue, Value)) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
Info.SecondArg = TemplateArgument(Value, NTTP->getType());
Info.SecondArg = TemplateArgument(Value, ValueType);
return Sema::TDK_Inconsistent;
}
@ -137,8 +141,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
"Expression template argument must be type- or value-dependent.");
if (Deduced[NTTP->getIndex()].isNull()) {
// FIXME: Clone the Value?
Deduced[NTTP->getIndex()] = TemplateArgument(Value);
Deduced[NTTP->getIndex()] = TemplateArgument(Value->Retain());
return Sema::TDK_Success;
}
@ -570,6 +573,7 @@ DeduceTemplateArguments(Sema &S,
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
return DeduceNonTypeTemplateArgument(S, NTTP, Size,
S.Context.getSizeType(),
Info, Deduced);
}
if (const DependentSizedArrayType *DependentArrayArg
@ -816,8 +820,7 @@ DeduceTemplateArguments(Sema &S,
case TemplateArgument::Integral:
if (Arg.getKind() == TemplateArgument::Integral) {
// FIXME: Zero extension + sign checking here?
if (*Param.getAsIntegral() == *Arg.getAsIntegral())
if (hasSameExtendedValue(*Param.getAsIntegral(), *Arg.getAsIntegral()))
return Sema::TDK_Success;
Info.FirstArg = Param;
@ -840,9 +843,9 @@ DeduceTemplateArguments(Sema &S,
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
// FIXME: Sign problems here
return DeduceNonTypeTemplateArgument(S, NTTP,
*Arg.getAsIntegral(),
Arg.getIntegralType(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),