r257869 - Add new diff modes to template type diffing.
Richard Trieu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 14 21:01:53 PST 2016
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.
More information about the cfe-commits
mailing list