forked from OSchip/llvm-project
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). llvm-svn: 257869
This commit is contained in:
parent
2c485a7003
commit
9213ce559a
|
@ -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) {
|
||||
|
|
|
@ -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]]]>
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue