]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
Upgrade xz to git snapshot as of 20101010
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / AST / TemplateBase.cpp
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
23 using namespace clang;
24
25 //===----------------------------------------------------------------------===//
26 // TemplateArgument Implementation
27 //===----------------------------------------------------------------------===//
28
29 /// \brief Construct a template argument pack.
30 void 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
48 void 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
93 bool 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
124 SourceRange 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     if (TypeSourceInfo *TSI = getTypeSourceInfo())
134       return TSI->getTypeLoc().getSourceRange();
135     else
136       return SourceRange();
137
138   case TemplateArgument::Template:
139     if (getTemplateQualifierRange().isValid())
140       return SourceRange(getTemplateQualifierRange().getBegin(),
141                          getTemplateNameLoc());
142     return SourceRange(getTemplateNameLoc());
143
144   case TemplateArgument::Integral:
145   case TemplateArgument::Pack:
146   case TemplateArgument::Null:
147     return SourceRange();
148   }
149
150   // Silence bonus gcc warning.
151   return SourceRange();
152 }
153
154 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
155                                            const TemplateArgument &Arg) {
156   switch (Arg.getKind()) {
157   case TemplateArgument::Null:
158     // This is bad, but not as bad as crashing because of argument
159     // count mismatches.
160     return DB << "(null template argument)";
161       
162   case TemplateArgument::Type:
163     return DB << Arg.getAsType();
164       
165   case TemplateArgument::Declaration:
166     return DB << Arg.getAsDecl();
167       
168   case TemplateArgument::Integral:
169     return DB << Arg.getAsIntegral()->toString(10);
170       
171   case TemplateArgument::Template:
172     return DB << Arg.getAsTemplate();
173       
174   case TemplateArgument::Expression: {
175     // This shouldn't actually ever happen, so it's okay that we're
176     // regurgitating an expression here.
177     // FIXME: We're guessing at LangOptions!
178     llvm::SmallString<32> Str;
179     llvm::raw_svector_ostream OS(Str);
180     LangOptions LangOpts;
181     LangOpts.CPlusPlus = true;
182     PrintingPolicy Policy(LangOpts);
183     Arg.getAsExpr()->printPretty(OS, 0, Policy);
184     return DB << OS.str();
185   }
186       
187   case TemplateArgument::Pack:
188     // FIXME: Format arguments in a list!
189     return DB << "<parameter pack>";
190   }
191   
192   return DB;
193 }