diff options
-rw-r--r-- | clang/lib/AST/ASTDiagnostic.cpp | 36 | ||||
-rw-r--r-- | clang/test/Misc/diag-template-diffing.cpp | 56 |
2 files changed, 76 insertions, 16 deletions
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 12774c67233..cff92513298 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -473,14 +473,14 @@ class TemplateDiff { /// ShowColor - Diagnostics support color, so bolding will be used. bool ShowColor; - /// FromType - When single type printing is selected, this is the type to be - /// be printed. When tree printing is selected, this type will show up first - /// in the tree. - QualType FromType; + /// FromTemplateType - When single type printing is selected, this is the + /// type to be be printed. When tree printing is selected, this type will + /// show up first in the tree. + QualType FromTemplateType; - /// ToType - The type that FromType is compared to. Only in tree printing - /// will this type be outputed. - QualType ToType; + /// ToTemplateType - The type that FromType is compared to. Only in tree + /// printing will this type be outputed. + QualType ToTemplateType; /// OS - The stream used to construct the output strings. raw_ostream &OS; @@ -704,12 +704,16 @@ class TemplateDiff { /// Up - Changes the node to the parent of the current node. void Up() { + assert(FlatTree[CurrentNode].Kind != Invalid && + "Cannot exit node before setting node information."); CurrentNode = FlatTree[CurrentNode].ParentNode; } /// AddNode - Adds a child node to the current node, then sets that node /// node as the current node. void AddNode() { + assert(FlatTree[CurrentNode].Kind == Template && + "Only Template nodes can have children nodes."); FlatTree.push_back(DiffNode(CurrentNode)); DiffNode &Node = FlatTree[CurrentNode]; if (Node.ChildNode == 0) { @@ -1032,7 +1036,7 @@ class TemplateDiff { // These functions build up the template diff tree, including functions to // retrieve and compare template arguments. - static const TemplateSpecializationType * GetTemplateSpecializationType( + static const TemplateSpecializationType *GetTemplateSpecializationType( ASTContext &Context, QualType Ty) { if (const TemplateSpecializationType *TST = Ty->getAs<TemplateSpecializationType>()) @@ -1507,6 +1511,8 @@ class TemplateDiff { Qualifiers FromQual, ToQual; Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual); + PrintQualifiers(FromQual, ToQual); + if (!Tree.HasChildren()) { // If we're dealing with a template specialization with zero // arguments, there are no children; special-case this. @@ -1514,8 +1520,6 @@ class TemplateDiff { return; } - PrintQualifiers(FromQual, ToQual); - OS << FromTD->getNameAsString() << '<'; Tree.MoveToChild(); unsigned NumElideArgs = 0; @@ -1962,21 +1966,21 @@ public: PrintTree(PrintTree), ShowColor(ShowColor), // When printing a single type, the FromType is the one printed. - FromType(PrintFromType ? FromType : ToType), - ToType(PrintFromType ? ToType : FromType), + FromTemplateType(PrintFromType ? FromType : ToType), + ToTemplateType(PrintFromType ? ToType : FromType), OS(OS), IsBold(false) { } /// DiffTemplate - Start the template type diffing. void DiffTemplate() { - Qualifiers FromQual = FromType.getQualifiers(), - ToQual = ToType.getQualifiers(); + Qualifiers FromQual = FromTemplateType.getQualifiers(), + ToQual = ToTemplateType.getQualifiers(); const TemplateSpecializationType *FromOrigTST = - GetTemplateSpecializationType(Context, FromType); + GetTemplateSpecializationType(Context, FromTemplateType); const TemplateSpecializationType *ToOrigTST = - GetTemplateSpecializationType(Context, ToType); + GetTemplateSpecializationType(Context, ToTemplateType); // Only checking templates. if (!FromOrigTST || !ToOrigTST) diff --git a/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index cf850a5fc05..70d5e7c8709 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/test/Misc/diag-template-diffing.cpp @@ -1371,6 +1371,62 @@ C<int &, x> c2 = C<int>(); // CHECK-ELIDE-TREE: [(default) 11 != x]> } +namespace default_args { + template <int x, int y = 1+1, int z = 2> + class A {}; + + void foo(A<0> &M) { + // CHECK-ELIDE-NOTREE: no viable conversion from 'A<[...], (default) 1 + 1 aka 2, (default) 2>' to 'A<[...], 0, 0>' + A<0, 0, 0> N = M; + + // CHECK-ELIDE-NOTREE: no viable conversion from 'A<[2 * ...], (default) 2>' to 'A<[2 * ...], 0>' + A<0, 2, 0> N2 = M; + } +} + +namespace DefaultNonTypeArgWithDependentType { +// We used to crash diffing integer template arguments when the argument type +// is dependent and default arguments were used. +template <typename SizeType = int, SizeType = 0> struct A {}; +template <typename R = A<>> R bar(); +A<> &foo() { return bar(); } +// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<[2 * ...]>' cannot bind to a temporary of type 'A<[2 * ...]>' +// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A<int, 0>' cannot bind to a temporary of type 'A<int, 0>' +} + +namespace PR24587 { +template <typename T, T v> +struct integral_constant {}; + +auto false_ = integral_constant<bool, false> {}; + +template <typename T> +void f(T, decltype(false_)); + +void run() { + f(1, integral_constant<bool, true>{}); +} +// CHECK-ELIDE-NOTREE: error: no matching function for call to 'f' +// CHECK-ELIDE-NOTREE: note: candidate function [with T = int] not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument +} + +namespace ZeroArgs { +template <int N = 0> class A {}; +template <class T = A<>> class B {}; +A<1> a1 = A<>(); +A<> a2 = A<1>(); +B<> b1 = B<int>(); +B<int> b2 = B<>(); +B<> b3 = B<const A<>>(); +B<const A<>> b4 = B<>(); +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<(default) 0>' to 'A<1>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<1>' to 'A<(default) 0>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int>' to 'B<(default) ZeroArgs::A<0>>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<(default) ZeroArgs::A<0>>' to 'B<int>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<const A<[...]>>' to 'B<A<[...]>>' +// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<A<[...]>>' to 'B<const A<[...]>>' +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. |