зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
00a8541416
Коммит
54c4545335
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче