From b970d0ca9d2e7ad8eecc5bdb2aa1bb959317b304 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 12 Mar 2009 22:20:26 +0000 Subject: [PATCH] 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 --- clang/include/clang/AST/DeclTemplate.h | 36 ++++++++++++++++------ clang/lib/Sema/SemaTemplate.cpp | 3 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 16 +++------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index cc309b4ea5fe..17e5ad0b6756 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -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(&IntegralValue[0]); + return reinterpret_cast(&Integer.Value[0]); } const llvm::APInt *getAsIntegral() const { return const_cast(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: diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ea91a3836a5e..6fc451557177 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 6ed4d9fb4450..6252e29e5682 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -595,19 +595,11 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { Decl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast(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");