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