From: Sebastian Redl Date: Sat, 7 Feb 2009 19:52:04 +0000 (+0000) Subject: Make one expected-diag directive match exactly one actual diagnostic. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3cb069213c8502dbb7a67860d40122d869ed8fd6;p=clang Make one expected-diag directive match exactly one actual diagnostic. This uncovers some bugs, so several test cases now fail. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64025 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/DiagChecker.cpp b/Driver/DiagChecker.cpp index 5b1669b18d..346d9e0b06 100644 --- a/Driver/DiagChecker.cpp +++ b/Driver/DiagChecker.cpp @@ -43,6 +43,15 @@ static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){ // // You can place as many diagnostics on one line as you wish. To make the code // more readable, you can use slash-newline to separate out the diagnostics. +// +// The simple syntax above allows each specification to match exactly one error. +// You can use the extended syntax to customize this. The extended syntax is +// "expected- {{diag text}}", where is one of "error", +// "warning" or "note", and is a positive integer. This allows the +// diagnostic to appear as many times as specified. Example: +// +// void f(); // expected-note 2 {{previous declaration is here}} +// /// FindDiagnostics - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in a diagnostic list. @@ -73,6 +82,24 @@ static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, 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] != '{') { @@ -81,7 +108,7 @@ static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, else EmitError(PP, Pos, "cannot find start ('{{') of expected string"); return; - } + } CommentStart += 2; // Find the }}. @@ -103,8 +130,10 @@ static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, 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)); - + // Add is possibly multiple times. + for (int i = 0; i < Times; ++i) + ExpectedDiags.push_back(std::make_pair(Pos, Msg)); + CommentStart = ExpectedEnd; } } @@ -178,31 +207,39 @@ static bool CompareDiagLists(SourceManager &SourceMgr, const_diag_iterator d1_end, const_diag_iterator d2_begin, const_diag_iterator d2_end, - const char *Msg) { - DiagList DiffList; + 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 = d1_begin, E = d1_end; I != E; ++I) { + 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; - bool Found = false; - for (const_diag_iterator II = d2_begin, IE = d2_end; II != IE; ++II) { + 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) { - Found = true; break; } } - - if (!Found) - DiffList.push_back(std::make_pair(I->first, Diag1)); + 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, DiffList.begin(), DiffList.end(), Msg); + return PrintProblem(SourceMgr, LeftOnly.begin(), LeftOnly.end(), MsgLeftOnly) + | PrintProblem(SourceMgr, Right.begin(), Right.end(), MsgRightOnly); } /// CheckResults - This compares the expected results to those that @@ -227,44 +264,27 @@ static bool CheckResults(Preprocessor &PP, // Seen \ Expected - set seen but not expected bool HadProblem = false; - // See if there were errors that were expected but not seen. + // See if there are error mismatches. HadProblem |= CompareDiagLists(SourceMgr, ExpectedErrors.begin(), ExpectedErrors.end(), Diags.err_begin(), Diags.err_end(), - "Errors expected but not seen:"); - - // See if there were errors that were seen but not expected. - HadProblem |= CompareDiagLists(SourceMgr, - Diags.err_begin(), Diags.err_end(), - ExpectedErrors.begin(), ExpectedErrors.end(), + "Errors expected but not seen:", "Errors seen but not expected:"); - // See if there were warnings that were expected but not seen. + // See if there are warning mismatches. HadProblem |= CompareDiagLists(SourceMgr, ExpectedWarnings.begin(), ExpectedWarnings.end(), Diags.warn_begin(), Diags.warn_end(), - "Warnings expected but not seen:"); - - // See if there were warnings that were seen but not expected. - HadProblem |= CompareDiagLists(SourceMgr, - Diags.warn_begin(), Diags.warn_end(), - ExpectedWarnings.begin(), - ExpectedWarnings.end(), + "Warnings expected but not seen:", "Warnings seen but not expected:"); - // See if there were notes that were expected but not seen. + // See if there are note mismatches. HadProblem |= CompareDiagLists(SourceMgr, ExpectedNotes.begin(), ExpectedNotes.end(), Diags.note_begin(), Diags.note_end(), - "Notes expected but not seen:"); - - // See if there were notes that were seen but not expected. - HadProblem |= CompareDiagLists(SourceMgr, - Diags.note_begin(), Diags.note_end(), - ExpectedNotes.begin(), - ExpectedNotes.end(), + "Notes expected but not seen:", "Notes seen but not expected:"); return HadProblem; diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c index 69475b76f6..d35b0acdfe 100644 --- a/test/Sema/array-constraint.c +++ b/test/Sema/array-constraint.c @@ -1,6 +1,6 @@ // RUN: clang -fsyntax-only -verify -pedantic %s -struct s; // expected-note {{forward declaration of 'struct s'}} +struct s; // expected-note 2 {{forward declaration of 'struct s'}} struct s* t (struct s z[]) { // expected-error {{array has incomplete element type}} return z; } diff --git a/test/Sema/flexible-array-init.c b/test/Sema/flexible-array-init.c index 9ef6eb3bc0..99ef66abe9 100644 --- a/test/Sema/flexible-array-init.c +++ b/test/Sema/flexible-array-init.c @@ -12,7 +12,7 @@ void test() { struct foo { int x; - int y[]; // expected-note{{initialized flexible array member 'y' is here}} + int y[]; // expected-note 3 {{initialized flexible array member 'y' is here}} }; struct bar { struct foo z; }; diff --git a/test/Sema/incomplete-decl.c b/test/Sema/incomplete-decl.c index bd603681d6..be52cfd707 100644 --- a/test/Sema/incomplete-decl.c +++ b/test/Sema/incomplete-decl.c @@ -1,6 +1,6 @@ // RUN: clang -fsyntax-only -verify %s -struct foo; // expected-note {{forward declaration of 'struct foo'}} +struct foo; // expected-note 4 {{forward declaration of 'struct foo'}} void b; // expected-error {{variable has incomplete type 'void'}} struct foo f; // expected-error {{variable has incomplete type 'struct foo'}} diff --git a/test/Sema/pointer-addition.c b/test/Sema/pointer-addition.c index 81a1dc06c1..3a924b0082 100644 --- a/test/Sema/pointer-addition.c +++ b/test/Sema/pointer-addition.c @@ -1,6 +1,6 @@ // RUN: clang %s -fsyntax-only -verify -pedantic -typedef struct S S; // expected-note{{forward declaration of 'struct S'}} +typedef struct S S; // expected-note 3 {{forward declaration of 'struct S'}} void a(S* b, void* c) { void (*fp)(int) = 0; b++; // expected-error {{arithmetic on pointer to incomplete type}} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index eb1e095c9c..babb827108 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -20,7 +20,7 @@ void test() { while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{value of type 'struct ' is not contextually convertible to 'bool'}} switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}} - if (int x=0) { // expected-note {{previous definition is here}} + if (int x=0) { // expected-note 2 {{previous definition is here}} int x; // expected-error {{redefinition of 'x'}} } else diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index fbe7de1563..bed526d399 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -15,7 +15,7 @@ struct NonAggregate { }; NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} -NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error{{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} // C++ [dcl.init.aggr]p3 @@ -40,8 +40,8 @@ char cv[4] = { 'a', 's', 'd', 'f', 0 }; // expected-error{{excess elements in ar struct TooFew { int a; char* b; int c; }; TooFew too_few = { 1, "asdf" }; // okay -struct NoDefaultConstructor { // expected-note{{candidate function}} - NoDefaultConstructor(int); // expected-note{{candidate function}} +struct NoDefaultConstructor { // expected-note 5 {{candidate function}} + NoDefaultConstructor(int); // expected-note 5 {{candidate function}} }; struct TooFewError { int a; @@ -53,7 +53,7 @@ TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} TooFewError too_few_okay2[2] = { 1, 1 }; TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} -NoDefaultConstructor too_few_error3[3] = { }; // expected-error{{no matching constructor}} +NoDefaultConstructor too_few_error3[3] = { }; // expected-error 3 {{no matching constructor}} // C++ [dcl.init.aggr]p8 struct Empty { }; diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp index 654f2e41bc..1fa8c3dc2a 100644 --- a/test/SemaCXX/dynamic-cast.cpp +++ b/test/SemaCXX/dynamic-cast.cpp @@ -8,7 +8,7 @@ struct D : private A {}; struct E : A {}; struct F : B, E {}; -struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}} +struct Incomplete; // expected-note 2 {{forward declaration of 'struct Incomplete'}} struct Poly { diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp index 3b65031d9c..9db742e732 100644 --- a/test/SemaCXX/functional-cast.cpp +++ b/test/SemaCXX/functional-cast.cpp @@ -10,8 +10,8 @@ struct InitViaConstructor { // FIXME: error messages for implicitly-declared special member // function candidates are very poor -struct NoValueInit { // expected-note{{candidate function}} - NoValueInit(int i, int j); // expected-note{{candidate function}} +struct NoValueInit { // expected-note 2 {{candidate function}} + NoValueInit(int i, int j); // expected-note 2 {{candidate function}} }; void test_cxx_functional_value_init() { diff --git a/test/SemaCXX/namespace.cpp b/test/SemaCXX/namespace.cpp index 7af25ec35f..ea7737e8a9 100644 --- a/test/SemaCXX/namespace.cpp +++ b/test/SemaCXX/namespace.cpp @@ -1,5 +1,5 @@ // RUN: clang -fsyntax-only -verify %s -namespace A { // expected-note {{previous definition is here}} +namespace A { // expected-note 2 {{previous definition is here}} int A; void f() { A = 0; } } diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index ce96897e1f..5618b47f20 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -5,8 +5,8 @@ struct S // expected-note {{candidate}} { S(int, int, double); // expected-note {{candidate}} - S(double, int); // expected-note {{candidate}} expected-note {{candidate}} - S(float, int); // expected-note {{candidate}} expected-note {{candidate}} + S(double, int); // expected-note 2 {{candidate}} + S(float, int); // expected-note 2 {{candidate}} }; struct T; // expected-note{{forward declaration of 'struct T'}} struct U @@ -18,9 +18,9 @@ struct V : U { }; -void* operator new(size_t); // expected-note {{candidate}} -void* operator new(size_t, int*); // expected-note {{candidate}} -void* operator new(size_t, float*); // expected-note {{candidate}} +void* operator new(size_t); // expected-note 2 {{candidate}} +void* operator new(size_t, int*); // expected-note 3 {{candidate}} +void* operator new(size_t, float*); // expected-note 3 {{candidate}} void good_news() { diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp index 8b7b148b3f..07936e7eec 100644 --- a/test/SemaCXX/overload-member-call.cpp +++ b/test/SemaCXX/overload-member-call.cpp @@ -1,8 +1,8 @@ // RUN: clang -fsyntax-only -verify %s struct X { - int& f(int) const; // expected-note{{candidate function}} - float& f(int); // expected-note{{candidate function}} + int& f(int) const; // expected-note 2 {{candidate function}} + float& f(int); // expected-note 2 {{candidate function}} void test_f(int x) const { int& i = f(x); @@ -12,9 +12,9 @@ struct X { float& f2 = f(x); } - int& g(int) const; // expected-note{{candidate function}} - float& g(int); // expected-note{{candidate function}} - static double& g(double); // expected-note{{candidate function}} + int& g(int) const; // expected-note 2 {{candidate function}} + float& g(int); // expected-note 2 {{candidate function}} + static double& g(double); // expected-note 2 {{candidate function}} void h(int); diff --git a/test/SemaCXX/try-catch.cpp b/test/SemaCXX/try-catch.cpp index 0d72f119df..cb5d0f8454 100644 --- a/test/SemaCXX/try-catch.cpp +++ b/test/SemaCXX/try-catch.cpp @@ -1,6 +1,6 @@ // RUN: clang -fsyntax-only -verify %s -struct A; // expected-note{{forward declaration of 'struct A'}} +struct A; // expected-note 3 {{forward declaration of 'struct A'}} void f() { diff --git a/test/SemaObjC/check-dup-objc-decls-1.m b/test/SemaObjC/check-dup-objc-decls-1.m index fa9b8674be..5498850113 100644 --- a/test/SemaObjC/check-dup-objc-decls-1.m +++ b/test/SemaObjC/check-dup-objc-decls-1.m @@ -18,13 +18,13 @@ typedef int OBJECT; // expected-note {{previous definition is here}} @class OBJECT ; // expected-error {{redefinition of 'OBJECT' as different kind of symbol}} -typedef int Gorf; // expected-note {{previous definition is here}} +typedef int Gorf; // expected-note 2 {{previous definition is here}} @interface Gorf @end // expected-error {{redefinition of 'Gorf' as different kind of symbol}} void Gorf() // expected-error {{redefinition of 'Gorf' as different kind of symbol}} { - int Bar, Foo, FooBar; + int Bar, Foo, FooBar; } @protocol P -im1; @end