forked from OSchip/llvm-project
Add support for nullptr template arguments to template type diffing.
llvm-svn: 213840
This commit is contained in:
parent
7fd11896a8
commit
3880089fc7
|
@ -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 << ']';
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue