VerifyDiagnosticConsumer.h revision 3b81b7d604e851498243ee732dee3babc1cf20d4
1621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie//===- VerifyDiagnosticConsumer.h - Verifying Diagnostic Client -*- C++ -*-===//
281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//                     The LLVM Compiler Infrastructure
481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// This file is distributed under the University of Illinois Open Source
681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// License. See LICENSE.TXT for details.
781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
1081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
1181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
1281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
1381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "clang/Basic/Diagnostic.h"
1481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "llvm/ADT/OwningPtr.h"
154313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose#include "llvm/ADT/STLExtras.h"
164313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose#include <climits>
1781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
1881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbarnamespace clang {
1981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
20d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikieclass DiagnosticsEngine;
2181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbarclass TextDiagnosticBuffer;
2281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
23621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie/// VerifyDiagnosticConsumer - Create a diagnostic client which will use
24621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie/// markers in the input source to check that all the emitted diagnostics match
25621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie/// those expected.
2681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
2781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// USING THE DIAGNOSTIC CHECKER:
2881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
2981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// Indicating that a line expects an error or a warning is simple. Put a
3060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// comment on the line that has the diagnostic, use:
3160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
3260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///     expected-{error,warning,note}
3360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
3481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// to tag if it's an expected error or warning, and place the expected text
3581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// between {{ and }} markers. The full text doesn't have to be included, only
3681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// enough to ensure that the correct diagnostic was emitted.
3781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
3881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// Here's an example:
3981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
40a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// \code
4181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///   int A = B; // expected-error {{use of undeclared identifier 'B'}}
42a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// \endcode
4381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
4481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// You can place as many diagnostics on one line as you wish. To make the code
4581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// more readable, you can use slash-newline to separate out the diagnostics.
4681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
47aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// Alternatively, it is possible to specify the line on which the diagnostic
48aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// should appear by appending "@<line>" to "expected-<type>", for example:
49aa48fe80a1b2000809900a437f0819d929793002Jordan Rose///
503b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \code
51aa48fe80a1b2000809900a437f0819d929793002Jordan Rose///   #warning some text
52aa48fe80a1b2000809900a437f0819d929793002Jordan Rose///   // expected-warning@10 {{some text}}
533b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \endcode
54aa48fe80a1b2000809900a437f0819d929793002Jordan Rose///
55aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// The line number may be absolute (as above), or relative to the current
56aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// line by prefixing the number with either '+' or '-'.
57aa48fe80a1b2000809900a437f0819d929793002Jordan Rose///
5881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// The simple syntax above allows each specification to match exactly one
5981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// error.  You can use the extended syntax to customize this. The extended
60a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of
61a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// "error", "warning" or "note", and \<n> is a positive integer. This allows
62a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// the diagnostic to appear as many times as specified. Example:
6381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
64a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// \code
6581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///   void f(); // expected-note 2 {{previous declaration is here}}
66a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett/// \endcode
6781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
683b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// Where the diagnostic is expected to occur a minimum number of times, this
693b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// can be specified by appending a '+' to the number. Example:
703b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
713b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \code
723b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///   void f(); // expected-note 0+ {{previous declaration is here}}
733b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///   void g(); // expected-note 1+ {{previous declaration is here}}
743b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \endcode
753b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
763b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// In the first example, the diagnostic becomes optional, i.e. it will be
773b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// swallowed if it occurs, but will not generate an error if it does not
783b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// occur.  In the second example, the diagnostic must occur at least once.
793b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// As a short-hand, "one or more" can be specified simply by '+'. Example:
803b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
813b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \code
823b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///   void g(); // expected-note + {{previous declaration is here}}
833b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \endcode
843b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
853b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// A range can also be specified by "<n>-<m>".  Example:
863b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
873b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \code
883b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///   void f(); // expected-note 0-1 {{previous declaration is here}}
893b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// \endcode
903b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
913b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose/// In this example, the diagnostic may appear only once, if at all.
923b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose///
9360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// Regex matching mode may be selected by appending '-re' to type. Example:
9460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
9560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   expected-error-re
9660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
9760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// Examples matching error: "variable has incomplete type 'struct s'"
9860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
9960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error {{variable has incomplete type 'struct s'}}
10060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error {{variable has incomplete type}}
10160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
10260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error-re {{variable has has type 'struct .'}}
10360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error-re {{variable has has type 'struct .*'}}
10460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error-re {{variable has has type 'struct (.*)'}}
10560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///   // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
10660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
107621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikieclass VerifyDiagnosticConsumer: public DiagnosticConsumer {
10881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbarpublic:
1094313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  /// Directive - Abstract class representing a parsed verify directive.
1104313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  ///
1114313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  class Directive {
1124313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  public:
113aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,
114aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                             SourceLocation DiagnosticLoc,
1153b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                             StringRef Text, unsigned Min, unsigned Max);
1164313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  public:
1173b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    /// Constant representing n or more matches.
1183b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    static const unsigned MaxCount = UINT_MAX;
1194313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
120aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    SourceLocation DirectiveLoc;
121aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    SourceLocation DiagnosticLoc;
1224313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    const std::string Text;
1233b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    unsigned Min, Max;
1244313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1254313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    virtual ~Directive() { }
1264313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1274313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    // Returns true if directive text is valid.
1284313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    // Otherwise returns false and populates E.
1294313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    virtual bool isValid(std::string &Error) = 0;
1304313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1314313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    // Returns true on match.
1324313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    virtual bool match(StringRef S) = 0;
1334313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1344313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  protected:
135aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
1363b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose              StringRef Text, unsigned Min, unsigned Max)
137aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
1383b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        Text(Text), Min(Min), Max(Max) {
1393b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
1403b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
1413b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    }
1424313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1434313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  private:
1444313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    Directive(const Directive&); // DO NOT IMPLEMENT
1454313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    void operator=(const Directive&); // DO NOT IMPLEMENT
1464313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  };
1474313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1484313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  typedef std::vector<Directive*> DirectiveList;
1494313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1504313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  /// ExpectedData - owns directive objects and deletes on destructor.
1514313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  ///
1524313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  struct ExpectedData {
1534313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    DirectiveList Errors;
1544313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    DirectiveList Warnings;
1554313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    DirectiveList Notes;
1564313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1574313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    ~ExpectedData() {
1584313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      llvm::DeleteContainerPointers(Errors);
1594313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      llvm::DeleteContainerPointers(Warnings);
1604313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      llvm::DeleteContainerPointers(Notes);
1614313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    }
1624313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  };
1634313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose
1644313c013c658f6c97e6460e7780c26faa6b78d9aJordan Roseprivate:
165d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diags;
16678ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *PrimaryClient;
16778243658c533168d51fd076fba328437932ba6f1Douglas Gregor  bool OwnsPrimaryClient;
1686f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<TextDiagnosticBuffer> Buffer;
16981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Preprocessor *CurrentPreprocessor;
1704313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  ExpectedData ED;
17101231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  FileID FirstErrorFID; // FileID of first diagnostic
17281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  void CheckDiagnostics();
17381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
17481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbarpublic:
175a6366f5c7e92466ebad0042afa55c2e5952ebe61James Dennett  /// Create a new verifying diagnostic client, which will issue errors to
17678243658c533168d51fd076fba328437932ba6f1Douglas Gregor  /// the currently-attached diagnostic client when a diagnostic does not match
17778243658c533168d51fd076fba328437932ba6f1Douglas Gregor  /// what is expected (as indicated in the source file).
178621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie  VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
179621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie  ~VerifyDiagnosticConsumer();
18081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
18181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  virtual void BeginSourceFile(const LangOptions &LangOpts,
18281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar                               const Preprocessor *PP);
18381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
18481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  virtual void EndSourceFile();
185221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar
186d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
18740847cfb58acc3cac7d68727df9455ac45f2e118David Blaikie                                const Diagnostic &Info);
188aee526e77657afd1600276450e9c346953ad51d7Douglas Gregor
189aee526e77657afd1600276450e9c346953ad51d7Douglas Gregor  virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const;
19081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar};
19181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
19281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar} // end namspace clang
19381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
19481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#endif
195