zcov: / include/clang/AST/TemplateBase.h


Files: 1 Branches Taken: 47.3% 44 / 93
Generated: 2010-02-10 01:31 Branches Executed: 75.3% 70 / 93
Line Coverage: 84.4% 152 / 180


Programs: 40 Runs 63136


       1                 : //===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file provides definitions which are common for all kinds of
      11                 : //  template representation.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
      16                 : #define LLVM_CLANG_AST_TEMPLATEBASE_H
      17                 : 
      18                 : #include "llvm/ADT/APSInt.h"
      19                 : #include "llvm/ADT/SmallVector.h"
      20                 : #include "llvm/Support/ErrorHandling.h"
      21                 : #include "clang/AST/Type.h"
      22                 : #include "clang/AST/TemplateName.h"
      23                 : 
      24                 : namespace llvm {
      25                 :   class FoldingSetNodeID;
      26                 : }
      27                 : 
      28                 : namespace clang {
      29                 : 
      30                 : class Decl;
      31                 : class Expr;
      32                 : class TypeSourceInfo;
      33                 : 
      34                 : /// \brief Represents a template argument within a class template
      35                 : /// specialization.
      36                 : class TemplateArgument {
      37                 :   union {
      38                 :     uintptr_t TypeOrValue;
      39                 :     struct {
      40                 :       char Value[sizeof(llvm::APSInt)];
      41                 :       void *Type;
      42                 :     } Integer;
      43                 :     struct {
      44                 :       TemplateArgument *Args;
      45                 :       unsigned NumArgs;
      46                 :       bool CopyArgs;
      47                 :     } Args;
      48                 :   };
      49                 : 
      50                 : public:
      51                 :   /// \brief The type of template argument we're storing.
      52                 :   enum ArgKind {
      53                 :     /// \brief Represents an empty template argument, e.g., one that has not
      54                 :     /// been deduced.
      55                 :     Null = 0,
      56                 :     /// The template argument is a type. Its value is stored in the
      57                 :     /// TypeOrValue field.
      58                 :     Type,
      59                 :     /// The template argument is a declaration that was provided for a pointer
      60                 :     /// or reference non-type template parameter.
      61                 :     Declaration,
      62                 :     /// The template argument is an integral value stored in an llvm::APSInt
      63                 :     /// that was provided for an integral non-type template parameter. 
      64                 :     Integral,
      65                 :     /// The template argument is a template name that was provided for a 
      66                 :     /// template template parameter.
      67                 :     Template,
      68                 :     /// The template argument is a value- or type-dependent expression
      69                 :     /// stored in an Expr*.
      70                 :     Expression,
      71                 :     /// The template argument is actually a parameter pack. Arguments are stored
      72                 :     /// in the Args struct.
      73                 :     Pack
      74                 :   } Kind;
      75                 : 
      76                 :   /// \brief Construct an empty, invalid template argument.
      77            17596:   TemplateArgument() : TypeOrValue(0), Kind(Null) { }
      78                 : 
      79                 :   /// \brief Construct a template type argument.
      80            12326:   TemplateArgument(QualType T) : Kind(Type) {
      81            12326:     TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
      82            12326:   }
      83                 : 
      84                 :   /// \brief Construct a template argument that refers to a
      85                 :   /// declaration, which is either an external declaration or a
      86                 :   /// template declaration.
      87               79:   TemplateArgument(Decl *D) : Kind(Declaration) {
      88                 :     // FIXME: Need to be sure we have the "canonical" declaration!
      89               79:     TypeOrValue = reinterpret_cast<uintptr_t>(D);
      90               79:   }
      91                 : 
      92                 :   /// \brief Construct an integral constant template argument.
      93             2008:   TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
                     2008: branch 1 taken
                        0: branch 2 not taken
      94             2008:     new (Integer.Value) llvm::APSInt(Value);
      95             2008:     Integer.Type = Type.getAsOpaquePtr();
      96             2008:   }
      97                 : 
      98                 :   /// \brief Construct a template argument that is a template.
      99                 :   ///
     100                 :   /// This form of template argument is generally used for template template
     101                 :   /// parameters. However, the template name could be a dependent template
     102                 :   /// name that ends up being instantiated to a function template whose address
     103                 :   /// is taken.
     104               91:   TemplateArgument(TemplateName Name) : Kind(Template) {
     105               91:     TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
     106               91:   }
     107                 :   
     108                 :   /// \brief Construct a template argument that is an expression.
     109                 :   ///
     110                 :   /// This form of template argument only occurs in template argument
     111                 :   /// lists used for dependent types and for expression; it will not
     112                 :   /// occur in a non-dependent, canonical template argument list.
     113             1856:   TemplateArgument(Expr *E) : Kind(Expression) {
     114             1856:     TypeOrValue = reinterpret_cast<uintptr_t>(E);
     115             1856:   }
     116                 : 
     117                 :   /// \brief Copy constructor for a template argument.
     118            29344:   TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
                      356: branch 0 taken
                    28988: branch 1 taken
     119            29344:     if (Kind == Integral) {
                      356: branch 2 taken
                        0: branch 3 not taken
     120              356:       new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
     121              356:       Integer.Type = Other.Integer.Type;
                        0: branch 0 not taken
                    28988: branch 1 taken
     122            28988:     } else if (Kind == Pack) {
     123                0:       Args.NumArgs = Other.Args.NumArgs;
                        0: branch 2 not taken
                        0: branch 3 not taken
     124                0:       Args.Args = new TemplateArgument[Args.NumArgs];
                        0: branch 0 not taken
                        0: branch 1 not taken
     125                0:       for (unsigned I = 0; I != Args.NumArgs; ++I)
     126                0:         Args.Args[I] = Other.Args.Args[I];
     127                 :     }
     128                 :     else
     129            28988:       TypeOrValue = Other.TypeOrValue;
     130            29344:   }
     131                 : 
     132            16241:   TemplateArgument& operator=(const TemplateArgument& Other) {
     133                 :     // FIXME: Does not provide the strong guarantee for exception
     134                 :     // safety.
     135                 :     using llvm::APSInt;
     136                 : 
     137                 :     // FIXME: Handle Packs
                        0: branch 0 not taken
                    16241: branch 1 taken
     138            16241:     assert(Kind != Pack && "FIXME: Handle packs");
                        0: branch 0 not taken
                    16241: branch 1 taken
     139            16241:     assert(Other.Kind != Pack && "FIXME: Handle packs");
     140                 : 
                      722: branch 0 taken
                    15519: branch 1 taken
                        0: branch 2 not taken
                      722: branch 3 taken
     141            16241:     if (Kind == Other.Kind && Kind == Integral) {
     142                 :       // Copy integral values.
     143                0:       *this->getAsIntegral() = *Other.getAsIntegral();
     144                0:       Integer.Type = Other.Integer.Type;
     145                 :     } else {
     146                 :       // Destroy the current integral value, if that's what we're holding.
                        0: branch 0 not taken
                    16241: branch 1 taken
     147            16241:       if (Kind == Integral)
     148                0:         getAsIntegral()->~APSInt();
     149                 : 
     150            16241:       Kind = Other.Kind;
     151                 : 
                     4697: branch 0 taken
                    11544: branch 1 taken
     152            16241:       if (Other.Kind == Integral) {
                     4697: branch 2 taken
                        0: branch 3 not taken
     153             4697:         new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
     154             4697:         Integer.Type = Other.Integer.Type;
     155                 :       } else
     156            11544:         TypeOrValue = Other.TypeOrValue;
     157                 :     }
     158                 : 
     159            16241:     return *this;
     160                 :   }
     161                 : 
     162            49232:   ~TemplateArgument() {
     163                 :     using llvm::APSInt;
     164                 : 
                     5331: branch 0 taken
                    43901: branch 1 taken
     165            49232:     if (Kind == Integral)
     166             5331:       getAsIntegral()->~APSInt();
                        0: branch 0 not taken
                    43901: branch 1 taken
                    43901: branch 2 taken
                    43901: branch 3 taken
     167            43901:     else if (Kind == Pack && Args.CopyArgs)
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     168                0:       delete[] Args.Args;
     169            49232:   }
     170                 : 
     171                 :   /// \brief Return the kind of stored template argument.
     172            58051:   ArgKind getKind() const { return Kind; }
     173                 : 
     174                 :   /// \brief Determine whether this template argument has no value.
     175             7509:   bool isNull() const { return Kind == Null; }
     176                 : 
     177                 :   /// \brief Retrieve the template argument as a type.
     178            32633:   QualType getAsType() const {
                        0: branch 0 not taken
                    32633: branch 1 taken
     179            32633:     if (Kind != Type)
     180                0:       return QualType();
     181                 : 
     182            32633:     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
     183                 :   }
     184                 : 
     185                 :   /// \brief Retrieve the template argument as a declaration.
     186              261:   Decl *getAsDecl() const {
                        0: branch 0 not taken
                      261: branch 1 taken
     187              261:     if (Kind != Declaration)
     188                0:       return 0;
     189              261:     return reinterpret_cast<Decl *>(TypeOrValue);
     190                 :   }
     191                 : 
     192                 :   /// \brief Retrieve the template argument as a template name.
     193              235:   TemplateName getAsTemplate() const {
                        0: branch 0 not taken
                      235: branch 1 taken
     194              235:     if (Kind != Template)
     195                0:       return TemplateName();
     196                 :     
     197                 :     return TemplateName::getFromVoidPointer(
     198              235:                                         reinterpret_cast<void *> (TypeOrValue));
     199                 :   }
     200                 :   
     201                 :   /// \brief Retrieve the template argument as an integral value.
     202            18098:   llvm::APSInt *getAsIntegral() {
                        0: branch 0 not taken
                    18098: branch 1 taken
     203            18098:     if (Kind != Integral)
     204                0:       return 0;
     205            18098:     return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
     206                 :   }
     207                 : 
     208            12764:   const llvm::APSInt *getAsIntegral() const {
     209            12764:     return const_cast<TemplateArgument*>(this)->getAsIntegral();
     210                 :   }
     211                 : 
     212                 :   /// \brief Retrieve the type of the integral value.
     213             4354:   QualType getIntegralType() const {
                        0: branch 1 not taken
                        0: branch 1 not taken
     214             4354:     if (Kind != Integral)
     215                0:       return QualType();
     216                 : 
     217             4354:     return QualType::getFromOpaquePtr(Integer.Type);
     218                 :   }
     219                 : 
     220                 :   void setIntegralType(QualType T) {
     221                 :     assert(Kind == Integral &&
     222                 :            "Cannot set the integral type of a non-integral template argument");
     223                 :     Integer.Type = T.getAsOpaquePtr();
     224                 :   }
     225                 : 
     226                 :   /// \brief Retrieve the template argument as an expression.
     227             8931:   Expr *getAsExpr() const {
                        8: branch 1 taken
                     8923: branch 1 taken
     228             8931:     if (Kind != Expression)
     229                8:       return 0;
     230                 : 
     231             8923:     return reinterpret_cast<Expr *>(TypeOrValue);
     232                 :   }
     233                 : 
     234                 :   /// \brief Iterator that traverses the elements of a template argument pack.
     235                 :   typedef const TemplateArgument * pack_iterator;
     236                 : 
     237                 :   /// \brief Iterator referencing the first argument of a template argument
     238                 :   /// pack.
     239                0:   pack_iterator pack_begin() const {
                        0: branch 0 not taken
                        0: branch 1 not taken
     240                0:     assert(Kind == Pack);
     241                0:     return Args.Args;
     242                 :   }
     243                 : 
     244                 :   /// \brief Iterator referencing one past the last argument of a template
     245                 :   /// argument pack.
     246                0:   pack_iterator pack_end() const {
                        0: branch 1 not taken
                        0: branch 1 not taken
     247                0:     assert(Kind == Pack);
     248                0:     return Args.Args + Args.NumArgs;
     249                 :   }
     250                 : 
     251                 :   /// \brief The number of template arguments in the given template argument
     252                 :   /// pack.
     253                0:   unsigned pack_size() const {
                        0: branch 0 not taken
                        0: branch 1 not taken
     254                0:     assert(Kind == Pack);
     255                0:     return Args.NumArgs;
     256                 :   }
     257                 : 
     258                 :   /// \brief Construct a template argument pack.
     259                 :   void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
     260                 : 
     261                 :   /// \brief Used to insert TemplateArguments into FoldingSets.
     262                 :   void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
     263                 : };
     264                 : 
     265                 : /// Location information for a TemplateArgument.
     266                 : struct TemplateArgumentLocInfo {
     267                 : private:
     268                 :   union {
     269                 :     Expr *Expression;
     270                 :     TypeSourceInfo *Declarator;
     271                 :     struct {
     272                 :       unsigned QualifierRange[2];
     273                 :       unsigned TemplateNameLoc;
     274                 :     } Template;
     275                 :   };
     276                 : 
     277                 : #ifndef NDEBUG
     278                 :   enum Kind {
     279                 :     K_None,
     280                 :     K_TypeSourceInfo,
     281                 :     K_Expression,
     282                 :     K_Template
     283                 :   } Kind;
     284                 : #endif
     285                 : 
     286                 : public:
     287             4422:   TemplateArgumentLocInfo()
     288                 :     : Expression(0)
     289                 : #ifndef NDEBUG
     290             4422:       , Kind(K_None) 
     291                 : #endif
     292             4422:     {}
     293                 :   
     294             4572:   TemplateArgumentLocInfo(TypeSourceInfo *TInfo)
     295                 :     : Declarator(TInfo)
     296                 : #ifndef NDEBUG
     297             4572:       , Kind(K_TypeSourceInfo) 
     298                 : #endif
     299             4572:     {}
     300                 :   
     301             2616:   TemplateArgumentLocInfo(Expr *E)
     302                 :     : Expression(E)
     303                 : #ifndef NDEBUG
     304             2616:       , Kind(K_Expression) 
     305                 : #endif
     306             2616:     {}
     307                 :   
     308                 :   TemplateArgumentLocInfo(SourceRange QualifierRange, 
     309               54:                           SourceLocation TemplateNameLoc)
     310                 : #ifndef NDEBUG
     311               54:     : Kind(K_Template)
     312                 : #endif
     313                 :   {
     314               54:     Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
     315               54:     Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
     316               54:     Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
     317               54:   }
     318                 : 
     319             4897:   TypeSourceInfo *getAsTypeSourceInfo() const {
                     4897: branch 1 taken
     320             4897:     assert(Kind == K_TypeSourceInfo);
     321             4897:     return Declarator;
     322                 :   }
     323                 : 
     324             1198:   Expr *getAsExpr() const {
                        0: branch 0 not taken
                     1198: branch 1 taken
     325             1198:     assert(Kind == K_Expression);
     326             1198:     return Expression;
     327                 :   }
     328                 : 
     329               24:   SourceRange getTemplateQualifierRange() const {
                        0: branch 0 not taken
                       24: branch 1 taken
     330               24:     assert(Kind == K_Template);
     331                 :     return SourceRange(
     332                 :                 SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
     333               24:                 SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
     334                 :   }
     335                 :   
     336               83:   SourceLocation getTemplateNameLoc() const {
                        0: branch 0 not taken
                       83: branch 1 taken
     337               83:     assert(Kind == K_Template);
     338               83:     return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
     339                 :   }
     340                 :   
     341                 : #ifndef NDEBUG
     342             4034:   void validateForArgument(const TemplateArgument &Arg) {
                     2731: branch 1 taken
                     1281: branch 2 taken
                       22: branch 3 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     343             4034:     switch (Arg.getKind()) {
     344                 :     case TemplateArgument::Type:
                        0: branch 0 not taken
                     2731: branch 1 taken
     345             2731:       assert(Kind == K_TypeSourceInfo);
     346             2731:       break;
     347                 :     case TemplateArgument::Expression:
     348                 :     case TemplateArgument::Declaration:
                        0: branch 0 not taken
                     1281: branch 1 taken
     349             1281:       assert(Kind == K_Expression);
     350             1281:       break;
     351                 :     case TemplateArgument::Template:
                        0: branch 0 not taken
                       22: branch 1 taken
     352               22:       assert(Kind == K_Template);
     353               22:       break;
     354                 :     case TemplateArgument::Integral:
     355                 :     case TemplateArgument::Pack:
                        0: branch 0 not taken
                        0: branch 1 not taken
     356                0:       assert(Kind == K_None);
     357                0:       break;
     358                 :     case TemplateArgument::Null:
     359                0:       llvm_unreachable("source info for null template argument?");
     360                 :     }
     361             4034:   }
     362                 : #endif
     363                 : };
     364                 : 
     365                 : /// Location wrapper for a TemplateArgument.  TemplateArgument is to
     366                 : /// TemplateArgumentLoc as Type is to TypeLoc.
     367            24308: class TemplateArgumentLoc {
     368                 :   TemplateArgument Argument;
     369                 :   TemplateArgumentLocInfo LocInfo;
     370                 : 
     371                 : public:
     372             2717:   TemplateArgumentLoc() {}
     373                 : 
     374                 :   TemplateArgumentLoc(const TemplateArgument &Argument,
     375             1835:                       TemplateArgumentLocInfo Opaque)
     376             1835:     : Argument(Argument), LocInfo(Opaque) {
     377             1835:   }
     378                 : 
     379             3773:   TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
     380             3773:     : Argument(Argument), LocInfo(TInfo) {
                     3773: branch 2 taken
                        0: branch 2 not taken
     381             3773:     assert(Argument.getKind() == TemplateArgument::Type);
     382             3773:   }
     383                 : 
     384             1710:   TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
     385             1710:     : Argument(Argument), LocInfo(E) {
                        0: branch 1 not taken
                     1710: branch 2 taken
     386             1710:     assert(Argument.getKind() == TemplateArgument::Expression);
     387             1710:   }
     388                 : 
     389                 :   TemplateArgumentLoc(const TemplateArgument &Argument, 
     390                 :                       SourceRange QualifierRange,
     391               54:                       SourceLocation TemplateNameLoc)
     392               54:     : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
                        0: branch 1 not taken
                       54: branch 2 taken
     393               54:     assert(Argument.getKind() == TemplateArgument::Template);
     394               54:   }
     395                 :   
     396                 :   /// \brief - Fetches the primary location of the argument.
     397               58:   SourceLocation getLocation() const {
                       56: branch 1 taken
                        2: branch 2 taken
     398               58:     if (Argument.getKind() == TemplateArgument::Template)
     399               56:       return getTemplateNameLoc();
     400                 :     
     401                2:     return getSourceRange().getBegin();
     402                 :   }
     403                 : 
     404                 :   /// \brief - Fetches the full source range of the argument.
     405                 :   SourceRange getSourceRange() const;
     406                 : 
     407            20346:   const TemplateArgument &getArgument() const {
     408            20346:     return Argument;
     409                 :   }
     410                 : 
     411             4034:   TemplateArgumentLocInfo getLocInfo() const {
     412             4034:     return LocInfo;
     413                 :   }
     414                 : 
     415             4897:   TypeSourceInfo *getTypeSourceInfo() const {
                        0: branch 1 not taken
                     4897: branch 2 taken
     416             4897:     assert(Argument.getKind() == TemplateArgument::Type);
     417             4897:     return LocInfo.getAsTypeSourceInfo();
     418                 :   }
     419                 : 
     420             1198:   Expr *getSourceExpression() const {
                        0: branch 1 not taken
                     1198: branch 2 taken
     421             1198:     assert(Argument.getKind() == TemplateArgument::Expression);
     422             1198:     return LocInfo.getAsExpr();
     423                 :   }
     424                 : 
     425                0:   Expr *getSourceDeclExpression() const {
                        0: branch 1 not taken
                        0: branch 2 not taken
     426                0:     assert(Argument.getKind() == TemplateArgument::Declaration);
     427                0:     return LocInfo.getAsExpr();
     428                 :   }
     429                 :   
     430               24:   SourceRange getTemplateQualifierRange() const {
                        0: branch 1 not taken
                       24: branch 2 taken
     431               24:     assert(Argument.getKind() == TemplateArgument::Template);
     432               24:     return LocInfo.getTemplateQualifierRange();
     433                 :   }
     434                 :   
     435               83:   SourceLocation getTemplateNameLoc() const {
                        0: branch 1 not taken
                       83: branch 2 taken
     436               83:     assert(Argument.getKind() == TemplateArgument::Template);
     437               83:     return LocInfo.getTemplateNameLoc();
     438                 :   }  
     439                 : };
     440                 : 
     441                 : /// A convenient class for passing around template argument
     442                 : /// information.  Designed to be passed by reference.
     443            53081: class TemplateArgumentListInfo {
     444                 :   llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
     445                 :   SourceLocation LAngleLoc;
     446                 :   SourceLocation RAngleLoc;
     447                 : 
     448                 : public:
     449            50969:   TemplateArgumentListInfo() {}
     450                 : 
     451                 :   TemplateArgumentListInfo(SourceLocation LAngleLoc,
     452             2112:                            SourceLocation RAngleLoc)
     453             2112:     : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
     454                 : 
     455              315:   SourceLocation getLAngleLoc() const { return LAngleLoc; }
     456             4427:   SourceLocation getRAngleLoc() const { return RAngleLoc; }
     457                 : 
     458             2097:   void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
     459             2097:   void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
     460                 : 
     461            17195:   unsigned size() const { return Arguments.size(); }
     462                 : 
     463             3307:   const TemplateArgumentLoc *getArgumentArray() const {
     464             3307:     return Arguments.data();
     465                 :   }
     466                 : 
     467            14626:   const TemplateArgumentLoc &operator[](unsigned I) const {
     468            14626:     return Arguments[I];
     469                 :   }
     470                 : 
     471             5770:   void addArgument(const TemplateArgumentLoc &Loc) {
     472             5770:     Arguments.push_back(Loc);
     473             5770:   }
     474                 : };
     475                 : 
     476                 : }
     477                 : 
     478                 : #endif

Generated: 2010-02-10 01:31 by zcov