TemplateBase.cpp revision 4ba2a17694148e16eaa8d3917f657ffcd3667be4
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/TypeLoc.h" 22#include "clang/Basic/Diagnostic.h" 23#include "llvm/ADT/FoldingSet.h" 24#include <algorithm> 25 26using namespace clang; 27 28//===----------------------------------------------------------------------===// 29// TemplateArgument Implementation 30//===----------------------------------------------------------------------===// 31 32TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, 33 const TemplateArgument *Args, 34 unsigned NumArgs) { 35 if (NumArgs == 0) 36 return TemplateArgument(0, 0); 37 38 TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; 39 std::copy(Args, Args + NumArgs, Storage); 40 return TemplateArgument(Storage, NumArgs); 41} 42 43bool TemplateArgument::isDependent() const { 44 switch (getKind()) { 45 case Null: 46 assert(false && "Should not have a NULL template argument"); 47 return false; 48 49 case Type: 50 return getAsType()->isDependentType(); 51 52 case Template: 53 return getAsTemplate().isDependent(); 54 55 case TemplateExpansion: 56 return true; 57 58 case Declaration: 59 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 60 return DC->isDependentContext(); 61 return getAsDecl()->getDeclContext()->isDependentContext(); 62 63 case Integral: 64 // Never dependent 65 return false; 66 67 case Expression: 68 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); 69 70 case Pack: 71 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { 72 if (P->isDependent()) 73 return true; 74 } 75 76 return false; 77 } 78 79 return false; 80} 81 82bool TemplateArgument::isPackExpansion() const { 83 switch (getKind()) { 84 case Null: 85 case Declaration: 86 case Integral: 87 case Pack: 88 case Template: 89 return false; 90 91 case TemplateExpansion: 92 return true; 93 94 case Type: 95 return isa<PackExpansionType>(getAsType()); 96 97 case Expression: 98 return isa<PackExpansionExpr>(getAsExpr()); 99 } 100 101 return false; 102} 103 104bool TemplateArgument::containsUnexpandedParameterPack() const { 105 switch (getKind()) { 106 case Null: 107 case Declaration: 108 case Integral: 109 case TemplateExpansion: 110 break; 111 112 case Type: 113 if (getAsType()->containsUnexpandedParameterPack()) 114 return true; 115 break; 116 117 case Template: 118 if (getAsTemplate().containsUnexpandedParameterPack()) 119 return true; 120 break; 121 122 case Expression: 123 if (getAsExpr()->containsUnexpandedParameterPack()) 124 return true; 125 break; 126 127 case Pack: 128 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) 129 if (P->containsUnexpandedParameterPack()) 130 return true; 131 132 break; 133 } 134 135 return false; 136} 137 138void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 139 const ASTContext &Context) const { 140 ID.AddInteger(Kind); 141 switch (Kind) { 142 case Null: 143 break; 144 145 case Type: 146 getAsType().Profile(ID); 147 break; 148 149 case Declaration: 150 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 151 break; 152 153 case Template: 154 case TemplateExpansion: { 155 TemplateName Template = getAsTemplateOrTemplatePattern(); 156 if (TemplateTemplateParmDecl *TTP 157 = dyn_cast_or_null<TemplateTemplateParmDecl>( 158 Template.getAsTemplateDecl())) { 159 ID.AddBoolean(true); 160 ID.AddInteger(TTP->getDepth()); 161 ID.AddInteger(TTP->getPosition()); 162 ID.AddBoolean(TTP->isParameterPack()); 163 } else { 164 ID.AddBoolean(false); 165 ID.AddPointer(Context.getCanonicalTemplateName(Template) 166 .getAsVoidPointer()); 167 } 168 break; 169 } 170 171 case Integral: 172 getAsIntegral()->Profile(ID); 173 getIntegralType().Profile(ID); 174 break; 175 176 case Expression: 177 getAsExpr()->Profile(ID, Context, true); 178 break; 179 180 case Pack: 181 ID.AddInteger(Args.NumArgs); 182 for (unsigned I = 0; I != Args.NumArgs; ++I) 183 Args.Args[I].Profile(ID, Context); 184 } 185} 186 187bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 188 if (getKind() != Other.getKind()) return false; 189 190 switch (getKind()) { 191 case Null: 192 case Type: 193 case Declaration: 194 case Expression: 195 case Template: 196 case TemplateExpansion: 197 return TypeOrValue == Other.TypeOrValue; 198 199 case Integral: 200 return getIntegralType() == Other.getIntegralType() && 201 *getAsIntegral() == *Other.getAsIntegral(); 202 203 case Pack: 204 if (Args.NumArgs != Other.Args.NumArgs) return false; 205 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 206 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 207 return false; 208 return true; 209 } 210 211 // Suppress warnings. 212 return false; 213} 214 215TemplateArgument TemplateArgument::getPackExpansionPattern() const { 216 assert(isPackExpansion()); 217 218 switch (getKind()) { 219 case Type: 220 return getAsType()->getAs<PackExpansionType>()->getPattern(); 221 222 case Expression: 223 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 224 225 case TemplateExpansion: 226 return TemplateArgument(getAsTemplateOrTemplatePattern(), false); 227 228 case Declaration: 229 case Integral: 230 case Pack: 231 case Null: 232 case Template: 233 return TemplateArgument(); 234 } 235 236 return TemplateArgument(); 237} 238 239void TemplateArgument::print(const PrintingPolicy &Policy, 240 llvm::raw_ostream &Out) const { 241 switch (getKind()) { 242 case Null: 243 Out << "<no value>"; 244 break; 245 246 case Type: { 247 std::string TypeStr; 248 getAsType().getAsStringInternal(TypeStr, Policy); 249 Out << TypeStr; 250 break; 251 } 252 253 case Declaration: { 254 bool Unnamed = true; 255 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 256 if (ND->getDeclName()) { 257 Unnamed = false; 258 Out << ND->getNameAsString(); 259 } 260 } 261 262 if (Unnamed) { 263 Out << "<anonymous>"; 264 } 265 break; 266 } 267 268 case Template: 269 getAsTemplate().print(Out, Policy); 270 break; 271 272 case TemplateExpansion: 273 getAsTemplateOrTemplatePattern().print(Out, Policy); 274 Out << "..."; 275 break; 276 277 case Integral: { 278 Out << getAsIntegral()->toString(10); 279 break; 280 } 281 282 case Expression: 283 getAsExpr()->printPretty(Out, 0, Policy); 284 break; 285 286 case Pack: 287 Out << "<"; 288 bool First = true; 289 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 290 P != PEnd; ++P) { 291 if (First) 292 First = false; 293 else 294 Out << ", "; 295 296 P->print(Policy, Out); 297 } 298 Out << ">"; 299 break; 300 } 301} 302 303//===----------------------------------------------------------------------===// 304// TemplateArgumentLoc Implementation 305//===----------------------------------------------------------------------===// 306 307TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 308 memset(this, 0, sizeof(TemplateArgumentLocInfo)); 309} 310 311SourceRange TemplateArgumentLoc::getSourceRange() const { 312 switch (Argument.getKind()) { 313 case TemplateArgument::Expression: 314 return getSourceExpression()->getSourceRange(); 315 316 case TemplateArgument::Declaration: 317 return getSourceDeclExpression()->getSourceRange(); 318 319 case TemplateArgument::Type: 320 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 321 return TSI->getTypeLoc().getSourceRange(); 322 else 323 return SourceRange(); 324 325 case TemplateArgument::Template: 326 if (getTemplateQualifierRange().isValid()) 327 return SourceRange(getTemplateQualifierRange().getBegin(), 328 getTemplateNameLoc()); 329 return SourceRange(getTemplateNameLoc()); 330 331 case TemplateArgument::TemplateExpansion: 332 if (getTemplateQualifierRange().isValid()) 333 return SourceRange(getTemplateQualifierRange().getBegin(), 334 getTemplateEllipsisLoc()); 335 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 336 337 case TemplateArgument::Integral: 338 case TemplateArgument::Pack: 339 case TemplateArgument::Null: 340 return SourceRange(); 341 } 342 343 // Silence bonus gcc warning. 344 return SourceRange(); 345} 346 347TemplateArgumentLoc 348TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 349 ASTContext &Context) const { 350 assert(Argument.isPackExpansion()); 351 352 switch (Argument.getKind()) { 353 case TemplateArgument::Type: { 354 // FIXME: We shouldn't ever have to worry about missing 355 // type-source info! 356 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 357 if (!ExpansionTSInfo) 358 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 359 getArgument().getAsType(), 360 Ellipsis); 361 PackExpansionTypeLoc Expansion 362 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 363 Ellipsis = Expansion.getEllipsisLoc(); 364 365 TypeLoc Pattern = Expansion.getPatternLoc(); 366 367 // FIXME: This is horrible. We know where the source location data is for 368 // the pattern, and we have the pattern's type, but we are forced to copy 369 // them into an ASTContext because TypeSourceInfo bundles them together 370 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 371 TypeSourceInfo *PatternTSInfo 372 = Context.CreateTypeSourceInfo(Pattern.getType(), 373 Pattern.getFullDataSize()); 374 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 375 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 376 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 377 PatternTSInfo); 378 } 379 380 case TemplateArgument::Expression: { 381 PackExpansionExpr *Expansion 382 = cast<PackExpansionExpr>(Argument.getAsExpr()); 383 Expr *Pattern = Expansion->getPattern(); 384 Ellipsis = Expansion->getEllipsisLoc(); 385 return TemplateArgumentLoc(Pattern, Pattern); 386 } 387 388 case TemplateArgument::TemplateExpansion: 389 Ellipsis = getTemplateEllipsisLoc(); 390 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 391 getTemplateQualifierRange(), 392 getTemplateNameLoc()); 393 394 case TemplateArgument::Declaration: 395 case TemplateArgument::Template: 396 case TemplateArgument::Integral: 397 case TemplateArgument::Pack: 398 case TemplateArgument::Null: 399 return TemplateArgumentLoc(); 400 } 401 402 return TemplateArgumentLoc(); 403} 404 405const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 406 const TemplateArgument &Arg) { 407 switch (Arg.getKind()) { 408 case TemplateArgument::Null: 409 // This is bad, but not as bad as crashing because of argument 410 // count mismatches. 411 return DB << "(null template argument)"; 412 413 case TemplateArgument::Type: 414 return DB << Arg.getAsType(); 415 416 case TemplateArgument::Declaration: 417 return DB << Arg.getAsDecl(); 418 419 case TemplateArgument::Integral: 420 return DB << Arg.getAsIntegral()->toString(10); 421 422 case TemplateArgument::Template: 423 return DB << Arg.getAsTemplate(); 424 425 case TemplateArgument::TemplateExpansion: 426 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 427 428 case TemplateArgument::Expression: { 429 // This shouldn't actually ever happen, so it's okay that we're 430 // regurgitating an expression here. 431 // FIXME: We're guessing at LangOptions! 432 llvm::SmallString<32> Str; 433 llvm::raw_svector_ostream OS(Str); 434 LangOptions LangOpts; 435 LangOpts.CPlusPlus = true; 436 PrintingPolicy Policy(LangOpts); 437 Arg.getAsExpr()->printPretty(OS, 0, Policy); 438 return DB << OS.str(); 439 } 440 441 case TemplateArgument::Pack: { 442 // FIXME: We're guessing at LangOptions! 443 llvm::SmallString<32> Str; 444 llvm::raw_svector_ostream OS(Str); 445 LangOptions LangOpts; 446 LangOpts.CPlusPlus = true; 447 PrintingPolicy Policy(LangOpts); 448 Arg.print(Policy, OS); 449 return DB << OS.str(); 450 } 451 } 452 453 return DB; 454} 455