TemplateBase.cpp revision 212904
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 "llvm/ADT/FoldingSet.h" 16#include "clang/AST/TemplateBase.h" 17#include "clang/AST/DeclBase.h" 18#include "clang/AST/DeclTemplate.h" 19#include "clang/AST/Expr.h" 20#include "clang/AST/TypeLoc.h" 21#include "clang/Basic/Diagnostic.h" 22 23using namespace clang; 24 25//===----------------------------------------------------------------------===// 26// TemplateArgument Implementation 27//===----------------------------------------------------------------------===// 28 29/// \brief Construct a template argument pack. 30void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, 31 bool CopyArgs) { 32 assert(isNull() && "Must call setArgumentPack on a null argument"); 33 34 Kind = Pack; 35 Args.NumArgs = NumArgs; 36 Args.CopyArgs = CopyArgs; 37 if (!Args.CopyArgs) { 38 Args.Args = args; 39 return; 40 } 41 42 // FIXME: Allocate in ASTContext 43 Args.Args = new TemplateArgument[NumArgs]; 44 for (unsigned I = 0; I != Args.NumArgs; ++I) 45 Args.Args[I] = args[I]; 46} 47 48void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 49 ASTContext &Context) const { 50 ID.AddInteger(Kind); 51 switch (Kind) { 52 case Null: 53 break; 54 55 case Type: 56 getAsType().Profile(ID); 57 break; 58 59 case Declaration: 60 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 61 break; 62 63 case Template: 64 if (TemplateTemplateParmDecl *TTP 65 = dyn_cast_or_null<TemplateTemplateParmDecl>( 66 getAsTemplate().getAsTemplateDecl())) { 67 ID.AddBoolean(true); 68 ID.AddInteger(TTP->getDepth()); 69 ID.AddInteger(TTP->getPosition()); 70 } else { 71 ID.AddBoolean(false); 72 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) 73 .getAsVoidPointer()); 74 } 75 break; 76 77 case Integral: 78 getAsIntegral()->Profile(ID); 79 getIntegralType().Profile(ID); 80 break; 81 82 case Expression: 83 getAsExpr()->Profile(ID, Context, true); 84 break; 85 86 case Pack: 87 ID.AddInteger(Args.NumArgs); 88 for (unsigned I = 0; I != Args.NumArgs; ++I) 89 Args.Args[I].Profile(ID, Context); 90 } 91} 92 93bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 94 if (getKind() != Other.getKind()) return false; 95 96 switch (getKind()) { 97 case Null: 98 case Type: 99 case Declaration: 100 case Template: 101 case Expression: 102 return TypeOrValue == Other.TypeOrValue; 103 104 case Integral: 105 return getIntegralType() == Other.getIntegralType() && 106 *getAsIntegral() == *Other.getAsIntegral(); 107 108 case Pack: 109 if (Args.NumArgs != Other.Args.NumArgs) return false; 110 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 111 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 112 return false; 113 return true; 114 } 115 116 // Suppress warnings. 117 return false; 118} 119 120//===----------------------------------------------------------------------===// 121// TemplateArgumentLoc Implementation 122//===----------------------------------------------------------------------===// 123 124SourceRange TemplateArgumentLoc::getSourceRange() const { 125 switch (Argument.getKind()) { 126 case TemplateArgument::Expression: 127 return getSourceExpression()->getSourceRange(); 128 129 case TemplateArgument::Declaration: 130 return getSourceDeclExpression()->getSourceRange(); 131 132 case TemplateArgument::Type: 133 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 134 return TSI->getTypeLoc().getSourceRange(); 135 else 136 return SourceRange(); 137 138 case TemplateArgument::Template: 139 if (getTemplateQualifierRange().isValid()) 140 return SourceRange(getTemplateQualifierRange().getBegin(), 141 getTemplateNameLoc()); 142 return SourceRange(getTemplateNameLoc()); 143 144 case TemplateArgument::Integral: 145 case TemplateArgument::Pack: 146 case TemplateArgument::Null: 147 return SourceRange(); 148 } 149 150 // Silence bonus gcc warning. 151 return SourceRange(); 152} 153 154const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 155 const TemplateArgument &Arg) { 156 switch (Arg.getKind()) { 157 case TemplateArgument::Null: 158 // This is bad, but not as bad as crashing because of argument 159 // count mismatches. 160 return DB << "(null template argument)"; 161 162 case TemplateArgument::Type: 163 return DB << Arg.getAsType(); 164 165 case TemplateArgument::Declaration: 166 return DB << Arg.getAsDecl(); 167 168 case TemplateArgument::Integral: 169 return DB << Arg.getAsIntegral()->toString(10); 170 171 case TemplateArgument::Template: 172 return DB << Arg.getAsTemplate(); 173 174 case TemplateArgument::Expression: { 175 // This shouldn't actually ever happen, so it's okay that we're 176 // regurgitating an expression here. 177 // FIXME: We're guessing at LangOptions! 178 llvm::SmallString<32> Str; 179 llvm::raw_svector_ostream OS(Str); 180 LangOptions LangOpts; 181 LangOpts.CPlusPlus = true; 182 PrintingPolicy Policy(LangOpts); 183 Arg.getAsExpr()->printPretty(OS, 0, Policy); 184 return DB << OS.str(); 185 } 186 187 case TemplateArgument::Pack: 188 // FIXME: Format arguments in a list! 189 return DB << "<parameter pack>"; 190 } 191 192 return DB; 193} 194