123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- //===--- TemplateBase.cpp - Common template AST class implementation ------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements common classes used throughout C++ template
- // representations.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/TemplateBase.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/DeclBase.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/ExprCXX.h"
- #include "clang/AST/Type.h"
- #include "clang/AST/TypeLoc.h"
- #include "clang/Basic/Diagnostic.h"
- #include "llvm/ADT/FoldingSet.h"
- #include "llvm/ADT/SmallString.h"
- #include <algorithm>
- #include <cctype>
- using namespace clang;
- /// \brief Print a template integral argument value.
- ///
- /// \param TemplArg the TemplateArgument instance to print.
- ///
- /// \param Out the raw_ostream instance to use for printing.
- static void printIntegral(const TemplateArgument &TemplArg,
- raw_ostream &Out) {
- const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
- const llvm::APSInt *Val = TemplArg.getAsIntegral();
- if (T->isBooleanType()) {
- Out << (Val->getBoolValue() ? "true" : "false");
- } else if (T->isCharType()) {
- const char Ch = Val->getZExtValue();
- Out << ((Ch == '\'') ? "'\\" : "'");
- Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
- Out << "'";
- } else {
- Out << Val->toString(10);
- }
- }
- //===----------------------------------------------------------------------===//
- // TemplateArgument Implementation
- //===----------------------------------------------------------------------===//
- TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
- const TemplateArgument *Args,
- unsigned NumArgs) {
- if (NumArgs == 0)
- return TemplateArgument(0, 0);
-
- TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
- std::copy(Args, Args + NumArgs, Storage);
- return TemplateArgument(Storage, NumArgs);
- }
- bool TemplateArgument::isDependent() const {
- switch (getKind()) {
- case Null:
- llvm_unreachable("Should not have a NULL template argument");
- case Type:
- return getAsType()->isDependentType();
- case Template:
- return getAsTemplate().isDependent();
- case TemplateExpansion:
- return true;
- case Declaration:
- if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
- return DC->isDependentContext();
- return getAsDecl()->getDeclContext()->isDependentContext();
- case Integral:
- // Never dependent
- return false;
- case Expression:
- return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
- case Pack:
- for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
- if (P->isDependent())
- return true;
- }
- return false;
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- bool TemplateArgument::isInstantiationDependent() const {
- switch (getKind()) {
- case Null:
- llvm_unreachable("Should not have a NULL template argument");
-
- case Type:
- return getAsType()->isInstantiationDependentType();
-
- case Template:
- return getAsTemplate().isInstantiationDependent();
-
- case TemplateExpansion:
- return true;
-
- case Declaration:
- if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
- return DC->isDependentContext();
- return getAsDecl()->getDeclContext()->isDependentContext();
-
- case Integral:
- // Never dependent
- return false;
-
- case Expression:
- return getAsExpr()->isInstantiationDependent();
-
- case Pack:
- for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
- if (P->isInstantiationDependent())
- return true;
- }
-
- return false;
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- bool TemplateArgument::isPackExpansion() const {
- switch (getKind()) {
- case Null:
- case Declaration:
- case Integral:
- case Pack:
- case Template:
- return false;
-
- case TemplateExpansion:
- return true;
-
- case Type:
- return isa<PackExpansionType>(getAsType());
-
- case Expression:
- return isa<PackExpansionExpr>(getAsExpr());
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- bool TemplateArgument::containsUnexpandedParameterPack() const {
- switch (getKind()) {
- case Null:
- case Declaration:
- case Integral:
- case TemplateExpansion:
- break;
- case Type:
- if (getAsType()->containsUnexpandedParameterPack())
- return true;
- break;
- case Template:
- if (getAsTemplate().containsUnexpandedParameterPack())
- return true;
- break;
-
- case Expression:
- if (getAsExpr()->containsUnexpandedParameterPack())
- return true;
- break;
- case Pack:
- for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
- if (P->containsUnexpandedParameterPack())
- return true;
- break;
- }
- return false;
- }
- llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
- assert(Kind == TemplateExpansion);
- if (TemplateArg.NumExpansions)
- return TemplateArg.NumExpansions - 1;
-
- return llvm::Optional<unsigned>();
- }
- void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
- const ASTContext &Context) const {
- ID.AddInteger(Kind);
- switch (Kind) {
- case Null:
- break;
- case Type:
- getAsType().Profile(ID);
- break;
- case Declaration:
- ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
- break;
- case Template:
- case TemplateExpansion: {
- TemplateName Template = getAsTemplateOrTemplatePattern();
- if (TemplateTemplateParmDecl *TTP
- = dyn_cast_or_null<TemplateTemplateParmDecl>(
- Template.getAsTemplateDecl())) {
- ID.AddBoolean(true);
- ID.AddInteger(TTP->getDepth());
- ID.AddInteger(TTP->getPosition());
- ID.AddBoolean(TTP->isParameterPack());
- } else {
- ID.AddBoolean(false);
- ID.AddPointer(Context.getCanonicalTemplateName(Template)
- .getAsVoidPointer());
- }
- break;
- }
-
- case Integral:
- getAsIntegral()->Profile(ID);
- getIntegralType().Profile(ID);
- break;
- case Expression:
- getAsExpr()->Profile(ID, Context, true);
- break;
- case Pack:
- ID.AddInteger(Args.NumArgs);
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I].Profile(ID, Context);
- }
- }
- bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
- if (getKind() != Other.getKind()) return false;
- switch (getKind()) {
- case Null:
- case Type:
- case Declaration:
- case Expression:
- case Template:
- case TemplateExpansion:
- return TypeOrValue == Other.TypeOrValue;
- case Integral:
- return getIntegralType() == Other.getIntegralType() &&
- *getAsIntegral() == *Other.getAsIntegral();
- case Pack:
- if (Args.NumArgs != Other.Args.NumArgs) return false;
- for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
- if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
- return false;
- return true;
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- TemplateArgument TemplateArgument::getPackExpansionPattern() const {
- assert(isPackExpansion());
-
- switch (getKind()) {
- case Type:
- return getAsType()->getAs<PackExpansionType>()->getPattern();
-
- case Expression:
- return cast<PackExpansionExpr>(getAsExpr())->getPattern();
-
- case TemplateExpansion:
- return TemplateArgument(getAsTemplateOrTemplatePattern());
-
- case Declaration:
- case Integral:
- case Pack:
- case Null:
- case Template:
- return TemplateArgument();
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- void TemplateArgument::print(const PrintingPolicy &Policy,
- raw_ostream &Out) const {
- switch (getKind()) {
- case Null:
- Out << "<no value>";
- break;
-
- case Type: {
- PrintingPolicy SubPolicy(Policy);
- SubPolicy.SuppressStrongLifetime = true;
- std::string TypeStr;
- getAsType().getAsStringInternal(TypeStr, SubPolicy);
- Out << TypeStr;
- break;
- }
-
- case Declaration: {
- bool Unnamed = true;
- if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
- if (ND->getDeclName()) {
- Unnamed = false;
- Out << ND->getNameAsString();
- }
- }
-
- if (Unnamed) {
- Out << "<anonymous>";
- }
- break;
- }
-
- case Template:
- getAsTemplate().print(Out, Policy);
- break;
- case TemplateExpansion:
- getAsTemplateOrTemplatePattern().print(Out, Policy);
- Out << "...";
- break;
-
- case Integral: {
- printIntegral(*this, Out);
- break;
- }
-
- case Expression:
- getAsExpr()->printPretty(Out, 0, Policy);
- break;
-
- case Pack:
- Out << "<";
- bool First = true;
- for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
- P != PEnd; ++P) {
- if (First)
- First = false;
- else
- Out << ", ";
-
- P->print(Policy, Out);
- }
- Out << ">";
- break;
- }
- }
- //===----------------------------------------------------------------------===//
- // TemplateArgumentLoc Implementation
- //===----------------------------------------------------------------------===//
- TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
- memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
- }
- SourceRange TemplateArgumentLoc::getSourceRange() const {
- switch (Argument.getKind()) {
- case TemplateArgument::Expression:
- return getSourceExpression()->getSourceRange();
- case TemplateArgument::Declaration:
- return getSourceDeclExpression()->getSourceRange();
- case TemplateArgument::Type:
- if (TypeSourceInfo *TSI = getTypeSourceInfo())
- return TSI->getTypeLoc().getSourceRange();
- else
- return SourceRange();
- case TemplateArgument::Template:
- if (getTemplateQualifierLoc())
- return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
- getTemplateNameLoc());
- return SourceRange(getTemplateNameLoc());
- case TemplateArgument::TemplateExpansion:
- if (getTemplateQualifierLoc())
- return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
- getTemplateEllipsisLoc());
- return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- case TemplateArgument::Null:
- return SourceRange();
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- TemplateArgumentLoc
- TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
- llvm::Optional<unsigned> &NumExpansions,
- ASTContext &Context) const {
- assert(Argument.isPackExpansion());
-
- switch (Argument.getKind()) {
- case TemplateArgument::Type: {
- // FIXME: We shouldn't ever have to worry about missing
- // type-source info!
- TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
- if (!ExpansionTSInfo)
- ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
- getArgument().getAsType(),
- Ellipsis);
- PackExpansionTypeLoc Expansion
- = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
- Ellipsis = Expansion.getEllipsisLoc();
-
- TypeLoc Pattern = Expansion.getPatternLoc();
- NumExpansions = Expansion.getTypePtr()->getNumExpansions();
-
- // FIXME: This is horrible. We know where the source location data is for
- // the pattern, and we have the pattern's type, but we are forced to copy
- // them into an ASTContext because TypeSourceInfo bundles them together
- // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
- TypeSourceInfo *PatternTSInfo
- = Context.CreateTypeSourceInfo(Pattern.getType(),
- Pattern.getFullDataSize());
- memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
- Pattern.getOpaqueData(), Pattern.getFullDataSize());
- return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
- PatternTSInfo);
- }
-
- case TemplateArgument::Expression: {
- PackExpansionExpr *Expansion
- = cast<PackExpansionExpr>(Argument.getAsExpr());
- Expr *Pattern = Expansion->getPattern();
- Ellipsis = Expansion->getEllipsisLoc();
- NumExpansions = Expansion->getNumExpansions();
- return TemplateArgumentLoc(Pattern, Pattern);
- }
- case TemplateArgument::TemplateExpansion:
- Ellipsis = getTemplateEllipsisLoc();
- NumExpansions = Argument.getNumTemplateExpansions();
- return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
- getTemplateQualifierLoc(),
- getTemplateNameLoc());
-
- case TemplateArgument::Declaration:
- case TemplateArgument::Template:
- case TemplateArgument::Integral:
- case TemplateArgument::Pack:
- case TemplateArgument::Null:
- return TemplateArgumentLoc();
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
- const TemplateArgument &Arg) {
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- // This is bad, but not as bad as crashing because of argument
- // count mismatches.
- return DB << "(null template argument)";
-
- case TemplateArgument::Type:
- return DB << Arg.getAsType();
-
- case TemplateArgument::Declaration:
- return DB << Arg.getAsDecl();
-
- case TemplateArgument::Integral:
- return DB << Arg.getAsIntegral()->toString(10);
-
- case TemplateArgument::Template:
- return DB << Arg.getAsTemplate();
- case TemplateArgument::TemplateExpansion:
- return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
- case TemplateArgument::Expression: {
- // This shouldn't actually ever happen, so it's okay that we're
- // regurgitating an expression here.
- // FIXME: We're guessing at LangOptions!
- SmallString<32> Str;
- llvm::raw_svector_ostream OS(Str);
- LangOptions LangOpts;
- LangOpts.CPlusPlus = true;
- PrintingPolicy Policy(LangOpts);
- Arg.getAsExpr()->printPretty(OS, 0, Policy);
- return DB << OS.str();
- }
-
- case TemplateArgument::Pack: {
- // FIXME: We're guessing at LangOptions!
- SmallString<32> Str;
- llvm::raw_svector_ostream OS(Str);
- LangOptions LangOpts;
- LangOpts.CPlusPlus = true;
- PrintingPolicy Policy(LangOpts);
- Arg.print(Policy, OS);
- return DB << OS.str();
- }
- }
- llvm_unreachable("Invalid TemplateArgument Kind!");
- }
- const ASTTemplateArgumentListInfo *
- ASTTemplateArgumentListInfo::Create(ASTContext &C,
- const TemplateArgumentListInfo &List) {
- std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
- ASTTemplateArgumentListInfo::sizeFor(List.size());
- void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
- ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
- TAI->initializeFrom(List);
- return TAI;
- }
- void ASTTemplateArgumentListInfo::initializeFrom(
- const TemplateArgumentListInfo &Info) {
- LAngleLoc = Info.getLAngleLoc();
- RAngleLoc = Info.getRAngleLoc();
- NumTemplateArgs = Info.size();
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
- for (unsigned i = 0; i != NumTemplateArgs; ++i)
- new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
- }
- void ASTTemplateArgumentListInfo::initializeFrom(
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack) {
- LAngleLoc = Info.getLAngleLoc();
- RAngleLoc = Info.getRAngleLoc();
- NumTemplateArgs = Info.size();
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
- for (unsigned i = 0; i != NumTemplateArgs; ++i) {
- Dependent = Dependent || Info[i].getArgument().isDependent();
- InstantiationDependent = InstantiationDependent ||
- Info[i].getArgument().isInstantiationDependent();
- ContainsUnexpandedParameterPack
- = ContainsUnexpandedParameterPack ||
- Info[i].getArgument().containsUnexpandedParameterPack();
- new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
- }
- }
- void ASTTemplateArgumentListInfo::copyInto(
- TemplateArgumentListInfo &Info) const {
- Info.setLAngleLoc(LAngleLoc);
- Info.setRAngleLoc(RAngleLoc);
- for (unsigned I = 0; I != NumTemplateArgs; ++I)
- Info.addArgument(getTemplateArgs()[I]);
- }
- std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
- return sizeof(ASTTemplateArgumentListInfo) +
- sizeof(TemplateArgumentLoc) * NumTemplateArgs;
- }
- void
- ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &Info) {
- Base::initializeFrom(Info);
- setTemplateKeywordLoc(TemplateKWLoc);
- }
- void
- ASTTemplateKWAndArgsInfo
- ::initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack) {
- Base::initializeFrom(Info, Dependent, InstantiationDependent,
- ContainsUnexpandedParameterPack);
- setTemplateKeywordLoc(TemplateKWLoc);
- }
- void
- ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
- // No explicit template arguments, but template keyword loc is valid.
- assert(TemplateKWLoc.isValid());
- LAngleLoc = SourceLocation();
- RAngleLoc = SourceLocation();
- NumTemplateArgs = 0;
- setTemplateKeywordLoc(TemplateKWLoc);
- }
- std::size_t
- ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
- // Add space for the template keyword location.
- return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
- }
|