TemplateBase.cpp revision bebbe0d9b7568ce43a464286bee49429489ef483
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 29bool TemplateArgument::isDependent() const { 30 switch (getKind()) { 31 case Null: 32 assert(false && "Should not have a NULL template argument"); 33 return false; 34 35 case Type: 36 return getAsType()->isDependentType(); 37 38 case Template: 39 return getAsTemplate().isDependent(); 40 41 case Declaration: 42 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) 43 return DC->isDependentContext(); 44 return getAsDecl()->getDeclContext()->isDependentContext(); 45 46 case Integral: 47 // Never dependent 48 return false; 49 50 case Expression: 51 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); 52 53 case Pack: 54 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { 55 if (P->isDependent()) 56 return true; 57 } 58 59 return false; 60 } 61 62 return false; 63} 64 65bool TemplateArgument::containsUnexpandedParameterPack() const { 66 switch (getKind()) { 67 case Null: 68 case Declaration: 69 case Integral: 70 break; 71 72 case Type: 73 if (getAsType()->containsUnexpandedParameterPack()) 74 return true; 75 break; 76 77 case Template: 78 if (getAsTemplate().containsUnexpandedParameterPack()) 79 return true; 80 break; 81 82 case Expression: 83 if (getAsExpr()->containsUnexpandedParameterPack()) 84 return true; 85 break; 86 87 case Pack: 88 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) 89 if (P->containsUnexpandedParameterPack()) 90 return true; 91 92 break; 93 } 94 95 return false; 96} 97 98void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 99 ASTContext &Context) const { 100 ID.AddInteger(Kind); 101 switch (Kind) { 102 case Null: 103 break; 104 105 case Type: 106 getAsType().Profile(ID); 107 break; 108 109 case Declaration: 110 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 111 break; 112 113 case Template: 114 if (TemplateTemplateParmDecl *TTP 115 = dyn_cast_or_null<TemplateTemplateParmDecl>( 116 getAsTemplate().getAsTemplateDecl())) { 117 ID.AddBoolean(true); 118 ID.AddInteger(TTP->getDepth()); 119 ID.AddInteger(TTP->getPosition()); 120 } else { 121 ID.AddBoolean(false); 122 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) 123 .getAsVoidPointer()); 124 } 125 break; 126 127 case Integral: 128 getAsIntegral()->Profile(ID); 129 getIntegralType().Profile(ID); 130 break; 131 132 case Expression: 133 getAsExpr()->Profile(ID, Context, true); 134 break; 135 136 case Pack: 137 ID.AddInteger(Args.NumArgs); 138 for (unsigned I = 0; I != Args.NumArgs; ++I) 139 Args.Args[I].Profile(ID, Context); 140 } 141} 142 143bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 144 if (getKind() != Other.getKind()) return false; 145 146 switch (getKind()) { 147 case Null: 148 case Type: 149 case Declaration: 150 case Template: 151 case Expression: 152 return TypeOrValue == Other.TypeOrValue; 153 154 case Integral: 155 return getIntegralType() == Other.getIntegralType() && 156 *getAsIntegral() == *Other.getAsIntegral(); 157 158 case Pack: 159 if (Args.NumArgs != Other.Args.NumArgs) return false; 160 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 161 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 162 return false; 163 return true; 164 } 165 166 // Suppress warnings. 167 return false; 168} 169 170//===----------------------------------------------------------------------===// 171// TemplateArgumentLoc Implementation 172//===----------------------------------------------------------------------===// 173 174SourceRange TemplateArgumentLoc::getSourceRange() const { 175 switch (Argument.getKind()) { 176 case TemplateArgument::Expression: 177 return getSourceExpression()->getSourceRange(); 178 179 case TemplateArgument::Declaration: 180 return getSourceDeclExpression()->getSourceRange(); 181 182 case TemplateArgument::Type: 183 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 184 return TSI->getTypeLoc().getSourceRange(); 185 else 186 return SourceRange(); 187 188 case TemplateArgument::Template: 189 if (getTemplateQualifierRange().isValid()) 190 return SourceRange(getTemplateQualifierRange().getBegin(), 191 getTemplateNameLoc()); 192 return SourceRange(getTemplateNameLoc()); 193 194 case TemplateArgument::Integral: 195 case TemplateArgument::Pack: 196 case TemplateArgument::Null: 197 return SourceRange(); 198 } 199 200 // Silence bonus gcc warning. 201 return SourceRange(); 202} 203 204const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 205 const TemplateArgument &Arg) { 206 switch (Arg.getKind()) { 207 case TemplateArgument::Null: 208 // This is bad, but not as bad as crashing because of argument 209 // count mismatches. 210 return DB << "(null template argument)"; 211 212 case TemplateArgument::Type: 213 return DB << Arg.getAsType(); 214 215 case TemplateArgument::Declaration: 216 return DB << Arg.getAsDecl(); 217 218 case TemplateArgument::Integral: 219 return DB << Arg.getAsIntegral()->toString(10); 220 221 case TemplateArgument::Template: 222 return DB << Arg.getAsTemplate(); 223 224 case TemplateArgument::Expression: { 225 // This shouldn't actually ever happen, so it's okay that we're 226 // regurgitating an expression here. 227 // FIXME: We're guessing at LangOptions! 228 llvm::SmallString<32> Str; 229 llvm::raw_svector_ostream OS(Str); 230 LangOptions LangOpts; 231 LangOpts.CPlusPlus = true; 232 PrintingPolicy Policy(LangOpts); 233 Arg.getAsExpr()->printPretty(OS, 0, Policy); 234 return DB << OS.str(); 235 } 236 237 case TemplateArgument::Pack: 238 // FIXME: Format arguments in a list! 239 return DB << "<parameter pack>"; 240 } 241 242 return DB; 243} 244