| //===--- TemplateBase.cpp - Common template AST class implementation ------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements common classes used throughout C++ template | 
 | // representations. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/ADT/FoldingSet.h" | 
 | #include "clang/AST/TemplateBase.h" | 
 | #include "clang/AST/DeclBase.h" | 
 | #include "clang/AST/DeclTemplate.h" | 
 | #include "clang/AST/Expr.h" | 
 | #include "clang/AST/TypeLoc.h" | 
 | #include "clang/Basic/Diagnostic.h" | 
 |  | 
 | using namespace clang; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // TemplateArgument Implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | /// \brief Construct a template argument pack. | 
 | void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs, | 
 |                                        bool CopyArgs) { | 
 |   assert(isNull() && "Must call setArgumentPack on a null argument"); | 
 |  | 
 |   Kind = Pack; | 
 |   Args.NumArgs = NumArgs; | 
 |   Args.CopyArgs = CopyArgs; | 
 |   if (!Args.CopyArgs) { | 
 |     Args.Args = args; | 
 |     return; | 
 |   } | 
 |  | 
 |   // FIXME: Allocate in ASTContext | 
 |   Args.Args = new TemplateArgument[NumArgs]; | 
 |   for (unsigned I = 0; I != Args.NumArgs; ++I) | 
 |     Args.Args[I] = args[I]; | 
 | } | 
 |  | 
 | void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, | 
 |                                ASTContext &Context) const { | 
 |   ID.AddInteger(Kind); | 
 |   switch (Kind) { | 
 |   case Null: | 
 |     break; | 
 |  | 
 |   case Type: | 
 |     getAsType().Profile(ID); | 
 |     break; | 
 |  | 
 |   case Declaration: | 
 |     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); | 
 |     break; | 
 |  | 
 |   case Template: | 
 |     if (TemplateTemplateParmDecl *TTP | 
 |           = dyn_cast_or_null<TemplateTemplateParmDecl>( | 
 |                                        getAsTemplate().getAsTemplateDecl())) { | 
 |       ID.AddBoolean(true); | 
 |       ID.AddInteger(TTP->getDepth()); | 
 |       ID.AddInteger(TTP->getPosition()); | 
 |     } else { | 
 |       ID.AddBoolean(false); | 
 |       ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) | 
 |                       .getAsVoidPointer()); | 
 |     } | 
 |     break; | 
 |        | 
 |   case Integral: | 
 |     getAsIntegral()->Profile(ID); | 
 |     getIntegralType().Profile(ID); | 
 |     break; | 
 |  | 
 |   case Expression: | 
 |     getAsExpr()->Profile(ID, Context, true); | 
 |     break; | 
 |  | 
 |   case Pack: | 
 |     ID.AddInteger(Args.NumArgs); | 
 |     for (unsigned I = 0; I != Args.NumArgs; ++I) | 
 |       Args.Args[I].Profile(ID, Context); | 
 |   } | 
 | } | 
 |  | 
 | bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { | 
 |   if (getKind() != Other.getKind()) return false; | 
 |  | 
 |   switch (getKind()) { | 
 |   case Null: | 
 |   case Type: | 
 |   case Declaration: | 
 |   case Template: | 
 |   case Expression: | 
 |     return TypeOrValue == Other.TypeOrValue; | 
 |  | 
 |   case Integral: | 
 |     return getIntegralType() == Other.getIntegralType() && | 
 |            *getAsIntegral() == *Other.getAsIntegral(); | 
 |  | 
 |   case Pack: | 
 |     if (Args.NumArgs != Other.Args.NumArgs) return false; | 
 |     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) | 
 |       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) | 
 |         return false; | 
 |     return true; | 
 |   } | 
 |  | 
 |   // Suppress warnings. | 
 |   return false; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // TemplateArgumentLoc Implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | SourceRange TemplateArgumentLoc::getSourceRange() const { | 
 |   switch (Argument.getKind()) { | 
 |   case TemplateArgument::Expression: | 
 |     return getSourceExpression()->getSourceRange(); | 
 |        | 
 |   case TemplateArgument::Declaration: | 
 |     return getSourceDeclExpression()->getSourceRange(); | 
 |        | 
 |   case TemplateArgument::Type: | 
 |     return getTypeSourceInfo()->getTypeLoc().getSourceRange(); | 
 |        | 
 |   case TemplateArgument::Template: | 
 |     if (getTemplateQualifierRange().isValid()) | 
 |       return SourceRange(getTemplateQualifierRange().getBegin(), | 
 |                          getTemplateNameLoc()); | 
 |     return SourceRange(getTemplateNameLoc()); | 
 |        | 
 |   case TemplateArgument::Integral: | 
 |   case TemplateArgument::Pack: | 
 |   case TemplateArgument::Null: | 
 |     return SourceRange(); | 
 |   } | 
 |  | 
 |   // Silence bonus gcc warning. | 
 |   return SourceRange(); | 
 | } | 
 |  | 
 | const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, | 
 |                                            const TemplateArgument &Arg) { | 
 |   switch (Arg.getKind()) { | 
 |   case TemplateArgument::Null: | 
 |     // This is bad, but not as bad as crashing because of argument | 
 |     // count mismatches. | 
 |     return DB << "(null template argument)"; | 
 |        | 
 |   case TemplateArgument::Type: | 
 |     return DB << Arg.getAsType(); | 
 |        | 
 |   case TemplateArgument::Declaration: | 
 |     return DB << Arg.getAsDecl(); | 
 |        | 
 |   case TemplateArgument::Integral: | 
 |     return DB << Arg.getAsIntegral()->toString(10); | 
 |        | 
 |   case TemplateArgument::Template: | 
 |     return DB << Arg.getAsTemplate(); | 
 |        | 
 |   case TemplateArgument::Expression: { | 
 |     // This shouldn't actually ever happen, so it's okay that we're | 
 |     // regurgitating an expression here. | 
 |     // FIXME: We're guessing at LangOptions! | 
 |     llvm::SmallString<32> Str; | 
 |     llvm::raw_svector_ostream OS(Str); | 
 |     LangOptions LangOpts; | 
 |     LangOpts.CPlusPlus = true; | 
 |     PrintingPolicy Policy(LangOpts); | 
 |     Arg.getAsExpr()->printPretty(OS, 0, Policy); | 
 |     return DB << OS.str(); | 
 |   } | 
 |        | 
 |   case TemplateArgument::Pack: | 
 |     // FIXME: Format arguments in a list! | 
 |     return DB << "<parameter pack>"; | 
 |   } | 
 |    | 
 |   return DB; | 
 | } |