TemplateBase.cpp revision 210299
1198893Srdivacky//===--- TemplateBase.cpp - Common template AST class implementation ------===// 2198893Srdivacky// 3198893Srdivacky// The LLVM Compiler Infrastructure 4198893Srdivacky// 5198893Srdivacky// This file is distributed under the University of Illinois Open Source 6198893Srdivacky// License. See LICENSE.TXT for details. 7198893Srdivacky// 8198893Srdivacky//===----------------------------------------------------------------------===// 9198893Srdivacky// 10198893Srdivacky// This file implements common classes used throughout C++ template 11198893Srdivacky// representations. 12198893Srdivacky// 13198893Srdivacky//===----------------------------------------------------------------------===// 14198893Srdivacky 15198893Srdivacky#include "llvm/ADT/FoldingSet.h" 16198893Srdivacky#include "clang/AST/TemplateBase.h" 17198893Srdivacky#include "clang/AST/DeclBase.h" 18199990Srdivacky#include "clang/AST/DeclTemplate.h" 19198893Srdivacky#include "clang/AST/Expr.h" 20198893Srdivacky#include "clang/AST/TypeLoc.h" 21208600Srdivacky#include "clang/Basic/Diagnostic.h" 22198893Srdivacky 23198893Srdivackyusing namespace clang; 24198893Srdivacky 25198893Srdivacky//===----------------------------------------------------------------------===// 26198893Srdivacky// TemplateArgument Implementation 27198893Srdivacky//===----------------------------------------------------------------------===// 28198893Srdivacky 29198893Srdivacky/// \brief Construct a template argument pack. 30198893Srdivackyvoid TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, 31198893Srdivacky bool CopyArgs) { 32198893Srdivacky assert(isNull() && "Must call setArgumentPack on a null argument"); 33198893Srdivacky 34198893Srdivacky Kind = Pack; 35198893Srdivacky Args.NumArgs = NumArgs; 36198893Srdivacky Args.CopyArgs = CopyArgs; 37198893Srdivacky if (!Args.CopyArgs) { 38198893Srdivacky Args.Args = args; 39198893Srdivacky return; 40198893Srdivacky } 41198893Srdivacky 42198893Srdivacky // FIXME: Allocate in ASTContext 43198893Srdivacky Args.Args = new TemplateArgument[NumArgs]; 44198893Srdivacky for (unsigned I = 0; I != Args.NumArgs; ++I) 45198893Srdivacky Args.Args[I] = args[I]; 46198893Srdivacky} 47198893Srdivacky 48198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 49198893Srdivacky ASTContext &Context) const { 50198893Srdivacky ID.AddInteger(Kind); 51198893Srdivacky switch (Kind) { 52198893Srdivacky case Null: 53198893Srdivacky break; 54198893Srdivacky 55198893Srdivacky case Type: 56198893Srdivacky getAsType().Profile(ID); 57198893Srdivacky break; 58198893Srdivacky 59198893Srdivacky case Declaration: 60198893Srdivacky ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 61198893Srdivacky break; 62198893Srdivacky 63199482Srdivacky case Template: 64199990Srdivacky if (TemplateTemplateParmDecl *TTP 65199990Srdivacky = dyn_cast_or_null<TemplateTemplateParmDecl>( 66199990Srdivacky getAsTemplate().getAsTemplateDecl())) { 67199990Srdivacky ID.AddBoolean(true); 68199990Srdivacky ID.AddInteger(TTP->getDepth()); 69199990Srdivacky ID.AddInteger(TTP->getPosition()); 70199990Srdivacky } else { 71199990Srdivacky ID.AddBoolean(false); 72199990Srdivacky ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) 73199990Srdivacky .getAsVoidPointer()); 74199990Srdivacky } 75199482Srdivacky break; 76199482Srdivacky 77198893Srdivacky case Integral: 78198893Srdivacky getAsIntegral()->Profile(ID); 79198893Srdivacky getIntegralType().Profile(ID); 80198893Srdivacky break; 81198893Srdivacky 82198893Srdivacky case Expression: 83198893Srdivacky getAsExpr()->Profile(ID, Context, true); 84198893Srdivacky break; 85198893Srdivacky 86198893Srdivacky case Pack: 87198893Srdivacky ID.AddInteger(Args.NumArgs); 88198893Srdivacky for (unsigned I = 0; I != Args.NumArgs; ++I) 89198893Srdivacky Args.Args[I].Profile(ID, Context); 90198893Srdivacky } 91198893Srdivacky} 92198893Srdivacky 93210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 94210299Sed if (getKind() != Other.getKind()) return false; 95210299Sed 96210299Sed switch (getKind()) { 97210299Sed case Null: 98210299Sed case Type: 99210299Sed case Declaration: 100210299Sed case Template: 101210299Sed case Expression: 102210299Sed return TypeOrValue == Other.TypeOrValue; 103210299Sed 104210299Sed case Integral: 105210299Sed return getIntegralType() == Other.getIntegralType() && 106210299Sed *getAsIntegral() == *Other.getAsIntegral(); 107210299Sed 108210299Sed case Pack: 109210299Sed if (Args.NumArgs != Other.Args.NumArgs) return false; 110210299Sed for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 111210299Sed if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 112210299Sed return false; 113210299Sed return true; 114210299Sed } 115210299Sed 116210299Sed // Suppress warnings. 117210299Sed return false; 118210299Sed} 119210299Sed 120198893Srdivacky//===----------------------------------------------------------------------===// 121198893Srdivacky// TemplateArgumentLoc Implementation 122198893Srdivacky//===----------------------------------------------------------------------===// 123198893Srdivacky 124198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const { 125198893Srdivacky switch (Argument.getKind()) { 126198893Srdivacky case TemplateArgument::Expression: 127198893Srdivacky return getSourceExpression()->getSourceRange(); 128199482Srdivacky 129198893Srdivacky case TemplateArgument::Declaration: 130198893Srdivacky return getSourceDeclExpression()->getSourceRange(); 131199482Srdivacky 132198893Srdivacky case TemplateArgument::Type: 133208600Srdivacky return getTypeSourceInfo()->getTypeLoc().getSourceRange(); 134199482Srdivacky 135199482Srdivacky case TemplateArgument::Template: 136199482Srdivacky if (getTemplateQualifierRange().isValid()) 137199482Srdivacky return SourceRange(getTemplateQualifierRange().getBegin(), 138199482Srdivacky getTemplateNameLoc()); 139199482Srdivacky return SourceRange(getTemplateNameLoc()); 140199482Srdivacky 141198893Srdivacky case TemplateArgument::Integral: 142198893Srdivacky case TemplateArgument::Pack: 143198893Srdivacky case TemplateArgument::Null: 144198893Srdivacky return SourceRange(); 145198893Srdivacky } 146198893Srdivacky 147198893Srdivacky // Silence bonus gcc warning. 148198893Srdivacky return SourceRange(); 149198893Srdivacky} 150208600Srdivacky 151208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 152208600Srdivacky const TemplateArgument &Arg) { 153208600Srdivacky switch (Arg.getKind()) { 154208600Srdivacky case TemplateArgument::Null: 155208600Srdivacky return DB; 156208600Srdivacky 157208600Srdivacky case TemplateArgument::Type: 158208600Srdivacky return DB << Arg.getAsType(); 159208600Srdivacky 160208600Srdivacky case TemplateArgument::Declaration: 161208600Srdivacky return DB << Arg.getAsDecl(); 162208600Srdivacky 163208600Srdivacky case TemplateArgument::Integral: 164208600Srdivacky return DB << Arg.getAsIntegral()->toString(10); 165208600Srdivacky 166208600Srdivacky case TemplateArgument::Template: 167208600Srdivacky return DB << Arg.getAsTemplate(); 168208600Srdivacky 169208600Srdivacky case TemplateArgument::Expression: { 170208600Srdivacky // This shouldn't actually ever happen, so it's okay that we're 171208600Srdivacky // regurgitating an expression here. 172208600Srdivacky // FIXME: We're guessing at LangOptions! 173208600Srdivacky llvm::SmallString<32> Str; 174208600Srdivacky llvm::raw_svector_ostream OS(Str); 175208600Srdivacky LangOptions LangOpts; 176208600Srdivacky LangOpts.CPlusPlus = true; 177208600Srdivacky PrintingPolicy Policy(LangOpts); 178208600Srdivacky Arg.getAsExpr()->printPretty(OS, 0, Policy); 179208600Srdivacky return DB << OS.str(); 180208600Srdivacky } 181208600Srdivacky 182208600Srdivacky case TemplateArgument::Pack: 183208600Srdivacky // FIXME: Format arguments in a list! 184208600Srdivacky return DB << "<parameter pack>"; 185208600Srdivacky } 186208600Srdivacky 187208600Srdivacky return DB; 188208600Srdivacky} 189