aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Basic/Diagnostic.cpp28
-rw-r--r--test/Misc/diag-template-diffing.cpp15
2 files changed, 38 insertions, 5 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index f8e2148140..1c8b3728c1 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -726,15 +726,33 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
unsigned ArgNo2 = ArgNo;
DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
- if (Kind == DiagnosticsEngine::ak_qualtype &&
- ModifierIs(Modifier, ModifierLen, "diff")) {
- Kind = DiagnosticsEngine::ak_qualtype_pair;
+ if (ModifierIs(Modifier, ModifierLen, "diff")) {
assert(*DiagStr == ',' && isdigit(*(DiagStr + 1)) &&
"Invalid format for diff modifier");
++DiagStr; // Comma.
ArgNo2 = *DiagStr++ - '0';
- assert(getArgKind(ArgNo2) == DiagnosticsEngine::ak_qualtype &&
- "Second value of type diff must be a qualtype");
+ DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
+ if (Kind == DiagnosticsEngine::ak_qualtype &&
+ Kind2 == DiagnosticsEngine::ak_qualtype)
+ Kind = DiagnosticsEngine::ak_qualtype_pair;
+ else {
+ // %diff only supports QualTypes. For other kinds of arguments,
+ // use the default printing. For example, if the modifier is:
+ // "%diff{compare $ to $|other text}1,2"
+ // treat it as:
+ // "compare %1 to %2"
+ const char *Pipe = ScanFormat(Argument, Argument + ArgumentLen, '|');
+ const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
+ const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
+ const char ArgStr1[] = { '%', '0' + ArgNo };
+ const char ArgStr2[] = { '%', '0' + ArgNo2 };
+ FormatDiagnostic(Argument, FirstDollar, OutStr);
+ FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
+ FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
+ FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
+ FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
+ continue;
+ }
}
switch (Kind) {
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index bb85a45d5d..c158255f80 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -830,6 +830,21 @@ namespace rdar12456626 {
};
}
+namespace PR15023 {
+ // Don't crash when non-QualTypes are passed to a diff modifier.
+ template <typename... Args>
+ void func(void (*func)(Args...), Args...) { }
+
+ void bar(int, int &) {
+ }
+
+ void foo(int x) {
+ func(bar, 1, x)
+ }
+ // CHECK-ELIDE-NOTREE: no matching function for call to 'func'
+ // CHECK-ELIDE-NOTREE: candidate template ignored: deduced conflicting types for parameter 'Args' (<int, int &> vs. <int, int>)
+}
+
// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.