Author: rtrieu Date: Thu Jan 14 23:01:53 2016 New Revision: 257869 URL: http://llvm.org/viewvc/llvm-project?rev=257869&view=rev Log: Add new diff modes to template type diffing.
Remove an old assertion that does not hold. It is possible for a template argument to be a declaration in one instantiation and an integer in another. Create two new diff kinds for these (decl vs int and int vs decl). Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp cfe/trunk/test/Misc/diag-template-diffing-color.cpp cfe/trunk/test/Misc/diag-template-diffing.cpp Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=257869&r1=257868&r2=257869&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original) +++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Thu Jan 14 23:01:53 2016 @@ -511,7 +511,10 @@ class TemplateDiff { /// Integer difference Integer, /// Declaration difference, nullptr arguments are included here - Declaration + Declaration, + /// One argument being integer and the other being declaration + FromIntegerAndToDeclaration, + FromDeclarationAndToInteger }; private: @@ -648,6 +651,40 @@ class TemplateDiff { SetDefault(FromDefault, ToDefault); } + void SetFromDeclarationAndToIntegerDiff( + ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr, + Expr *FromExpr, llvm::APSInt ToInt, bool IsValidToInt, + QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger; + FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl; + FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf; + FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.Val = ToInt; + FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt; + FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + + void SetFromIntegerAndToDeclarationDiff( + llvm::APSInt FromInt, bool IsValidFromInt, QualType FromIntType, + Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf, + bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) { + assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); + FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration; + FlatTree[CurrentNode].FromArgInfo.Val = FromInt; + FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt; + FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType; + FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; + FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl; + FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf; + FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr; + FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; + SetDefault(FromDefault, ToDefault); + } + /// SetDefault - Sets FromDefault and ToDefault flags of the current node. void SetDefault(bool FromDefault, bool ToDefault) { assert(!FromDefault || !ToDefault && "Both arguments cannot be default."); @@ -761,6 +798,38 @@ class TemplateDiff { ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; } + void GetFromDeclarationAndToIntegerDiff( + ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr, + Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt, + QualType &ToIntType, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger && + "Unexpected kind."); + FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD; + FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf; + FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToInt = FlatTree[ReadNode].ToArgInfo.Val; + IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt; + ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + + void GetFromIntegerAndToDeclarationDiff( + llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType, + Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf, + bool &ToNullPtr, Expr *&ToExpr) { + assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration && + "Unexpected kind."); + FromInt = FlatTree[ReadNode].FromArgInfo.Val; + IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt; + FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType; + FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; + ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD; + ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf; + ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr; + ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; + } + /// FromDefault - Return true if the from argument is the default. bool FromDefault() { return FlatTree[ReadNode].FromArgInfo.IsDefault; @@ -1139,18 +1208,31 @@ class TemplateDiff { HasToInt, ToIntType, ToNullPtr, ToExpr, ToValueDecl, NeedToAddressOf); - bool FromDeclaration = FromValueDecl || FromNullPtr; - bool ToDeclaration = ToValueDecl || ToNullPtr; - - assert(((!HasFromInt && !HasToInt) || - (!FromDeclaration && !ToDeclaration)) && - "Template argument cannot be both integer and declaration"); - bool FromDefault = FromIter.isEnd() && (FromExpr || FromValueDecl || HasFromInt || FromNullPtr); bool ToDefault = ToIter.isEnd() && (ToExpr || ToValueDecl || HasToInt || ToNullPtr); + bool FromDeclaration = FromValueDecl || FromNullPtr; + bool ToDeclaration = ToValueDecl || ToNullPtr; + + if (FromDeclaration && HasToInt) { + Tree.SetFromDeclarationAndToIntegerDiff( + FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt, + HasToInt, ToIntType, ToExpr, FromDefault, ToDefault); + Tree.SetSame(false); + return; + + } + + if (HasFromInt && ToDeclaration) { + Tree.SetFromIntegerAndToDeclarationDiff( + FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl, + NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault); + Tree.SetSame(false); + return; + } + if (HasFromInt || HasToInt) { Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType, ToIntType, FromExpr, ToExpr, FromDefault, ToDefault); @@ -1383,6 +1465,42 @@ class TemplateDiff { Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } + case DiffTree::FromDeclarationAndToInteger: { + ValueDecl *FromValueDecl; + bool FromAddressOf; + bool FromNullPtr; + Expr *FromExpr; + llvm::APSInt ToInt; + bool IsValidToInt; + QualType ToIntType; + Expr *ToExpr; + Tree.GetFromDeclarationAndToIntegerDiff( + FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt, + IsValidToInt, ToIntType, ToExpr); + assert((FromValueDecl || FromNullPtr) && IsValidToInt); + PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr, + FromExpr, Tree.FromDefault(), ToInt, ToIntType, + ToExpr, Tree.ToDefault()); + return; + } + case DiffTree::FromIntegerAndToDeclaration: { + llvm::APSInt FromInt; + bool IsValidFromInt; + QualType FromIntType; + Expr *FromExpr; + ValueDecl *ToValueDecl; + bool ToAddressOf; + bool ToNullPtr; + Expr *ToExpr; + Tree.GetFromIntegerAndToDeclarationDiff( + FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl, + ToAddressOf, ToNullPtr, ToExpr); + assert(IsValidFromInt && (ToValueDecl || ToNullPtr)); + PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr, + Tree.FromDefault(), ToValueDecl, ToAddressOf, + ToNullPtr, ToExpr, Tree.ToDefault()); + return; + } case DiffTree::Template: { // Node is root of template. Recurse on children. TemplateDecl *FromTD, *ToTD; @@ -1715,6 +1833,48 @@ class TemplateDiff { } + /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and + /// APSInt to print a mixed difference. + void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf, + bool IsNullPtr, Expr *VDExpr, bool DefaultDecl, + llvm::APSInt Val, QualType IntType, + Expr *IntExpr, bool DefaultInt) { + if (!PrintTree) { + OS << (DefaultDecl ? "(default) " : ""); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); + Unbold(); + } else { + OS << (DefaultDecl ? "[(default) " : "["); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); + Unbold(); + OS << " != " << (DefaultInt ? "(default) " : ""); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); + OS << ']'; + } + } + + /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and + /// ValueDecl to print a mixed difference. + void PrintIntegerAndValueDecl(llvm::APSInt Val, QualType IntType, + Expr *IntExpr, bool DefaultInt, ValueDecl *VD, + bool NeedAddressOf, bool IsNullPtr, + Expr *VDExpr, bool DefaultDecl) { + if (!PrintTree) { + OS << (DefaultInt ? "(default) " : ""); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); + } else { + OS << (DefaultInt ? "[(default) " : "["); + PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); + OS << " != " << (DefaultDecl ? "(default) " : ""); + Bold(); + PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); + Unbold(); + OS << ']'; + } + } + // Prints the appropriate placeholder for elided template arguments. void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) { if (PrintTree) { Modified: cfe/trunk/test/Misc/diag-template-diffing-color.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing-color.cpp?rev=257869&r1=257868&r2=257869&view=diff ============================================================================== --- cfe/trunk/test/Misc/diag-template-diffing-color.cpp (original) +++ cfe/trunk/test/Misc/diag-template-diffing-color.cpp Thu Jan 14 23:01:53 2016 @@ -1,5 +1,5 @@ -// RUN: not %clang_cc1 -fsyntax-only -fcolor-diagnostics %s 2>&1 | FileCheck %s -// RUN: not %clang_cc1 -fsyntax-only -fcolor-diagnostics -fdiagnostics-show-template-tree %s 2>&1 | FileCheck %s -check-prefix=TREE +// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fcolor-diagnostics %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fcolor-diagnostics -fdiagnostics-show-template-tree %s 2>&1 | FileCheck %s -check-prefix=TREE // REQUIRES: ansi-escape-sequences template<typename> struct foo {}; void func(foo<int>); @@ -82,5 +82,23 @@ namespace default_args { // CHECK: no viable conversion from 'A<[2 * ...], (default) [[CYAN]]2[[RESET]][[BOLD]]>' to 'A<[2 * ...], [[CYAN]]0[[RESET]][[BOLD]]>' A<0, 2, 0> N2 = M; } +} +namespace MixedDeclarationIntegerArgument { + template<typename T, T n = 5> class A{}; + int x; + int y[5]; + A<int> a1 = A<int&, x>(); + // CHECK: no viable conversion from 'A<[[CYAN]]int &[[RESET]][[BOLD]], [[CYAN]]x[[RESET]][[BOLD]]>' to 'A<[[CYAN]]int[[RESET]][[BOLD]], (default) [[CYAN]]5[[RESET]][[BOLD]]>' + // TREE: no viable conversion + // TREE: A< + // TREE: {{\[}}[[CYAN]]int &[[RESET]][[BOLD]] != [[CYAN]]int[[RESET]][[BOLD]]], + // TREE: {{\[}}[[CYAN]]x[[RESET]][[BOLD]] != (default) [[CYAN]]5[[RESET]][[BOLD]]]> + + A<int**, nullptr> a2 = A<int, 3 + 1>(); + // CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<[[CYAN]]int[[RESET]][[BOLD]], [[CYAN]]3 + 1[[RESET]][[BOLD]] aka [[CYAN]]4[[RESET]][[BOLD]]>' to 'A<[[CYAN]]int **[[RESET]][[BOLD]], [[CYAN]]nullptr[[RESET]][[BOLD]]>' + // TREE: no viable conversion + // TREE: A< + // TREE: {{\[}}[[CYAN]]int[[RESET]][[BOLD]] != [[CYAN]]int **[[RESET]][[BOLD]]], + // TREE: {{\[}}[[CYAN]]3 + 1[[RESET]][[BOLD]] aka [[CYAN]]4[[RESET]][[BOLD]] != [[CYAN]]nullptr[[RESET]][[BOLD]]]> } Modified: cfe/trunk/test/Misc/diag-template-diffing.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=257869&r1=257868&r2=257869&view=diff ============================================================================== --- cfe/trunk/test/Misc/diag-template-diffing.cpp (original) +++ cfe/trunk/test/Misc/diag-template-diffing.cpp Thu Jan 14 23:01:53 2016 @@ -1287,6 +1287,89 @@ void foo() { // CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<signed char, (signed char) 1>' to 'A<bool, (bool) true>' } +namespace MixedDeclarationIntegerArgument { +template<typename T, T n> class A{}; +int x; +int y[5]; + +A<int, 5> a1 = A<int&, x>(); +A<int, 5 - 1> a2 = A<int*, &x>(); +A<int, 5 + 1> a3 = A<int*, y>(); +A<int, 0> a4 = A<int**, nullptr>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int &, x>' to 'A<int, 5>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int *, &x>' to 'A<int, 5 - 1 aka 4>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int *, y>' to 'A<int, 5 + 1 aka 6>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int **, nullptr>' to 'A<int, 0>' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int & != int], +// CHECK-ELIDE-TREE: [x != 5]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int * != int], +// CHECK-ELIDE-TREE: [&x != 5 - 1 aka 4]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int * != int], +// CHECK-ELIDE-TREE: [y != 5 + 1 aka 6]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int ** != int], +// CHECK-ELIDE-TREE: [nullptr != 0]> + +A<int&, x> a5 = A<int, 3>(); +A<int*, &x> a6 = A<int, 3 - 1>(); +A<int*, y> a7 = A<int, 3 + 1>(); +A<int**, nullptr> a8 = A<int, 3>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3>' to 'A<int &, x>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3 - 1 aka 2>' to 'A<int *, &x>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3 + 1 aka 4>' to 'A<int *, y>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3>' to 'A<int **, nullptr>' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int != int &], +// CHECK-ELIDE-TREE: [3 != x]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int != int *], +// CHECK-ELIDE-TREE: [3 - 1 aka 2 != &x]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int != int *], +// CHECK-ELIDE-TREE: [3 + 1 aka 4 != y]> +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: A< +// CHECK-ELIDE-TREE: [int != int **], +// CHECK-ELIDE-TREE: [3 != nullptr]> + +template<class T, T n = x> class B{} ; +B<int, 5> b1 = B<int&>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int &, (default) x>' to 'B<int, 5>' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: B< +// CHECK-ELIDE-TREE: [int & != int], +// CHECK-ELIDE-TREE: [(default) x != 5]> + +B<int &> b2 = B<int, 2>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int, 2>' to 'B<int &, (default) x>' +// CHECK-ELIDE-TREE: B< +// CHECK-ELIDE-TREE: [int != int &], +// CHECK-ELIDE-TREE: [2 != (default) x]> + +template<class T, T n = 11> class C {}; +C<int> c1 = C<int&, x>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C<int &, x>' to 'C<int, (default) 11>' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: C< +// CHECK-ELIDE-TREE: [int & != int], +// CHECK-ELIDE-TREE: [x != (default) 11]> + +C<int &, x> c2 = C<int>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C<int, (default) 11>' to 'C<int &, x>' +// CHECK-ELIDE-TREE: C< +// CHECK-ELIDE-TREE: [int != int &], +// CHECK-ELIDE-TREE: [(default) 11 != x]> +} // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits