Update template diffing to handle template arguments that are declarations.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176153 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Trieu 2013-02-27 01:41:53 +00:00
Родитель b3a49f567a
Коммит da8910519b
2 изменённых файлов: 125 добавлений и 4 удалений

Просмотреть файл

@ -435,6 +435,9 @@ class TemplateDiff {
/// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
bool IsValidFromInt, IsValidToInt;
/// FromValueDecl, ToValueDecl - Whether the argument is a decl.
ValueDecl *FromValueDecl, *ToValueDecl;
/// FromDefault, ToDefault - Whether the argument is a default argument.
bool FromDefault, ToDefault;
@ -444,8 +447,8 @@ class TemplateDiff {
DiffNode(unsigned ParentNode = 0)
: NextNode(0), ChildNode(0), ParentNode(ParentNode),
FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
IsValidFromInt(false), IsValidToInt(false),
FromDefault(false), ToDefault(false), Same(false) { }
IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { }
};
/// FlatTree - A flattened tree used to store the DiffNodes.
@ -501,6 +504,12 @@ class TemplateDiff {
FlatTree[CurrentNode].ToQual = ToQual;
}
/// SetNode - Set FromValueDecl and ToValueDecl of the current node.
void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) {
FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
}
/// SetSame - Sets the same flag of the current node.
void SetSame(bool Same) {
FlatTree[CurrentNode].Same = Same;
@ -584,6 +593,11 @@ class TemplateDiff {
FlatTree[ReadNode].IsValidToInt;
}
/// NodeIsDecl - Returns true if the arguments are stored as Decl's.
bool NodeIsValueDecl() {
return FlatTree[ReadNode].FromValueDecl || FlatTree[ReadNode].ToValueDecl;
}
/// GetNode - Gets the FromType and ToType.
void GetNode(QualType &FromType, QualType &ToType) {
FromType = FlatTree[ReadNode].FromType;
@ -617,6 +631,12 @@ class TemplateDiff {
ToQual = FlatTree[ReadNode].ToQual;
}
/// GetNode - Gets the FromValueDecl and ToValueDecl.
void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) {
FromValueDecl = FlatTree[ReadNode].FromValueDecl;
ToValueDecl = FlatTree[ReadNode].ToValueDecl;
}
/// NodeIsSame - Returns true the arguments are the same.
bool NodeIsSame() {
return FlatTree[ReadNode].Same;
@ -845,6 +865,7 @@ class TemplateDiff {
dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
Expr *FromExpr, *ToExpr;
llvm::APSInt FromInt, ToInt;
ValueDecl *FromValueDecl = 0, *ToValueDecl = 0;
unsigned ParamWidth = 128; // Safe default
if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
@ -852,23 +873,37 @@ class TemplateDiff {
FromIter->getKind() == TemplateArgument::Integral;
bool HasToInt = !ToIter.isEnd() &&
ToIter->getKind() == TemplateArgument::Integral;
bool HasFromValueDecl =
!FromIter.isEnd() &&
FromIter->getKind() == TemplateArgument::Declaration;
bool HasToValueDecl =
!ToIter.isEnd() &&
ToIter->getKind() == TemplateArgument::Declaration;
assert(((!HasFromInt && !HasToInt) ||
(!HasFromValueDecl && !HasToValueDecl)) &&
"Template argument cannot be both integer and declaration");
if (HasFromInt)
FromInt = FromIter->getAsIntegral();
else if (HasFromValueDecl)
FromValueDecl = FromIter->getAsDecl();
else
GetExpr(FromIter, DefaultNTTPD, FromExpr);
if (HasToInt)
ToInt = ToIter->getAsIntegral();
else if (HasToValueDecl)
ToValueDecl = ToIter->getAsDecl();
else
GetExpr(ToIter, DefaultNTTPD, ToExpr);
if (!HasFromInt && !HasToInt) {
if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
Tree.SetNode(FromExpr, ToExpr);
Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr));
Tree.SetDefault(FromIter.isEnd() && FromExpr,
ToIter.isEnd() && ToExpr);
} else {
} else if (HasFromInt || HasToInt) {
if (!HasFromInt && FromExpr) {
FromInt = FromExpr->EvaluateKnownConstInt(Context);
HasFromInt = true;
@ -881,6 +916,20 @@ class TemplateDiff {
Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
Tree.SetDefault(FromIter.isEnd() && HasFromInt,
ToIter.isEnd() && HasToInt);
} else {
if (!HasFromValueDecl && FromExpr) {
DeclRefExpr *DRE = cast<DeclRefExpr>(FromExpr);
FromValueDecl = cast<ValueDecl>(DRE->getDecl());
}
if (!HasToValueDecl && ToExpr) {
DeclRefExpr *DRE = cast<DeclRefExpr>(ToExpr);
ToValueDecl = cast<ValueDecl>(DRE->getDecl());
}
Tree.SetNode(FromValueDecl, ToValueDecl);
Tree.SetSame(FromValueDecl->getCanonicalDecl() ==
ToValueDecl->getCanonicalDecl());
Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
ToIter.isEnd() && ToValueDecl);
}
}
@ -1116,6 +1165,15 @@ class TemplateDiff {
Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
return;
}
if (Tree.NodeIsValueDecl()) {
ValueDecl *FromValueDecl, *ToValueDecl;
Tree.GetNode(FromValueDecl, ToValueDecl);
PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(),
Tree.ToDefault(), Tree.NodeIsSame());
return;
}
llvm_unreachable("Unable to deduce template difference.");
}
@ -1331,6 +1389,35 @@ class TemplateDiff {
}
}
/// PrintDecl - Handles printing of Decl arguments, highlighting
/// argument differences.
void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
bool FromDefault, bool ToDefault, bool Same) {
assert((FromValueDecl || ToValueDecl) &&
"Only one Decl argument may be NULL");
if (Same) {
OS << FromValueDecl->getName();
} else if (!PrintTree) {
OS << (FromDefault ? "(default) " : "");
Bold();
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
Unbold();
} else {
OS << (FromDefault ? "[(default) " : "[");
Bold();
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
Unbold();
OS << " != " << (ToDefault ? "(default) " : "");
Bold();
OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
Unbold();
OS << ']';
}
}
// Prints the appropriate placeholder for elided template arguments.
void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
if (PrintTree) {

Просмотреть файл

@ -869,6 +869,40 @@ namespace rdar12931988 {
}
}
namespace ValueDecl {
int int1, int2, default_int;
template <const int& T = default_int>
struct S {};
typedef S<int1> T1;
typedef S<int2> T2;
typedef S<> TD;
void test() {
T1 t1;
T2 t2;
TD td;
t1 = t2;
// CHECK-ELIDE-NOTREE: no viable overloaded '='
// CHECK-ELIDE-NOTREE: no known conversion from 'S<int2>' to 'S<int1>'
t2 = t1;
// CHECK-ELIDE-NOTREE: no viable overloaded '='
// CHECK-ELIDE-NOTREE: no known conversion from 'S<int1>' to 'S<int2>'
td = t1;
// TODO: Find out why (default) isn't printed on second template.
// CHECK-ELIDE-NOTREE: no viable overloaded '='
// CHECK-ELIDE-NOTREE: no known conversion from 'S<int1>' to 'S<default_int>'
t2 = td;
// CHECK-ELIDE-NOTREE: no viable overloaded '='
// CHECK-ELIDE-NOTREE: no known conversion from 'S<(default) default_int>' to 'S<int2>'
}
}
// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.