/// CompareDiagLists - Compare two diagnostic lists and return the difference /// between them. /// static bool CompareDiagLists(SourceManager &SourceMgr, const_diag_iterator d1_begin, const_diag_iterator d1_end, const_diag_iterator d2_begin, const_diag_iterator d2_end, const char *MsgLeftOnly, const char *MsgRightOnly) { DiagList LeftOnly; DiagList Left(d1_begin, d1_end); DiagList Right(d2_begin, d2_end); for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) { unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first); const std::string &Diag1 = I->second; DiagList::iterator II, IE; for (II = Right.begin(), IE = Right.end(); II != IE; ++II) { unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first); if (LineNo1 != LineNo2) continue; const std::string &Diag2 = II->second; if (Diag2.find(Diag1) != std::string::npos || Diag1.find(Diag2) != std::string::npos) { break; } } if (II == IE) { // Not found. LeftOnly.push_back(*I); } else { // Found. The same cannot be found twice. Right.erase(II); } } // Now all that's left in Right are those that were not matched. return PrintProblem(SourceMgr, LeftOnly.begin(), LeftOnly.end(), MsgLeftOnly) | PrintProblem(SourceMgr, Right.begin(), Right.end(), MsgRightOnly); }
/// FindDiagnostics - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in a diagnostic list. /// static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, DiagList &ExpectedDiags, Preprocessor &PP, SourceLocation Pos, const char *ExpectedStr) { const char *CommentEnd = CommentStart+CommentLen; unsigned ExpectedStrLen = strlen(ExpectedStr); // Find all expected-foo diagnostics in the string and add them to // ExpectedDiags. while (CommentStart != CommentEnd) { CommentStart = std::find(CommentStart, CommentEnd, 'e'); if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return; // If this isn't expected-foo, ignore it. if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) { ++CommentStart; continue; } CommentStart += ExpectedStrLen; // Skip whitespace. while (CommentStart != CommentEnd && isspace(CommentStart[0])) ++CommentStart; // Default, if we find the '{' now, is 1 time. int Times = 1; int Temp = 0; // In extended syntax, there could be a digit now. while (CommentStart != CommentEnd && CommentStart[0] >= '0' && CommentStart[0] <= '9') { Temp *= 10; Temp += CommentStart[0] - '0'; ++CommentStart; } if (Temp > 0) Times = Temp; // Skip whitespace again. while (CommentStart != CommentEnd && isspace(CommentStart[0])) ++CommentStart; // We should have a {{ now. if (CommentEnd-CommentStart < 2 || CommentStart[0] != '{' || CommentStart[1] != '{') { if (std::find(CommentStart, CommentEnd, '{') != CommentEnd) EmitError(PP, Pos, "bogus characters before '{{' in expected string"); else EmitError(PP, Pos, "cannot find start ('{{') of expected string"); return; } CommentStart += 2; // Find the }}. const char *ExpectedEnd = CommentStart; while (1) { ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}'); if (CommentEnd-ExpectedEnd < 2) { EmitError(PP, Pos, "cannot find end ('}}') of expected string"); return; } if (ExpectedEnd[1] == '}') break; ++ExpectedEnd; // Skip over singular }'s } std::string Msg(CommentStart, ExpectedEnd); std::string::size_type FindPos; while ((FindPos = Msg.find("\\n")) != std::string::npos) Msg.replace(FindPos, 2, "\n"); // Add is possibly multiple times. for (int i = 0; i < Times; ++i) ExpectedDiags.push_back(std::make_pair(Pos, Msg)); CommentStart = ExpectedEnd; } }