TemplateBase.cpp revision 2be29f423acad3bbe39099a78db2805acb5bdf17
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 138llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 139 assert(Kind == TemplateExpansion); 140 if (TemplateArg.NumExpansions) 141 return TemplateArg.NumExpansions - 1; 142 143 return llvm::Optional<unsigned>(); 144} 145 146void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 147 const ASTContext &Context) const { 148 ID.AddInteger(Kind); 149 switch (Kind) { 150 case Null: 151 break; 152 153 case Type: 154 getAsType().Profile(ID); 155 break; 156 157 case Declaration: 158 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 159 break; 160 161 case Template: 162 case TemplateExpansion: { 163 TemplateName Template = getAsTemplateOrTemplatePattern(); 164 if (TemplateTemplateParmDecl *TTP 165 = dyn_cast_or_null<TemplateTemplateParmDecl>( 166 Template.getAsTemplateDecl())) { 167 ID.AddBoolean(true); 168 ID.AddInteger(TTP->getDepth()); 169 ID.AddInteger(TTP->getPosition()); 170 ID.AddBoolean(TTP->isParameterPack()); 171 } else { 172 ID.AddBoolean(false); 173 ID.AddPointer(Context.getCanonicalTemplateName(Template) 174 .getAsVoidPointer()); 175 } 176 break; 177 } 178 179 case Integral: 180 getAsIntegral()->Profile(ID); 181 getIntegralType().Profile(ID); 182 break; 183 184 case Expression: 185 getAsExpr()->Profile(ID, Context, true); 186 break; 187 188 case Pack: 189 ID.AddInteger(Args.NumArgs); 190 for (unsigned I = 0; I != Args.NumArgs; ++I) 191 Args.Args[I].Profile(ID, Context); 192 } 193} 194 195bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 196 if (getKind() != Other.getKind()) return false; 197 198 switch (getKind()) { 199 case Null: 200 case Type: 201 case Declaration: 202 case Expression: 203 case Template: 204 case TemplateExpansion: 205 return TypeOrValue == Other.TypeOrValue; 206 207 case Integral: 208 return getIntegralType() == Other.getIntegralType() && 209 *getAsIntegral() == *Other.getAsIntegral(); 210 211 case Pack: 212 if (Args.NumArgs != Other.Args.NumArgs) return false; 213 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 214 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 215 return false; 216 return true; 217 } 218 219 // Suppress warnings. 220 return false; 221} 222 223TemplateArgument TemplateArgument::getPackExpansionPattern() const { 224 assert(isPackExpansion()); 225 226 switch (getKind()) { 227 case Type: 228 return getAsType()->getAs<PackExpansionType>()->getPattern(); 229 230 case Expression: 231 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 232 233 case TemplateExpansion: 234 return TemplateArgument(getAsTemplateOrTemplatePattern()); 235 236 case Declaration: 237 case Integral: 238 case Pack: 239 case Null: 240 case Template: 241 return TemplateArgument(); 242 } 243 244 return TemplateArgument(); 245} 246 247void TemplateArgument::print(const PrintingPolicy &Policy, 248 llvm::raw_ostream &Out) const { 249 switch (getKind()) { 250 case Null: 251 Out << "<no value>"; 252 break; 253 254 case Type: { 255 std::string TypeStr; 256 getAsType().getAsStringInternal(TypeStr, Policy); 257 Out << TypeStr; 258 break; 259 } 260 261 case Declaration: { 262 bool Unnamed = true; 263 if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { 264 if (ND->getDeclName()) { 265 Unnamed = false; 266 Out << ND->getNameAsString(); 267 } 268 } 269 270 if (Unnamed) { 271 Out << "<anonymous>"; 272 } 273 break; 274 } 275 276 case Template: 277 getAsTemplate().print(Out, Policy); 278 break; 279 280 case TemplateExpansion: 281 getAsTemplateOrTemplatePattern().print(Out, Policy); 282 Out << "..."; 283 break; 284 285 case Integral: { 286 Out << getAsIntegral()->toString(10); 287 break; 288 } 289 290 case Expression: 291 getAsExpr()->printPretty(Out, 0, Policy); 292 break; 293 294 case Pack: 295 Out << "<"; 296 bool First = true; 297 for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); 298 P != PEnd; ++P) { 299 if (First) 300 First = false; 301 else 302 Out << ", "; 303 304 P->print(Policy, Out); 305 } 306 Out << ">"; 307 break; 308 } 309} 310 311//===----------------------------------------------------------------------===// 312// TemplateArgumentLoc Implementation 313//===----------------------------------------------------------------------===// 314 315TemplateArgumentLocInfo::TemplateArgumentLocInfo() { 316 memset(this, 0, sizeof(TemplateArgumentLocInfo)); 317} 318 319SourceRange TemplateArgumentLoc::getSourceRange() const { 320 switch (Argument.getKind()) { 321 case TemplateArgument::Expression: 322 return getSourceExpression()->getSourceRange(); 323 324 case TemplateArgument::Declaration: 325 return getSourceDeclExpression()->getSourceRange(); 326 327 case TemplateArgument::Type: 328 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 329 return TSI->getTypeLoc().getSourceRange(); 330 else 331 return SourceRange(); 332 333 case TemplateArgument::Template: 334 if (getTemplateQualifierRange().isValid()) 335 return SourceRange(getTemplateQualifierRange().getBegin(), 336 getTemplateNameLoc()); 337 return SourceRange(getTemplateNameLoc()); 338 339 case TemplateArgument::TemplateExpansion: 340 if (getTemplateQualifierRange().isValid()) 341 return SourceRange(getTemplateQualifierRange().getBegin(), 342 getTemplateEllipsisLoc()); 343 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 344 345 case TemplateArgument::Integral: 346 case TemplateArgument::Pack: 347 case TemplateArgument::Null: 348 return SourceRange(); 349 } 350 351 // Silence bonus gcc warning. 352 return SourceRange(); 353} 354 355TemplateArgumentLoc 356TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, 357 llvm::Optional<unsigned> &NumExpansions, 358 ASTContext &Context) const { 359 assert(Argument.isPackExpansion()); 360 361 switch (Argument.getKind()) { 362 case TemplateArgument::Type: { 363 // FIXME: We shouldn't ever have to worry about missing 364 // type-source info! 365 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 366 if (!ExpansionTSInfo) 367 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 368 getArgument().getAsType(), 369 Ellipsis); 370 PackExpansionTypeLoc Expansion 371 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 372 Ellipsis = Expansion.getEllipsisLoc(); 373 374 TypeLoc Pattern = Expansion.getPatternLoc(); 375 NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 376 377 // FIXME: This is horrible. We know where the source location data is for 378 // the pattern, and we have the pattern's type, but we are forced to copy 379 // them into an ASTContext because TypeSourceInfo bundles them together 380 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 381 TypeSourceInfo *PatternTSInfo 382 = Context.CreateTypeSourceInfo(Pattern.getType(), 383 Pattern.getFullDataSize()); 384 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 385 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 386 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 387 PatternTSInfo); 388 } 389 390 case TemplateArgument::Expression: { 391 PackExpansionExpr *Expansion 392 = cast<PackExpansionExpr>(Argument.getAsExpr()); 393 Expr *Pattern = Expansion->getPattern(); 394 Ellipsis = Expansion->getEllipsisLoc(); 395 NumExpansions = Expansion->getNumExpansions(); 396 return TemplateArgumentLoc(Pattern, Pattern); 397 } 398 399 case TemplateArgument::TemplateExpansion: 400 Ellipsis = getTemplateEllipsisLoc(); 401 NumExpansions = Argument.getNumTemplateExpansions(); 402 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 403 getTemplateQualifierRange(), 404 getTemplateNameLoc()); 405 406 case TemplateArgument::Declaration: 407 case TemplateArgument::Template: 408 case TemplateArgument::Integral: 409 case TemplateArgument::Pack: 410 case TemplateArgument::Null: 411 return TemplateArgumentLoc(); 412 } 413 414 return TemplateArgumentLoc(); 415} 416 417const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 418 const TemplateArgument &Arg) { 419 switch (Arg.getKind()) { 420 case TemplateArgument::Null: 421 // This is bad, but not as bad as crashing because of argument 422 // count mismatches. 423 return DB << "(null template argument)"; 424 425 case TemplateArgument::Type: 426 return DB << Arg.getAsType(); 427 428 case TemplateArgument::Declaration: 429 return DB << Arg.getAsDecl(); 430 431 case TemplateArgument::Integral: 432 return DB << Arg.getAsIntegral()->toString(10); 433 434 case TemplateArgument::Template: 435 return DB << Arg.getAsTemplate(); 436 437 case TemplateArgument::TemplateExpansion: 438 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 439 440 case TemplateArgument::Expression: { 441 // This shouldn't actually ever happen, so it's okay that we're 442 // regurgitating an expression here. 443 // FIXME: We're guessing at LangOptions! 444 llvm::SmallString<32> Str; 445 llvm::raw_svector_ostream OS(Str); 446 LangOptions LangOpts; 447 LangOpts.CPlusPlus = true; 448 PrintingPolicy Policy(LangOpts); 449 Arg.getAsExpr()->printPretty(OS, 0, Policy); 450 return DB << OS.str(); 451 } 452 453 case TemplateArgument::Pack: { 454 // FIXME: We're guessing at LangOptions! 455 llvm::SmallString<32> Str; 456 llvm::raw_svector_ostream OS(Str); 457 LangOptions LangOpts; 458 LangOpts.CPlusPlus = true; 459 PrintingPolicy Policy(LangOpts); 460 Arg.print(Policy, OS); 461 return DB << OS.str(); 462 } 463 } 464 465 return DB; 466} 467