Add support for nullptr template arguments to template type diffing.

llvm-svn: 213840
This commit is contained in:
Richard Trieu 2014-07-24 04:24:50 +00:00
parent 7fd11896a8
commit 3880089fc7
2 changed files with 161 additions and 31 deletions

View File

@ -472,6 +472,9 @@ class TemplateDiff {
/// FromExpr, ToExpr - The expression arguments.
Expr *FromExpr, *ToExpr;
/// FromNullPtr, ToNullPtr - If the template argument is a nullptr
bool FromNullPtr, ToNullPtr;
/// FromTD, ToTD - The template decl for template template
/// arguments or the type arguments that are templates.
TemplateDecl *FromTD, *ToTD;
@ -501,6 +504,7 @@ class TemplateDiff {
DiffNode(unsigned ParentNode = 0)
: Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr),
FromNullPtr(false), ToNullPtr(false),
FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false),
IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr),
FromAddressOf(false), ToAddressOf(false), FromDefault(false),
@ -574,6 +578,12 @@ class TemplateDiff {
FlatTree[CurrentNode].Same = Same;
}
/// SetNullPtr - Sets the NullPtr flags of the current node.
void SetNullPtr(bool FromNullPtr, bool ToNullPtr) {
FlatTree[CurrentNode].FromNullPtr = FromNullPtr;
FlatTree[CurrentNode].ToNullPtr = ToNullPtr;
}
/// SetDefault - Sets FromDefault and ToDefault flags of the current node.
void SetDefault(bool FromDefault, bool ToDefault) {
FlatTree[CurrentNode].FromDefault = FromDefault;
@ -696,6 +706,16 @@ class TemplateDiff {
return FlatTree[ReadNode].NextNode != 0;
}
/// FromNullPtr - Returns true if the from argument is null.
bool FromNullPtr() {
return FlatTree[ReadNode].FromNullPtr;
}
/// ToNullPtr - Returns true if the to argument is null.
bool ToNullPtr() {
return FlatTree[ReadNode].ToNullPtr;
}
/// FromDefault - Return true if the from argument is the default.
bool FromDefault() {
return FlatTree[ReadNode].FromDefault;
@ -934,6 +954,10 @@ class TemplateDiff {
bool HasToValueDecl =
!ToIter.isEnd() &&
ToIter->getKind() == TemplateArgument::Declaration;
bool FromNullPtr = !FromIter.isEnd() &&
FromIter->getKind() == TemplateArgument::NullPtr;
bool ToNullPtr =
!ToIter.isEnd() && ToIter->getKind() == TemplateArgument::NullPtr;
assert(((!HasFromInt && !HasToInt) ||
(!HasFromValueDecl && !HasToValueDecl)) &&
@ -943,16 +967,25 @@ class TemplateDiff {
FromInt = FromIter->getAsIntegral();
else if (HasFromValueDecl)
FromValueDecl = FromIter->getAsDecl();
else
else if (!FromNullPtr)
FromExpr = GetExpr(FromIter, DefaultNTTPD);
if (HasToInt)
ToInt = ToIter->getAsIntegral();
else if (HasToValueDecl)
ToValueDecl = ToIter->getAsDecl();
else
else if (!ToNullPtr)
ToExpr = GetExpr(ToIter, DefaultNTTPD);
bool TemplateArgumentIsPointerType =
DefaultNTTPD->getType()->isPointerType();
if (FromExpr && TemplateArgumentIsPointerType) {
FromNullPtr = CheckForNullPtr(FromExpr);
}
if (ToExpr && TemplateArgumentIsPointerType) {
ToNullPtr = CheckForNullPtr(ToExpr);
}
if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
Tree.SetNode(FromExpr, ToExpr);
Tree.SetDefault(FromIter.isEnd() && FromExpr,
@ -972,7 +1005,9 @@ class TemplateDiff {
Tree.SetSame(false);
Tree.SetKind(DiffTree::Integer);
} else {
Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr));
Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) ||
(FromNullPtr && ToNullPtr));
Tree.SetNullPtr(FromNullPtr, ToNullPtr);
Tree.SetKind(DiffTree::Expression);
}
} else if (HasFromInt || HasToInt) {
@ -1020,6 +1055,7 @@ class TemplateDiff {
}
}
}
Tree.SetNullPtr(FromNullPtr, ToNullPtr);
Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
Tree.SetSame(FromValueDecl && ToValueDecl &&
FromValueDecl->getCanonicalDecl() ==
@ -1187,13 +1223,36 @@ class TemplateDiff {
}
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
if (!DRE) {
DRE = cast<DeclRefExpr>(
cast<UnaryOperator>(ArgExpr->IgnoreParens())->getSubExpr());
UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens());
if (!UO)
return nullptr;
DRE = cast<DeclRefExpr>(UO->getSubExpr());
}
return DRE->getDecl();
}
/// CheckForNullPtr - returns true if the expression can be evaluated as
/// a null pointer
bool CheckForNullPtr(Expr *E) {
assert(E && "Expected expression");
E = E->IgnoreParenCasts();
if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
return true;
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE)
return false;
VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
if (!VD || !VD->hasInit())
return false;
return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNull);
}
/// GetTemplateDecl - Retrieves the template template arguments, including
/// default arguments.
TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
@ -1300,8 +1359,8 @@ class TemplateDiff {
case DiffTree::Expression: {
Expr *FromExpr, *ToExpr;
Tree.GetNode(FromExpr, ToExpr);
PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
Tree.NodeIsSame());
PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(),
Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
return;
}
case DiffTree::TemplateTemplate: {
@ -1327,7 +1386,8 @@ class TemplateDiff {
bool FromAddressOf, ToAddressOf;
Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(),
Tree.ToDefault(), Tree.NodeIsSame());
return;
}
case DiffTree::Template: {
@ -1452,36 +1512,41 @@ class TemplateDiff {
/// PrintExpr - Prints out the expr template arguments, highlighting argument
/// differences.
void PrintExpr(const Expr *FromExpr, const Expr *ToExpr,
bool FromDefault, bool ToDefault, bool Same) {
void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr,
bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) {
assert((FromExpr || ToExpr) &&
"Only one template argument may be missing.");
if (Same) {
PrintExpr(FromExpr);
PrintExpr(FromExpr, FromNullPtr);
} else if (!PrintTree) {
OS << (FromDefault ? "(default) " : "");
Bold();
PrintExpr(FromExpr);
PrintExpr(FromExpr, FromNullPtr);
Unbold();
} else {
OS << (FromDefault ? "[(default) " : "[");
Bold();
PrintExpr(FromExpr);
PrintExpr(FromExpr, FromNullPtr);
Unbold();
OS << " != " << (ToDefault ? "(default) " : "");
Bold();
PrintExpr(ToExpr);
PrintExpr(ToExpr, ToNullPtr);
Unbold();
OS << ']';
}
}
/// PrintExpr - Actual formatting and printing of expressions.
void PrintExpr(const Expr *E) {
if (!E)
OS << "(no argument)";
else
void PrintExpr(const Expr *E, bool NullPtr = false) {
if (E) {
E->printPretty(OS, nullptr, Policy);
return;
}
if (NullPtr) {
OS << "nullptr";
return;
}
OS << "(no argument)";
}
/// PrintTemplateTemplate - Handles printing of template template arguments,
@ -1573,35 +1638,46 @@ class TemplateDiff {
return true;
}
void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) {
if (VD) {
if (AddressOf)
OS << "&";
OS << VD->getName();
return;
}
if (NullPtr) {
OS << "nullptr";
return;
}
OS << "(no argument)";
}
/// PrintDecl - Handles printing of Decl arguments, highlighting
/// argument differences.
void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
bool FromAddressOf, bool ToAddressOf, bool FromDefault,
bool ToDefault, bool Same) {
assert((FromValueDecl || ToValueDecl) &&
bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
bool ToNullPtr, bool FromDefault, bool ToDefault,
bool Same) {
assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
"Only one Decl argument may be NULL");
if (Same) {
OS << FromValueDecl->getName();
PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
} else if (!PrintTree) {
OS << (FromDefault ? "(default) " : "");
Bold();
if (FromAddressOf)
OS << "&";
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
Unbold();
} else {
OS << (FromDefault ? "[(default) " : "[");
Bold();
if (FromAddressOf)
OS << "&";
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
Unbold();
OS << " != " << (ToDefault ? "(default) " : "");
Bold();
if (ToAddressOf)
OS << "&";
OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr);
Unbold();
OS << ']';
}

View File

@ -1129,6 +1129,60 @@ Wrapper<S<(&global2)>> W4 = MakeWrapper<S<(&global)>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<&global2>>'
}
namespace NullPtr {
template <int*, int*>
struct S {};
template <class T>
struct Wrapper {};
template <class T>
Wrapper<T> MakeWrapper();
int global, global2;
constexpr int * ptr = nullptr;
constexpr int * ptr2 = static_cast<int*>(0);
S<&global> s1 = S<&global, ptr>();
S<&global, nullptr> s2 = S<&global, ptr>();
S<&global, nullptr> s3 = S<&global, &global>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'S<[...], &global>' to 'S<[...], nullptr>'
S<&global, ptr> s4 = S<&global, &global>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'S<[...], &global>' to 'S<[...], ptr>
Wrapper<S<&global, nullptr>> W1 = MakeWrapper<S<&global, ptr>>();
Wrapper<S<&global, static_cast<int*>(0)>> W2 = MakeWrapper<S<&global, ptr>>();
Wrapper<S<&global, nullptr>> W3 = MakeWrapper<S<&global, &global>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], nullptr>>'
Wrapper<S<&global, ptr>> W4 = MakeWrapper<S<&global, &global>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr>>'
Wrapper<S<&global2, ptr>> W5 = MakeWrapper<S<&global, nullptr>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, nullptr>> W6 = MakeWrapper<S<&global, nullptr>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, ptr2>> W7 = MakeWrapper<S<&global, nullptr>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, nullptr>> W8 = MakeWrapper<S<&global, ptr2>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, ptr>> W9 = MakeWrapper<S<&global, ptr2>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, ptr2>> W10 = MakeWrapper<S<&global, ptr>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, static_cast<int *>(0)>> W11 =
MakeWrapper<S<&global, nullptr>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global2, nullptr>> W12 =
MakeWrapper<S<&global, static_cast<int *>(0)>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
Wrapper<S<&global, &global>> W13 = MakeWrapper<S<&global, ptr>>();
// C HECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], nullptr>>' to 'Wrapper<S<[...], &global>>'
Wrapper<S<&global, ptr>> W14 = MakeWrapper<S<&global, &global>>();
// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr>>'
}
// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.