Store the type of the integral value within a TemplateArgument, so that we can more efficiently reconstruct an IntegerLiteral from it during template instantiation

llvm-svn: 66833
This commit is contained in:
Douglas Gregor 2009-03-12 22:20:26 +00:00
parent dd772264f4
commit b970d0ca9d
3 changed files with 33 additions and 22 deletions

View File

@ -406,7 +406,10 @@ protected:
class TemplateArgument {
union {
uintptr_t TypeOrValue;
char IntegralValue[sizeof(llvm::APInt)];
struct {
char Value[sizeof(llvm::APInt)];
void *Type;
} Integer;
};
/// \brief Location of the beginning of this template argument.
@ -446,9 +449,11 @@ public:
}
/// \brief Construct an integral constant template argument.
TemplateArgument(SourceLocation Loc, const llvm::APInt &Value)
TemplateArgument(SourceLocation Loc, const llvm::APInt &Value,
QualType Type)
: Kind(Integral) {
new (IntegralValue) llvm::APInt(Value);
new (Integer.Value) llvm::APInt(Value);
Integer.Type = Type.getAsOpaquePtr();
StartLoc = Loc;
}
@ -461,8 +466,10 @@ public:
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
if (Kind == Integral)
new (IntegralValue) llvm::APInt(*Other.getAsIntegral());
if (Kind == Integral) {
new (Integer.Value) llvm::APInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
}
else
TypeOrValue = Other.TypeOrValue;
StartLoc = Other.StartLoc;
@ -476,6 +483,7 @@ public:
if (Kind == Other.Kind && Kind == Integral) {
// Copy integral values.
*this->getAsIntegral() = *Other.getAsIntegral();
Integer.Type = Other.Integer.Type;
} else {
// Destroy the current integral value, if that's what we're holding.
if (Kind == Integral)
@ -483,9 +491,10 @@ public:
Kind = Other.Kind;
if (Other.Kind == Integral)
new (IntegralValue) llvm::APInt(*Other.getAsIntegral());
else
if (Other.Kind == Integral) {
new (Integer.Value) llvm::APInt(*Other.getAsIntegral());
Integer.Type = Other.Integer.Type;
} else
TypeOrValue = Other.TypeOrValue;
}
StartLoc = Other.StartLoc;
@ -523,13 +532,21 @@ public:
llvm::APInt *getAsIntegral() {
if (Kind != Integral)
return 0;
return reinterpret_cast<llvm::APInt*>(&IntegralValue[0]);
return reinterpret_cast<llvm::APInt*>(&Integer.Value[0]);
}
const llvm::APInt *getAsIntegral() const {
return const_cast<TemplateArgument*>(this)->getAsIntegral();
}
/// \brief Retrieve the type of the integral value.
QualType getIntegralType() const {
if (Kind != Integral)
return QualType();
return QualType::getFromOpaquePtr(Integer.Type);
}
/// \brief Retrieve the template argument as an expression.
Expr *getAsExpr() const {
if (Kind != Expression)
@ -555,6 +572,7 @@ public:
case Integral:
getAsIntegral()->Profile(ID);
getIntegralType().Profile(ID);
break;
case Expression:

View File

@ -1280,7 +1280,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
IntegerType->isSignedIntegerType());
CanonicalArg = Value;
Converted->push_back(TemplateArgument(StartLoc, CanonicalArg));
Converted->push_back(TemplateArgument(StartLoc, CanonicalArg,
Context.getCanonicalType(IntegerType)));
}
return false;

View File

@ -595,19 +595,11 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
Decl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
assert(NTTP->getDepth() == 0 && "No nested templates yet");
QualType T = NTTP->getType();
if (T->isDependentType()) {
// FIXME: We'll be doing this instantiation a lot. Should we
// cache this information in the TemplateArgument itself?
T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
E->getSourceRange().getBegin(),
NTTP->getDeclName());
if (T.isNull())
return SemaRef.ExprError();
}
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
*TemplateArgs[NTTP->getPosition()].getAsIntegral(),
T, E->getSourceRange().getBegin()));
*Arg.getAsIntegral(),
Arg.getIntegralType(),
E->getSourceRange().getBegin()));
} else
assert(false && "Can't handle arbitrary declaration references");