From da8910519b8dc79826781e74aaafddbd5c4ba19c Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 27 Feb 2013 01:41:53 +0000 Subject: [PATCH] Update template diffing to handle template arguments that are declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176153 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTDiagnostic.cpp | 95 +++++++++++++++++++++++++++-- test/Misc/diag-template-diffing.cpp | 34 +++++++++++ 2 files changed, 125 insertions(+), 4 deletions(-) diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 92b1ca0d5b..d67423ed3d 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -435,6 +435,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; @@ -444,8 +447,8 @@ class TemplateDiff { DiffNode(unsigned ParentNode = 0) : NextNode(0), ChildNode(0), ParentNode(ParentNode), FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), - IsValidFromInt(false), IsValidToInt(false), - 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. @@ -501,6 +504,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; @@ -584,6 +593,11 @@ class TemplateDiff { FlatTree[ReadNode].IsValidToInt; } + /// NodeIsDecl - Returns true if the arguments are stored as Decl's. + bool NodeIsValueDecl() { + return FlatTree[ReadNode].FromValueDecl || FlatTree[ReadNode].ToValueDecl; + } + /// GetNode - Gets the FromType and ToType. void GetNode(QualType &FromType, QualType &ToType) { FromType = FlatTree[ReadNode].FromType; @@ -617,6 +631,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; @@ -845,6 +865,7 @@ class TemplateDiff { dyn_cast(ParamND)) { Expr *FromExpr, *ToExpr; llvm::APSInt FromInt, ToInt; + ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; unsigned ParamWidth = 128; // Safe default if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); @@ -852,23 +873,37 @@ class TemplateDiff { FromIter->getKind() == TemplateArgument::Integral; bool HasToInt = !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::Integral; + 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); if (HasToInt) ToInt = ToIter->getAsIntegral(); + else if (HasToValueDecl) + ToValueDecl = ToIter->getAsDecl(); else GetExpr(ToIter, DefaultNTTPD, ToExpr); - if (!HasFromInt && !HasToInt) { + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { Tree.SetNode(FromExpr, ToExpr); Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); - } else { + } else if (HasFromInt || HasToInt) { if (!HasFromInt && FromExpr) { FromInt = FromExpr->EvaluateKnownConstInt(Context); HasFromInt = true; @@ -881,6 +916,20 @@ class TemplateDiff { Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, ToIter.isEnd() && HasToInt); + } else { + if (!HasFromValueDecl && FromExpr) { + DeclRefExpr *DRE = cast(FromExpr); + FromValueDecl = cast(DRE->getDecl()); + } + if (!HasToValueDecl && ToExpr) { + DeclRefExpr *DRE = cast(ToExpr); + ToValueDecl = cast(DRE->getDecl()); + } + Tree.SetNode(FromValueDecl, ToValueDecl); + Tree.SetSame(FromValueDecl->getCanonicalDecl() == + ToValueDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromValueDecl, + ToIter.isEnd() && ToValueDecl); } } @@ -1116,6 +1165,15 @@ class TemplateDiff { Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } + + if (Tree.NodeIsValueDecl()) { + ValueDecl *FromValueDecl, *ToValueDecl; + Tree.GetNode(FromValueDecl, ToValueDecl); + PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); + return; + } + llvm_unreachable("Unable to deduce template difference."); } @@ -1331,6 +1389,35 @@ class TemplateDiff { } } + + /// 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 << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + Unbold(); + } else { + OS << (FromDefault ? "[(default) " : "["); + Bold(); + OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + Unbold(); + OS << " != " << (ToDefault ? "(default) " : ""); + Bold(); + OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); + Unbold(); + OS << ']'; + } + + } + // Prints the appropriate placeholder for elided template arguments. void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) { if (PrintTree) { diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index c6fc32d1b3..6be705511d 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -869,6 +869,40 @@ namespace rdar12931988 { } } +namespace ValueDecl { + int int1, int2, default_int; + template + struct S {}; + + typedef S T1; + typedef S T2; + typedef S<> TD; + + void test() { + T1 t1; + T2 t2; + TD td; + + t1 = t2; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'S' to 'S' + + t2 = t1; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'S' to 'S' + + td = t1; + // TODO: Find out why (default) isn't printed on second template. + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'S' to 'S' + + t2 = td; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'S<(default) default_int>' to 'S' + + } +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. -- 2.40.0