blob: 31c1fbf1b780ceb8e7ba287506a5bf4d112e196f [file] [log] [blame]
Douglas Gregor639cccc2010-02-09 22:26:47 +00001//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
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 a diagnostic formatting hook for AST elements.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/AST/ASTDiagnostic.h"
Douglas Gregor639cccc2010-02-09 22:26:47 +000014#include "clang/AST/ASTContext.h"
15#include "clang/AST/DeclObjC.h"
Richard Trieu91844232012-06-26 18:18:47 +000016#include "clang/AST/DeclTemplate.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "clang/AST/ExprCXX.h"
18#include "clang/AST/TemplateBase.h"
Douglas Gregor639cccc2010-02-09 22:26:47 +000019#include "clang/AST/Type.h"
Richard Trieu91844232012-06-26 18:18:47 +000020#include "llvm/ADT/SmallString.h"
Douglas Gregor639cccc2010-02-09 22:26:47 +000021#include "llvm/Support/raw_ostream.h"
22
23using namespace clang;
24
Chandler Carruthd102f2d2010-05-13 11:37:24 +000025// Returns a desugared version of the QualType, and marks ShouldAKA as true
26// whenever we remove significant sugar from the type.
27static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
28 QualifierCollector QC;
29
Douglas Gregor639cccc2010-02-09 22:26:47 +000030 while (true) {
Chandler Carruthd102f2d2010-05-13 11:37:24 +000031 const Type *Ty = QC.strip(QT);
32
Douglas Gregor639cccc2010-02-09 22:26:47 +000033 // Don't aka just because we saw an elaborated type...
Richard Smith30482bc2011-02-20 03:19:35 +000034 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
35 QT = ET->desugar();
Douglas Gregor639cccc2010-02-09 22:26:47 +000036 continue;
37 }
Abramo Bagnara924a8f32010-12-10 16:29:40 +000038 // ... or a paren type ...
Richard Smith30482bc2011-02-20 03:19:35 +000039 if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
40 QT = PT->desugar();
Abramo Bagnara924a8f32010-12-10 16:29:40 +000041 continue;
42 }
Richard Smith30482bc2011-02-20 03:19:35 +000043 // ...or a substituted template type parameter ...
44 if (const SubstTemplateTypeParmType *ST =
45 dyn_cast<SubstTemplateTypeParmType>(Ty)) {
46 QT = ST->desugar();
47 continue;
48 }
John McCall4223a9e2011-03-04 04:00:19 +000049 // ...or an attributed type...
50 if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {
51 QT = AT->desugar();
52 continue;
53 }
Richard Smith30482bc2011-02-20 03:19:35 +000054 // ... or an auto type.
55 if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
56 if (!AT->isSugared())
57 break;
58 QT = AT->desugar();
Douglas Gregor639cccc2010-02-09 22:26:47 +000059 continue;
60 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +000061
Richard Smith3f1b5d02011-05-05 21:57:07 +000062 // Don't desugar template specializations, unless it's an alias template.
63 if (const TemplateSpecializationType *TST
64 = dyn_cast<TemplateSpecializationType>(Ty))
65 if (!TST->isTypeAlias())
66 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +000067
Douglas Gregor639cccc2010-02-09 22:26:47 +000068 // Don't desugar magic Objective-C types.
69 if (QualType(Ty,0) == Context.getObjCIdType() ||
70 QualType(Ty,0) == Context.getObjCClassType() ||
71 QualType(Ty,0) == Context.getObjCSelType() ||
72 QualType(Ty,0) == Context.getObjCProtoType())
73 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +000074
Douglas Gregor639cccc2010-02-09 22:26:47 +000075 // Don't desugar va_list.
76 if (QualType(Ty,0) == Context.getBuiltinVaListType())
77 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +000078
Douglas Gregor639cccc2010-02-09 22:26:47 +000079 // Otherwise, do a single-step desugar.
80 QualType Underlying;
81 bool IsSugar = false;
82 switch (Ty->getTypeClass()) {
83#define ABSTRACT_TYPE(Class, Base)
84#define TYPE(Class, Base) \
85case Type::Class: { \
86const Class##Type *CTy = cast<Class##Type>(Ty); \
87if (CTy->isSugared()) { \
88IsSugar = true; \
89Underlying = CTy->desugar(); \
90} \
91break; \
92}
93#include "clang/AST/TypeNodes.def"
94 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +000095
Douglas Gregor639cccc2010-02-09 22:26:47 +000096 // If it wasn't sugared, we're done.
97 if (!IsSugar)
98 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +000099
Douglas Gregor639cccc2010-02-09 22:26:47 +0000100 // If the desugared type is a vector type, we don't want to expand
101 // it, it will turn into an attribute mess. People want their "vec4".
102 if (isa<VectorType>(Underlying))
103 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000104
Douglas Gregor639cccc2010-02-09 22:26:47 +0000105 // Don't desugar through the primary typedef of an anonymous type.
Chris Lattneredbdff62010-09-04 23:16:01 +0000106 if (const TagType *UTT = Underlying->getAs<TagType>())
107 if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
Richard Smithdda56e42011-04-15 14:24:37 +0000108 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
Chris Lattneredbdff62010-09-04 23:16:01 +0000109 break;
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000110
111 // Record that we actually looked through an opaque type here.
112 ShouldAKA = true;
Douglas Gregor639cccc2010-02-09 22:26:47 +0000113 QT = Underlying;
Douglas Gregor639cccc2010-02-09 22:26:47 +0000114 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000115
116 // If we have a pointer-like type, desugar the pointee as well.
117 // FIXME: Handle other pointer-like types.
118 if (const PointerType *Ty = QT->getAs<PointerType>()) {
Chris Lattneredbdff62010-09-04 23:16:01 +0000119 QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
120 ShouldAKA));
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000121 } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
Chris Lattneredbdff62010-09-04 23:16:01 +0000122 QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
123 ShouldAKA));
Douglas Gregor7a2a1162011-01-20 16:08:06 +0000124 } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
125 QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
126 ShouldAKA));
Douglas Gregor639cccc2010-02-09 22:26:47 +0000127 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000128
John McCall717d9b02010-12-10 11:01:00 +0000129 return QC.apply(Context, QT);
Douglas Gregor639cccc2010-02-09 22:26:47 +0000130}
131
132/// \brief Convert the given type to a string suitable for printing as part of
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000133/// a diagnostic.
134///
Chandler Carruthd5173952011-07-11 17:49:21 +0000135/// There are four main criteria when determining whether we should have an
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000136/// a.k.a. clause when pretty-printing a type:
137///
138/// 1) Some types provide very minimal sugar that doesn't impede the
139/// user's understanding --- for example, elaborated type
140/// specifiers. If this is all the sugar we see, we don't want an
141/// a.k.a. clause.
142/// 2) Some types are technically sugared but are much more familiar
143/// when seen in their sugared form --- for example, va_list,
144/// vector types, and the magic Objective C types. We don't
145/// want to desugar these, even if we do produce an a.k.a. clause.
146/// 3) Some types may have already been desugared previously in this diagnostic.
147/// if this is the case, doing another "aka" would just be clutter.
Chandler Carruthd5173952011-07-11 17:49:21 +0000148/// 4) Two different types within the same diagnostic have the same output
149/// string. In this case, force an a.k.a with the desugared type when
150/// doing so will provide additional information.
Douglas Gregor639cccc2010-02-09 22:26:47 +0000151///
152/// \param Context the context in which the type was allocated
153/// \param Ty the type to print
Chandler Carruthd5173952011-07-11 17:49:21 +0000154/// \param QualTypeVals pointer values to QualTypes which are used in the
155/// diagnostic message
Douglas Gregor639cccc2010-02-09 22:26:47 +0000156static std::string
157ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
David Blaikie9c902b52011-09-25 23:23:43 +0000158 const DiagnosticsEngine::ArgumentValue *PrevArgs,
Chandler Carruthd5173952011-07-11 17:49:21 +0000159 unsigned NumPrevArgs,
Bill Wendling8eb771d2012-02-22 09:51:33 +0000160 ArrayRef<intptr_t> QualTypeVals) {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000161 // FIXME: Playing with std::string is really slow.
Chandler Carruthd5173952011-07-11 17:49:21 +0000162 bool ForceAKA = false;
163 QualType CanTy = Ty.getCanonicalType();
Douglas Gregorc0b07282011-09-27 22:38:19 +0000164 std::string S = Ty.getAsString(Context.getPrintingPolicy());
165 std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
Chandler Carruthd5173952011-07-11 17:49:21 +0000166
Bill Wendling8eb771d2012-02-22 09:51:33 +0000167 for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) {
Chandler Carruthd5173952011-07-11 17:49:21 +0000168 QualType CompareTy =
Bill Wendling8eb771d2012-02-22 09:51:33 +0000169 QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I]));
Richard Smithbcc22fc2012-03-09 08:00:36 +0000170 if (CompareTy.isNull())
171 continue;
Chandler Carruthd5173952011-07-11 17:49:21 +0000172 if (CompareTy == Ty)
173 continue; // Same types
174 QualType CompareCanTy = CompareTy.getCanonicalType();
175 if (CompareCanTy == CanTy)
176 continue; // Same canonical types
Douglas Gregorc0b07282011-09-27 22:38:19 +0000177 std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
Richard Trieu5d1aff02011-11-14 19:39:25 +0000178 bool aka;
179 QualType CompareDesugar = Desugar(Context, CompareTy, aka);
180 std::string CompareDesugarStr =
181 CompareDesugar.getAsString(Context.getPrintingPolicy());
182 if (CompareS != S && CompareDesugarStr != S)
183 continue; // The type string is different than the comparison string
184 // and the desugared comparison string.
185 std::string CompareCanS =
186 CompareCanTy.getAsString(Context.getPrintingPolicy());
187
Chandler Carruthd5173952011-07-11 17:49:21 +0000188 if (CompareCanS == CanS)
189 continue; // No new info from canonical type
190
191 ForceAKA = true;
192 break;
193 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000194
195 // Check to see if we already desugared this type in this
196 // diagnostic. If so, don't do it again.
197 bool Repeated = false;
198 for (unsigned i = 0; i != NumPrevArgs; ++i) {
199 // TODO: Handle ak_declcontext case.
David Blaikie9c902b52011-09-25 23:23:43 +0000200 if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) {
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000201 void *Ptr = (void*)PrevArgs[i].second;
202 QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
203 if (PrevTy == Ty) {
204 Repeated = true;
205 break;
206 }
207 }
208 }
209
Douglas Gregor639cccc2010-02-09 22:26:47 +0000210 // Consider producing an a.k.a. clause if removing all the direct
211 // sugar gives us something "significantly different".
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000212 if (!Repeated) {
213 bool ShouldAKA = false;
214 QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
Chandler Carruthd5173952011-07-11 17:49:21 +0000215 if (ShouldAKA || ForceAKA) {
216 if (DesugaredTy == Ty) {
217 DesugaredTy = Ty.getCanonicalType();
218 }
Douglas Gregorc0b07282011-09-27 22:38:19 +0000219 std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
Chandler Carruthd5173952011-07-11 17:49:21 +0000220 if (akaStr != S) {
221 S = "'" + S + "' (aka '" + akaStr + "')";
222 return S;
223 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000224 }
Douglas Gregor639cccc2010-02-09 22:26:47 +0000225 }
Chandler Carruthd102f2d2010-05-13 11:37:24 +0000226
Douglas Gregor639cccc2010-02-09 22:26:47 +0000227 S = "'" + S + "'";
228 return S;
229}
230
Richard Trieu91844232012-06-26 18:18:47 +0000231static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
232 QualType ToType, bool PrintTree,
233 bool PrintFromType, bool ElideType,
234 bool ShowColors, std::string &S);
235
Chandler Carruthd5173952011-07-11 17:49:21 +0000236void clang::FormatASTNodeDiagnosticArgument(
David Blaikie9c902b52011-09-25 23:23:43 +0000237 DiagnosticsEngine::ArgumentKind Kind,
Chandler Carruthd5173952011-07-11 17:49:21 +0000238 intptr_t Val,
239 const char *Modifier,
240 unsigned ModLen,
241 const char *Argument,
242 unsigned ArgLen,
David Blaikie9c902b52011-09-25 23:23:43 +0000243 const DiagnosticsEngine::ArgumentValue *PrevArgs,
Chandler Carruthd5173952011-07-11 17:49:21 +0000244 unsigned NumPrevArgs,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000245 SmallVectorImpl<char> &Output,
Chandler Carruthd5173952011-07-11 17:49:21 +0000246 void *Cookie,
Bill Wendling8eb771d2012-02-22 09:51:33 +0000247 ArrayRef<intptr_t> QualTypeVals) {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000248 ASTContext &Context = *static_cast<ASTContext*>(Cookie);
249
250 std::string S;
251 bool NeedQuotes = true;
252
253 switch (Kind) {
David Blaikie83d382b2011-09-23 05:06:16 +0000254 default: llvm_unreachable("unknown ArgumentKind");
Richard Trieu91844232012-06-26 18:18:47 +0000255 case DiagnosticsEngine::ak_qualtype_pair: {
Richard Trieu50f5f462012-07-10 01:46:04 +0000256 TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);
Richard Trieu91844232012-06-26 18:18:47 +0000257 QualType FromType =
258 QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));
259 QualType ToType =
260 QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));
261
262 if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,
263 TDT.PrintFromType, TDT.ElideType,
264 TDT.ShowColors, S)) {
265 NeedQuotes = !TDT.PrintTree;
Richard Trieu50f5f462012-07-10 01:46:04 +0000266 TDT.TemplateDiffUsed = true;
Richard Trieu91844232012-06-26 18:18:47 +0000267 break;
268 }
269
270 // Don't fall-back during tree printing. The caller will handle
271 // this case.
272 if (TDT.PrintTree)
273 return;
274
275 // Attempting to do a templete diff on non-templates. Set the variables
276 // and continue with regular type printing of the appropriate type.
277 Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;
278 ModLen = 0;
279 ArgLen = 0;
280 // Fall through
281 }
David Blaikie9c902b52011-09-25 23:23:43 +0000282 case DiagnosticsEngine::ak_qualtype: {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000283 assert(ModLen == 0 && ArgLen == 0 &&
284 "Invalid modifier for QualType argument");
285
286 QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
Chandler Carruthd5173952011-07-11 17:49:21 +0000287 S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs,
288 QualTypeVals);
Douglas Gregor639cccc2010-02-09 22:26:47 +0000289 NeedQuotes = false;
290 break;
291 }
David Blaikie9c902b52011-09-25 23:23:43 +0000292 case DiagnosticsEngine::ak_declarationname: {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000293 DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
294 S = N.getAsString();
295
296 if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
297 S = '+' + S;
298 else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12)
299 && ArgLen==0)
300 S = '-' + S;
301 else
302 assert(ModLen == 0 && ArgLen == 0 &&
303 "Invalid modifier for DeclarationName argument");
304 break;
305 }
David Blaikie9c902b52011-09-25 23:23:43 +0000306 case DiagnosticsEngine::ak_nameddecl: {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000307 bool Qualified;
308 if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
309 Qualified = true;
310 else {
311 assert(ModLen == 0 && ArgLen == 0 &&
312 "Invalid modifier for NamedDecl* argument");
313 Qualified = false;
314 }
Chandler Carruthc841b6e2011-08-31 09:01:53 +0000315 const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
Douglas Gregorc0b07282011-09-27 22:38:19 +0000316 ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified);
Douglas Gregor639cccc2010-02-09 22:26:47 +0000317 break;
318 }
David Blaikie9c902b52011-09-25 23:23:43 +0000319 case DiagnosticsEngine::ak_nestednamespec: {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000320 llvm::raw_string_ostream OS(S);
321 reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
Douglas Gregorc0b07282011-09-27 22:38:19 +0000322 Context.getPrintingPolicy());
Douglas Gregor639cccc2010-02-09 22:26:47 +0000323 NeedQuotes = false;
324 break;
325 }
David Blaikie9c902b52011-09-25 23:23:43 +0000326 case DiagnosticsEngine::ak_declcontext: {
Douglas Gregor639cccc2010-02-09 22:26:47 +0000327 DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
328 assert(DC && "Should never have a null declaration context");
329
330 if (DC->isTranslationUnit()) {
331 // FIXME: Get these strings from some localized place
David Blaikiebbafb8a2012-03-11 07:00:24 +0000332 if (Context.getLangOpts().CPlusPlus)
Douglas Gregor639cccc2010-02-09 22:26:47 +0000333 S = "the global namespace";
334 else
335 S = "the global scope";
336 } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
337 S = ConvertTypeToDiagnosticString(Context,
338 Context.getTypeDeclType(Type),
Chandler Carruthd5173952011-07-11 17:49:21 +0000339 PrevArgs, NumPrevArgs, QualTypeVals);
Douglas Gregor639cccc2010-02-09 22:26:47 +0000340 } else {
341 // FIXME: Get these strings from some localized place
342 NamedDecl *ND = cast<NamedDecl>(DC);
343 if (isa<NamespaceDecl>(ND))
344 S += "namespace ";
345 else if (isa<ObjCMethodDecl>(ND))
346 S += "method ";
347 else if (isa<FunctionDecl>(ND))
348 S += "function ";
349
350 S += "'";
Douglas Gregorc0b07282011-09-27 22:38:19 +0000351 ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true);
Douglas Gregor639cccc2010-02-09 22:26:47 +0000352 S += "'";
353 }
354 NeedQuotes = false;
355 break;
356 }
357 }
358
359 if (NeedQuotes)
360 Output.push_back('\'');
361
362 Output.append(S.begin(), S.end());
363
364 if (NeedQuotes)
365 Output.push_back('\'');
366}
Richard Trieu91844232012-06-26 18:18:47 +0000367
368/// TemplateDiff - A class that constructs a pretty string for a pair of
369/// QualTypes. For the pair of types, a diff tree will be created containing
370/// all the information about the templates and template arguments. Afterwards,
371/// the tree is transformed to a string according to the options passed in.
372namespace {
373class TemplateDiff {
374 /// Context - The ASTContext which is used for comparing template arguments.
375 ASTContext &Context;
376
377 /// Policy - Used during expression printing.
378 PrintingPolicy Policy;
379
380 /// ElideType - Option to elide identical types.
381 bool ElideType;
382
383 /// PrintTree - Format output string as a tree.
384 bool PrintTree;
385
386 /// ShowColor - Diagnostics support color, so bolding will be used.
387 bool ShowColor;
388
389 /// FromType - When single type printing is selected, this is the type to be
390 /// be printed. When tree printing is selected, this type will show up first
391 /// in the tree.
392 QualType FromType;
393
394 /// ToType - The type that FromType is compared to. Only in tree printing
395 /// will this type be outputed.
396 QualType ToType;
397
398 /// Str - Storage for the output stream.
399 llvm::SmallString<128> Str;
400
401 /// OS - The stream used to construct the output strings.
402 llvm::raw_svector_ostream OS;
403
404 /// IsBold - Keeps track of the bold formatting for the output string.
405 bool IsBold;
406
407 /// DiffTree - A tree representation the differences between two types.
408 class DiffTree {
409 /// DiffNode - The root node stores the original type. Each child node
410 /// stores template arguments of their parents. For templated types, the
411 /// template decl is also stored.
412 struct DiffNode {
413 /// NextNode - The index of the next sibling node or 0.
414 unsigned NextNode;
415
416 /// ChildNode - The index of the first child node or 0.
417 unsigned ChildNode;
418
419 /// ParentNode - The index of the parent node.
420 unsigned ParentNode;
421
422 /// FromType, ToType - The type arguments.
423 QualType FromType, ToType;
424
425 /// FromExpr, ToExpr - The expression arguments.
426 Expr *FromExpr, *ToExpr;
427
428 /// FromTD, ToTD - The template decl for template template
429 /// arguments or the type arguments that are templates.
430 TemplateDecl *FromTD, *ToTD;
431
Richard Trieub7243852012-09-28 20:32:51 +0000432 /// FromQual, ToQual - Qualifiers for template types.
433 Qualifiers FromQual, ToQual;
434
Richard Trieu6df89452012-11-01 21:29:28 +0000435 /// FromInt, ToInt - APSInt's for integral arguments.
436 llvm::APSInt FromInt, ToInt;
437
438 /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
439 bool IsValidFromInt, IsValidToInt;
440
Richard Trieu91844232012-06-26 18:18:47 +0000441 /// FromDefault, ToDefault - Whether the argument is a default argument.
442 bool FromDefault, ToDefault;
443
444 /// Same - Whether the two arguments evaluate to the same value.
445 bool Same;
446
447 DiffNode(unsigned ParentNode = 0)
448 : NextNode(0), ChildNode(0), ParentNode(ParentNode),
449 FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
450 FromDefault(false), ToDefault(false), Same(false) { }
451 };
452
453 /// FlatTree - A flattened tree used to store the DiffNodes.
454 llvm::SmallVector<DiffNode, 16> FlatTree;
455
456 /// CurrentNode - The index of the current node being used.
457 unsigned CurrentNode;
458
459 /// NextFreeNode - The index of the next unused node. Used when creating
460 /// child nodes.
461 unsigned NextFreeNode;
462
463 /// ReadNode - The index of the current node being read.
464 unsigned ReadNode;
465
466 public:
467 DiffTree() :
468 CurrentNode(0), NextFreeNode(1) {
469 FlatTree.push_back(DiffNode());
470 }
471
472 // Node writing functions.
473 /// SetNode - Sets FromTD and ToTD of the current node.
474 void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) {
475 FlatTree[CurrentNode].FromTD = FromTD;
476 FlatTree[CurrentNode].ToTD = ToTD;
477 }
478
479 /// SetNode - Sets FromType and ToType of the current node.
480 void SetNode(QualType FromType, QualType ToType) {
481 FlatTree[CurrentNode].FromType = FromType;
482 FlatTree[CurrentNode].ToType = ToType;
483 }
484
485 /// SetNode - Set FromExpr and ToExpr of the current node.
486 void SetNode(Expr *FromExpr, Expr *ToExpr) {
487 FlatTree[CurrentNode].FromExpr = FromExpr;
488 FlatTree[CurrentNode].ToExpr = ToExpr;
489 }
490
Richard Trieu6df89452012-11-01 21:29:28 +0000491 /// SetNode - Set FromInt and ToInt of the current node.
492 void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt,
493 bool IsValidFromInt, bool IsValidToInt) {
494 FlatTree[CurrentNode].FromInt = FromInt;
495 FlatTree[CurrentNode].ToInt = ToInt;
496 FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt;
497 FlatTree[CurrentNode].IsValidToInt = IsValidToInt;
498 }
499
Richard Trieub7243852012-09-28 20:32:51 +0000500 /// SetNode - Set FromQual and ToQual of the current node.
501 void SetNode(Qualifiers FromQual, Qualifiers ToQual) {
502 FlatTree[CurrentNode].FromQual = FromQual;
503 FlatTree[CurrentNode].ToQual = ToQual;
504 }
505
Richard Trieu91844232012-06-26 18:18:47 +0000506 /// SetSame - Sets the same flag of the current node.
507 void SetSame(bool Same) {
508 FlatTree[CurrentNode].Same = Same;
509 }
510
511 /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
512 void SetDefault(bool FromDefault, bool ToDefault) {
513 FlatTree[CurrentNode].FromDefault = FromDefault;
514 FlatTree[CurrentNode].ToDefault = ToDefault;
515 }
516
517 /// Up - Changes the node to the parent of the current node.
518 void Up() {
519 CurrentNode = FlatTree[CurrentNode].ParentNode;
520 }
521
522 /// AddNode - Adds a child node to the current node, then sets that node
523 /// node as the current node.
524 void AddNode() {
525 FlatTree.push_back(DiffNode(CurrentNode));
526 DiffNode &Node = FlatTree[CurrentNode];
527 if (Node.ChildNode == 0) {
528 // If a child node doesn't exist, add one.
529 Node.ChildNode = NextFreeNode;
530 } else {
531 // If a child node exists, find the last child node and add a
532 // next node to it.
533 unsigned i;
534 for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
535 i = FlatTree[i].NextNode) {
536 }
537 FlatTree[i].NextNode = NextFreeNode;
538 }
539 CurrentNode = NextFreeNode;
540 ++NextFreeNode;
541 }
542
543 // Node reading functions.
544 /// StartTraverse - Prepares the tree for recursive traversal.
545 void StartTraverse() {
546 ReadNode = 0;
547 CurrentNode = NextFreeNode;
548 NextFreeNode = 0;
549 }
550
551 /// Parent - Move the current read node to its parent.
552 void Parent() {
553 ReadNode = FlatTree[ReadNode].ParentNode;
554 }
555
556 /// NodeIsTemplate - Returns true if a template decl is set, and types are
557 /// set.
558 bool NodeIsTemplate() {
559 return (FlatTree[ReadNode].FromTD &&
560 !FlatTree[ReadNode].ToType.isNull()) ||
561 (FlatTree[ReadNode].ToTD && !FlatTree[ReadNode].ToType.isNull());
562 }
563
564 /// NodeIsQualType - Returns true if a Qualtype is set.
565 bool NodeIsQualType() {
566 return !FlatTree[ReadNode].FromType.isNull() ||
567 !FlatTree[ReadNode].ToType.isNull();
568 }
569
570 /// NodeIsExpr - Returns true if an expr is set.
571 bool NodeIsExpr() {
572 return FlatTree[ReadNode].FromExpr || FlatTree[ReadNode].ToExpr;
573 }
574
575 /// NodeIsTemplateTemplate - Returns true if the argument is a template
576 /// template type.
577 bool NodeIsTemplateTemplate() {
578 return FlatTree[ReadNode].FromType.isNull() &&
579 FlatTree[ReadNode].ToType.isNull() &&
580 (FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD);
581 }
582
Richard Trieu6df89452012-11-01 21:29:28 +0000583 /// NodeIsAPSInt - Returns true if the arugments are stored in APSInt's.
584 bool NodeIsAPSInt() {
585 return FlatTree[ReadNode].IsValidFromInt ||
586 FlatTree[ReadNode].IsValidToInt;
587 }
588
Richard Trieu91844232012-06-26 18:18:47 +0000589 /// GetNode - Gets the FromType and ToType.
590 void GetNode(QualType &FromType, QualType &ToType) {
591 FromType = FlatTree[ReadNode].FromType;
592 ToType = FlatTree[ReadNode].ToType;
593 }
594
595 /// GetNode - Gets the FromExpr and ToExpr.
596 void GetNode(Expr *&FromExpr, Expr *&ToExpr) {
597 FromExpr = FlatTree[ReadNode].FromExpr;
598 ToExpr = FlatTree[ReadNode].ToExpr;
599 }
600
601 /// GetNode - Gets the FromTD and ToTD.
602 void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
603 FromTD = FlatTree[ReadNode].FromTD;
604 ToTD = FlatTree[ReadNode].ToTD;
605 }
606
Richard Trieu6df89452012-11-01 21:29:28 +0000607 /// GetNode - Gets the FromInt and ToInt.
608 void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
609 bool &IsValidFromInt, bool &IsValidToInt) {
610 FromInt = FlatTree[ReadNode].FromInt;
611 ToInt = FlatTree[ReadNode].ToInt;
612 IsValidFromInt = FlatTree[ReadNode].IsValidFromInt;
613 IsValidToInt = FlatTree[ReadNode].IsValidToInt;
614 }
615
Richard Trieub7243852012-09-28 20:32:51 +0000616 /// GetNode - Gets the FromQual and ToQual.
617 void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) {
618 FromQual = FlatTree[ReadNode].FromQual;
619 ToQual = FlatTree[ReadNode].ToQual;
620 }
621
Richard Trieu91844232012-06-26 18:18:47 +0000622 /// NodeIsSame - Returns true the arguments are the same.
623 bool NodeIsSame() {
624 return FlatTree[ReadNode].Same;
625 }
626
627 /// HasChildrend - Returns true if the node has children.
628 bool HasChildren() {
629 return FlatTree[ReadNode].ChildNode != 0;
630 }
631
632 /// MoveToChild - Moves from the current node to its child.
633 void MoveToChild() {
634 ReadNode = FlatTree[ReadNode].ChildNode;
635 }
636
637 /// AdvanceSibling - If there is a next sibling, advance to it and return
638 /// true. Otherwise, return false.
639 bool AdvanceSibling() {
640 if (FlatTree[ReadNode].NextNode == 0)
641 return false;
642
643 ReadNode = FlatTree[ReadNode].NextNode;
644 return true;
645 }
646
647 /// HasNextSibling - Return true if the node has a next sibling.
648 bool HasNextSibling() {
649 return FlatTree[ReadNode].NextNode != 0;
650 }
651
652 /// FromDefault - Return true if the from argument is the default.
653 bool FromDefault() {
654 return FlatTree[ReadNode].FromDefault;
655 }
656
657 /// ToDefault - Return true if the to argument is the default.
658 bool ToDefault() {
659 return FlatTree[ReadNode].ToDefault;
660 }
661
662 /// Empty - Returns true if the tree has no information.
663 bool Empty() {
664 return !FlatTree[0].FromTD && !FlatTree[0].ToTD &&
665 !FlatTree[0].FromExpr && !FlatTree[0].ToExpr &&
666 FlatTree[0].FromType.isNull() && FlatTree[0].ToType.isNull();
667 }
668 };
669
670 DiffTree Tree;
671
672 /// TSTiterator - an iterator that is used to enter a
673 /// TemplateSpecializationType and read TemplateArguments inside template
674 /// parameter packs in order with the rest of the TemplateArguments.
675 struct TSTiterator {
676 typedef const TemplateArgument& reference;
677 typedef const TemplateArgument* pointer;
678
679 /// TST - the template specialization whose arguments this iterator
680 /// traverse over.
681 const TemplateSpecializationType *TST;
682
683 /// Index - the index of the template argument in TST.
684 unsigned Index;
685
686 /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
687 /// points to a TemplateArgument within a parameter pack.
688 TemplateArgument::pack_iterator CurrentTA;
689
690 /// EndTA - the end iterator of a parameter pack
691 TemplateArgument::pack_iterator EndTA;
692
693 /// TSTiterator - Constructs an iterator and sets it to the first template
694 /// argument.
695 TSTiterator(const TemplateSpecializationType *TST)
696 : TST(TST), Index(0), CurrentTA(0), EndTA(0) {
697 if (isEnd()) return;
698
699 // Set to first template argument. If not a parameter pack, done.
700 TemplateArgument TA = TST->getArg(0);
701 if (TA.getKind() != TemplateArgument::Pack) return;
702
703 // Start looking into the parameter pack.
704 CurrentTA = TA.pack_begin();
705 EndTA = TA.pack_end();
706
707 // Found a valid template argument.
708 if (CurrentTA != EndTA) return;
709
710 // Parameter pack is empty, use the increment to get to a valid
711 // template argument.
712 ++(*this);
713 }
714
715 /// isEnd - Returns true if the iterator is one past the end.
716 bool isEnd() const {
717 return Index == TST->getNumArgs();
718 }
719
720 /// &operator++ - Increment the iterator to the next template argument.
721 TSTiterator &operator++() {
722 assert(!isEnd() && "Iterator incremented past end of arguments.");
723
724 // If in a parameter pack, advance in the parameter pack.
725 if (CurrentTA != EndTA) {
726 ++CurrentTA;
727 if (CurrentTA != EndTA)
728 return *this;
729 }
730
731 // Loop until a template argument is found, or the end is reached.
732 while (true) {
733 // Advance to the next template argument. Break if reached the end.
734 if (++Index == TST->getNumArgs()) break;
735
736 // If the TemplateArgument is not a parameter pack, done.
737 TemplateArgument TA = TST->getArg(Index);
738 if (TA.getKind() != TemplateArgument::Pack) break;
739
740 // Handle parameter packs.
741 CurrentTA = TA.pack_begin();
742 EndTA = TA.pack_end();
743
744 // If the parameter pack is empty, try to advance again.
745 if (CurrentTA != EndTA) break;
746 }
747 return *this;
748 }
749
750 /// operator* - Returns the appropriate TemplateArgument.
751 reference operator*() const {
752 assert(!isEnd() && "Index exceeds number of arguments.");
753 if (CurrentTA == EndTA)
754 return TST->getArg(Index);
755 else
756 return *CurrentTA;
757 }
758
759 /// operator-> - Allow access to the underlying TemplateArgument.
760 pointer operator->() const {
761 return &operator*();
762 }
763 };
764
765 // These functions build up the template diff tree, including functions to
766 // retrieve and compare template arguments.
767
768 static const TemplateSpecializationType * GetTemplateSpecializationType(
769 ASTContext &Context, QualType Ty) {
770 if (const TemplateSpecializationType *TST =
771 Ty->getAs<TemplateSpecializationType>())
772 return TST;
773
774 const RecordType *RT = Ty->getAs<RecordType>();
775
776 if (!RT)
777 return 0;
778
779 const ClassTemplateSpecializationDecl *CTSD =
780 dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
781
782 if (!CTSD)
783 return 0;
784
785 Ty = Context.getTemplateSpecializationType(
786 TemplateName(CTSD->getSpecializedTemplate()),
787 CTSD->getTemplateArgs().data(),
788 CTSD->getTemplateArgs().size(),
789 Ty.getCanonicalType());
790
791 return Ty->getAs<TemplateSpecializationType>();
792 }
793
794 /// DiffTemplate - recursively visits template arguments and stores the
795 /// argument info into a tree.
796 void DiffTemplate(const TemplateSpecializationType *FromTST,
797 const TemplateSpecializationType *ToTST) {
798 // Begin descent into diffing template tree.
799 TemplateParameterList *Params =
800 FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
801 unsigned TotalArgs = 0;
802 for (TSTiterator FromIter(FromTST), ToIter(ToTST);
803 !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
804 Tree.AddNode();
805
806 // Get the parameter at index TotalArgs. If index is larger
807 // than the total number of parameters, then there is an
808 // argument pack, so re-use the last parameter.
809 NamedDecl *ParamND = Params->getParam(
810 (TotalArgs < Params->size()) ? TotalArgs
811 : Params->size() - 1);
812 // Handle Types
813 if (TemplateTypeParmDecl *DefaultTTPD =
814 dyn_cast<TemplateTypeParmDecl>(ParamND)) {
815 QualType FromType, ToType;
816 GetType(FromIter, DefaultTTPD, FromType);
817 GetType(ToIter, DefaultTTPD, ToType);
818 Tree.SetNode(FromType, ToType);
819 Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
820 ToIter.isEnd() && !ToType.isNull());
821 if (!FromType.isNull() && !ToType.isNull()) {
822 if (Context.hasSameType(FromType, ToType)) {
823 Tree.SetSame(true);
824 } else {
Richard Trieub7243852012-09-28 20:32:51 +0000825 Qualifiers FromQual = FromType.getQualifiers(),
826 ToQual = ToType.getQualifiers();
Richard Trieu91844232012-06-26 18:18:47 +0000827 const TemplateSpecializationType *FromArgTST =
828 GetTemplateSpecializationType(Context, FromType);
829 const TemplateSpecializationType *ToArgTST =
830 GetTemplateSpecializationType(Context, ToType);
831
Richard Trieu8e14cac2012-09-28 19:51:57 +0000832 if (FromArgTST && ToArgTST &&
833 hasSameTemplate(FromArgTST, ToArgTST)) {
Richard Trieub7243852012-09-28 20:32:51 +0000834 FromQual -= QualType(FromArgTST, 0).getQualifiers();
835 ToQual -= QualType(ToArgTST, 0).getQualifiers();
Richard Trieu8e14cac2012-09-28 19:51:57 +0000836 Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
837 ToArgTST->getTemplateName().getAsTemplateDecl());
Richard Trieub7243852012-09-28 20:32:51 +0000838 Tree.SetNode(FromQual, ToQual);
Richard Trieu8e14cac2012-09-28 19:51:57 +0000839 DiffTemplate(FromArgTST, ToArgTST);
Richard Trieu91844232012-06-26 18:18:47 +0000840 }
841 }
842 }
843 }
844
845 // Handle Expressions
846 if (NonTypeTemplateParmDecl *DefaultNTTPD =
847 dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
848 Expr *FromExpr, *ToExpr;
Richard Trieu6df89452012-11-01 21:29:28 +0000849 llvm::APSInt FromInt, ToInt;
Eli Friedmanc2c982c2012-11-14 23:57:08 +0000850 unsigned ParamWidth = 0;
851 if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
852 ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
Richard Trieu6df89452012-11-01 21:29:28 +0000853 bool HasFromInt = !FromIter.isEnd() &&
854 FromIter->getKind() == TemplateArgument::Integral;
855 bool HasToInt = !ToIter.isEnd() &&
856 ToIter->getKind() == TemplateArgument::Integral;
857 //bool IsValidFromInt = false, IsValidToInt = false;
858 if (HasFromInt)
859 FromInt = FromIter->getAsIntegral();
860 else
861 GetExpr(FromIter, DefaultNTTPD, FromExpr);
862
863 if (HasToInt)
864 ToInt = ToIter->getAsIntegral();
865 else
866 GetExpr(ToIter, DefaultNTTPD, ToExpr);
867
868 if (!HasFromInt && !HasToInt) {
869 Tree.SetNode(FromExpr, ToExpr);
Eli Friedmanc2c982c2012-11-14 23:57:08 +0000870 Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr));
Richard Trieu6df89452012-11-01 21:29:28 +0000871 Tree.SetDefault(FromIter.isEnd() && FromExpr,
872 ToIter.isEnd() && ToExpr);
873 } else {
874 if (!HasFromInt && FromExpr) {
875 FromInt = FromExpr->EvaluateKnownConstInt(Context);
876 HasFromInt = true;
877 }
878 if (!HasToInt && ToExpr) {
879 ToInt = ToExpr->EvaluateKnownConstInt(Context);
880 HasToInt = true;
881 }
882 Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
Eli Friedmanc2c982c2012-11-14 23:57:08 +0000883 Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
Richard Trieu6df89452012-11-01 21:29:28 +0000884 Tree.SetDefault(FromIter.isEnd() && HasFromInt,
885 ToIter.isEnd() && HasToInt);
886 }
Richard Trieu91844232012-06-26 18:18:47 +0000887 }
888
889 // Handle Templates
890 if (TemplateTemplateParmDecl *DefaultTTPD =
891 dyn_cast<TemplateTemplateParmDecl>(ParamND)) {
892 TemplateDecl *FromDecl, *ToDecl;
893 GetTemplateDecl(FromIter, DefaultTTPD, FromDecl);
894 GetTemplateDecl(ToIter, DefaultTTPD, ToDecl);
895 Tree.SetNode(FromDecl, ToDecl);
896 Tree.SetSame(FromDecl && ToDecl &&
897 FromDecl->getIdentifier() == ToDecl->getIdentifier());
898 }
899
900 if (!FromIter.isEnd()) ++FromIter;
901 if (!ToIter.isEnd()) ++ToIter;
902 Tree.Up();
903 }
904 }
905
Richard Trieu8e14cac2012-09-28 19:51:57 +0000906 /// makeTemplateList - Dump every template alias into the vector.
907 static void makeTemplateList(
908 SmallVector<const TemplateSpecializationType*, 1> &TemplateList,
909 const TemplateSpecializationType *TST) {
910 while (TST) {
911 TemplateList.push_back(TST);
912 if (!TST->isTypeAlias())
913 return;
914 TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
915 }
916 }
917
918 /// hasSameBaseTemplate - Returns true when the base templates are the same,
919 /// even if the template arguments are not.
920 static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
921 const TemplateSpecializationType *ToTST) {
922 return FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() ==
923 ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier();
924 }
925
Richard Trieu91844232012-06-26 18:18:47 +0000926 /// hasSameTemplate - Returns true if both types are specialized from the
927 /// same template declaration. If they come from different template aliases,
928 /// do a parallel ascension search to determine the highest template alias in
929 /// common and set the arguments to them.
930 static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
931 const TemplateSpecializationType *&ToTST) {
932 // Check the top templates if they are the same.
Richard Trieu8e14cac2012-09-28 19:51:57 +0000933 if (hasSameBaseTemplate(FromTST, ToTST))
Richard Trieu91844232012-06-26 18:18:47 +0000934 return true;
935
936 // Create vectors of template aliases.
937 SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
938 ToTemplateList;
939
Richard Trieu8e14cac2012-09-28 19:51:57 +0000940 makeTemplateList(FromTemplateList, FromTST);
941 makeTemplateList(ToTemplateList, ToTST);
Richard Trieu91844232012-06-26 18:18:47 +0000942
943 SmallVector<const TemplateSpecializationType*, 1>::reverse_iterator
944 FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
945 ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
946
947 // Check if the lowest template types are the same. If not, return.
Richard Trieu8e14cac2012-09-28 19:51:57 +0000948 if (!hasSameBaseTemplate(*FromIter, *ToIter))
Richard Trieu91844232012-06-26 18:18:47 +0000949 return false;
950
951 // Begin searching up the template aliases. The bottom most template
952 // matches so move up until one pair does not match. Use the template
953 // right before that one.
954 for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
Richard Trieu8e14cac2012-09-28 19:51:57 +0000955 if (!hasSameBaseTemplate(*FromIter, *ToIter))
Richard Trieu91844232012-06-26 18:18:47 +0000956 break;
957 }
958
959 FromTST = FromIter[-1];
960 ToTST = ToIter[-1];
961
962 return true;
963 }
964
965 /// GetType - Retrieves the template type arguments, including default
966 /// arguments.
967 void GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD,
968 QualType &ArgType) {
969 ArgType = QualType();
970 bool isVariadic = DefaultTTPD->isParameterPack();
971
972 if (!Iter.isEnd())
973 ArgType = Iter->getAsType();
974 else if (!isVariadic)
975 ArgType = DefaultTTPD->getDefaultArgument();
David Blaikie47e45182012-06-26 18:52:09 +0000976 }
Richard Trieu91844232012-06-26 18:18:47 +0000977
978 /// GetExpr - Retrieves the template expression argument, including default
979 /// arguments.
980 void GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD,
981 Expr *&ArgExpr) {
982 ArgExpr = 0;
983 bool isVariadic = DefaultNTTPD->isParameterPack();
984
985 if (!Iter.isEnd())
986 ArgExpr = Iter->getAsExpr();
987 else if (!isVariadic)
988 ArgExpr = DefaultNTTPD->getDefaultArgument();
989
990 if (ArgExpr)
991 while (SubstNonTypeTemplateParmExpr *SNTTPE =
992 dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr))
993 ArgExpr = SNTTPE->getReplacement();
994 }
995
996 /// GetTemplateDecl - Retrieves the template template arguments, including
997 /// default arguments.
998 void GetTemplateDecl(const TSTiterator &Iter,
999 TemplateTemplateParmDecl *DefaultTTPD,
1000 TemplateDecl *&ArgDecl) {
1001 ArgDecl = 0;
1002 bool isVariadic = DefaultTTPD->isParameterPack();
1003
1004 TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
Eli Friedmanb826a002012-09-26 02:36:12 +00001005 TemplateDecl *DefaultTD = 0;
1006 if (TA.getKind() != TemplateArgument::Null)
1007 DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
Richard Trieu91844232012-06-26 18:18:47 +00001008
1009 if (!Iter.isEnd())
1010 ArgDecl = Iter->getAsTemplate().getAsTemplateDecl();
1011 else if (!isVariadic)
1012 ArgDecl = DefaultTD;
1013 }
1014
Eli Friedmanc2c982c2012-11-14 23:57:08 +00001015 /// IsSameConvertedInt - Returns true if both integers are equal when
1016 /// converted to an integer type with the given width.
1017 static bool IsSameConvertedInt(unsigned Width, const llvm::APSInt &X,
1018 const llvm::APSInt &Y) {
1019 llvm::APInt ConvertedX = X.extOrTrunc(Width);
1020 llvm::APInt ConvertedY = Y.extOrTrunc(Width);
1021 return ConvertedX == ConvertedY;
1022 }
1023
Richard Trieu91844232012-06-26 18:18:47 +00001024 /// IsEqualExpr - Returns true if the expressions evaluate to the same value.
Eli Friedmanc2c982c2012-11-14 23:57:08 +00001025 static bool IsEqualExpr(ASTContext &Context, unsigned ParamWidth,
1026 Expr *FromExpr, Expr *ToExpr) {
Richard Trieu91844232012-06-26 18:18:47 +00001027 if (FromExpr == ToExpr)
1028 return true;
1029
1030 if (!FromExpr || !ToExpr)
1031 return false;
1032
1033 FromExpr = FromExpr->IgnoreParens();
1034 ToExpr = ToExpr->IgnoreParens();
1035
1036 DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr),
1037 *ToDRE = dyn_cast<DeclRefExpr>(ToExpr);
1038
1039 if (FromDRE || ToDRE) {
1040 if (!FromDRE || !ToDRE)
1041 return false;
1042 return FromDRE->getDecl() == ToDRE->getDecl();
1043 }
1044
1045 Expr::EvalResult FromResult, ToResult;
1046 if (!FromExpr->EvaluateAsRValue(FromResult, Context) ||
1047 !ToExpr->EvaluateAsRValue(ToResult, Context))
1048 assert(0 && "Template arguments must be known at compile time.");
1049
1050 APValue &FromVal = FromResult.Val;
1051 APValue &ToVal = ToResult.Val;
1052
1053 if (FromVal.getKind() != ToVal.getKind()) return false;
1054
1055 switch (FromVal.getKind()) {
1056 case APValue::Int:
Eli Friedmanc2c982c2012-11-14 23:57:08 +00001057 return IsSameConvertedInt(ParamWidth, FromVal.getInt(), ToVal.getInt());
Richard Trieu91844232012-06-26 18:18:47 +00001058 case APValue::LValue: {
1059 APValue::LValueBase FromBase = FromVal.getLValueBase();
1060 APValue::LValueBase ToBase = ToVal.getLValueBase();
1061 if (FromBase.isNull() && ToBase.isNull())
1062 return true;
1063 if (FromBase.isNull() || ToBase.isNull())
1064 return false;
1065 return FromBase.get<const ValueDecl*>() ==
1066 ToBase.get<const ValueDecl*>();
1067 }
1068 case APValue::MemberPointer:
1069 return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl();
1070 default:
1071 llvm_unreachable("Unknown template argument expression.");
1072 }
1073 }
1074
1075 // These functions converts the tree representation of the template
1076 // differences into the internal character vector.
1077
1078 /// TreeToString - Converts the Tree object into a character stream which
1079 /// will later be turned into the output string.
1080 void TreeToString(int Indent = 1) {
1081 if (PrintTree) {
1082 OS << '\n';
1083 for (int i = 0; i < Indent; ++i)
1084 OS << " ";
1085 ++Indent;
1086 }
1087
1088 // Handle cases where the difference is not templates with different
1089 // arguments.
1090 if (!Tree.NodeIsTemplate()) {
1091 if (Tree.NodeIsQualType()) {
1092 QualType FromType, ToType;
1093 Tree.GetNode(FromType, ToType);
1094 PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
1095 Tree.NodeIsSame());
1096 return;
1097 }
1098 if (Tree.NodeIsExpr()) {
1099 Expr *FromExpr, *ToExpr;
1100 Tree.GetNode(FromExpr, ToExpr);
1101 PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
1102 Tree.NodeIsSame());
1103 return;
1104 }
1105 if (Tree.NodeIsTemplateTemplate()) {
1106 TemplateDecl *FromTD, *ToTD;
1107 Tree.GetNode(FromTD, ToTD);
1108 PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
1109 Tree.ToDefault(), Tree.NodeIsSame());
1110 return;
1111 }
Richard Trieu6df89452012-11-01 21:29:28 +00001112
1113 if (Tree.NodeIsAPSInt()) {
1114 llvm::APSInt FromInt, ToInt;
1115 bool IsValidFromInt, IsValidToInt;
1116 Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
1117 PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
1118 Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
1119 return;
1120 }
Richard Trieu91844232012-06-26 18:18:47 +00001121 llvm_unreachable("Unable to deduce template difference.");
1122 }
1123
1124 // Node is root of template. Recurse on children.
1125 TemplateDecl *FromTD, *ToTD;
1126 Tree.GetNode(FromTD, ToTD);
1127
1128 assert(Tree.HasChildren() && "Template difference not found in diff tree.");
1129
Richard Trieub7243852012-09-28 20:32:51 +00001130 Qualifiers FromQual, ToQual;
1131 Tree.GetNode(FromQual, ToQual);
1132 PrintQualifiers(FromQual, ToQual);
1133
Richard Trieu91844232012-06-26 18:18:47 +00001134 OS << FromTD->getNameAsString() << '<';
1135 Tree.MoveToChild();
1136 unsigned NumElideArgs = 0;
1137 do {
1138 if (ElideType) {
1139 if (Tree.NodeIsSame()) {
1140 ++NumElideArgs;
1141 continue;
1142 }
1143 if (NumElideArgs > 0) {
1144 PrintElideArgs(NumElideArgs, Indent);
1145 NumElideArgs = 0;
1146 OS << ", ";
1147 }
1148 }
1149 TreeToString(Indent);
1150 if (Tree.HasNextSibling())
1151 OS << ", ";
1152 } while (Tree.AdvanceSibling());
1153 if (NumElideArgs > 0)
1154 PrintElideArgs(NumElideArgs, Indent);
1155
1156 Tree.Parent();
1157 OS << ">";
1158 }
1159
1160 // To signal to the text printer that a certain text needs to be bolded,
1161 // a special character is injected into the character stream which the
1162 // text printer will later strip out.
1163
1164 /// Bold - Start bolding text.
1165 void Bold() {
1166 assert(!IsBold && "Attempting to bold text that is already bold.");
1167 IsBold = true;
1168 if (ShowColor)
1169 OS << ToggleHighlight;
1170 }
1171
1172 /// Unbold - Stop bolding text.
1173 void Unbold() {
1174 assert(IsBold && "Attempting to remove bold from unbold text.");
1175 IsBold = false;
1176 if (ShowColor)
1177 OS << ToggleHighlight;
1178 }
1179
1180 // Functions to print out the arguments and highlighting the difference.
1181
1182 /// PrintTypeNames - prints the typenames, bolding differences. Will detect
1183 /// typenames that are the same and attempt to disambiguate them by using
1184 /// canonical typenames.
1185 void PrintTypeNames(QualType FromType, QualType ToType,
1186 bool FromDefault, bool ToDefault, bool Same) {
1187 assert((!FromType.isNull() || !ToType.isNull()) &&
1188 "Only one template argument may be missing.");
1189
1190 if (Same) {
1191 OS << FromType.getAsString();
1192 return;
1193 }
1194
Richard Trieub7243852012-09-28 20:32:51 +00001195 if (!FromType.isNull() && !ToType.isNull() &&
1196 FromType.getLocalUnqualifiedType() ==
1197 ToType.getLocalUnqualifiedType()) {
1198 Qualifiers FromQual = FromType.getLocalQualifiers(),
1199 ToQual = ToType.getLocalQualifiers(),
1200 CommonQual;
1201 PrintQualifiers(FromQual, ToQual);
1202 FromType.getLocalUnqualifiedType().print(OS, Policy);
1203 return;
1204 }
1205
Richard Trieu91844232012-06-26 18:18:47 +00001206 std::string FromTypeStr = FromType.isNull() ? "(no argument)"
1207 : FromType.getAsString();
1208 std::string ToTypeStr = ToType.isNull() ? "(no argument)"
1209 : ToType.getAsString();
1210 // Switch to canonical typename if it is better.
1211 // TODO: merge this with other aka printing above.
1212 if (FromTypeStr == ToTypeStr) {
1213 std::string FromCanTypeStr = FromType.getCanonicalType().getAsString();
1214 std::string ToCanTypeStr = ToType.getCanonicalType().getAsString();
1215 if (FromCanTypeStr != ToCanTypeStr) {
1216 FromTypeStr = FromCanTypeStr;
1217 ToTypeStr = ToCanTypeStr;
1218 }
1219 }
1220
1221 if (PrintTree) OS << '[';
1222 OS << (FromDefault ? "(default) " : "");
1223 Bold();
1224 OS << FromTypeStr;
1225 Unbold();
1226 if (PrintTree) {
1227 OS << " != " << (ToDefault ? "(default) " : "");
1228 Bold();
1229 OS << ToTypeStr;
1230 Unbold();
1231 OS << "]";
1232 }
1233 return;
1234 }
1235
1236 /// PrintExpr - Prints out the expr template arguments, highlighting argument
1237 /// differences.
1238 void PrintExpr(const Expr *FromExpr, const Expr *ToExpr,
1239 bool FromDefault, bool ToDefault, bool Same) {
1240 assert((FromExpr || ToExpr) &&
1241 "Only one template argument may be missing.");
1242 if (Same) {
1243 PrintExpr(FromExpr);
1244 } else if (!PrintTree) {
1245 OS << (FromDefault ? "(default) " : "");
1246 Bold();
1247 PrintExpr(FromExpr);
1248 Unbold();
1249 } else {
1250 OS << (FromDefault ? "[(default) " : "[");
1251 Bold();
1252 PrintExpr(FromExpr);
1253 Unbold();
1254 OS << " != " << (ToDefault ? "(default) " : "");
1255 Bold();
1256 PrintExpr(ToExpr);
1257 Unbold();
1258 OS << ']';
1259 }
1260 }
1261
1262 /// PrintExpr - Actual formatting and printing of expressions.
1263 void PrintExpr(const Expr *E) {
1264 if (!E)
1265 OS << "(no argument)";
1266 else
Richard Smith235341b2012-08-16 03:56:14 +00001267 E->printPretty(OS, 0, Policy); return;
Richard Trieu91844232012-06-26 18:18:47 +00001268 }
1269
1270 /// PrintTemplateTemplate - Handles printing of template template arguments,
1271 /// highlighting argument differences.
1272 void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
1273 bool FromDefault, bool ToDefault, bool Same) {
1274 assert((FromTD || ToTD) && "Only one template argument may be missing.");
1275 if (Same) {
1276 OS << "template " << FromTD->getNameAsString();
1277 } else if (!PrintTree) {
1278 OS << (FromDefault ? "(default) template " : "template ");
1279 Bold();
1280 OS << (FromTD ? FromTD->getNameAsString() : "(no argument)");
1281 Unbold();
1282 } else {
1283 OS << (FromDefault ? "[(default) template " : "[template ");
1284 Bold();
1285 OS << (FromTD ? FromTD->getNameAsString() : "(no argument)");
1286 Unbold();
1287 OS << " != " << (ToDefault ? "(default) template " : "template ");
1288 Bold();
1289 OS << (ToTD ? ToTD->getNameAsString() : "(no argument)");
1290 Unbold();
1291 OS << ']';
1292 }
1293 }
1294
Richard Trieu6df89452012-11-01 21:29:28 +00001295 /// PrintAPSInt - Handles printing of integral arguments, highlighting
1296 /// argument differences.
1297 void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
1298 bool IsValidFromInt, bool IsValidToInt, bool FromDefault,
1299 bool ToDefault, bool Same) {
1300 assert((IsValidFromInt || IsValidToInt) &&
1301 "Only one integral argument may be missing.");
1302
1303 if (Same) {
1304 OS << FromInt.toString(10);
1305 } else if (!PrintTree) {
1306 OS << (FromDefault ? "(default) " : "");
1307 Bold();
1308 OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
1309 Unbold();
1310 } else {
1311 OS << (FromDefault ? "[(default) " : "[");
1312 Bold();
1313 OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
1314 Unbold();
1315 OS << " != " << (ToDefault ? "(default) " : "");
1316 Bold();
1317 OS << (IsValidToInt ? ToInt.toString(10) : "(no argument)");
1318 Unbold();
1319 OS << ']';
1320 }
1321 }
1322
Richard Trieu91844232012-06-26 18:18:47 +00001323 // Prints the appropriate placeholder for elided template arguments.
1324 void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
1325 if (PrintTree) {
1326 OS << '\n';
1327 for (unsigned i = 0; i < Indent; ++i)
1328 OS << " ";
1329 }
1330 if (NumElideArgs == 0) return;
1331 if (NumElideArgs == 1)
1332 OS << "[...]";
1333 else
1334 OS << "[" << NumElideArgs << " * ...]";
1335 }
1336
Richard Trieub7243852012-09-28 20:32:51 +00001337 // Prints and highlights differences in Qualifiers.
1338 void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
1339 // Both types have no qualifiers
1340 if (FromQual.empty() && ToQual.empty())
1341 return;
1342
1343 // Both types have same qualifiers
1344 if (FromQual == ToQual) {
1345 PrintQualifier(FromQual, /*ApplyBold*/false);
1346 return;
1347 }
1348
1349 // Find common qualifiers and strip them from FromQual and ToQual.
1350 Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,
1351 ToQual);
1352
1353 // The qualifiers are printed before the template name.
1354 // Inline printing:
1355 // The common qualifiers are printed. Then, qualifiers only in this type
1356 // are printed and highlighted. Finally, qualifiers only in the other
1357 // type are printed and highlighted inside parentheses after "missing".
1358 // Tree printing:
1359 // Qualifiers are printed next to each other, inside brackets, and
1360 // separated by "!=". The printing order is:
1361 // common qualifiers, highlighted from qualifiers, "!=",
1362 // common qualifiers, highlighted to qualifiers
1363 if (PrintTree) {
1364 OS << "[";
1365 if (CommonQual.empty() && FromQual.empty()) {
1366 Bold();
1367 OS << "(no qualifiers) ";
1368 Unbold();
1369 } else {
1370 PrintQualifier(CommonQual, /*ApplyBold*/false);
1371 PrintQualifier(FromQual, /*ApplyBold*/true);
1372 }
1373 OS << "!= ";
1374 if (CommonQual.empty() && ToQual.empty()) {
1375 Bold();
1376 OS << "(no qualifiers)";
1377 Unbold();
1378 } else {
1379 PrintQualifier(CommonQual, /*ApplyBold*/false,
1380 /*appendSpaceIfNonEmpty*/!ToQual.empty());
1381 PrintQualifier(ToQual, /*ApplyBold*/true,
1382 /*appendSpaceIfNonEmpty*/false);
1383 }
1384 OS << "] ";
1385 } else {
1386 PrintQualifier(CommonQual, /*ApplyBold*/false);
1387 PrintQualifier(FromQual, /*ApplyBold*/true);
1388 }
1389 }
1390
1391 void PrintQualifier(Qualifiers Q, bool ApplyBold,
1392 bool AppendSpaceIfNonEmpty = true) {
1393 if (Q.empty()) return;
1394 if (ApplyBold) Bold();
1395 Q.print(OS, Policy, AppendSpaceIfNonEmpty);
1396 if (ApplyBold) Unbold();
1397 }
1398
Richard Trieu91844232012-06-26 18:18:47 +00001399public:
1400
1401 TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType,
1402 bool PrintTree, bool PrintFromType, bool ElideType,
1403 bool ShowColor)
1404 : Context(Context),
1405 Policy(Context.getLangOpts()),
1406 ElideType(ElideType),
1407 PrintTree(PrintTree),
1408 ShowColor(ShowColor),
1409 // When printing a single type, the FromType is the one printed.
1410 FromType(PrintFromType ? FromType : ToType),
1411 ToType(PrintFromType ? ToType : FromType),
1412 OS(Str),
1413 IsBold(false) {
1414 }
1415
1416 /// DiffTemplate - Start the template type diffing.
1417 void DiffTemplate() {
Richard Trieub7243852012-09-28 20:32:51 +00001418 Qualifiers FromQual = FromType.getQualifiers(),
1419 ToQual = ToType.getQualifiers();
1420
Richard Trieu91844232012-06-26 18:18:47 +00001421 const TemplateSpecializationType *FromOrigTST =
1422 GetTemplateSpecializationType(Context, FromType);
1423 const TemplateSpecializationType *ToOrigTST =
1424 GetTemplateSpecializationType(Context, ToType);
1425
1426 // Only checking templates.
1427 if (!FromOrigTST || !ToOrigTST)
1428 return;
1429
1430 // Different base templates.
1431 if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {
1432 return;
1433 }
1434
Richard Trieub7243852012-09-28 20:32:51 +00001435 FromQual -= QualType(FromOrigTST, 0).getQualifiers();
1436 ToQual -= QualType(ToOrigTST, 0).getQualifiers();
Richard Trieu91844232012-06-26 18:18:47 +00001437 Tree.SetNode(FromType, ToType);
Richard Trieub7243852012-09-28 20:32:51 +00001438 Tree.SetNode(FromQual, ToQual);
Richard Trieu91844232012-06-26 18:18:47 +00001439
1440 // Same base template, but different arguments.
1441 Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),
1442 ToOrigTST->getTemplateName().getAsTemplateDecl());
1443
1444 DiffTemplate(FromOrigTST, ToOrigTST);
David Blaikie47e45182012-06-26 18:52:09 +00001445 }
Richard Trieu91844232012-06-26 18:18:47 +00001446
1447 /// MakeString - When the two types given are templated types with the same
1448 /// base template, a string representation of the type difference will be
1449 /// loaded into S and return true. Otherwise, return false.
1450 bool MakeString(std::string &S) {
1451 Tree.StartTraverse();
1452 if (Tree.Empty())
1453 return false;
1454
1455 TreeToString();
1456 assert(!IsBold && "Bold is applied to end of string.");
1457 S = OS.str();
1458 return true;
1459 }
1460}; // end class TemplateDiff
1461} // end namespace
1462
1463/// FormatTemplateTypeDiff - A helper static function to start the template
1464/// diff and return the properly formatted string. Returns true if the diff
1465/// is successful.
1466static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
1467 QualType ToType, bool PrintTree,
1468 bool PrintFromType, bool ElideType,
1469 bool ShowColors, std::string &S) {
1470 if (PrintTree)
1471 PrintFromType = true;
1472 TemplateDiff TD(Context, FromType, ToType, PrintTree, PrintFromType,
1473 ElideType, ShowColors);
1474 TD.DiffTemplate();
1475 return TD.MakeString(S);
1476}