diff options
author | Richard Trieu <rtrieu@google.com> | 2012-11-01 21:29:28 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2012-11-01 21:29:28 +0000 |
commit | 54c45453359b47646a1c8d072b02f628b7e16eaa (patch) | |
tree | 6c12015b51de61c9e8a953e6dc0347e6014bb06d | |
parent | 00a8541416df6e2ca8b298759267bea479b6adfb (diff) |
Fix the template type diffing to handle integral template arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 108 | ||||
-rw-r--r-- | test/Misc/diag-template-diffing.cpp | 163 |
2 files changed, 265 insertions, 6 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 7018ba9c2d..0b9c524944 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -433,6 +433,12 @@ class TemplateDiff { /// FromQual, ToQual - Qualifiers for template types. Qualifiers FromQual, ToQual; + /// FromInt, ToInt - APSInt's for integral arguments. + llvm::APSInt FromInt, ToInt; + + /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. + bool IsValidFromInt, IsValidToInt; + /// FromDefault, ToDefault - Whether the argument is a default argument. bool FromDefault, ToDefault; @@ -483,6 +489,15 @@ class TemplateDiff { FlatTree[CurrentNode].ToExpr = ToExpr; } + /// SetNode - Set FromInt and ToInt of the current node. + void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt, + bool IsValidFromInt, bool IsValidToInt) { + FlatTree[CurrentNode].FromInt = FromInt; + FlatTree[CurrentNode].ToInt = ToInt; + FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt; + FlatTree[CurrentNode].IsValidToInt = IsValidToInt; + } + /// SetNode - Set FromQual and ToQual of the current node. void SetNode(Qualifiers FromQual, Qualifiers ToQual) { FlatTree[CurrentNode].FromQual = FromQual; @@ -566,6 +581,12 @@ class TemplateDiff { (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; @@ -584,6 +605,15 @@ class TemplateDiff { ToTD = FlatTree[ReadNode].ToTD; } + /// GetNode - Gets the FromInt and ToInt. + void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt, + bool &IsValidFromInt, bool &IsValidToInt) { + FromInt = FlatTree[ReadNode].FromInt; + ToInt = FlatTree[ReadNode].ToInt; + IsValidFromInt = FlatTree[ReadNode].IsValidFromInt; + IsValidToInt = FlatTree[ReadNode].IsValidToInt; + } + /// GetNode - Gets the FromQual and ToQual. void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) { FromQual = FlatTree[ReadNode].FromQual; @@ -817,12 +847,41 @@ class TemplateDiff { if (NonTypeTemplateParmDecl *DefaultNTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { Expr *FromExpr, *ToExpr; - GetExpr(FromIter, DefaultNTTPD, FromExpr); - GetExpr(ToIter, DefaultNTTPD, ToExpr); - Tree.SetNode(FromExpr, ToExpr); - Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); - Tree.SetDefault(FromIter.isEnd() && FromExpr, - ToIter.isEnd() && ToExpr); + llvm::APSInt FromInt, ToInt; + bool HasFromInt = !FromIter.isEnd() && + FromIter->getKind() == TemplateArgument::Integral; + bool HasToInt = !ToIter.isEnd() && + ToIter->getKind() == TemplateArgument::Integral; + //bool IsValidFromInt = false, IsValidToInt = false; + if (HasFromInt) + FromInt = FromIter->getAsIntegral(); + else + GetExpr(FromIter, DefaultNTTPD, FromExpr); + + if (HasToInt) + ToInt = ToIter->getAsIntegral(); + else + GetExpr(ToIter, DefaultNTTPD, ToExpr); + + if (!HasFromInt && !HasToInt) { + Tree.SetNode(FromExpr, ToExpr); + Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); + Tree.SetDefault(FromIter.isEnd() && FromExpr, + ToIter.isEnd() && ToExpr); + } else { + if (!HasFromInt && FromExpr) { + FromInt = FromExpr->EvaluateKnownConstInt(Context); + HasFromInt = true; + } + if (!HasToInt && ToExpr) { + ToInt = ToExpr->EvaluateKnownConstInt(Context); + HasToInt = true; + } + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(llvm::APSInt::isSameValue(FromInt, ToInt)); + Tree.SetDefault(FromIter.isEnd() && HasFromInt, + ToIter.isEnd() && HasToInt); + } } // Handle Templates @@ -1038,6 +1097,15 @@ class TemplateDiff { Tree.ToDefault(), Tree.NodeIsSame()); return; } + + if (Tree.NodeIsAPSInt()) { + llvm::APSInt FromInt, ToInt; + bool IsValidFromInt, IsValidToInt; + Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); + PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, + Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + return; + } llvm_unreachable("Unable to deduce template difference."); } @@ -1212,6 +1280,34 @@ 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) { + assert((IsValidFromInt || IsValidToInt) && + "Only one integral argument may be missing."); + + if (Same) { + OS << FromInt.toString(10); + } else if (!PrintTree) { + OS << (FromDefault ? "(default) " : ""); + Bold(); + OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + Unbold(); + } else { + OS << (FromDefault ? "[(default) " : "["); + Bold(); + OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)"); + Unbold(); + OS << " != " << (ToDefault ? "(default) " : ""); + Bold(); + OS << (IsValidToInt ? ToInt.toString(10) : "(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 e4b074ae7e..2c044f877e 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -630,6 +630,169 @@ void test23() { // CHECK-NOELIDE-TREE: D23< // CHECK-NOELIDE-TREE: [char != A23<>]> +namespace PR14015 { +template <unsigned N> class Foo1 {}; +template <unsigned N = 2> class Foo2 {}; +template <unsigned ...N> class Foo3 {}; + +void Play1() { + Foo1<1> F1; + Foo1<2> F2, F3; + F2 = F1; + F1 = F2; + F2 = F3; + F3 = F2; +} + +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo1< +// CHECK-ELIDE-TREE: [1 != 2]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo1< +// CHECK-ELIDE-TREE: [1 != 2]> +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo1< +// CHECK-ELIDE-TREE: [2 != 1]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo1< +// CHECK-ELIDE-TREE: [2 != 1]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo1< +// CHECK-NOELIDE-TREE: [1 != 2]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo1< +// CHECK-NOELIDE-TREE: [1 != 2]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo1< +// CHECK-NOELIDE-TREE: [2 != 1]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo1< +// CHECK-NOELIDE-TREE: [2 != 1]> + +void Play2() { + Foo2<1> F1; + Foo2<> F2, F3; + F2 = F1; + F1 = F2; + F2 = F3; + F3 = F2; +} +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo2< +// CHECK-ELIDE-TREE: [1 != 2]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo2< +// CHECK-ELIDE-TREE: [1 != 2]> +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo2< +// CHECK-ELIDE-TREE: [(default) 2 != 1]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo2< +// CHECK-ELIDE-TREE: [(default) 2 != 1]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo2< +// CHECK-NOELIDE-TREE: [1 != 2]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo2< +// CHECK-NOELIDE-TREE: [1 != 2]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo2< +// CHECK-NOELIDE-TREE: [(default) 2 != 1]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo2< +// CHECK-NOELIDE-TREE: [(default) 2 != 1]> + +void Play3() { + Foo3<1> F1; + Foo3<2, 1> F2, F3; + F2 = F1; + F1 = F2; + F2 = F3; + F3 = F2; +} +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument +// CHECK-ELIDE-NOTREE: no viable overloaded '=' +// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument +// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument +// CHECK-NOELIDE-NOTREE: no viable overloaded '=' +// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument +// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo3< +// CHECK-ELIDE-TREE: [1 != 2], +// CHECK-ELIDE-TREE: [(no argument) != 1]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo3< +// CHECK-ELIDE-TREE: [1 != 2], +// CHECK-ELIDE-TREE: [(no argument) != 1]> +// CHECK-ELIDE-TREE: no viable overloaded '=' +// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo3< +// CHECK-ELIDE-TREE: [2 != 1], +// CHECK-ELIDE-TREE: [1 != (no argument)]> +// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: Foo3< +// CHECK-ELIDE-TREE: [2 != 1], +// CHECK-ELIDE-TREE: [1 != (no argument)]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo3< +// CHECK-NOELIDE-TREE: [1 != 2], +// CHECK-NOELIDE-TREE: [(no argument) != 1]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo3< +// CHECK-NOELIDE-TREE: [1 != 2], +// CHECK-NOELIDE-TREE: [(no argument) != 1]> +// CHECK-NOELIDE-TREE: no viable overloaded '=' +// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo3< +// CHECK-NOELIDE-TREE: [2 != 1], +// CHECK-NOELIDE-TREE: [1 != (no argument)]> +// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: Foo3< +// CHECK-NOELIDE-TREE: [2 != 1], +// CHECK-NOELIDE-TREE: [1 != (no argument)]> +} + + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. |