diff options
author | Bill Wendling <isanbard@gmail.com> | 2014-08-04 04:35:31 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2014-08-04 04:35:31 +0000 |
commit | 009ef32ff23d521ab793d8bad10fb1a250451176 (patch) | |
tree | 0b5c2a4d990ddee5f2afd50f030755880fcd663f /clang | |
parent | 3869e6a78950823e8a162fdfe7f0f947d3ea0428 (diff) | |
download | llvm-009ef32ff23d521ab793d8bad10fb1a250451176.zip llvm-009ef32ff23d521ab793d8bad10fb1a250451176.tar.gz llvm-009ef32ff23d521ab793d8bad10fb1a250451176.tar.bz2 |
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.
------------------------------------------------------------------------
llvm-svn: 214693
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ASTDiagnostic.cpp | 138 | ||||
-rw-r--r-- | clang/test/Misc/diag-template-diffing.cpp | 54 |
2 files changed, 161 insertions, 31 deletions
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 5f78df2..5e6acf8 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/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/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index fcafb332..55ffb19 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/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. |