Home | History | Annotate | Download | only in AST
      1 //===--- TemplateBase.cpp - Common template AST class implementation ------===//
      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 implements common classes used throughout C++ template
     11 // representations.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/AST/TemplateBase.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/DeclBase.h"
     18 #include "clang/AST/DeclTemplate.h"
     19 #include "clang/AST/Expr.h"
     20 #include "clang/AST/ExprCXX.h"
     21 #include "clang/AST/Type.h"
     22 #include "clang/AST/TypeLoc.h"
     23 #include "clang/Basic/Diagnostic.h"
     24 #include "llvm/ADT/FoldingSet.h"
     25 #include "llvm/ADT/SmallString.h"
     26 #include "llvm/Support/raw_ostream.h"
     27 #include <algorithm>
     28 
     29 using namespace clang;
     30 
     31 /// \brief Print a template integral argument value.
     32 ///
     33 /// \param TemplArg the TemplateArgument instance to print.
     34 ///
     35 /// \param Out the raw_ostream instance to use for printing.
     36 ///
     37 /// \param Policy the printing policy for EnumConstantDecl printing.
     38 static void printIntegral(const TemplateArgument &TemplArg,
     39                           raw_ostream &Out, const PrintingPolicy& Policy) {
     40   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
     41   const llvm::APSInt &Val = TemplArg.getAsIntegral();
     42 
     43   if (const EnumType *ET = T->getAs<EnumType>()) {
     44     for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
     45       // In Sema::CheckTemplateArugment, enum template arguments value are
     46       // extended to the size of the integer underlying the enum type.  This
     47       // may create a size difference between the enum value and template
     48       // argument value, requiring isSameValue here instead of operator==.
     49       if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
     50         ECD->printQualifiedName(Out, Policy);
     51         return;
     52       }
     53     }
     54   }
     55 
     56   if (T->isBooleanType() && !Policy.MSVCFormatting) {
     57     Out << (Val.getBoolValue() ? "true" : "false");
     58   } else if (T->isCharType()) {
     59     const char Ch = Val.getZExtValue();
     60     Out << ((Ch == '\'') ? "'\\" : "'");
     61     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
     62     Out << "'";
     63   } else {
     64     Out << Val;
     65   }
     66 }
     67 
     68 //===----------------------------------------------------------------------===//
     69 // TemplateArgument Implementation
     70 //===----------------------------------------------------------------------===//
     71 
     72 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
     73                                    QualType Type) {
     74   Integer.Kind = Integral;
     75   // Copy the APSInt value into our decomposed form.
     76   Integer.BitWidth = Value.getBitWidth();
     77   Integer.IsUnsigned = Value.isUnsigned();
     78   // If the value is large, we have to get additional memory from the ASTContext
     79   unsigned NumWords = Value.getNumWords();
     80   if (NumWords > 1) {
     81     void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
     82     std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
     83     Integer.pVal = static_cast<uint64_t *>(Mem);
     84   } else {
     85     Integer.VAL = Value.getZExtValue();
     86   }
     87 
     88   Integer.Type = Type.getAsOpaquePtr();
     89 }
     90 
     91 TemplateArgument
     92 TemplateArgument::CreatePackCopy(ASTContext &Context,
     93                                  ArrayRef<TemplateArgument> Args) {
     94   if (Args.empty())
     95     return getEmptyPack();
     96 
     97   return TemplateArgument(Args.copy(Context));
     98 }
     99 
    100 bool TemplateArgument::isDependent() const {
    101   switch (getKind()) {
    102   case Null:
    103     llvm_unreachable("Should not have a NULL template argument");
    104 
    105   case Type:
    106     return getAsType()->isDependentType() ||
    107            isa<PackExpansionType>(getAsType());
    108 
    109   case Template:
    110     return getAsTemplate().isDependent();
    111 
    112   case TemplateExpansion:
    113     return true;
    114 
    115   case Declaration:
    116     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
    117       return DC->isDependentContext();
    118     return getAsDecl()->getDeclContext()->isDependentContext();
    119 
    120   case NullPtr:
    121     return false;
    122 
    123   case Integral:
    124     // Never dependent
    125     return false;
    126 
    127   case Expression:
    128     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
    129             isa<PackExpansionExpr>(getAsExpr()));
    130 
    131   case Pack:
    132     for (const auto &P : pack_elements())
    133       if (P.isDependent())
    134         return true;
    135     return false;
    136   }
    137 
    138   llvm_unreachable("Invalid TemplateArgument Kind!");
    139 }
    140 
    141 bool TemplateArgument::isInstantiationDependent() const {
    142   switch (getKind()) {
    143   case Null:
    144     llvm_unreachable("Should not have a NULL template argument");
    145 
    146   case Type:
    147     return getAsType()->isInstantiationDependentType();
    148 
    149   case Template:
    150     return getAsTemplate().isInstantiationDependent();
    151 
    152   case TemplateExpansion:
    153     return true;
    154 
    155   case Declaration:
    156     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
    157       return DC->isDependentContext();
    158     return getAsDecl()->getDeclContext()->isDependentContext();
    159 
    160   case NullPtr:
    161     return false;
    162 
    163   case Integral:
    164     // Never dependent
    165     return false;
    166 
    167   case Expression:
    168     return getAsExpr()->isInstantiationDependent();
    169 
    170   case Pack:
    171     for (const auto &P : pack_elements())
    172       if (P.isInstantiationDependent())
    173         return true;
    174     return false;
    175   }
    176 
    177   llvm_unreachable("Invalid TemplateArgument Kind!");
    178 }
    179 
    180 bool TemplateArgument::isPackExpansion() const {
    181   switch (getKind()) {
    182   case Null:
    183   case Declaration:
    184   case Integral:
    185   case Pack:
    186   case Template:
    187   case NullPtr:
    188     return false;
    189 
    190   case TemplateExpansion:
    191     return true;
    192 
    193   case Type:
    194     return isa<PackExpansionType>(getAsType());
    195 
    196   case Expression:
    197     return isa<PackExpansionExpr>(getAsExpr());
    198   }
    199 
    200   llvm_unreachable("Invalid TemplateArgument Kind!");
    201 }
    202 
    203 bool TemplateArgument::containsUnexpandedParameterPack() const {
    204   switch (getKind()) {
    205   case Null:
    206   case Declaration:
    207   case Integral:
    208   case TemplateExpansion:
    209   case NullPtr:
    210     break;
    211 
    212   case Type:
    213     if (getAsType()->containsUnexpandedParameterPack())
    214       return true;
    215     break;
    216 
    217   case Template:
    218     if (getAsTemplate().containsUnexpandedParameterPack())
    219       return true;
    220     break;
    221 
    222   case Expression:
    223     if (getAsExpr()->containsUnexpandedParameterPack())
    224       return true;
    225     break;
    226 
    227   case Pack:
    228     for (const auto &P : pack_elements())
    229       if (P.containsUnexpandedParameterPack())
    230         return true;
    231 
    232     break;
    233   }
    234 
    235   return false;
    236 }
    237 
    238 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
    239   assert(getKind() == TemplateExpansion);
    240   if (TemplateArg.NumExpansions)
    241     return TemplateArg.NumExpansions - 1;
    242 
    243   return None;
    244 }
    245 
    246 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
    247                                const ASTContext &Context) const {
    248   ID.AddInteger(getKind());
    249   switch (getKind()) {
    250   case Null:
    251     break;
    252 
    253   case Type:
    254     getAsType().Profile(ID);
    255     break;
    256 
    257   case NullPtr:
    258     getNullPtrType().Profile(ID);
    259     break;
    260 
    261   case Declaration:
    262     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
    263     break;
    264 
    265   case Template:
    266   case TemplateExpansion: {
    267     TemplateName Template = getAsTemplateOrTemplatePattern();
    268     if (TemplateTemplateParmDecl *TTP
    269           = dyn_cast_or_null<TemplateTemplateParmDecl>(
    270                                                 Template.getAsTemplateDecl())) {
    271       ID.AddBoolean(true);
    272       ID.AddInteger(TTP->getDepth());
    273       ID.AddInteger(TTP->getPosition());
    274       ID.AddBoolean(TTP->isParameterPack());
    275     } else {
    276       ID.AddBoolean(false);
    277       ID.AddPointer(Context.getCanonicalTemplateName(Template)
    278                                                           .getAsVoidPointer());
    279     }
    280     break;
    281   }
    282 
    283   case Integral:
    284     getAsIntegral().Profile(ID);
    285     getIntegralType().Profile(ID);
    286     break;
    287 
    288   case Expression:
    289     getAsExpr()->Profile(ID, Context, true);
    290     break;
    291 
    292   case Pack:
    293     ID.AddInteger(Args.NumArgs);
    294     for (unsigned I = 0; I != Args.NumArgs; ++I)
    295       Args.Args[I].Profile(ID, Context);
    296   }
    297 }
    298 
    299 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
    300   if (getKind() != Other.getKind()) return false;
    301 
    302   switch (getKind()) {
    303   case Null:
    304   case Type:
    305   case Expression:
    306   case Template:
    307   case TemplateExpansion:
    308   case NullPtr:
    309     return TypeOrValue.V == Other.TypeOrValue.V;
    310 
    311   case Declaration:
    312     return getAsDecl() == Other.getAsDecl();
    313 
    314   case Integral:
    315     return getIntegralType() == Other.getIntegralType() &&
    316            getAsIntegral() == Other.getAsIntegral();
    317 
    318   case Pack:
    319     if (Args.NumArgs != Other.Args.NumArgs) return false;
    320     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
    321       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
    322         return false;
    323     return true;
    324   }
    325 
    326   llvm_unreachable("Invalid TemplateArgument Kind!");
    327 }
    328 
    329 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
    330   assert(isPackExpansion());
    331 
    332   switch (getKind()) {
    333   case Type:
    334     return getAsType()->getAs<PackExpansionType>()->getPattern();
    335 
    336   case Expression:
    337     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
    338 
    339   case TemplateExpansion:
    340     return TemplateArgument(getAsTemplateOrTemplatePattern());
    341 
    342   case Declaration:
    343   case Integral:
    344   case Pack:
    345   case Null:
    346   case Template:
    347   case NullPtr:
    348     return TemplateArgument();
    349   }
    350 
    351   llvm_unreachable("Invalid TemplateArgument Kind!");
    352 }
    353 
    354 void TemplateArgument::print(const PrintingPolicy &Policy,
    355                              raw_ostream &Out) const {
    356   switch (getKind()) {
    357   case Null:
    358     Out << "(no value)";
    359     break;
    360 
    361   case Type: {
    362     PrintingPolicy SubPolicy(Policy);
    363     SubPolicy.SuppressStrongLifetime = true;
    364     getAsType().print(Out, SubPolicy);
    365     break;
    366   }
    367 
    368   case Declaration: {
    369     NamedDecl *ND = cast<NamedDecl>(getAsDecl());
    370     Out << '&';
    371     if (ND->getDeclName()) {
    372       // FIXME: distinguish between pointer and reference args?
    373       ND->printQualifiedName(Out);
    374     } else {
    375       Out << "(anonymous)";
    376     }
    377     break;
    378   }
    379 
    380   case NullPtr:
    381     Out << "nullptr";
    382     break;
    383 
    384   case Template:
    385     getAsTemplate().print(Out, Policy);
    386     break;
    387 
    388   case TemplateExpansion:
    389     getAsTemplateOrTemplatePattern().print(Out, Policy);
    390     Out << "...";
    391     break;
    392 
    393   case Integral: {
    394     printIntegral(*this, Out, Policy);
    395     break;
    396   }
    397 
    398   case Expression:
    399     getAsExpr()->printPretty(Out, nullptr, Policy);
    400     break;
    401 
    402   case Pack:
    403     Out << "<";
    404     bool First = true;
    405     for (const auto &P : pack_elements()) {
    406       if (First)
    407         First = false;
    408       else
    409         Out << ", ";
    410 
    411       P.print(Policy, Out);
    412     }
    413     Out << ">";
    414     break;
    415   }
    416 }
    417 
    418 void TemplateArgument::dump(raw_ostream &Out) const {
    419   LangOptions LO; // FIXME! see also TemplateName::dump().
    420   LO.CPlusPlus = true;
    421   LO.Bool = true;
    422   print(PrintingPolicy(LO), Out);
    423 }
    424 
    425 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
    426 
    427 //===----------------------------------------------------------------------===//
    428 // TemplateArgumentLoc Implementation
    429 //===----------------------------------------------------------------------===//
    430 
    431 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
    432   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
    433 }
    434 
    435 SourceRange TemplateArgumentLoc::getSourceRange() const {
    436   switch (Argument.getKind()) {
    437   case TemplateArgument::Expression:
    438     return getSourceExpression()->getSourceRange();
    439 
    440   case TemplateArgument::Declaration:
    441     return getSourceDeclExpression()->getSourceRange();
    442 
    443   case TemplateArgument::NullPtr:
    444     return getSourceNullPtrExpression()->getSourceRange();
    445 
    446   case TemplateArgument::Type:
    447     if (TypeSourceInfo *TSI = getTypeSourceInfo())
    448       return TSI->getTypeLoc().getSourceRange();
    449     else
    450       return SourceRange();
    451 
    452   case TemplateArgument::Template:
    453     if (getTemplateQualifierLoc())
    454       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
    455                          getTemplateNameLoc());
    456     return SourceRange(getTemplateNameLoc());
    457 
    458   case TemplateArgument::TemplateExpansion:
    459     if (getTemplateQualifierLoc())
    460       return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
    461                          getTemplateEllipsisLoc());
    462     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
    463 
    464   case TemplateArgument::Integral:
    465     return getSourceIntegralExpression()->getSourceRange();
    466 
    467   case TemplateArgument::Pack:
    468   case TemplateArgument::Null:
    469     return SourceRange();
    470   }
    471 
    472   llvm_unreachable("Invalid TemplateArgument Kind!");
    473 }
    474 
    475 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
    476                                            const TemplateArgument &Arg) {
    477   switch (Arg.getKind()) {
    478   case TemplateArgument::Null:
    479     // This is bad, but not as bad as crashing because of argument
    480     // count mismatches.
    481     return DB << "(null template argument)";
    482 
    483   case TemplateArgument::Type:
    484     return DB << Arg.getAsType();
    485 
    486   case TemplateArgument::Declaration:
    487     return DB << Arg.getAsDecl();
    488 
    489   case TemplateArgument::NullPtr:
    490     return DB << "nullptr";
    491 
    492   case TemplateArgument::Integral:
    493     return DB << Arg.getAsIntegral().toString(10);
    494 
    495   case TemplateArgument::Template:
    496     return DB << Arg.getAsTemplate();
    497 
    498   case TemplateArgument::TemplateExpansion:
    499     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
    500 
    501   case TemplateArgument::Expression: {
    502     // This shouldn't actually ever happen, so it's okay that we're
    503     // regurgitating an expression here.
    504     // FIXME: We're guessing at LangOptions!
    505     SmallString<32> Str;
    506     llvm::raw_svector_ostream OS(Str);
    507     LangOptions LangOpts;
    508     LangOpts.CPlusPlus = true;
    509     PrintingPolicy Policy(LangOpts);
    510     Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
    511     return DB << OS.str();
    512   }
    513 
    514   case TemplateArgument::Pack: {
    515     // FIXME: We're guessing at LangOptions!
    516     SmallString<32> Str;
    517     llvm::raw_svector_ostream OS(Str);
    518     LangOptions LangOpts;
    519     LangOpts.CPlusPlus = true;
    520     PrintingPolicy Policy(LangOpts);
    521     Arg.print(Policy, OS);
    522     return DB << OS.str();
    523   }
    524   }
    525 
    526   llvm_unreachable("Invalid TemplateArgument Kind!");
    527 }
    528 
    529 const ASTTemplateArgumentListInfo *
    530 ASTTemplateArgumentListInfo::Create(ASTContext &C,
    531                                     const TemplateArgumentListInfo &List) {
    532   std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
    533   void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
    534   return new (Mem) ASTTemplateArgumentListInfo(List);
    535 }
    536 
    537 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
    538     const TemplateArgumentListInfo &Info) {
    539   LAngleLoc = Info.getLAngleLoc();
    540   RAngleLoc = Info.getRAngleLoc();
    541   NumTemplateArgs = Info.size();
    542 
    543   TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
    544   for (unsigned i = 0; i != NumTemplateArgs; ++i)
    545     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
    546 }
    547 
    548 void ASTTemplateKWAndArgsInfo::initializeFrom(
    549     SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
    550     TemplateArgumentLoc *OutArgArray) {
    551   this->TemplateKWLoc = TemplateKWLoc;
    552   LAngleLoc = Info.getLAngleLoc();
    553   RAngleLoc = Info.getRAngleLoc();
    554   NumTemplateArgs = Info.size();
    555 
    556   for (unsigned i = 0; i != NumTemplateArgs; ++i)
    557     new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
    558 }
    559 
    560 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
    561   assert(TemplateKWLoc.isValid());
    562   LAngleLoc = SourceLocation();
    563   RAngleLoc = SourceLocation();
    564   this->TemplateKWLoc = TemplateKWLoc;
    565   NumTemplateArgs = 0;
    566 }
    567 
    568 void ASTTemplateKWAndArgsInfo::initializeFrom(
    569     SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
    570     TemplateArgumentLoc *OutArgArray, bool &Dependent,
    571     bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) {
    572   this->TemplateKWLoc = TemplateKWLoc;
    573   LAngleLoc = Info.getLAngleLoc();
    574   RAngleLoc = Info.getRAngleLoc();
    575   NumTemplateArgs = Info.size();
    576 
    577   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
    578     Dependent = Dependent || Info[i].getArgument().isDependent();
    579     InstantiationDependent = InstantiationDependent ||
    580                              Info[i].getArgument().isInstantiationDependent();
    581     ContainsUnexpandedParameterPack =
    582         ContainsUnexpandedParameterPack ||
    583         Info[i].getArgument().containsUnexpandedParameterPack();
    584 
    585     new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
    586   }
    587 }
    588 
    589 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
    590                                         TemplateArgumentListInfo &Info) const {
    591   Info.setLAngleLoc(LAngleLoc);
    592   Info.setRAngleLoc(RAngleLoc);
    593   for (unsigned I = 0; I != NumTemplateArgs; ++I)
    594     Info.addArgument(ArgArray[I]);
    595 }
    596