TemplateBase.cpp revision 67c4a0ca65dd72784a1778264938c8ba45506cea
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 29/// \brief Construct a template argument pack. 30void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, 31 bool CopyArgs) { 32 assert(isNull() && "Must call setArgumentPack on a null argument"); 33 34 Kind = Pack; 35 Args.NumArgs = NumArgs; 36 Args.CopyArgs = CopyArgs; 37 if (!Args.CopyArgs) { 38 Args.Args = args; 39 return; 40 } 41 42 // FIXME: Allocate in ASTContext 43 Args.Args = new TemplateArgument[NumArgs]; 44 for (unsigned I = 0; I != Args.NumArgs; ++I) 45 Args.Args[I] = args[I]; 46} 47 48void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 49 ASTContext &Context) const { 50 ID.AddInteger(Kind); 51 switch (Kind) { 52 case Null: 53 break; 54 55 case Type: 56 getAsType().Profile(ID); 57 break; 58 59 case Declaration: 60 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); 61 break; 62 63 case Template: 64 if (TemplateTemplateParmDecl *TTP 65 = dyn_cast_or_null<TemplateTemplateParmDecl>( 66 getAsTemplate().getAsTemplateDecl())) { 67 ID.AddBoolean(true); 68 ID.AddInteger(TTP->getDepth()); 69 ID.AddInteger(TTP->getPosition()); 70 } else { 71 ID.AddBoolean(false); 72 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) 73 .getAsVoidPointer()); 74 } 75 break; 76 77 case Integral: 78 getAsIntegral()->Profile(ID); 79 getIntegralType().Profile(ID); 80 break; 81 82 case Expression: 83 getAsExpr()->Profile(ID, Context, true); 84 break; 85 86 case Pack: 87 ID.AddInteger(Args.NumArgs); 88 for (unsigned I = 0; I != Args.NumArgs; ++I) 89 Args.Args[I].Profile(ID, Context); 90 } 91} 92 93bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 94 if (getKind() != Other.getKind()) return false; 95 96 switch (getKind()) { 97 case Null: 98 case Type: 99 case Declaration: 100 case Template: 101 case Expression: 102 return TypeOrValue == Other.TypeOrValue; 103 104 case Integral: 105 return getIntegralType() == Other.getIntegralType() && 106 *getAsIntegral() == *Other.getAsIntegral(); 107 108 case Pack: 109 if (Args.NumArgs != Other.Args.NumArgs) return false; 110 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 111 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 112 return false; 113 return true; 114 } 115 116 // Suppress warnings. 117 return false; 118} 119 120//===----------------------------------------------------------------------===// 121// TemplateArgumentLoc Implementation 122//===----------------------------------------------------------------------===// 123 124SourceRange TemplateArgumentLoc::getSourceRange() const { 125 switch (Argument.getKind()) { 126 case TemplateArgument::Expression: 127 return getSourceExpression()->getSourceRange(); 128 129 case TemplateArgument::Declaration: 130 return getSourceDeclExpression()->getSourceRange(); 131 132 case TemplateArgument::Type: 133 return getTypeSourceInfo()->getTypeLoc().getSourceRange(); 134 135 case TemplateArgument::Template: 136 if (getTemplateQualifierRange().isValid()) 137 return SourceRange(getTemplateQualifierRange().getBegin(), 138 getTemplateNameLoc()); 139 return SourceRange(getTemplateNameLoc()); 140 141 case TemplateArgument::Integral: 142 case TemplateArgument::Pack: 143 case TemplateArgument::Null: 144 return SourceRange(); 145 } 146 147 // Silence bonus gcc warning. 148 return SourceRange(); 149} 150 151const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 152 const TemplateArgument &Arg) { 153 switch (Arg.getKind()) { 154 case TemplateArgument::Null: 155 // This is bad, but not as bad as crashing because of argument 156 // count mismatches. 157 return DB << "(null template argument)"; 158 159 case TemplateArgument::Type: 160 return DB << Arg.getAsType(); 161 162 case TemplateArgument::Declaration: 163 return DB << Arg.getAsDecl(); 164 165 case TemplateArgument::Integral: 166 return DB << Arg.getAsIntegral()->toString(10); 167 168 case TemplateArgument::Template: 169 return DB << Arg.getAsTemplate(); 170 171 case TemplateArgument::Expression: { 172 // This shouldn't actually ever happen, so it's okay that we're 173 // regurgitating an expression here. 174 // FIXME: We're guessing at LangOptions! 175 llvm::SmallString<32> Str; 176 llvm::raw_svector_ostream OS(Str); 177 LangOptions LangOpts; 178 LangOpts.CPlusPlus = true; 179 PrintingPolicy Policy(LangOpts); 180 Arg.getAsExpr()->printPretty(OS, 0, Policy); 181 return DB << OS.str(); 182 } 183 184 case TemplateArgument::Pack: 185 // FIXME: Format arguments in a list! 186 return DB << "<parameter pack>"; 187 } 188 189 return DB; 190} 191