Handle passing non-Qualtypes to %diff better. Instead of asserting, fall back
authorRichard Trieu <rtrieu@google.com>
Wed, 30 Jan 2013 20:04:31 +0000 (20:04 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 30 Jan 2013 20:04:31 +0000 (20:04 +0000)
to printing the default case.  This is a fix for PR15023.

llvm-svn: 173965

clang/lib/Basic/Diagnostic.cpp
clang/test/Misc/diag-template-diffing.cpp

index f8e2148..1c8b372 100644 (file)
@@ -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) {
index bb85a45..c158255 100644 (file)
@@ -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.