[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