diff options
Diffstat (limited to 'lib/AST/ASTDiagnostic.cpp')
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 567 |
1 files changed, 381 insertions, 186 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 0b9c524..1ed65e4 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -11,12 +11,11 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/ASTDiagnostic.h" - #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -232,7 +231,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColors, std::string &S); + bool ShowColors, raw_ostream &OS); void clang::FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, @@ -248,7 +247,8 @@ void clang::FormatASTNodeDiagnosticArgument( ArrayRef<intptr_t> QualTypeVals) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); - std::string S; + size_t OldEnd = Output.size(); + llvm::raw_svector_ostream OS(Output); bool NeedQuotes = true; switch (Kind) { @@ -262,7 +262,7 @@ void clang::FormatASTNodeDiagnosticArgument( if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, TDT.PrintFromType, TDT.ElideType, - TDT.ShowColors, S)) { + TDT.ShowColors, OS)) { NeedQuotes = !TDT.PrintTree; TDT.TemplateDiffUsed = true; break; @@ -273,7 +273,7 @@ void clang::FormatASTNodeDiagnosticArgument( if (TDT.PrintTree) return; - // Attempting to do a templete diff on non-templates. Set the variables + // Attempting to do a template diff on non-templates. Set the variables // and continue with regular type printing of the appropriate type. Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; ModLen = 0; @@ -285,23 +285,23 @@ void clang::FormatASTNodeDiagnosticArgument( "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, - QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, + QualTypeVals); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declarationname: { - DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); - S = N.getAsString(); - if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) - S = '+' + S; + OS << '+'; else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0) - S = '-' + S; + OS << '-'; else assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); + + DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); + N.printName(OS); break; } case DiagnosticsEngine::ak_nameddecl: { @@ -314,13 +314,12 @@ void clang::FormatASTNodeDiagnosticArgument( Qualified = false; } const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); - ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified); + ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); break; } case DiagnosticsEngine::ak_nestednamespec: { - llvm::raw_string_ostream OS(S); - reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, - Context.getPrintingPolicy()); + NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val); + NNS->print(OS, Context.getPrintingPolicy()); NeedQuotes = false; break; } @@ -331,39 +330,39 @@ void clang::FormatASTNodeDiagnosticArgument( if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) - S = "the global namespace"; + OS << "the global namespace"; else - S = "the global scope"; + OS << "the global scope"; } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { - S = ConvertTypeToDiagnosticString(Context, - Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs, QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, + Context.getTypeDeclType(Type), + PrevArgs, NumPrevArgs, + QualTypeVals); } else { // FIXME: Get these strings from some localized place NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) - S += "namespace "; + OS << "namespace "; else if (isa<ObjCMethodDecl>(ND)) - S += "method "; + OS << "method "; else if (isa<FunctionDecl>(ND)) - S += "function "; - - S += "'"; - ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true); - S += "'"; + OS << "function "; + + OS << '\''; + ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); + OS << '\''; } NeedQuotes = false; break; } } - - if (NeedQuotes) - Output.push_back('\''); - - Output.append(S.begin(), S.end()); - - if (NeedQuotes) + + OS.flush(); + + if (NeedQuotes) { + Output.insert(Output.begin()+OldEnd, '\''); Output.push_back('\''); + } } /// TemplateDiff - A class that constructs a pretty string for a pair of @@ -396,21 +395,39 @@ class TemplateDiff { /// will this type be outputed. QualType ToType; - /// Str - Storage for the output stream. - llvm::SmallString<128> Str; - /// OS - The stream used to construct the output strings. - llvm::raw_svector_ostream OS; + raw_ostream &OS; /// IsBold - Keeps track of the bold formatting for the output string. bool IsBold; /// DiffTree - A tree representation the differences between two types. class DiffTree { + public: + /// DiffKind - The difference in a DiffNode and which fields are used. + enum DiffKind { + /// Incomplete or invalid node. + Invalid, + /// Another level of templates, uses TemplateDecl and Qualifiers + Template, + /// Type difference, uses QualType + Type, + /// Expression difference, uses Expr + Expression, + /// Template argument difference, uses TemplateDecl + TemplateTemplate, + /// Integer difference, uses APSInt and Expr + Integer, + /// Declaration difference, uses ValueDecl + Declaration + }; + private: /// DiffNode - The root node stores the original type. Each child node /// stores template arguments of their parents. For templated types, the /// template decl is also stored. struct DiffNode { + DiffKind Kind; + /// NextNode - The index of the next sibling node or 0. unsigned NextNode; @@ -439,6 +456,9 @@ class TemplateDiff { /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. bool IsValidFromInt, IsValidToInt; + /// FromValueDecl, ToValueDecl - Whether the argument is a decl. + ValueDecl *FromValueDecl, *ToValueDecl; + /// FromDefault, ToDefault - Whether the argument is a default argument. bool FromDefault, ToDefault; @@ -446,13 +466,14 @@ class TemplateDiff { bool Same; DiffNode(unsigned ParentNode = 0) - : NextNode(0), ChildNode(0), ParentNode(ParentNode), + : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), - FromDefault(false), ToDefault(false), Same(false) { } + IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), + ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { } }; /// FlatTree - A flattened tree used to store the DiffNodes. - llvm::SmallVector<DiffNode, 16> FlatTree; + SmallVector<DiffNode, 16> FlatTree; /// CurrentNode - The index of the current node being used. unsigned CurrentNode; @@ -504,6 +525,12 @@ class TemplateDiff { FlatTree[CurrentNode].ToQual = ToQual; } + /// SetNode - Set FromValueDecl and ToValueDecl of the current node. + void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) { + FlatTree[CurrentNode].FromValueDecl = FromValueDecl; + FlatTree[CurrentNode].ToValueDecl = ToValueDecl; + } + /// SetSame - Sets the same flag of the current node. void SetSame(bool Same) { FlatTree[CurrentNode].Same = Same; @@ -515,6 +542,11 @@ class TemplateDiff { FlatTree[CurrentNode].ToDefault = ToDefault; } + /// SetKind - Sets the current node's type. + void SetKind(DiffKind Kind) { + FlatTree[CurrentNode].Kind = Kind; + } + /// Up - Changes the node to the parent of the current node. void Up() { CurrentNode = FlatTree[CurrentNode].ParentNode; @@ -554,39 +586,6 @@ class TemplateDiff { ReadNode = FlatTree[ReadNode].ParentNode; } - /// NodeIsTemplate - Returns true if a template decl is set, and types are - /// set. - bool NodeIsTemplate() { - return (FlatTree[ReadNode].FromTD && - !FlatTree[ReadNode].ToType.isNull()) || - (FlatTree[ReadNode].ToTD && !FlatTree[ReadNode].ToType.isNull()); - } - - /// NodeIsQualType - Returns true if a Qualtype is set. - bool NodeIsQualType() { - return !FlatTree[ReadNode].FromType.isNull() || - !FlatTree[ReadNode].ToType.isNull(); - } - - /// NodeIsExpr - Returns true if an expr is set. - bool NodeIsExpr() { - return FlatTree[ReadNode].FromExpr || FlatTree[ReadNode].ToExpr; - } - - /// NodeIsTemplateTemplate - Returns true if the argument is a template - /// template type. - bool NodeIsTemplateTemplate() { - return FlatTree[ReadNode].FromType.isNull() && - FlatTree[ReadNode].ToType.isNull() && - (FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD); - } - - /// NodeIsAPSInt - Returns true if the arugments are stored in APSInt's. - bool NodeIsAPSInt() { - return FlatTree[ReadNode].IsValidFromInt || - FlatTree[ReadNode].IsValidToInt; - } - /// GetNode - Gets the FromType and ToType. void GetNode(QualType &FromType, QualType &ToType) { FromType = FlatTree[ReadNode].FromType; @@ -620,6 +619,12 @@ class TemplateDiff { ToQual = FlatTree[ReadNode].ToQual; } + /// GetNode - Gets the FromValueDecl and ToValueDecl. + void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) { + FromValueDecl = FlatTree[ReadNode].FromValueDecl; + ToValueDecl = FlatTree[ReadNode].ToValueDecl; + } + /// NodeIsSame - Returns true the arguments are the same. bool NodeIsSame() { return FlatTree[ReadNode].Same; @@ -662,9 +667,12 @@ class TemplateDiff { /// Empty - Returns true if the tree has no information. bool Empty() { - return !FlatTree[0].FromTD && !FlatTree[0].ToTD && - !FlatTree[0].FromExpr && !FlatTree[0].ToExpr && - FlatTree[0].FromType.isNull() && FlatTree[0].ToType.isNull(); + return GetKind() == Invalid; + } + + /// GetKind - Returns the current node's type. + DiffKind GetKind() { + return FlatTree[ReadNode].Kind; } }; @@ -681,6 +689,10 @@ class TemplateDiff { /// traverse over. const TemplateSpecializationType *TST; + /// DesugarTST - desugared template specialization used to extract + /// default argument information + const TemplateSpecializationType *DesugarTST; + /// Index - the index of the template argument in TST. unsigned Index; @@ -693,8 +705,10 @@ class TemplateDiff { /// TSTiterator - Constructs an iterator and sets it to the first template /// argument. - TSTiterator(const TemplateSpecializationType *TST) - : TST(TST), Index(0), CurrentTA(0), EndTA(0) { + TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) + : TST(TST), + DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), + Index(0), CurrentTA(0), EndTA(0) { if (isEnd()) return; // Set to first template argument. If not a parameter pack, done. @@ -715,12 +729,17 @@ class TemplateDiff { /// isEnd - Returns true if the iterator is one past the end. bool isEnd() const { - return Index == TST->getNumArgs(); + return Index >= TST->getNumArgs(); } /// &operator++ - Increment the iterator to the next template argument. TSTiterator &operator++() { - assert(!isEnd() && "Iterator incremented past end of arguments."); + // After the end, Index should be the default argument position in + // DesugarTST, if it exists. + if (isEnd()) { + ++Index; + return *this; + } // If in a parameter pack, advance in the parameter pack. if (CurrentTA != EndTA) { @@ -761,6 +780,11 @@ class TemplateDiff { pointer operator->() const { return &operator*(); } + + /// getDesugar - Returns the deduced template argument from DesguarTST + reference getDesugar() const { + return DesugarTST->getArg(Index); + } }; // These functions build up the template diff tree, including functions to @@ -787,7 +811,7 @@ class TemplateDiff { TemplateName(CTSD->getSpecializedTemplate()), CTSD->getTemplateArgs().data(), CTSD->getTemplateArgs().size(), - Ty.getCanonicalType()); + Ty.getLocalUnqualifiedType().getCanonicalType()); return Ty->getAs<TemplateSpecializationType>(); } @@ -800,7 +824,7 @@ class TemplateDiff { TemplateParameterList *Params = FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); unsigned TotalArgs = 0; - for (TSTiterator FromIter(FromTST), ToIter(ToTST); + for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { Tree.AddNode(); @@ -814,11 +838,12 @@ class TemplateDiff { if (TemplateTypeParmDecl *DefaultTTPD = dyn_cast<TemplateTypeParmDecl>(ParamND)) { QualType FromType, ToType; - GetType(FromIter, DefaultTTPD, FromType); - GetType(ToIter, DefaultTTPD, ToType); + FromType = GetType(FromIter, DefaultTTPD); + ToType = GetType(ToIter, DefaultTTPD); Tree.SetNode(FromType, ToType); Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), ToIter.isEnd() && !ToType.isNull()); + Tree.SetKind(DiffTree::Type); if (!FromType.isNull() && !ToType.isNull()) { if (Context.hasSameType(FromType, ToType)) { Tree.SetSame(true); @@ -837,6 +862,7 @@ class TemplateDiff { Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), ToArgTST->getTemplateName().getAsTemplateDecl()); Tree.SetNode(FromQual, ToQual); + Tree.SetKind(DiffTree::Template); DiffTemplate(FromArgTST, ToArgTST); } } @@ -846,41 +872,83 @@ class TemplateDiff { // Handle Expressions if (NonTypeTemplateParmDecl *DefaultNTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { - Expr *FromExpr, *ToExpr; + Expr *FromExpr = 0, *ToExpr = 0; llvm::APSInt FromInt, ToInt; + ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; + unsigned ParamWidth = 128; // Safe default + if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) + ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); bool HasFromInt = !FromIter.isEnd() && FromIter->getKind() == TemplateArgument::Integral; bool HasToInt = !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::Integral; - //bool IsValidFromInt = false, IsValidToInt = false; + bool HasFromValueDecl = + !FromIter.isEnd() && + FromIter->getKind() == TemplateArgument::Declaration; + bool HasToValueDecl = + !ToIter.isEnd() && + ToIter->getKind() == TemplateArgument::Declaration; + + assert(((!HasFromInt && !HasToInt) || + (!HasFromValueDecl && !HasToValueDecl)) && + "Template argument cannot be both integer and declaration"); + if (HasFromInt) FromInt = FromIter->getAsIntegral(); + else if (HasFromValueDecl) + FromValueDecl = FromIter->getAsDecl(); else - GetExpr(FromIter, DefaultNTTPD, FromExpr); + FromExpr = GetExpr(FromIter, DefaultNTTPD); if (HasToInt) ToInt = ToIter->getAsIntegral(); + else if (HasToValueDecl) + ToValueDecl = ToIter->getAsDecl(); else - GetExpr(ToIter, DefaultNTTPD, ToExpr); + ToExpr = GetExpr(ToIter, DefaultNTTPD); - if (!HasFromInt && !HasToInt) { + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { Tree.SetNode(FromExpr, ToExpr); - Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); - } else { + if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { + if (FromExpr) + FromInt = GetInt(FromIter, FromExpr); + if (ToExpr) + ToInt = GetInt(ToIter, ToExpr); + Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); + Tree.SetKind(DiffTree::Integer); + } else { + Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); + Tree.SetKind(DiffTree::Expression); + } + } else if (HasFromInt || HasToInt) { if (!HasFromInt && FromExpr) { - FromInt = FromExpr->EvaluateKnownConstInt(Context); + FromInt = GetInt(FromIter, FromExpr); HasFromInt = true; } if (!HasToInt && ToExpr) { - ToInt = ToExpr->EvaluateKnownConstInt(Context); + ToInt = GetInt(ToIter, ToExpr); HasToInt = true; } Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); - Tree.SetSame(llvm::APSInt::isSameValue(FromInt, ToInt)); + Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, ToIter.isEnd() && HasToInt); + Tree.SetKind(DiffTree::Integer); + } else { + if (!HasFromValueDecl && FromExpr) + FromValueDecl = GetValueDecl(FromIter, FromExpr); + if (!HasToValueDecl && ToExpr) + ToValueDecl = GetValueDecl(ToIter, ToExpr); + Tree.SetNode(FromValueDecl, ToValueDecl); + Tree.SetSame(FromValueDecl && ToValueDecl && + FromValueDecl->getCanonicalDecl() == + ToValueDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromValueDecl, + ToIter.isEnd() && ToValueDecl); + Tree.SetKind(DiffTree::Declaration); } } @@ -888,15 +956,17 @@ class TemplateDiff { if (TemplateTemplateParmDecl *DefaultTTPD = dyn_cast<TemplateTemplateParmDecl>(ParamND)) { TemplateDecl *FromDecl, *ToDecl; - GetTemplateDecl(FromIter, DefaultTTPD, FromDecl); - GetTemplateDecl(ToIter, DefaultTTPD, ToDecl); + FromDecl = GetTemplateDecl(FromIter, DefaultTTPD); + ToDecl = GetTemplateDecl(ToIter, DefaultTTPD); Tree.SetNode(FromDecl, ToDecl); - Tree.SetSame(FromDecl && ToDecl && - FromDecl->getIdentifier() == ToDecl->getIdentifier()); + Tree.SetSame( + FromDecl && ToDecl && + FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); + Tree.SetKind(DiffTree::TemplateTemplate); } - if (!FromIter.isEnd()) ++FromIter; - if (!ToIter.isEnd()) ++ToIter; + ++FromIter; + ++ToIter; Tree.Up(); } } @@ -917,8 +987,8 @@ class TemplateDiff { /// even if the template arguments are not. static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { - return FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() == - ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier(); + return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() == + ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl(); } /// hasSameTemplate - Returns true if both types are specialized from the @@ -962,22 +1032,21 @@ class TemplateDiff { /// GetType - Retrieves the template type arguments, including default /// arguments. - void GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD, - QualType &ArgType) { - ArgType = QualType(); + QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); if (!Iter.isEnd()) - ArgType = Iter->getAsType(); - else if (!isVariadic) - ArgType = DefaultTTPD->getDefaultArgument(); + return Iter->getAsType(); + if (!isVariadic) + return DefaultTTPD->getDefaultArgument(); + + return QualType(); } /// GetExpr - Retrieves the template expression argument, including default /// arguments. - void GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD, - Expr *&ArgExpr) { - ArgExpr = 0; + Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { + Expr *ArgExpr = 0; bool isVariadic = DefaultNTTPD->isParameterPack(); if (!Iter.isEnd()) @@ -989,14 +1058,50 @@ class TemplateDiff { while (SubstNonTypeTemplateParmExpr *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr)) ArgExpr = SNTTPE->getReplacement(); + + return ArgExpr; + } + + /// GetInt - Retrieves the template integer argument, including evaluating + /// default arguments. + llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { + // Default, value-depenedent expressions require fetching + // from the desugared TemplateArgument + if (Iter.isEnd() && ArgExpr->isValueDependent()) + switch (Iter.getDesugar().getKind()) { + case TemplateArgument::Integral: + return Iter.getDesugar().getAsIntegral(); + case TemplateArgument::Expression: + ArgExpr = Iter.getDesugar().getAsExpr(); + return ArgExpr->EvaluateKnownConstInt(Context); + default: + assert(0 && "Unexpected template argument kind"); + } + return ArgExpr->EvaluateKnownConstInt(Context); + } + + /// GetValueDecl - Retrieves the template integer argument, including + /// default expression argument. + ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { + // Default, value-depenedent expressions require fetching + // from the desugared TemplateArgument + if (Iter.isEnd() && ArgExpr->isValueDependent()) + switch (Iter.getDesugar().getKind()) { + case TemplateArgument::Declaration: + return Iter.getDesugar().getAsDecl(); + case TemplateArgument::Expression: + ArgExpr = Iter.getDesugar().getAsExpr(); + return cast<DeclRefExpr>(ArgExpr)->getDecl(); + default: + assert(0 && "Unexpected template argument kind"); + } + return cast<DeclRefExpr>(ArgExpr)->getDecl(); } /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. - void GetTemplateDecl(const TSTiterator &Iter, - TemplateTemplateParmDecl *DefaultTTPD, - TemplateDecl *&ArgDecl) { - ArgDecl = 0; + TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, + TemplateTemplateParmDecl *DefaultTTPD) { bool isVariadic = DefaultTTPD->isParameterPack(); TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); @@ -1005,13 +1110,25 @@ class TemplateDiff { DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); if (!Iter.isEnd()) - ArgDecl = Iter->getAsTemplate().getAsTemplateDecl(); - else if (!isVariadic) - ArgDecl = DefaultTD; + return Iter->getAsTemplate().getAsTemplateDecl(); + if (!isVariadic) + return DefaultTD; + + return 0; + } + + /// IsSameConvertedInt - Returns true if both integers are equal when + /// converted to an integer type with the given width. + static bool IsSameConvertedInt(unsigned Width, const llvm::APSInt &X, + const llvm::APSInt &Y) { + llvm::APInt ConvertedX = X.extOrTrunc(Width); + llvm::APInt ConvertedY = Y.extOrTrunc(Width); + return ConvertedX == ConvertedY; } /// IsEqualExpr - Returns true if the expressions evaluate to the same value. - static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) { + static bool IsEqualExpr(ASTContext &Context, unsigned ParamWidth, + Expr *FromExpr, Expr *ToExpr) { if (FromExpr == ToExpr) return true; @@ -1033,7 +1150,7 @@ class TemplateDiff { Expr::EvalResult FromResult, ToResult; if (!FromExpr->EvaluateAsRValue(FromResult, Context) || !ToExpr->EvaluateAsRValue(ToResult, Context)) - assert(0 && "Template arguments must be known at compile time."); + return false; APValue &FromVal = FromResult.Val; APValue &ToVal = ToResult.Val; @@ -1042,7 +1159,7 @@ class TemplateDiff { switch (FromVal.getKind()) { case APValue::Int: - return FromVal.getInt() == ToVal.getInt(); + return IsSameConvertedInt(ParamWidth, FromVal.getInt(), ToVal.getInt()); case APValue::LValue: { APValue::LValueBase FromBase = FromVal.getLValueBase(); APValue::LValueBase ToBase = ToVal.getLValueBase(); @@ -1068,81 +1185,97 @@ class TemplateDiff { void TreeToString(int Indent = 1) { if (PrintTree) { OS << '\n'; - for (int i = 0; i < Indent; ++i) - OS << " "; + OS.indent(2 * Indent); ++Indent; } // Handle cases where the difference is not templates with different // arguments. - if (!Tree.NodeIsTemplate()) { - if (Tree.NodeIsQualType()) { + switch (Tree.GetKind()) { + case DiffTree::Invalid: + llvm_unreachable("Template diffing failed with bad DiffNode"); + case DiffTree::Type: { QualType FromType, ToType; Tree.GetNode(FromType, ToType); PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - if (Tree.NodeIsExpr()) { + case DiffTree::Expression: { Expr *FromExpr, *ToExpr; Tree.GetNode(FromExpr, ToExpr); PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - if (Tree.NodeIsTemplateTemplate()) { + case DiffTree::TemplateTemplate: { TemplateDecl *FromTD, *ToTD; Tree.GetNode(FromTD, ToTD); PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } - - if (Tree.NodeIsAPSInt()) { + case DiffTree::Integer: { llvm::APSInt FromInt, ToInt; + Expr *FromExpr, *ToExpr; bool IsValidFromInt, IsValidToInt; + Tree.GetNode(FromExpr, ToExpr); Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), + Tree.NodeIsSame()); return; } - llvm_unreachable("Unable to deduce template difference."); - } - - // Node is root of template. Recurse on children. - TemplateDecl *FromTD, *ToTD; - Tree.GetNode(FromTD, ToTD); - - assert(Tree.HasChildren() && "Template difference not found in diff tree."); - - Qualifiers FromQual, ToQual; - Tree.GetNode(FromQual, ToQual); - PrintQualifiers(FromQual, ToQual); + case DiffTree::Declaration: { + ValueDecl *FromValueDecl, *ToValueDecl; + Tree.GetNode(FromValueDecl, ToValueDecl); + PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); + return; + } + case DiffTree::Template: { + // Node is root of template. Recurse on children. + TemplateDecl *FromTD, *ToTD; + Tree.GetNode(FromTD, ToTD); - OS << FromTD->getNameAsString() << '<'; - Tree.MoveToChild(); - unsigned NumElideArgs = 0; - do { - if (ElideType) { - if (Tree.NodeIsSame()) { - ++NumElideArgs; - continue; + if (!Tree.HasChildren()) { + // If we're dealing with a template specialization with zero + // arguments, there are no children; special-case this. + OS << FromTD->getNameAsString() << "<>"; + return; } - if (NumElideArgs > 0) { + + Qualifiers FromQual, ToQual; + Tree.GetNode(FromQual, ToQual); + PrintQualifiers(FromQual, ToQual); + + OS << FromTD->getNameAsString() << '<'; + Tree.MoveToChild(); + unsigned NumElideArgs = 0; + do { + if (ElideType) { + if (Tree.NodeIsSame()) { + ++NumElideArgs; + continue; + } + if (NumElideArgs > 0) { + PrintElideArgs(NumElideArgs, Indent); + NumElideArgs = 0; + OS << ", "; + } + } + TreeToString(Indent); + if (Tree.HasNextSibling()) + OS << ", "; + } while (Tree.AdvanceSibling()); + if (NumElideArgs > 0) PrintElideArgs(NumElideArgs, Indent); - NumElideArgs = 0; - OS << ", "; - } + + Tree.Parent(); + OS << ">"; + return; } - TreeToString(Indent); - if (Tree.HasNextSibling()) - OS << ", "; - } while (Tree.AdvanceSibling()); - if (NumElideArgs > 0) - PrintElideArgs(NumElideArgs, Indent); - - Tree.Parent(); - OS << ">"; + } } // To signal to the text printer that a certain text needs to be bolded, @@ -1260,21 +1393,29 @@ class TemplateDiff { void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD, bool FromDefault, bool ToDefault, bool Same) { assert((FromTD || ToTD) && "Only one template argument may be missing."); + + std::string FromName = FromTD ? FromTD->getName() : "(no argument)"; + std::string ToName = ToTD ? ToTD->getName() : "(no argument)"; + if (FromTD && ToTD && FromName == ToName) { + FromName = FromTD->getQualifiedNameAsString(); + ToName = ToTD->getQualifiedNameAsString(); + } + if (Same) { OS << "template " << FromTD->getNameAsString(); } else if (!PrintTree) { OS << (FromDefault ? "(default) template " : "template "); Bold(); - OS << (FromTD ? FromTD->getNameAsString() : "(no argument)"); + OS << FromName; Unbold(); } else { OS << (FromDefault ? "[(default) template " : "[template "); Bold(); - OS << (FromTD ? FromTD->getNameAsString() : "(no argument)"); + OS << FromName; Unbold(); OS << " != " << (ToDefault ? "(default) template " : "template "); Bold(); - OS << (ToTD ? ToTD->getNameAsString() : "(no argument)"); + OS << ToName; Unbold(); OS << ']'; } @@ -1283,8 +1424,8 @@ class TemplateDiff { /// PrintAPSInt - Handles printing of integral arguments, highlighting /// argument differences. void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, - bool IsValidFromInt, bool IsValidToInt, bool FromDefault, - bool ToDefault, bool Same) { + bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr, + Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { assert((IsValidFromInt || IsValidToInt) && "Only one integral argument may be missing."); @@ -1292,20 +1433,74 @@ class TemplateDiff { OS << FromInt.toString(10); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + } else { + OS << (FromDefault ? "[(default) " : "["); + PrintAPSInt(FromInt, FromExpr, IsValidFromInt); + OS << " != " << (ToDefault ? "(default) " : ""); + PrintAPSInt(ToInt, ToExpr, IsValidToInt); + OS << ']'; + } + } + + /// PrintAPSInt - If valid, print the APSInt. If the expression is + /// gives more information, print it too. + void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) { + Bold(); + if (Valid) { + if (HasExtraInfo(E)) { + PrintExpr(E); + Unbold(); + OS << " aka "; + Bold(); + } + OS << Val.toString(10); + } else { + OS << "(no argument)"; + } + Unbold(); + } + + /// HasExtraInfo - Returns true if E is not an integer literal or the + /// negation of an integer literal + bool HasExtraInfo(Expr *E) { + if (!E) return false; + if (isa<IntegerLiteral>(E)) return false; + + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) + if (UO->getOpcode() == UO_Minus) + if (isa<IntegerLiteral>(UO->getSubExpr())) + return false; + + return true; + } + + /// PrintDecl - Handles printing of Decl arguments, highlighting + /// argument differences. + void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, + bool FromDefault, bool ToDefault, bool Same) { + assert((FromValueDecl || ToValueDecl) && + "Only one Decl argument may be NULL"); + + if (Same) { + OS << FromValueDecl->getName(); + } else if (!PrintTree) { + OS << (FromDefault ? "(default) " : ""); Bold(); - OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - OS << (IsValidToInt ? ToInt.toString(10) : "(no argument)"); + OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); Unbold(); OS << ']'; } + } // Prints the appropriate placeholder for elided template arguments. @@ -1386,9 +1581,9 @@ class TemplateDiff { public: - TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType, - bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColor) + TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType, + QualType ToType, bool PrintTree, bool PrintFromType, + bool ElideType, bool ShowColor) : Context(Context), Policy(Context.getLangOpts()), ElideType(ElideType), @@ -1397,7 +1592,7 @@ public: // When printing a single type, the FromType is the one printed. FromType(PrintFromType ? FromType : ToType), ToType(PrintFromType ? ToType : FromType), - OS(Str), + OS(OS), IsBold(false) { } @@ -1424,6 +1619,7 @@ public: ToQual -= QualType(ToOrigTST, 0).getQualifiers(); Tree.SetNode(FromType, ToType); Tree.SetNode(FromQual, ToQual); + Tree.SetKind(DiffTree::Template); // Same base template, but different arguments. Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), @@ -1432,17 +1628,16 @@ public: DiffTemplate(FromOrigTST, ToOrigTST); } - /// MakeString - When the two types given are templated types with the same + /// Emit - When the two types given are templated types with the same /// base template, a string representation of the type difference will be - /// loaded into S and return true. Otherwise, return false. - bool MakeString(std::string &S) { + /// emitted to the stream and return true. Otherwise, return false. + bool Emit() { Tree.StartTraverse(); if (Tree.Empty()) return false; TreeToString(); assert(!IsBold && "Bold is applied to end of string."); - S = OS.str(); return true; } }; // end class TemplateDiff @@ -1454,11 +1649,11 @@ public: static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, - bool ShowColors, std::string &S) { + bool ShowColors, raw_ostream &OS) { if (PrintTree) PrintFromType = true; - TemplateDiff TD(Context, FromType, ToType, PrintTree, PrintFromType, + TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType, ElideType, ShowColors); TD.DiffTemplate(); - return TD.MakeString(S); + return TD.Emit(); } |