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.
}
/// \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;
}
/// \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;
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)
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;
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)
case Integral:
getAsIntegral()->Profile(ID);
+ getIntegralType().Profile(ID);
break;
case Expression:
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");