[cfe-commits] r93447 - /cfe/trunk/lib/Basic/Diagnostic.cpp
John McCall
rjmccall at apple.com
Thu Jan 14 12:11:40 PST 2010
Author: rjmccall
Date: Thu Jan 14 14:11:39 2010
New Revision: 93447
URL: http://llvm.org/viewvc/llvm-project?rev=93447&view=rev
Log:
Pre-emptive bugfixes in the diagnostics code: allow arbitrary punctuation
characters to be escaped and implement a scan-forward function which
properly respects brace nesting.
Modified:
cfe/trunk/lib/Basic/Diagnostic.cpp
Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=93447&r1=93446&r2=93447&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Thu Jan 14 14:11:39 2010
@@ -541,6 +541,33 @@
return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
}
+/// ScanForward - Scans forward, looking for the given character, skipping
+/// nested clauses and escaped characters.
+static const char *ScanFormat(const char *I, const char *E, char Target) {
+ unsigned Depth = 0;
+
+ for ( ; I != E; ++I) {
+ if (Depth == 0 && *I == Target) return I;
+ if (Depth != 0 && *I == '}') Depth--;
+
+ if (*I == '%') {
+ I++;
+ if (I == E) break;
+
+ // Escaped characters get implicitly skipped here.
+
+ // Format specifier.
+ if (!isdigit(*I) && !ispunct(*I)) {
+ for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ;
+ if (I == E) break;
+ if (*I == '{')
+ Depth++;
+ }
+ }
+ }
+ return E;
+}
+
/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
/// like this: %select{foo|bar|baz}2. This means that the integer argument
/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
@@ -553,7 +580,7 @@
// Skip over 'ValNo' |'s.
while (ValNo) {
- const char *NextVal = std::find(Argument, ArgumentEnd, '|');
+ const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
" larger than the number of options in the diagnostic string!");
Argument = NextVal+1; // Skip this string.
@@ -561,7 +588,7 @@
}
// Get the end of the value. This is either the } or the |.
- const char *EndPtr = std::find(Argument, ArgumentEnd, '|');
+ const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
// Recursively format the result of the select clause into the output string.
DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
@@ -717,11 +744,11 @@
}
if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
Argument = ExprEnd + 1;
- ExprEnd = std::find(Argument, ArgumentEnd, '|');
+ ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
OutStr.append(Argument, ExprEnd);
return;
}
- Argument = std::find(Argument, ArgumentEnd - 1, '|') + 1;
+ Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
}
}
@@ -754,8 +781,8 @@
OutStr.append(DiagStr, StrEnd);
DiagStr = StrEnd;
continue;
- } else if (DiagStr[1] == '%') {
- OutStr.push_back('%'); // %% -> %.
+ } else if (ispunct(DiagStr[1])) {
+ OutStr.push_back(DiagStr[1]); // %% -> %.
DiagStr += 2;
continue;
}
@@ -784,8 +811,8 @@
++DiagStr; // Skip {.
Argument = DiagStr;
- for (; DiagStr[0] != '}'; ++DiagStr)
- assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!");
+ DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
+ assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
ArgumentLen = DiagStr-Argument;
++DiagStr; // Skip }.
}
More information about the cfe-commits
mailing list