//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===/
//
// This file implements C++ template argument deduction.
//
//===----------------------------------------------------------------------===/
#include "Sema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
static Sema::TemplateDeductionResult
DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced);
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
return 0;
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
llvm::APInt Value,
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()) {
Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(),
llvm::APSInt(Value),
NTTP->getType());
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->isSigned() && PrevValuePtr->isNegative()) {
// FIXME: This is wacky; we should be dealing with APSInts and
// checking the actual signs.
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
Info.SecondArg = TemplateArgument(SourceLocation(),
llvm::APSInt(Value),
NTTP->getType());
return Sema::TDK_Inconsistent;
}
llvm::APInt PrevValue = *PrevValuePtr;
if (Value.getBitWidth() > PrevValue.getBitWidth())
PrevValue.zext(Value.getBitWidth());
else if (Value.getBitWidth() < PrevValue.getBitWidth())
Value.zext(PrevValue.getBitWidth());
if (Value != PrevValue) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
Info.SecondArg = TemplateArgument(SourceLocation(),
llvm::APSInt(Value),
NTTP->getType());
return Sema::TDK_Inconsistent;
}
return Sema::TDK_Success;
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given type- or value-dependent expression.
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
assert((Value->isTypeDependent() || Value->isValueDependent()) &&
"Expression template argument must be type- or value-dependent.");
if (Deduced[NTTP->getIndex()].isNull()) {
// FIXME: Clone the Value?
Deduced[NTTP->getIndex()] = TemplateArgument(Value);
return Sema::TDK_Success;
}
if (