From 0947b4e6c778ca94bbd0a56548de0b6b5ff1dfc9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 24 Nov 2008 01:28:17 +0000 Subject: [PATCH] Rewrite FindDiagnostics to be more strict about the formatting of the expected-foo strings. Now the only allowed characters between expected-error and {{ is whitespace. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59925 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/DiagChecker.cpp | 88 +++++++++++++++++++++++------------- test/Analysis/CheckNSError.m | 8 ++-- test/Sema/decl-invalid.c | 4 +- test/Sema/vla.c | 2 +- test/SemaObjC/string.m | 2 +- 5 files changed, 64 insertions(+), 40 deletions(-) diff --git a/Driver/DiagChecker.cpp b/Driver/DiagChecker.cpp index 4c0aa4c6e9..6f4cd7c509 100644 --- a/Driver/DiagChecker.cpp +++ b/Driver/DiagChecker.cpp @@ -47,43 +47,65 @@ static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){ /// 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 std::string &Comment, +static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, DiagList &ExpectedDiags, - Preprocessor &PP, - SourceLocation Pos, - const char * const ExpectedStr) { - SourceManager &SourceMgr = PP.getSourceManager(); + Preprocessor &PP, SourceLocation Pos, + const char *ExpectedStr) { + const char *CommentEnd = CommentStart+CommentLen; + unsigned ExpectedStrLen = strlen(ExpectedStr); - // Find all expected diagnostics. - typedef std::string::size_type size_type; - size_type ColNo = 0; - - for (;;) { - ColNo = Comment.find(ExpectedStr, ColNo); - if (ColNo == std::string::npos) break; - - size_type OpenDiag = Comment.find("{{", ColNo); - - if (OpenDiag == std::string::npos) { - EmitError(PP, Pos, - "cannot find start ('{{') of expected diagnostic string"); + // 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; + + // 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 } - OpenDiag += 2; - size_type CloseDiag = Comment.find("}}", OpenDiag); - - if (CloseDiag == std::string::npos) { - EmitError(PP, Pos,"cannot find end ('}}') of expected diagnostic string"); - return; - } - - std::string Msg(Comment.substr(OpenDiag, CloseDiag - OpenDiag)); - size_type FindPos; + std::string Msg(CommentStart, ExpectedEnd); + std::string::size_type FindPos; while ((FindPos = Msg.find("\\n")) != std::string::npos) Msg.replace(FindPos, 2, "\n"); ExpectedDiags.push_back(std::make_pair(Pos, Msg)); - ColNo = CloseDiag + 2; + + CommentStart = ExpectedEnd; } } @@ -113,17 +135,19 @@ static void FindExpectedDiags(Preprocessor &PP, if (!Tok.is(tok::comment)) continue; std::string Comment = PP.getSpelling(Tok); + if (Comment.empty()) continue; + // Find all expected errors. - FindDiagnostics(Comment, ExpectedErrors, PP, + FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP, Tok.getLocation(), "expected-error"); // Find all expected warnings. - FindDiagnostics(Comment, ExpectedWarnings, PP, + FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP, Tok.getLocation(), "expected-warning"); // Find all expected notes. - FindDiagnostics(Comment, ExpectedNotes, PP, + FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP, Tok.getLocation(), "expected-note"); }; } diff --git a/test/Analysis/CheckNSError.m b/test/Analysis/CheckNSError.m index c6d846ef44..241c68cd85 100644 --- a/test/Analysis/CheckNSError.m +++ b/test/Analysis/CheckNSError.m @@ -20,8 +20,8 @@ extern NSString * const NSXMLParserErrorDomain ; @end @implementation A -- (void)myMethodWhichMayFail:(NSError **)error { // expected-warning: {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occured.}} - *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning: {{Potential null dereference.}} +- (void)myMethodWhichMayFail:(NSError **)error { // expected-warning {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occured.}} + *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference.}} } - (BOOL)myMethodWhichMayFail2:(NSError **)error { // no-warning @@ -33,8 +33,8 @@ extern NSString * const NSXMLParserErrorDomain ; struct __CFError {}; typedef struct __CFError* CFErrorRef; -void foo(CFErrorRef* error) { // expected-warning{{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occured.}} - *error = 0; // expected-warning{{Potential null dereference.}} +void foo(CFErrorRef* error) { // expected-warning {{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occured.}} + *error = 0; // expected-warning {{Potential null dereference.}} } int bar(CFErrorRef* error) { diff --git a/test/Sema/decl-invalid.c b/test/Sema/decl-invalid.c index b92146260e..767d6e6ab4 100644 --- a/test/Sema/decl-invalid.c +++ b/test/Sema/decl-invalid.c @@ -1,11 +1,11 @@ // RUN: clang %s -fsyntax-only -verify -typedef union __mbstate_t; // expected-error: {{declaration of anonymous union must be a definition}} +typedef union __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} // PR2017 void x(); int a() { - int r[x()]; // expected-error: {{size of array has non-integer type 'void'}} + int r[x()]; // expected-error {{size of array has non-integer type 'void'}} } diff --git a/test/Sema/vla.c b/test/Sema/vla.c index cd57eac9a4..682d2fb266 100644 --- a/test/Sema/vla.c +++ b/test/Sema/vla.c @@ -14,5 +14,5 @@ void f (unsigned int m) } // PR3048 -int x = sizeof(struct{char qq[x];}); // expected-error {{fields must have a constant size} +int x = sizeof(struct{char qq[x];}); // expected-error {{fields must have a constant size}} diff --git a/test/SemaObjC/string.m b/test/SemaObjC/string.m index e3974ad8f6..e14d3b15c1 100644 --- a/test/SemaObjC/string.m +++ b/test/SemaObjC/string.m @@ -11,5 +11,5 @@ id s = @"123"; // simple id t = @"123" @"456"; // concat -id u = @"123" @ blah; // expected-error: {{unexpected token}} +id u = @"123" @ blah; // expected-error {{unexpected token}}