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