summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2014-08-04 04:35:31 +0000
committerBill Wendling <isanbard@gmail.com>2014-08-04 04:35:31 +0000
commit3e91ed59516f8ccd6478346be9319baf8a843c17 (patch)
tree9a57c820e003129e357ee94cce12dd99f901e413
parent24816d294452aa017014a0f215333b45a6b49cbc (diff)
Merging r213840:
------------------------------------------------------------------------ r213840 | rtrieu | 2014-07-23 21:24:50 -0700 (Wed, 23 Jul 2014) | 2 lines Add support for nullptr template arguments to template type diffing. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_35@214693 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTDiagnostic.cpp138
-rw-r--r--test/Misc/diag-template-diffing.cpp54
2 files changed, 161 insertions, 31 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 5f78df2c47..5e6acf8e97 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -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 << ']';
}
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index fcafb33256..55ffb19c33 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -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.