[cfe-commits] r85500 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ lib/AST/ lib/Frontend/ lib/Sema/
Douglas Gregor
dgregor at apple.com
Thu Oct 29 10:19:43 PDT 2009
On Oct 29, 2009, at 1:12 AM, John McCall wrote:
> Author: rjmccall
> Date: Thu Oct 29 03:12:44 2009
> New Revision: 85500
>
> URL: http://llvm.org/viewvc/llvm-project?rev=85500&view=rev
> Log:
> Track source information for template arguments and template
> specialization
> types. Preserve it through template instantiation. Preserve it
> through PCH,
> although TSTs themselves aren't serializable, so that's pretty much
> meaningless.
Sweet.
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
> +++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Oct 29 03:12:44
> 2009
> @@ -572,11 +572,8 @@
> /// \brief Whether this is a parameter pack.
> bool ParameterPack : 1;
>
> - /// \brief The location of the default argument, if any.
> - SourceLocation DefaultArgumentLoc;
> -
> /// \brief The default template argument, if any.
> - QualType DefaultArgument;
> + DeclaratorInfo *DefaultArgument;
>
> TemplateTypeParmDecl(DeclContext *DC, SourceLocation L,
> IdentifierInfo *Id,
> bool Typename, QualType Type, bool
> ParameterPack)
Oh, cool. I hadn't realized we could use DeclaratorInfo's here, but of
course it makes sense.
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/include/clang/AST/TemplateBase.h (original)
> +++ cfe/trunk/include/clang/AST/TemplateBase.h Thu Oct 29 03:12:44
> 2009
> @@ -16,6 +16,7 @@
> #define LLVM_CLANG_AST_TEMPLATEBASE_H
>
> #include "llvm/ADT/APSInt.h"
> +#include "llvm/Support/ErrorHandling.h"
> #include "clang/AST/Type.h"
>
> namespace llvm {
> @@ -26,6 +27,7 @@
>
> class Decl;
> class Expr;
> +class DeclaratorInfo;
>
> /// \brief Represents a template argument within a class template
> /// specialization.
> @@ -43,9 +45,6 @@
> } Args;
> };
>
> - /// \brief Location of the beginning of this template argument.
> - SourceLocation StartLoc;
> -
Ah, TemplateArguments now have a saner canonical form...
>
> +/// Location information for a TemplateArgument.
> +struct TemplateArgumentLocInfo {
> +private:
> + void *Union;
Since this is storing either an Expr* or a DeclaratorInfo*, why not
use PointerUnion<Expr*, DeclaratorInfo*>? NULL can still represent the
empty state. Then, you won't have to do the #ifndef NDEBUG dance with
the Kind field.
>
> +/// Location wrapper for a TemplateArgument. TemplateArgument is to
> +/// TemplateArgumentLoc as Type is to TypeLoc.
> +class TemplateArgumentLoc {
> + TemplateArgument Argument;
> + TemplateArgumentLocInfo LocInfo;
> +
> + friend class TemplateSpecializationTypeLoc;
> + TemplateArgumentLoc(const TemplateArgument &Argument,
> + TemplateArgumentLocInfo Opaque)
> + : Argument(Argument), LocInfo(Opaque) {
> + }
> +
> +public:
> + TemplateArgumentLoc() {}
> +
> + TemplateArgumentLoc(const TemplateArgument &Argument,
> DeclaratorInfo *DInfo)
> + : Argument(Argument), LocInfo(DInfo) {
> + assert(Argument.getKind() == TemplateArgument::Type);
> + }
> +
> + TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
> + : Argument(Argument), LocInfo(E) {
> + assert(Argument.getKind() == TemplateArgument::Expression);
> + }
> +
> + /// This is a temporary measure.
> + TemplateArgumentLoc(const TemplateArgument &Argument)
> + : Argument(Argument), LocInfo() {
> + assert(Argument.getKind() != TemplateArgument::Expression &&
> + Argument.getKind() != TemplateArgument::Type);
> + }
Is this temporary measure still needed, now that r85501 has gotten rid
of the K_None TemplateArgumentLocInfos?
> + /// \brief - Fetches the start location of the argument, if
> possible.
> + SourceLocation getLocation() const;
It probably also makes sense to have a
SourceRange getSourceRange() const;
so that we can easily identify the whole template argument range.
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=85500&r1=85499&r2=85500&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Oct 29 03:12:44 2009
> @@ -843,7 +846,7 @@
> SawParameterPack = true;
> ParameterPackLoc = NewTypeParm->getLocation();
> } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
> - NewTypeParm->hasDefaultArgument()) {
> + NewTypeParm->hasDefaultArgument()) {
> OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
> NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
> SawDefaultArgument = true;
> @@ -853,8 +856,7 @@
> // Merge the default argument from the old declaration to the
> // new declaration.
> SawDefaultArgument = true;
> - NewTypeParm->setDefaultArgument(OldTypeParm-
> >getDefaultArgument(),
> - OldTypeParm-
> >getDefaultArgumentLoc(),
> + NewTypeParm->setDefaultArgument(OldTypeParm-
> >getDefaultArgumentInfo(),
> true);
> PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
> } else if (NewTypeParm->hasDefaultArgument()) {
> @@ -1096,24 +1098,28 @@
> /// into template arguments used by semantic analysis.
> void Sema::translateTemplateArguments(ASTTemplateArgsPtr
> &TemplateArgsIn,
> SourceLocation *TemplateArgLocs,
> - llvm::SmallVector<TemplateArgument, 16>
> &TemplateArgs) {
> + llvm::SmallVector<TemplateArgumentLoc, 16>
> &TemplateArgs) {
> TemplateArgs.reserve(TemplateArgsIn.size());
>
> void **Args = TemplateArgsIn.getArgs();
> bool *ArgIsType = TemplateArgsIn.getArgIsType();
> for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; +
> +Arg) {
> - TemplateArgs.push_back(
> - ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg],
> - //FIXME: Preserve type
> source info.
> - Sema::GetTypeFromParser(Args
> [Arg]))
> - : TemplateArgument(reinterpret_cast<Expr *>(Args
> [Arg])));
> + if (ArgIsType[Arg]) {
> + DeclaratorInfo *DI;
> + QualType T = Sema::GetTypeFromParser(Args[Arg], &DI);
> + if (!DI) DI = Context.getTrivialDeclaratorInfo(T,
> TemplateArgLocs[Arg]);
> + TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument
> (T), DI));
> + } else {
> + Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
> + TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument
> (E), E));
> + }
> }
> }
>
> QualType Sema::CheckTemplateIdType(TemplateName Name,
> SourceLocation TemplateLoc,
> SourceLocation LAngleLoc,
> - const TemplateArgument
> *TemplateArgs,
> + const TemplateArgumentLoc
> *TemplateArgs,
> unsigned NumTemplateArgs,
> SourceLocation RAngleLoc) {
> TemplateDecl *Template = Name.getAsTemplateDecl();
> @@ -1155,7 +1161,7 @@
> Converted.flatSize
> ());
>
> // FIXME: CanonType is not actually the canonical type, and
> unfortunately
> - // it is a TemplateTypeSpecializationType that we will never
> use again.
> + // it is a TemplateSpecializationType that we will never use
> again.
> // In the future, we need to teach getTemplateSpecializationType
> to only
> // build the canonical type and return that to us.
> CanonType = Context.getCanonicalType(CanonType);
> @@ -1190,7 +1196,6 @@
> // Build the fully-sugared type for this class template
> // specialization, which refers back to the class template
> // specialization we created or found.
> - //FIXME: Preserve type source info.
> return Context.getTemplateSpecializationType(Name, TemplateArgs,
> NumTemplateArgs,
> CanonType);
> }
> @@ -1199,13 +1204,13 @@
> Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation
> TemplateLoc,
> SourceLocation LAngleLoc,
> ASTTemplateArgsPtr TemplateArgsIn,
> - SourceLocation *TemplateArgLocs,
> + SourceLocation *TemplateArgLocsIn,
> SourceLocation RAngleLoc) {
> TemplateName Template = TemplateD.getAsVal<TemplateName>();
>
> // Translate the parser's template argument list in our AST format.
> - llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
> - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs,
> TemplateArgs);
> + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
> + translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn,
> TemplateArgs);
>
> QualType Result = CheckTemplateIdType(Template, TemplateLoc,
> LAngleLoc,
> TemplateArgs.data(),
> @@ -1216,7 +1221,16 @@
> if (Result.isNull())
> return true;
>
> - return Result.getAsOpaquePtr();
> + DeclaratorInfo *DI = Context.CreateDeclaratorInfo(Result);
> + TemplateSpecializationTypeLoc TL
> + = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
> + TL.setTemplateNameLoc(TemplateLoc);
> + TL.setLAngleLoc(LAngleLoc);
> + TL.setRAngleLoc(RAngleLoc);
> + for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
> + TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
> +
> + return CreateLocInfoType(Result, DI).getAsOpaquePtr();
> }
>
> Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
> @@ -1226,7 +1240,9 @@
> if (TypeResult.isInvalid())
> return Sema::TypeResult();
>
> - QualType Type = QualType::getFromOpaquePtr(TypeResult.get());
> + // FIXME: preserve source info, ideally without copying the DI.
> + DeclaratorInfo *DI;
> + QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
>
> // Verify the tag specifier.
> TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
> @@ -1256,7 +1272,7 @@
> TemplateName
> Template,
> SourceLocation
> TemplateNameLoc,
> SourceLocation
> LAngleLoc,
> - const TemplateArgument
> *TemplateArgs,
> + const TemplateArgumentLoc
> *TemplateArgs,
> unsigned
> NumTemplateArgs,
> SourceLocation
> RAngleLoc) {
> // FIXME: Can we do any checking at this point? I guess we could
> check the
> @@ -1296,13 +1312,13 @@
> SourceLocation
> TemplateNameLoc,
> SourceLocation
> LAngleLoc,
> ASTTemplateArgsPtr
> TemplateArgsIn,
> - SourceLocation
> *TemplateArgLocs,
> + SourceLocation
> *TemplateArgSLs,
> SourceLocation
> RAngleLoc) {
> TemplateName Template = TemplateD.getAsVal<TemplateName>();
>
> // Translate the parser's template argument list in our AST format.
> - llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
> - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs,
> TemplateArgs);
> + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
> + translateTemplateArguments(TemplateArgsIn, TemplateArgSLs,
> TemplateArgs);
> TemplateArgsIn.release();
>
> return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
> @@ -1336,7 +1352,7 @@
> Name = Template.getAsDependentTemplateName()->getName();
>
> // Translate the parser's template argument list in our AST format.
> - llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
> + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
> translateTemplateArguments(TemplateArgsIn, TemplateArgLocs,
> TemplateArgs);
> TemplateArgsIn.release();
>
> @@ -1397,8 +1413,10 @@
> }
>
> bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
> - const TemplateArgument &Arg,
> + const TemplateArgumentLoc &AL,
> TemplateArgumentListBuilder
> &Converted) {
> + const TemplateArgument &Arg = AL.getArgument();
> +
> // Check template type parameter.
> if (Arg.getKind() != TemplateArgument::Type) {
> // C++ [temp.arg.type]p1:
> @@ -1407,19 +1425,18 @@
>
> // We have a template type parameter but the template argument
> // is not a type.
> - Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
> + Diag(AL.getLocation(), diag::err_template_arg_must_be_type);
This is one of the places where it might be nice to have
AL.getSourceRange()
> Diag(Param->getLocation(), diag::note_template_param_here);
>
> return true;
> }
>
> - if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation
> ()))
> + if (CheckTemplateArgument(Param, AL.getSourceDeclaratorInfo()))
> return true;
>
> // Add the converted template type argument.
> Converted.Append(
> - TemplateArgument(Arg.getLocation(),
> - Context.getCanonicalType
> (Arg.getAsType())));
> + TemplateArgument(Context.getCanonicalType
> (Arg.getAsType())));
> return false;
> }
>
> @@ -1428,7 +1445,7 @@
> bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
> SourceLocation TemplateLoc,
> SourceLocation LAngleLoc,
> - const TemplateArgument
> *TemplateArgs,
> + const TemplateArgumentLoc
> *TemplateArgs,
> unsigned NumTemplateArgs,
> SourceLocation RAngleLoc,
> bool PartialTemplateArgs,
> @@ -1474,7 +1491,8 @@
> break;
>
> // Decode the template argument
> - TemplateArgument Arg;
> + TemplateArgumentLoc Arg;
> +
> if (ArgIdx >= NumArgs) {
> // Retrieve the default template argument from the template
> // parameter.
> @@ -1489,11 +1507,11 @@
> if (!TTP->hasDefaultArgument())
> break;
>
> - QualType ArgType = TTP->getDefaultArgument();
> + DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo();
>
> // If the argument type is dependent, instantiate it now based
> // on the previously-computed template arguments.
> - if (ArgType->isDependentType()) {
> + if (ArgType->getType()->isDependentType()) {
> InstantiatingTemplate Inst(*this, TemplateLoc,
> Template,
> Converted.getFlatArguments(),
> Converted.flatSize(),
> @@ -1507,10 +1525,10 @@
> TTP->getDeclName());
> }
>
> - if (ArgType.isNull())
> + if (!ArgType)
> return true;
>
> - Arg = TemplateArgument(TTP->getLocation(), ArgType);
> + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType
> ()), ArgType);
> } else if (NonTypeTemplateParmDecl *NTTP
> = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
> if (!NTTP->hasDefaultArgument())
> @@ -1530,7 +1548,8 @@
> if (E.isInvalid())
> return true;
>
> - Arg = TemplateArgument(E.takeAs<Expr>());
> + Expr *Ex = E.takeAs<Expr>();
> + Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
Ex->Retain() when building the template argument?
> } else {
> TemplateTemplateParmDecl *TempParm
> = cast<TemplateTemplateParmDecl>(*Param);
> @@ -1539,7 +1558,8 @@
> break;
>
> // FIXME: Subst default argument
> - Arg = TemplateArgument(TempParm->getDefaultArgument());
> + // FIXME: preserve source information
> + Arg = TemplateArgumentLoc(TemplateArgument(TempParm-
> >getDefaultArgument()));
> }
> } else {
> // Retrieve the template argument produced by the user.
> @@ -1592,13 +1612,13 @@
> }
> }
>
> - switch (Arg.getKind()) {
> + switch (Arg.getArgument().getKind()) {
> case TemplateArgument::Null:
> assert(false && "Should never see a NULL template argument
> here");
> break;
>
> case TemplateArgument::Expression: {
> - Expr *E = Arg.getAsExpr();
> + Expr *E = Arg.getArgument().getAsExpr();
> TemplateArgument Result;
> if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
> Invalid = true;
> @@ -1611,10 +1631,10 @@
> case TemplateArgument::Integral:
> // We've already checked this template argument, so just copy
> // it to the list of converted arguments.
> - Converted.Append(Arg);
> + Converted.Append(Arg.getArgument());
> break;
>
> - case TemplateArgument::Type:
> + case TemplateArgument::Type: {
> // We have a non-type template parameter but the template
> // argument is a type.
>
> @@ -1625,14 +1645,16 @@
> //
> // We warn specifically about this case, since it can be
> rather
> // confusing for users.
> - if (Arg.getAsType()->isFunctionType())
> + QualType T = Arg.getArgument().getAsType();
> + if (T->isFunctionType())
> Diag(Arg.getLocation(),
> diag::err_template_arg_nontype_ambig)
> - << Arg.getAsType();
> + << T;
Another place for AL.getSourceRange()?
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=85500&r1=85499&r2=85500&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Oct 29 03:12:44 2009
>
> +
> +template<typename Derived>
> +bool TreeTransform<Derived>::TransformTemplateArgument(
> + const TemplateArgumentLoc
> &Input,
> + TemplateArgumentLoc
> &Output) {
> + const TemplateArgument &Arg = Input.getArgument();
> switch (Arg.getKind()) {
> case TemplateArgument::Null:
> case TemplateArgument::Integral:
> - return Arg;
> + Output = Input;
> + return false;
>
> case TemplateArgument::Type: {
> - TemporaryBase Rebase(*this, Arg.getLocation(), DeclarationName
> ());
> - QualType T = getDerived().TransformType(Arg.getAsType());
> - if (T.isNull())
> - return TemplateArgument();
> - return TemplateArgument(Arg.getLocation(), T);
> + DeclaratorInfo *DI = Input.getSourceDeclaratorInfo();
> + if (DI == NULL)
> + DI = InventDeclaratorInfo(Input.getArgument().getAsType());
> +
> + DI = getDerived().TransformType(DI);
> + if (!DI) return true;
> +
> + Output = TemplateArgumentLoc(TemplateArgument(DI->getType()),
> DI);
> + return false;
> }
>
> case TemplateArgument::Declaration: {
> + // FIXME: we should never have to transform one of these.
> DeclarationName Name;
> if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
> Name = ND->getDeclName();
> - TemporaryBase Rebase(*this, Arg.getLocation(), Name);
> + TemporaryBase Rebase(*this, SourceLocation(), Name);
> Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
> - if (!D)
> - return TemplateArgument();
> - return TemplateArgument(Arg.getLocation(), D);
> + if (!D) return true;
> +
> + Output = TemplateArgumentLoc(TemplateArgument(D));
> + return false;
> }
Is this FIXME correct? If we've already resolved a template argument
down to a specific declaration (which may be dependent but have known
type/kind), won't we end up just transforming that declaration?
> +template<typename Derived>
> +QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
> + const
> TemplateSpecializationType *TST,
> + QualType
> ObjectType) {
> + // FIXME: this entire method is a temporary workaround; callers
> + // should be rewritten to provide real type locs.
>
> - return Result;
> + // Fake up a TemplateSpecializationTypeLoc.
> + TypeLocBuilder TLB;
> + TemplateSpecializationTypeLoc TL
> + = TLB.push<TemplateSpecializationTypeLoc>(QualType(TST, 0));
> +
> + TL.setTemplateNameLoc(getDerived().getBaseLocation());
> + TL.setLAngleLoc(SourceLocation());
> + TL.setRAngleLoc(SourceLocation());
Could we use getDerived().getBaseLocation() here, so that we don't
lose all source-location information?
This looks great!
- Doug
More information about the cfe-commits
mailing list