clang API Documentation

TemplateBase.cpp
Go to the documentation of this file.
00001 //===--- TemplateBase.cpp - Common template AST class implementation ------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements common classes used throughout C++ template
00011 // representations.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/AST/TemplateBase.h"
00016 #include "clang/AST/ASTContext.h"
00017 #include "clang/AST/DeclBase.h"
00018 #include "clang/AST/DeclTemplate.h"
00019 #include "clang/AST/Expr.h"
00020 #include "clang/AST/ExprCXX.h"
00021 #include "clang/AST/Type.h"
00022 #include "clang/AST/TypeLoc.h"
00023 #include "clang/Basic/Diagnostic.h"
00024 #include "llvm/ADT/FoldingSet.h"
00025 #include "llvm/ADT/SmallString.h"
00026 #include "llvm/Support/raw_ostream.h"
00027 #include <algorithm>
00028 
00029 using namespace clang;
00030 
00031 /// \brief Print a template integral argument value.
00032 ///
00033 /// \param TemplArg the TemplateArgument instance to print.
00034 ///
00035 /// \param Out the raw_ostream instance to use for printing.
00036 static void printIntegral(const TemplateArgument &TemplArg,
00037                           raw_ostream &Out) {
00038   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
00039   const llvm::APSInt &Val = TemplArg.getAsIntegral();
00040 
00041   if (T->isBooleanType()) {
00042     Out << (Val.getBoolValue() ? "true" : "false");
00043   } else if (T->isCharType()) {
00044     const char Ch = Val.getZExtValue();
00045     Out << ((Ch == '\'') ? "'\\" : "'");
00046     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
00047     Out << "'";
00048   } else {
00049     Out << Val;
00050   }
00051 }
00052 
00053 //===----------------------------------------------------------------------===//
00054 // TemplateArgument Implementation
00055 //===----------------------------------------------------------------------===//
00056 
00057 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
00058                                    QualType Type) {
00059   Integer.Kind = Integral;
00060   // Copy the APSInt value into our decomposed form.
00061   Integer.BitWidth = Value.getBitWidth();
00062   Integer.IsUnsigned = Value.isUnsigned();
00063   // If the value is large, we have to get additional memory from the ASTContext
00064   unsigned NumWords = Value.getNumWords();
00065   if (NumWords > 1) {
00066     void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
00067     std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
00068     Integer.pVal = static_cast<uint64_t *>(Mem);
00069   } else {
00070     Integer.VAL = Value.getZExtValue();
00071   }
00072 
00073   Integer.Type = Type.getAsOpaquePtr();
00074 }
00075 
00076 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
00077                                                   const TemplateArgument *Args,
00078                                                   unsigned NumArgs) {
00079   if (NumArgs == 0)
00080     return getEmptyPack();
00081   
00082   TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
00083   std::copy(Args, Args + NumArgs, Storage);
00084   return TemplateArgument(Storage, NumArgs);
00085 }
00086 
00087 bool TemplateArgument::isDependent() const {
00088   switch (getKind()) {
00089   case Null:
00090     llvm_unreachable("Should not have a NULL template argument");
00091 
00092   case Type:
00093     return getAsType()->isDependentType() ||
00094            isa<PackExpansionType>(getAsType());
00095 
00096   case Template:
00097     return getAsTemplate().isDependent();
00098 
00099   case TemplateExpansion:
00100     return true;
00101 
00102   case Declaration:
00103     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
00104       return DC->isDependentContext();
00105     return getAsDecl()->getDeclContext()->isDependentContext();
00106 
00107   case NullPtr:
00108     return false;
00109 
00110   case Integral:
00111     // Never dependent
00112     return false;
00113 
00114   case Expression:
00115     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
00116             isa<PackExpansionExpr>(getAsExpr()));
00117 
00118   case Pack:
00119     for (const auto &P : pack_elements())
00120       if (P.isDependent())
00121         return true;
00122     return false;
00123   }
00124 
00125   llvm_unreachable("Invalid TemplateArgument Kind!");
00126 }
00127 
00128 bool TemplateArgument::isInstantiationDependent() const {
00129   switch (getKind()) {
00130   case Null:
00131     llvm_unreachable("Should not have a NULL template argument");
00132     
00133   case Type:
00134     return getAsType()->isInstantiationDependentType();
00135     
00136   case Template:
00137     return getAsTemplate().isInstantiationDependent();
00138     
00139   case TemplateExpansion:
00140     return true;
00141     
00142   case Declaration:
00143     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
00144       return DC->isDependentContext();
00145     return getAsDecl()->getDeclContext()->isDependentContext();
00146 
00147   case NullPtr:
00148     return false;
00149       
00150   case Integral:
00151     // Never dependent
00152     return false;
00153     
00154   case Expression:
00155     return getAsExpr()->isInstantiationDependent();
00156     
00157   case Pack:
00158     for (const auto &P : pack_elements())
00159       if (P.isInstantiationDependent())
00160         return true;
00161     return false;
00162   }
00163 
00164   llvm_unreachable("Invalid TemplateArgument Kind!");
00165 }
00166 
00167 bool TemplateArgument::isPackExpansion() const {
00168   switch (getKind()) {
00169   case Null:
00170   case Declaration:
00171   case Integral:
00172   case Pack:    
00173   case Template:
00174   case NullPtr:
00175     return false;
00176       
00177   case TemplateExpansion:
00178     return true;
00179       
00180   case Type:
00181     return isa<PackExpansionType>(getAsType());
00182           
00183   case Expression:
00184     return isa<PackExpansionExpr>(getAsExpr());
00185   }
00186 
00187   llvm_unreachable("Invalid TemplateArgument Kind!");
00188 }
00189 
00190 bool TemplateArgument::containsUnexpandedParameterPack() const {
00191   switch (getKind()) {
00192   case Null:
00193   case Declaration:
00194   case Integral:
00195   case TemplateExpansion:
00196   case NullPtr:
00197     break;
00198 
00199   case Type:
00200     if (getAsType()->containsUnexpandedParameterPack())
00201       return true;
00202     break;
00203 
00204   case Template:
00205     if (getAsTemplate().containsUnexpandedParameterPack())
00206       return true;
00207     break;
00208         
00209   case Expression:
00210     if (getAsExpr()->containsUnexpandedParameterPack())
00211       return true;
00212     break;
00213 
00214   case Pack:
00215     for (const auto &P : pack_elements())
00216       if (P.containsUnexpandedParameterPack())
00217         return true;
00218 
00219     break;
00220   }
00221 
00222   return false;
00223 }
00224 
00225 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
00226   assert(getKind() == TemplateExpansion);
00227   if (TemplateArg.NumExpansions)
00228     return TemplateArg.NumExpansions - 1;
00229   
00230   return None; 
00231 }
00232 
00233 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
00234                                const ASTContext &Context) const {
00235   ID.AddInteger(getKind());
00236   switch (getKind()) {
00237   case Null:
00238     break;
00239 
00240   case Type:
00241     getAsType().Profile(ID);
00242     break;
00243 
00244   case NullPtr:
00245     getNullPtrType().Profile(ID);
00246     break;
00247 
00248   case Declaration:
00249     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
00250     break;
00251 
00252   case Template:
00253   case TemplateExpansion: {
00254     TemplateName Template = getAsTemplateOrTemplatePattern();
00255     if (TemplateTemplateParmDecl *TTP
00256           = dyn_cast_or_null<TemplateTemplateParmDecl>(
00257                                                 Template.getAsTemplateDecl())) {
00258       ID.AddBoolean(true);
00259       ID.AddInteger(TTP->getDepth());
00260       ID.AddInteger(TTP->getPosition());
00261       ID.AddBoolean(TTP->isParameterPack());
00262     } else {
00263       ID.AddBoolean(false);
00264       ID.AddPointer(Context.getCanonicalTemplateName(Template)
00265                                                           .getAsVoidPointer());
00266     }
00267     break;
00268   }
00269       
00270   case Integral:
00271     getAsIntegral().Profile(ID);
00272     getIntegralType().Profile(ID);
00273     break;
00274 
00275   case Expression:
00276     getAsExpr()->Profile(ID, Context, true);
00277     break;
00278 
00279   case Pack:
00280     ID.AddInteger(Args.NumArgs);
00281     for (unsigned I = 0; I != Args.NumArgs; ++I)
00282       Args.Args[I].Profile(ID, Context);
00283   }
00284 }
00285 
00286 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
00287   if (getKind() != Other.getKind()) return false;
00288 
00289   switch (getKind()) {
00290   case Null:
00291   case Type:
00292   case Expression:      
00293   case Template:
00294   case TemplateExpansion:
00295   case NullPtr:
00296     return TypeOrValue.V == Other.TypeOrValue.V;
00297 
00298   case Declaration:
00299     return getAsDecl() == Other.getAsDecl();
00300 
00301   case Integral:
00302     return getIntegralType() == Other.getIntegralType() &&
00303            getAsIntegral() == Other.getAsIntegral();
00304 
00305   case Pack:
00306     if (Args.NumArgs != Other.Args.NumArgs) return false;
00307     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
00308       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
00309         return false;
00310     return true;
00311   }
00312 
00313   llvm_unreachable("Invalid TemplateArgument Kind!");
00314 }
00315 
00316 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
00317   assert(isPackExpansion());
00318   
00319   switch (getKind()) {
00320   case Type:
00321     return getAsType()->getAs<PackExpansionType>()->getPattern();
00322     
00323   case Expression:
00324     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
00325     
00326   case TemplateExpansion:
00327     return TemplateArgument(getAsTemplateOrTemplatePattern());
00328 
00329   case Declaration:
00330   case Integral:
00331   case Pack:
00332   case Null:
00333   case Template:
00334   case NullPtr:
00335     return TemplateArgument();
00336   }
00337 
00338   llvm_unreachable("Invalid TemplateArgument Kind!");
00339 }
00340 
00341 void TemplateArgument::print(const PrintingPolicy &Policy, 
00342                              raw_ostream &Out) const {
00343   switch (getKind()) {
00344   case Null:
00345     Out << "(no value)";
00346     break;
00347     
00348   case Type: {
00349     PrintingPolicy SubPolicy(Policy);
00350     SubPolicy.SuppressStrongLifetime = true;
00351     getAsType().print(Out, SubPolicy);
00352     break;
00353   }
00354     
00355   case Declaration: {
00356     NamedDecl *ND = cast<NamedDecl>(getAsDecl());
00357     Out << '&';
00358     if (ND->getDeclName()) {
00359       // FIXME: distinguish between pointer and reference args?
00360       ND->printQualifiedName(Out);
00361     } else {
00362       Out << "(anonymous)";
00363     }
00364     break;
00365   }
00366 
00367   case NullPtr:
00368     Out << "nullptr";
00369     break;
00370 
00371   case Template:
00372     getAsTemplate().print(Out, Policy);
00373     break;
00374 
00375   case TemplateExpansion:
00376     getAsTemplateOrTemplatePattern().print(Out, Policy);
00377     Out << "...";
00378     break;
00379       
00380   case Integral: {
00381     printIntegral(*this, Out);
00382     break;
00383   }
00384     
00385   case Expression:
00386     getAsExpr()->printPretty(Out, nullptr, Policy);
00387     break;
00388     
00389   case Pack:
00390     Out << "<";
00391     bool First = true;
00392     for (const auto &P : pack_elements()) {
00393       if (First)
00394         First = false;
00395       else
00396         Out << ", ";
00397       
00398       P.print(Policy, Out);
00399     }
00400     Out << ">";
00401     break;        
00402   }
00403 }
00404 
00405 //===----------------------------------------------------------------------===//
00406 // TemplateArgumentLoc Implementation
00407 //===----------------------------------------------------------------------===//
00408 
00409 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
00410   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
00411 }
00412 
00413 SourceRange TemplateArgumentLoc::getSourceRange() const {
00414   switch (Argument.getKind()) {
00415   case TemplateArgument::Expression:
00416     return getSourceExpression()->getSourceRange();
00417 
00418   case TemplateArgument::Declaration:
00419     return getSourceDeclExpression()->getSourceRange();
00420 
00421   case TemplateArgument::NullPtr:
00422     return getSourceNullPtrExpression()->getSourceRange();
00423 
00424   case TemplateArgument::Type:
00425     if (TypeSourceInfo *TSI = getTypeSourceInfo())
00426       return TSI->getTypeLoc().getSourceRange();
00427     else
00428       return SourceRange();
00429 
00430   case TemplateArgument::Template:
00431     if (getTemplateQualifierLoc())
00432       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
00433                          getTemplateNameLoc());
00434     return SourceRange(getTemplateNameLoc());
00435 
00436   case TemplateArgument::TemplateExpansion:
00437     if (getTemplateQualifierLoc())
00438       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
00439                          getTemplateEllipsisLoc());
00440     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
00441 
00442   case TemplateArgument::Integral:
00443     return getSourceIntegralExpression()->getSourceRange();
00444 
00445   case TemplateArgument::Pack:
00446   case TemplateArgument::Null:
00447     return SourceRange();
00448   }
00449 
00450   llvm_unreachable("Invalid TemplateArgument Kind!");
00451 }
00452 
00453 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
00454                                            const TemplateArgument &Arg) {
00455   switch (Arg.getKind()) {
00456   case TemplateArgument::Null:
00457     // This is bad, but not as bad as crashing because of argument
00458     // count mismatches.
00459     return DB << "(null template argument)";
00460       
00461   case TemplateArgument::Type:
00462     return DB << Arg.getAsType();
00463       
00464   case TemplateArgument::Declaration:
00465     return DB << Arg.getAsDecl();
00466 
00467   case TemplateArgument::NullPtr:
00468     return DB << "nullptr";
00469       
00470   case TemplateArgument::Integral:
00471     return DB << Arg.getAsIntegral().toString(10);
00472       
00473   case TemplateArgument::Template:
00474     return DB << Arg.getAsTemplate();
00475 
00476   case TemplateArgument::TemplateExpansion:
00477     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
00478 
00479   case TemplateArgument::Expression: {
00480     // This shouldn't actually ever happen, so it's okay that we're
00481     // regurgitating an expression here.
00482     // FIXME: We're guessing at LangOptions!
00483     SmallString<32> Str;
00484     llvm::raw_svector_ostream OS(Str);
00485     LangOptions LangOpts;
00486     LangOpts.CPlusPlus = true;
00487     PrintingPolicy Policy(LangOpts);
00488     Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
00489     return DB << OS.str();
00490   }
00491       
00492   case TemplateArgument::Pack: {
00493     // FIXME: We're guessing at LangOptions!
00494     SmallString<32> Str;
00495     llvm::raw_svector_ostream OS(Str);
00496     LangOptions LangOpts;
00497     LangOpts.CPlusPlus = true;
00498     PrintingPolicy Policy(LangOpts);
00499     Arg.print(Policy, OS);
00500     return DB << OS.str();
00501   }
00502   }
00503 
00504   llvm_unreachable("Invalid TemplateArgument Kind!");
00505 }
00506 
00507 const ASTTemplateArgumentListInfo *
00508 ASTTemplateArgumentListInfo::Create(ASTContext &C,
00509                                     const TemplateArgumentListInfo &List) {
00510   assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >=
00511          llvm::alignOf<TemplateArgumentLoc>());
00512   std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size());
00513   void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
00514   ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
00515   TAI->initializeFrom(List);
00516   return TAI;
00517 }
00518 
00519 void ASTTemplateArgumentListInfo::initializeFrom(
00520                                       const TemplateArgumentListInfo &Info) {
00521   LAngleLoc = Info.getLAngleLoc();
00522   RAngleLoc = Info.getRAngleLoc();
00523   NumTemplateArgs = Info.size();
00524 
00525   TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
00526   for (unsigned i = 0; i != NumTemplateArgs; ++i)
00527     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
00528 }
00529 
00530 void ASTTemplateArgumentListInfo::initializeFrom(
00531                                           const TemplateArgumentListInfo &Info,
00532                                                   bool &Dependent, 
00533                                                   bool &InstantiationDependent,
00534                                        bool &ContainsUnexpandedParameterPack) {
00535   LAngleLoc = Info.getLAngleLoc();
00536   RAngleLoc = Info.getRAngleLoc();
00537   NumTemplateArgs = Info.size();
00538 
00539   TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
00540   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
00541     Dependent = Dependent || Info[i].getArgument().isDependent();
00542     InstantiationDependent = InstantiationDependent || 
00543                              Info[i].getArgument().isInstantiationDependent();
00544     ContainsUnexpandedParameterPack 
00545       = ContainsUnexpandedParameterPack || 
00546         Info[i].getArgument().containsUnexpandedParameterPack();
00547 
00548     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
00549   }
00550 }
00551 
00552 void ASTTemplateArgumentListInfo::copyInto(
00553                                       TemplateArgumentListInfo &Info) const {
00554   Info.setLAngleLoc(LAngleLoc);
00555   Info.setRAngleLoc(RAngleLoc);
00556   for (unsigned I = 0; I != NumTemplateArgs; ++I)
00557     Info.addArgument(getTemplateArgs()[I]);
00558 }
00559 
00560 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
00561   return sizeof(ASTTemplateArgumentListInfo) +
00562          sizeof(TemplateArgumentLoc) * NumTemplateArgs;
00563 }
00564 
00565 void
00566 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
00567                                          const TemplateArgumentListInfo &Info) {
00568   Base::initializeFrom(Info);
00569   setTemplateKeywordLoc(TemplateKWLoc);
00570 }
00571 
00572 void
00573 ASTTemplateKWAndArgsInfo
00574 ::initializeFrom(SourceLocation TemplateKWLoc,
00575                  const TemplateArgumentListInfo &Info,
00576                  bool &Dependent,
00577                  bool &InstantiationDependent,
00578                  bool &ContainsUnexpandedParameterPack) {
00579   Base::initializeFrom(Info, Dependent, InstantiationDependent,
00580                        ContainsUnexpandedParameterPack);
00581   setTemplateKeywordLoc(TemplateKWLoc);
00582 }
00583 
00584 void
00585 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
00586   // No explicit template arguments, but template keyword loc is valid.
00587   assert(TemplateKWLoc.isValid());
00588   LAngleLoc = SourceLocation();
00589   RAngleLoc = SourceLocation();
00590   NumTemplateArgs = 0;
00591   setTemplateKeywordLoc(TemplateKWLoc);
00592 }
00593 
00594 std::size_t
00595 ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
00596   // Add space for the template keyword location.
00597   // FIXME: There's room for this in the padding before the template args in
00598   //        64-bit builds.
00599   return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
00600 }