From: Richard Trieu Date: Fri, 15 Jan 2016 05:01:53 +0000 (+0000) Subject: Add new diff modes to template type diffing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a477b5ffc4676516a26d1147c8d1d8cf49b1f5af;p=clang 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). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@257869 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index c60dfa6e53..12774c6723 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -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) { diff --git a/test/Misc/diag-template-diffing-color.cpp b/test/Misc/diag-template-diffing-color.cpp index e73fc2c397..bf203153d8 100644 --- a/test/Misc/diag-template-diffing-color.cpp +++ b/test/Misc/diag-template-diffing-color.cpp @@ -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 struct foo {}; void func(foo); @@ -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 class A{}; + int x; + int y[5]; + A a1 = A(); + // 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 a2 = A(); + // 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]]]> } diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index 424ac51c9a..cf850a5fc0 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -1287,6 +1287,89 @@ void foo() { // CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' } +namespace MixedDeclarationIntegerArgument { +template class A{}; +int x; +int y[5]; + +A a1 = A(); +A a2 = A(); +A a3 = A(); +A a4 = A(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// 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 a5 = A(); +A a6 = A(); +A a7 = A(); +A a8 = A(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A' to 'A' +// 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 B{} ; +B b1 = B(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B' to 'B' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: B< +// CHECK-ELIDE-TREE: [int & != int], +// CHECK-ELIDE-TREE: [(default) x != 5]> + +B b2 = B(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B' to 'B' +// CHECK-ELIDE-TREE: B< +// CHECK-ELIDE-TREE: [int != int &], +// CHECK-ELIDE-TREE: [2 != (default) x]> + +template class C {}; +C c1 = C(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C' to 'C' +// CHECK-ELIDE-TREE: error: no viable conversion +// CHECK-ELIDE-TREE: C< +// CHECK-ELIDE-TREE: [int & != int], +// CHECK-ELIDE-TREE: [x != (default) 11]> + +C c2 = C(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C' to 'C' +// 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.