TemplateBase.cpp revision cded4f649cd4b7ba7d461c25c6482ef52b8d3a2a
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 llvm::Optional<unsigned> &NumExpansions, 350 ASTContext &Context) const { 351 assert(Argument.isPackExpansion()); 352 353 switch (Argument.getKind()) { 354 case TemplateArgument::Type: { 355 // FIXME: We shouldn't ever have to worry about missing 356 // type-source info! 357 TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo(); 358 if (!ExpansionTSInfo) 359 ExpansionTSInfo = Context.getTrivialTypeSourceInfo( 360 getArgument().getAsType(), 361 Ellipsis); 362 PackExpansionTypeLoc Expansion 363 = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc()); 364 Ellipsis = Expansion.getEllipsisLoc(); 365 366 TypeLoc Pattern = Expansion.getPatternLoc(); 367 NumExpansions = Expansion.getTypePtr()->getNumExpansions(); 368 369 // FIXME: This is horrible. We know where the source location data is for 370 // the pattern, and we have the pattern's type, but we are forced to copy 371 // them into an ASTContext because TypeSourceInfo bundles them together 372 // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. 373 TypeSourceInfo *PatternTSInfo 374 = Context.CreateTypeSourceInfo(Pattern.getType(), 375 Pattern.getFullDataSize()); 376 memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), 377 Pattern.getOpaqueData(), Pattern.getFullDataSize()); 378 return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), 379 PatternTSInfo); 380 } 381 382 case TemplateArgument::Expression: { 383 PackExpansionExpr *Expansion 384 = cast<PackExpansionExpr>(Argument.getAsExpr()); 385 Expr *Pattern = Expansion->getPattern(); 386 Ellipsis = Expansion->getEllipsisLoc(); 387 // FIXME: Variadic templates num expansions 388 return TemplateArgumentLoc(Pattern, Pattern); 389 } 390 391 case TemplateArgument::TemplateExpansion: 392 // FIXME: Variadic templates num expansions 393 Ellipsis = getTemplateEllipsisLoc(); 394 return TemplateArgumentLoc(Argument.getPackExpansionPattern(), 395 getTemplateQualifierRange(), 396 getTemplateNameLoc()); 397 398 case TemplateArgument::Declaration: 399 case TemplateArgument::Template: 400 case TemplateArgument::Integral: 401 case TemplateArgument::Pack: 402 case TemplateArgument::Null: 403 return TemplateArgumentLoc(); 404 } 405 406 return TemplateArgumentLoc(); 407} 408 409const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 410 const TemplateArgument &Arg) { 411 switch (Arg.getKind()) { 412 case TemplateArgument::Null: 413 // This is bad, but not as bad as crashing because of argument 414 // count mismatches. 415 return DB << "(null template argument)"; 416 417 case TemplateArgument::Type: 418 return DB << Arg.getAsType(); 419 420 case TemplateArgument::Declaration: 421 return DB << Arg.getAsDecl(); 422 423 case TemplateArgument::Integral: 424 return DB << Arg.getAsIntegral()->toString(10); 425 426 case TemplateArgument::Template: 427 return DB << Arg.getAsTemplate(); 428 429 case TemplateArgument::TemplateExpansion: 430 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 431 432 case TemplateArgument::Expression: { 433 // This shouldn't actually ever happen, so it's okay that we're 434 // regurgitating an expression here. 435 // FIXME: We're guessing at LangOptions! 436 llvm::SmallString<32> Str; 437 llvm::raw_svector_ostream OS(Str); 438 LangOptions LangOpts; 439 LangOpts.CPlusPlus = true; 440 PrintingPolicy Policy(LangOpts); 441 Arg.getAsExpr()->printPretty(OS, 0, Policy); 442 return DB << OS.str(); 443 } 444 445 case TemplateArgument::Pack: { 446 // FIXME: We're guessing at LangOptions! 447 llvm::SmallString<32> Str; 448 llvm::raw_svector_ostream OS(Str); 449 LangOptions LangOpts; 450 LangOpts.CPlusPlus = true; 451 PrintingPolicy Policy(LangOpts); 452 Arg.print(Policy, OS); 453 return DB << OS.str(); 454 } 455 } 456 457 return DB; 458} 459