From 3c88301b551add30e9a4b59af325534643dc4b21 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Fri, 28 Sep 2012 20:32:51 +0000 Subject: [PATCH] Update template type diffing to handle qualifiers. Differing qualifiers will now be printed with highlighting. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164843 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTDiagnostic.cpp | 103 ++++++++++++ test/Misc/diag-template-diffing-color.cpp | 53 +++++++ test/Misc/diag-template-diffing.cpp | 185 ++++++++++++++++++++++ 3 files changed, 341 insertions(+) diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 8a7dba76c4..7018ba9c2d 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -430,6 +430,9 @@ class TemplateDiff { /// arguments or the type arguments that are templates. TemplateDecl *FromTD, *ToTD; + /// FromQual, ToQual - Qualifiers for template types. + Qualifiers FromQual, ToQual; + /// FromDefault, ToDefault - Whether the argument is a default argument. bool FromDefault, ToDefault; @@ -480,6 +483,12 @@ class TemplateDiff { FlatTree[CurrentNode].ToExpr = ToExpr; } + /// SetNode - Set FromQual and ToQual of the current node. + void SetNode(Qualifiers FromQual, Qualifiers ToQual) { + FlatTree[CurrentNode].FromQual = FromQual; + FlatTree[CurrentNode].ToQual = ToQual; + } + /// SetSame - Sets the same flag of the current node. void SetSame(bool Same) { FlatTree[CurrentNode].Same = Same; @@ -575,6 +584,12 @@ class TemplateDiff { ToTD = FlatTree[ReadNode].ToTD; } + /// GetNode - Gets the FromQual and ToQual. + void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) { + FromQual = FlatTree[ReadNode].FromQual; + ToQual = FlatTree[ReadNode].ToQual; + } + /// NodeIsSame - Returns true the arguments are the same. bool NodeIsSame() { return FlatTree[ReadNode].Same; @@ -778,6 +793,8 @@ class TemplateDiff { if (Context.hasSameType(FromType, ToType)) { Tree.SetSame(true); } else { + Qualifiers FromQual = FromType.getQualifiers(), + ToQual = ToType.getQualifiers(); const TemplateSpecializationType *FromArgTST = GetTemplateSpecializationType(Context, FromType); const TemplateSpecializationType *ToArgTST = @@ -785,8 +802,11 @@ class TemplateDiff { if (FromArgTST && ToArgTST && hasSameTemplate(FromArgTST, ToArgTST)) { + FromQual -= QualType(FromArgTST, 0).getQualifiers(); + ToQual -= QualType(ToArgTST, 0).getQualifiers(); Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), ToArgTST->getTemplateName().getAsTemplateDecl()); + Tree.SetNode(FromQual, ToQual); DiffTemplate(FromArgTST, ToArgTST); } } @@ -1027,6 +1047,10 @@ class TemplateDiff { assert(Tree.HasChildren() && "Template difference not found in diff tree."); + Qualifiers FromQual, ToQual; + Tree.GetNode(FromQual, ToQual); + PrintQualifiers(FromQual, ToQual); + OS << FromTD->getNameAsString() << '<'; Tree.MoveToChild(); unsigned NumElideArgs = 0; @@ -1088,6 +1112,17 @@ class TemplateDiff { return; } + if (!FromType.isNull() && !ToType.isNull() && + FromType.getLocalUnqualifiedType() == + ToType.getLocalUnqualifiedType()) { + Qualifiers FromQual = FromType.getLocalQualifiers(), + ToQual = ToType.getLocalQualifiers(), + CommonQual; + PrintQualifiers(FromQual, ToQual); + FromType.getLocalUnqualifiedType().print(OS, Policy); + return; + } + std::string FromTypeStr = FromType.isNull() ? "(no argument)" : FromType.getAsString(); std::string ToTypeStr = ToType.isNull() ? "(no argument)" @@ -1191,6 +1226,68 @@ class TemplateDiff { OS << "[" << NumElideArgs << " * ...]"; } + // Prints and highlights differences in Qualifiers. + void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) { + // Both types have no qualifiers + if (FromQual.empty() && ToQual.empty()) + return; + + // Both types have same qualifiers + if (FromQual == ToQual) { + PrintQualifier(FromQual, /*ApplyBold*/false); + return; + } + + // Find common qualifiers and strip them from FromQual and ToQual. + Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual, + ToQual); + + // The qualifiers are printed before the template name. + // Inline printing: + // The common qualifiers are printed. Then, qualifiers only in this type + // are printed and highlighted. Finally, qualifiers only in the other + // type are printed and highlighted inside parentheses after "missing". + // Tree printing: + // Qualifiers are printed next to each other, inside brackets, and + // separated by "!=". The printing order is: + // common qualifiers, highlighted from qualifiers, "!=", + // common qualifiers, highlighted to qualifiers + if (PrintTree) { + OS << "["; + if (CommonQual.empty() && FromQual.empty()) { + Bold(); + OS << "(no qualifiers) "; + Unbold(); + } else { + PrintQualifier(CommonQual, /*ApplyBold*/false); + PrintQualifier(FromQual, /*ApplyBold*/true); + } + OS << "!= "; + if (CommonQual.empty() && ToQual.empty()) { + Bold(); + OS << "(no qualifiers)"; + Unbold(); + } else { + PrintQualifier(CommonQual, /*ApplyBold*/false, + /*appendSpaceIfNonEmpty*/!ToQual.empty()); + PrintQualifier(ToQual, /*ApplyBold*/true, + /*appendSpaceIfNonEmpty*/false); + } + OS << "] "; + } else { + PrintQualifier(CommonQual, /*ApplyBold*/false); + PrintQualifier(FromQual, /*ApplyBold*/true); + } + } + + void PrintQualifier(Qualifiers Q, bool ApplyBold, + bool AppendSpaceIfNonEmpty = true) { + if (Q.empty()) return; + if (ApplyBold) Bold(); + Q.print(OS, Policy, AppendSpaceIfNonEmpty); + if (ApplyBold) Unbold(); + } + public: TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType, @@ -1210,6 +1307,9 @@ public: /// DiffTemplate - Start the template type diffing. void DiffTemplate() { + Qualifiers FromQual = FromType.getQualifiers(), + ToQual = ToType.getQualifiers(); + const TemplateSpecializationType *FromOrigTST = GetTemplateSpecializationType(Context, FromType); const TemplateSpecializationType *ToOrigTST = @@ -1224,7 +1324,10 @@ public: return; } + FromQual -= QualType(FromOrigTST, 0).getQualifiers(); + ToQual -= QualType(ToOrigTST, 0).getQualifiers(); Tree.SetNode(FromType, ToType); + Tree.SetNode(FromQual, ToQual); // Same base template, but different arguments. Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), diff --git a/test/Misc/diag-template-diffing-color.cpp b/test/Misc/diag-template-diffing-color.cpp index 6903e848d3..cfa1a681e1 100644 --- a/test/Misc/diag-template-diffing-color.cpp +++ b/test/Misc/diag-template-diffing-color.cpp @@ -17,3 +17,56 @@ foo &B = A; // TREE: non-const lvalue reference cannot bind to a value of unrelated type // TREE: foo< // TREE: [{{.}}[0;1;36mdouble{{.}}[0m{{.}}[1m != {{.}}[0;1;36mint{{.}}[0m{{.}}[1m]>{{.}}[0m + +template class vector {}; + +void set15(vector >) {} +void test15() { + set15(vector >()); +} +// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// TREE: {{.*}}candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// TREE: vector< +// TREE: const vector< +// TREE: [{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}!= {{.}}[0;1;36m(no qualifiers){{.}}[0m] int>> + +void set16(vector >) {} +void test16() { + set16(vector >()); +} +// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}vector<[...]>>' to 'vector>' for 1st argument +// TREE: {{.*}}candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// TREE: vector< +// TREE: [{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}!= {{.}}[0;1;36m(no qualifiers){{ ?.}}[0m]{{ ?}}vector< +// TREE: [...]>> + +void set17(vector >) {} +void test17() { + set17(vector >()); +} +// CHECK: candidate function not viable: no known conversion from 'vector>' to 'vector<{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}vector<[...]>>' for 1st argument +// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// TREE: vector< +// TREE: [{{.}}[0;1;36m(no qualifiers){{ ?.}}[0m{{ ?}}!= {{.}}[0;1;36mconst{{.}}[0m] vector< +// TREE: [...]>> + +void set18(vector >) {} +void test18() { + set18(vector >()); +} +// CHECK: candidate function not viable: no known conversion from 'vector<{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}vector<[...]>>' to 'vector<{{.}}[0;1;36mvolatile{{ ?.}}[0m{{ ?}}vector<[...]>>' for 1st argument +// TREE: no matching function for call to 'set18' +// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// TREE: vector< +// TREE: [{{.}}[0;1;36mconst{{ ?.}}[0m{{ ?}}!= {{.}}[0;1;36mvolatile{{.}}[0m] vector< +// TREE: [...]>> + +void set19(vector >) {} +void test19() { + set19(vector >()); +} +// CHECK: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// TREE: vector< +// TREE: [const != const {{.}}[0;1;36mvolatile{{.}}[0m] vector< +// TREE: [...]>> diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index 24563e3ec8..e4b074ae7e 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -445,6 +445,191 @@ int k14 = f14(a14()); // CHECK-NOELIDE-TREE: a14< // CHECK-NOELIDE-TREE: [char != int]> +void set15(vector>) {} +void test15() { + set15(vector>()); +} +// CHECK-ELIDE-NOTREE-NOT: set15 +// CHECK-NOELIDE-NOTREE-NOT: set15 +// CHECK-ELIDE-TREE-NOT: set15 +// CHECK-NOELIDE-TREE-NOT: set15 +// no error here + +void set16(vector>) {} +void test16() { + set16(vector>()); +} +// CHECK-ELIDE-NOTREE: no matching function for call to 'set16' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'set16' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'set16' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: const vector< +// CHECK-ELIDE-TREE: [const != (no qualifiers)] int>> +// CHECK-NOELIDE-TREE: no matching function for call to 'set16' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: const vector< +// CHECK-NOELIDE-TREE: [const != (no qualifiers)] int>> + +void set17(vector>) {} +void test17() { + set17(vector>()); +} +// CHECK-ELIDE-NOTREE: no matching function for call to 'set17' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'set17' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'set17' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [const != (no qualifiers)] vector< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'set17' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [const != (no qualifiers)] vector< +// CHECK-NOELIDE-TREE: int>> + +void set18(vector>) {} +void test18() { + set18(vector>()); +} +// CHECK-ELIDE-NOTREE: no matching function for call to 'set18' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'set18' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'set18' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [(no qualifiers) != const] vector< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'set18' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [(no qualifiers) != const] vector< +// CHECK-NOELIDE-TREE: int>> + +void set19(vector>) {} +void test19() { + set19(vector>()); +} +// CHECK-ELIDE-NOTREE: no matching function for call to 'set19' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'set19' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'set19' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [const != volatile] vector< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'set19' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [const != volatile] vector< +// CHECK-NOELIDE-TREE: int>> + +void set20(vector>) {} +void test20() { + set20(vector>()); +} +// CHECK-ELIDE-NOTREE: no matching function for call to 'set20' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'set20' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'set20' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [const != const volatile] vector< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'set20' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [const != const volatile] vector< +// CHECK-NOELIDE-TREE: int>> + + +// Checks that volatile does not show up in diagnostics. +template struct S21 {}; +template using U21 = volatile S21; +int f21(vector>); +int k21 = f21(vector>()); +// CHECK-ELIDE-NOTREE: no matching function for call to 'f21' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'f21' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'f21' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [(no qualifiers) != const] U21< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'f21' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [(no qualifiers) != const] U21< +// CHECK-NOELIDE-TREE: int>> + +// Checks that volatile does not show up in diagnostics. +template struct S22 {}; +template using U22 = volatile S22; +int f22(vector>); +int k22 = f22(vector>()); +// CHECK-ELIDE-NOTREE: no matching function for call to 'f22' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'f22' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector>' to 'vector>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'f22' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: vector< +// CHECK-ELIDE-TREE: [(no qualifiers) != const] U22< +// CHECK-ELIDE-TREE: [...]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'f22' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: vector< +// CHECK-NOELIDE-TREE: [(no qualifiers) != const] U22< +// CHECK-NOELIDE-TREE: int>> + +// Testing qualifiers and typedefs. +template struct D23{}; +template using C23 = D23; +typedef const C23 B23; +template using A23 = B23; + +void foo23(D23> b) {} +void test23() { + foo23(D23>()); + foo23(C23()); +} + +// CHECK-ELIDE-NOTREE: no matching function for call to 'foo23' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'D23>' to 'D23>' for 1st argument +// CHECK-ELIDE-NOTREE: no matching function for call to 'foo23' +// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'D23' to 'D23>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'foo23' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'D23>' to 'D23>' for 1st argument +// CHECK-NOELIDE-NOTREE: no matching function for call to 'foo23' +// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'D23' to 'D23>' for 1st argument +// CHECK-ELIDE-TREE: no matching function for call to 'foo23' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: D23< +// CHECK-ELIDE-TREE: [(no qualifiers) != const] D23< +// CHECK-ELIDE-TREE: [char != int]>> +// CHECK-ELIDE-TREE: no matching function for call to 'foo23' +// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-ELIDE-TREE: D23< +// CHECK-ELIDE-TREE: [char != A23<>]> +// CHECK-NOELIDE-TREE: no matching function for call to 'foo23' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: D23< +// CHECK-NOELIDE-TREE: [(no qualifiers) != const] D23< +// CHECK-NOELIDE-TREE: [char != int]>> +// CHECK-NOELIDE-TREE: no matching function for call to 'foo23' +// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument +// CHECK-NOELIDE-TREE: D23< +// CHECK-NOELIDE-TREE: [char != A23<>]> + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. -- 2.40.0