Diagnostic.cpp revision 9e2dac9c9b6bc4384c816a447cca6516a03c89f2
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the Diagnostic-related interfaces. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/Diagnostic.h" 1527ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 1627ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Lex/LexDiagnostic.h" 1727ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Parse/ParseDiagnostic.h" 1827ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/AST/ASTDiagnostic.h" 1927ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Sema/SemaDiagnostic.h" 2027ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Frontend/FrontendDiagnostic.h" 2127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Analysis/AnalysisDiagnostic.h" 2227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Driver/DriverDiagnostic.h" 2327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 24d93256e55673a17d18543397ec462416acb13792Douglas Gregor#include "clang/Basic/FileManager.h" 2543b628cd47ecdc3caf640d79b3ad7ecef0f2c285Chris Lattner#include "clang/Basic/IdentifierTable.h" 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/SourceLocation.h" 27d93256e55673a17d18543397ec462416acb13792Douglas Gregor#include "clang/Basic/SourceManager.h" 28f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner#include "llvm/ADT/SmallVector.h" 2930bc96544346bea42921cf6837e66cef80d664b4Chris Lattner#include "llvm/ADT/StringExtras.h" 3023e47c6b6e8ccdd8daa378ab2a879644425c72d8Daniel Dunbar#include "llvm/Support/raw_ostream.h" 31182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner#include <vector> 32182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner#include <map> 3387cf5ac1b046a1db874b77dcb6e35f9c4b88c386Chris Lattner#include <cstring> 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 36182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 37182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner// Builtin Diagnostic information 38182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 39182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 40121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner// Diagnostic classes. 41121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattnerenum { 42121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner CLASS_NOTE = 0x01, 43121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner CLASS_WARNING = 0x02, 44121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner CLASS_EXTENSION = 0x03, 45121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner CLASS_ERROR = 0x04 46121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner}; 4727ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 4833dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattnerstruct StaticDiagInfoRec { 49121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner unsigned short DiagID; 50121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner unsigned Mapping : 3; 51121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner unsigned Class : 3; 525e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor bool SFINAE : 1; 53121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner const char *Description; 5433dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner const char *OptionGroup; 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5687d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner bool operator<(const StaticDiagInfoRec &RHS) const { 5787d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner return DiagID < RHS.DiagID; 5887d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner } 5987d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner bool operator>(const StaticDiagInfoRec &RHS) const { 6087d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner return DiagID > RHS.DiagID; 6187d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner } 6227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner}; 6327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 6433dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattnerstatic const StaticDiagInfoRec StaticDiagInfo[] = { 655e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) \ 665e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP }, 6727ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticCommonKinds.inc" 6827ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticDriverKinds.inc" 6927ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticFrontendKinds.inc" 7027ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticLexKinds.inc" 7127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticParseKinds.inc" 7227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticASTKinds.inc" 7327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticSemaKinds.inc" 7427ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner#include "clang/Basic/DiagnosticAnalysisKinds.inc" 755e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor { 0, 0, 0, 0, 0, 0} 7627ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner}; 778a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner#undef DIAG 7827ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 7987d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 8087d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner/// or null if the ID is invalid. 8133dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattnerstatic const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 8287d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1; 8387d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner 8487d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner // If assertions are enabled, verify that the StaticDiagInfo array is sorted. 8587d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner#ifndef NDEBUG 8687d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner static bool IsFirst = true; 8787d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner if (IsFirst) { 885a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner for (unsigned i = 1; i != NumDiagEntries; ++i) { 895a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID && 905a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner "Diag ID conflict, the enums at the start of clang::diag (in " 915a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner "Diagnostic.h) probably need to be increased"); 925a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner 9387d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] && 9487d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner "Improperly sorted diag info"); 955a3ce9b10c164d9bf75a70d429e55d4e171a9a9eChris Lattner } 9687d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner IsFirst = false; 9787d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner } 9887d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner#endif 991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10087d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner // Search the diagnostic table with a binary search. 1015e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 }; 1021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10387d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner const StaticDiagInfoRec *Found = 10487d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); 10587d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner if (Found == StaticDiagInfo + NumDiagEntries || 10687d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner Found->DiagID != DiagID) 10787d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner return 0; 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10987d854ebedb43a9ff0f55591821dc5600984e479Chris Lattner return Found; 11033dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner} 11133dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner 11233dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattnerstatic unsigned GetDefaultDiagMapping(unsigned DiagID) { 11333dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 114121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner return Info->Mapping; 115691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner return diag::MAP_FATAL; 116691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner} 117691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner 118d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattner/// getWarningOptionForDiag - Return the lowest-level warning option that 119d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattner/// enables the specified diagnostic. If there is no -Wfoo flag that controls 120d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattner/// the diagnostic, this returns null. 121d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattnerconst char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) { 12233dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 12333dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner return Info->OptionGroup; 12433dd2822f3972afe99b61315a890f8bad8ee5d7fChris Lattner return 0; 125d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattner} 126d51d74a3e89c5e5fc9bfd2814996a5feab6dc932Chris Lattner 1275e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregorbool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) { 1285e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 1298439fac3ce6c26db7982e34d119bf905b57eac91Douglas Gregor return Info->SFINAE && Info->Class == CLASS_ERROR; 1305e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor return false; 1315e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor} 1325e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor 1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDiagClass - Return the class field of the diagnostic. 1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1350750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattnerstatic unsigned getBuiltinDiagClass(unsigned DiagID) { 136121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 137121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner return Info->Class; 138121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner return ~0U; 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 141182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 142182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner// Custom Diagnostic information 143182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 144182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 145182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattnernamespace clang { 146182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner namespace diag { 147182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner class CustomDiagInfo { 148182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner typedef std::pair<Diagnostic::Level, std::string> DiagDesc; 149182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner std::vector<DiagDesc> DiagInfo; 150182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner std::map<DiagDesc, unsigned> DiagIDs; 151182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner public: 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner /// getDescription - Return the description of the specified custom 154182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner /// diagnostic. 155182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner const char *getDescription(unsigned DiagID) const { 15688eccaf06f9d88191723e71bdf5ca68409393be6Chris Lattner assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 157182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner "Invalid diagnosic ID"); 15888eccaf06f9d88191723e71bdf5ca68409393be6Chris Lattner return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str(); 159182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner } 1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 161182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner /// getLevel - Return the level of the specified custom diagnostic. 162182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner Diagnostic::Level getLevel(unsigned DiagID) const { 16388eccaf06f9d88191723e71bdf5ca68409393be6Chris Lattner assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 164182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner "Invalid diagnosic ID"); 16588eccaf06f9d88191723e71bdf5ca68409393be6Chris Lattner return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 166182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner } 1671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16832d4d80c26e8c4c1922cff4661e0b9f44a3aabfcDaniel Dunbar unsigned getOrCreateDiagID(Diagnostic::Level L, llvm::StringRef Message, 169a1f23cc7f5dae8b71b8ee631994274609d35eb89Chris Lattner Diagnostic &Diags) { 170182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner DiagDesc D(L, Message); 171182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner // Check to see if it already exists. 172182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 173182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner if (I != DiagIDs.end() && I->first == D) 174182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner return I->second; 1751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 176182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner // If not, assign a new ID. 17788eccaf06f9d88191723e71bdf5ca68409393be6Chris Lattner unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 178182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner DiagIDs.insert(std::make_pair(D, ID)); 179182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner DiagInfo.push_back(D); 180182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner return ID; 181182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner } 182182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner }; 1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } // end diag namespace 1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} // end clang namespace 186182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 187182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 188182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 189182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner// Common Diagnostic implementation 190182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner//===----------------------------------------------------------------------===// 191182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 1923fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattnerstatic void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, 1933fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattner const char *Modifier, unsigned ML, 1943fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattner const char *Argument, unsigned ArgLen, 195b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner const Diagnostic::ArgumentValue *PrevArgs, 196b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner unsigned NumPrevArgs, 19792dd386e3f05d176b45a638199d51f536bd9d1c4Chris Lattner llvm::SmallVectorImpl<char> &Output, 19892dd386e3f05d176b45a638199d51f536bd9d1c4Chris Lattner void *Cookie) { 1993fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattner const char *Str = "<can't format argument>"; 20022caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner Output.append(Str, Str+strlen(Str)); 20122caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner} 20222caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner 20322caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner 204b4398aa27da4d6919c3ae448d1ae66ba6cafc048Ted KremenekDiagnostic::Diagnostic(DiagnosticClient *client) : Client(client) { 20527ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner AllExtensionsSilenced = 0; 2065b4681c8ef65808ec4d72ab6081efd24d53d4969Chris Lattner IgnoreAllWarnings = false; 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer WarningsAsErrors = false; 208e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner ErrorsAsFatal = false; 2092fe0997427d92388e66e7573f4b043e7ba285ef0Daniel Dunbar SuppressSystemWarnings = false; 21081b747b7fcc91c2fba9a3183d8fac80adbfc1d3eDouglas Gregor SuppressAllDiagnostics = false; 211b54b276a920246c595a0498da281821eb9d22996Chris Lattner ExtBehavior = Ext_Ignore; 2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ErrorOccurred = false; 21415221422eda7bac679e38b07512feda49715ef66Chris Lattner FatalErrorOccurred = false; 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumDiagnostics = 0; 216e0c4d895ffe4320aa4e29485711ad7d154f2cc2bSteve Naroff 2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NumErrors = 0; 218182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner CustomDiagInfo = 0; 2193cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner CurDiagID = ~0U; 220525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor LastDiagLevel = Ignored; 2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2223fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattner ArgToStringFn = DummyArgToStringFn; 22392dd386e3f05d176b45a638199d51f536bd9d1c4Chris Lattner ArgToStringCookie = 0; 2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DelayedDiagID = 0; 22693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 227691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner // Set all mappings to 'unset'. 22804ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0); 22904ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner DiagMappingsStack.push_back(BlankDiags); 230182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner} 231182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 232182745ae7892bca0842d9c023370ade5f8d1c6e8Chris LattnerDiagnostic::~Diagnostic() { 233182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner delete CustomDiagInfo; 234182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner} 235182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 23604ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner 23704ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattnervoid Diagnostic::pushMappings() { 238ca2c3e2cfc630db614298e8d7f2aaca4507e01e1John Thompson // Avoids undefined behavior when the stack has to resize. 239ca2c3e2cfc630db614298e8d7f2aaca4507e01e1John Thompson DiagMappingsStack.reserve(DiagMappingsStack.size() + 1); 24004ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner DiagMappingsStack.push_back(DiagMappingsStack.back()); 24104ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner} 24204ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner 24304ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattnerbool Diagnostic::popMappings() { 24404ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner if (DiagMappingsStack.size() == 1) 24504ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner return false; 24604ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner 24704ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner DiagMappingsStack.pop_back(); 24804ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner return true; 24904ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner} 25004ae2df026b275aae5dddfc0db5ca55ff4e62179Chris Lattner 251182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner/// getCustomDiagID - Return an ID for a diagnostic with the specified message 252182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner/// and level. If this is the first request for this diagnosic, it is 253182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner/// registered and created, otherwise the existing ID is returned. 25432d4d80c26e8c4c1922cff4661e0b9f44a3aabfcDaniel Dunbarunsigned Diagnostic::getCustomDiagID(Level L, llvm::StringRef Message) { 2551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CustomDiagInfo == 0) 256182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner CustomDiagInfo = new diag::CustomDiagInfo(); 257a1f23cc7f5dae8b71b8ee631994274609d35eb89Chris Lattner return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 260182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner 261f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 262f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// level of the specified diagnostic ID is a Warning or Extension. 263f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// This only works on builtin diagnostics, not custom ones, and is not legal to 264f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// call on NOTEs. 265f5d2328fc849288c3a62e43d065685f516d57091Chris Lattnerbool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) { 2668a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner return DiagID < diag::DIAG_UPPER_LIMIT && 2678a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner getBuiltinDiagClass(DiagID) != CLASS_ERROR; 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 270ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor/// \brief Determine whether the given built-in diagnostic ID is a 271ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor/// Note. 272ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregorbool Diagnostic::isBuiltinNote(unsigned DiagID) { 2738a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner return DiagID < diag::DIAG_UPPER_LIMIT && 2748a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner getBuiltinDiagClass(DiagID) == CLASS_NOTE; 275ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor} 276ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor 27727ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 27827ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner/// ID is for an extension of some sort. 27927ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner/// 28027ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattnerbool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) { 2818a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner return DiagID < diag::DIAG_UPPER_LIMIT && 2828a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner getBuiltinDiagClass(DiagID) == CLASS_EXTENSION; 28327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner} 28427ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDescription - Given a diagnostic ID, return a description of the 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// issue. 2880a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattnerconst char *Diagnostic::getDescription(unsigned DiagID) const { 289121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 290121f60c2aa51eae81eac75a9bd8c076140896f3dChris Lattner return Info->Description; 29120c6b3b85e186cd52d5d99489132d71d498159ebChris Lattner return CustomDiagInfo->getDescription(DiagID); 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 29493ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregorvoid Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, 29593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor llvm::StringRef Arg2) { 29693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor if (DelayedDiagID) 29793ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor return; 29893ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 29993ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DelayedDiagID = DiagID; 3009e2dac9c9b6bc4384c816a447cca6516a03c89f2Douglas Gregor DelayedDiagArg1 = Arg1.str(); 3019e2dac9c9b6bc4384c816a447cca6516a03c89f2Douglas Gregor DelayedDiagArg2 = Arg2.str(); 30293ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor} 30393ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 30493ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregorvoid Diagnostic::ReportDelayed() { 30593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; 30693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DelayedDiagID = 0; 30793ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DelayedDiagArg1.clear(); 30893ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DelayedDiagArg2.clear(); 30993ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor} 31093ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDiagnosticLevel - Based on the way the client configured the Diagnostic 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// object, classify the specified diagnostic ID into a Level, consumable by 3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// the DiagnosticClient. 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerDiagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const { 315182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner // Handle custom diagnostics, which cannot be mapped. 31619e8e2cffc19606d0f44e7c2897cd126ffd3f9b0Chris Lattner if (DiagID >= diag::DIAG_UPPER_LIMIT) 317182745ae7892bca0842d9c023370ade5f8d1c6e8Chris Lattner return CustomDiagInfo->getLevel(DiagID); 3181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3190750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner unsigned DiagClass = getBuiltinDiagClass(DiagID); 3208a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); 321f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner return getDiagnosticLevel(DiagID, DiagClass); 322f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner} 323f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner 324f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// getDiagnosticLevel - Based on the way the client configured the Diagnostic 325f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// object, classify the specified diagnostic ID into a Level, consumable by 326f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner/// the DiagnosticClient. 327f5d2328fc849288c3a62e43d065685f516d57091Chris LattnerDiagnostic::Level 328f5d2328fc849288c3a62e43d065685f516d57091Chris LattnerDiagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const { 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Specific non-error diagnostics may be mapped to various levels from ignored 330f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // to error. Errors can only be mapped to fatal. 33127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner Diagnostic::Level Result = Diagnostic::Fatal; 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 333691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner // Get the mapping information, if unset, compute it lazily. 334691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID); 335691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner if (MappingInfo == 0) { 336691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner MappingInfo = GetDefaultDiagMapping(DiagID); 337691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner setDiagnosticMappingInternal(DiagID, MappingInfo, false); 338691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner } 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 340691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner switch (MappingInfo & 7) { 341691f1ae7164ba78c3dd7ac20c487399935b9544bChris Lattner default: assert(0 && "Unknown mapping!"); 34227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner case diag::MAP_IGNORE: 343b54b276a920246c595a0498da281821eb9d22996Chris Lattner // Ignore this, unless this is an extension diagnostic and we're mapping 344b54b276a920246c595a0498da281821eb9d22996Chris Lattner // them onto warnings or errors. 345b54b276a920246c595a0498da281821eb9d22996Chris Lattner if (!isBuiltinExtensionDiag(DiagID) || // Not an extension 346b54b276a920246c595a0498da281821eb9d22996Chris Lattner ExtBehavior == Ext_Ignore || // Extensions ignored anyway 347b54b276a920246c595a0498da281821eb9d22996Chris Lattner (MappingInfo & 8) != 0) // User explicitly mapped it. 348b54b276a920246c595a0498da281821eb9d22996Chris Lattner return Diagnostic::Ignored; 349b54b276a920246c595a0498da281821eb9d22996Chris Lattner Result = Diagnostic::Warning; 350b54b276a920246c595a0498da281821eb9d22996Chris Lattner if (ExtBehavior == Ext_Error) Result = Diagnostic::Error; 351e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner if (Result == Diagnostic::Error && ErrorsAsFatal) 352e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner Result = Diagnostic::Fatal; 353b54b276a920246c595a0498da281821eb9d22996Chris Lattner break; 35427ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner case diag::MAP_ERROR: 35527ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner Result = Diagnostic::Error; 356e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner if (ErrorsAsFatal) 357e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner Result = Diagnostic::Fatal; 35827ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner break; 35927ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner case diag::MAP_FATAL: 36027ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner Result = Diagnostic::Fatal; 36127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner break; 36227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner case diag::MAP_WARNING: 36327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner // If warnings are globally mapped to ignore or error, do it. 3645b4681c8ef65808ec4d72ab6081efd24d53d4969Chris Lattner if (IgnoreAllWarnings) 3655b4681c8ef65808ec4d72ab6081efd24d53d4969Chris Lattner return Diagnostic::Ignored; 3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3672b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner Result = Diagnostic::Warning; 3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 369b54b276a920246c595a0498da281821eb9d22996Chris Lattner // If this is an extension diagnostic and we're in -pedantic-error mode, and 370b54b276a920246c595a0498da281821eb9d22996Chris Lattner // if the user didn't explicitly map it, upgrade to an error. 371b54b276a920246c595a0498da281821eb9d22996Chris Lattner if (ExtBehavior == Ext_Error && 372b54b276a920246c595a0498da281821eb9d22996Chris Lattner (MappingInfo & 8) == 0 && 373b54b276a920246c595a0498da281821eb9d22996Chris Lattner isBuiltinExtensionDiag(DiagID)) 374b54b276a920246c595a0498da281821eb9d22996Chris Lattner Result = Diagnostic::Error; 3751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3762b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner if (WarningsAsErrors) 3772b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner Result = Diagnostic::Error; 378e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner if (Result == Diagnostic::Error && ErrorsAsFatal) 379e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner Result = Diagnostic::Fatal; 3802b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner break; 3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3822b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner case diag::MAP_WARNING_NO_WERROR: 3832b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner // Diagnostics specified with -Wno-error=foo should be set to warnings, but 3842b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner // not be adjusted by -Werror or -pedantic-errors. 3852b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner Result = Diagnostic::Warning; 3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3872b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner // If warnings are globally mapped to ignore or error, do it. 3882b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner if (IgnoreAllWarnings) 3892b07d8fe9e8a8ba12d64066632e17a9a5308a12eChris Lattner return Diagnostic::Ignored; 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner break; 392e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner 393e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner case diag::MAP_ERROR_NO_WFATAL: 394e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner // Diagnostics specified as -Wno-fatal-error=foo should be errors, but 395e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner // unaffected by -Wfatal-errors. 396e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner Result = Diagnostic::Error; 397e663c720063fc9ff9f75bcbe38cd070c73c78b0eChris Lattner break; 3985b4681c8ef65808ec4d72ab6081efd24d53d4969Chris Lattner } 39927ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner 40027ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner // Okay, we're about to return this as a "diagnostic to emit" one last check: 40127ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner // if this is any sort of extension warning, and if we're in an __extension__ 40227ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner // block, silence it. 40327ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) 40427ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner return Diagnostic::Ignored; 4051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 40627ceb9d77d929f02a8a811d189a96885629c7c0cChris Lattner return Result; 4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4093bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerstruct WarningOption { 4103bc172bc6a787842db6fea351cf6929539fca70dChris Lattner const char *Name; 4113bc172bc6a787842db6fea351cf6929539fca70dChris Lattner const short *Members; 4123bc172bc6a787842db6fea351cf6929539fca70dChris Lattner const char *SubGroups; 4133bc172bc6a787842db6fea351cf6929539fca70dChris Lattner}; 4143bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4153bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#define GET_DIAG_ARRAYS 4163bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#include "clang/Basic/DiagnosticGroups.inc" 4173bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#undef GET_DIAG_ARRAYS 4183bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4193bc172bc6a787842db6fea351cf6929539fca70dChris Lattner// Second the table of options, sorted by name for fast binary lookup. 4203bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerstatic const WarningOption OptionTable[] = { 4213bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#define GET_DIAG_TABLE 4223bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#include "clang/Basic/DiagnosticGroups.inc" 4233bc172bc6a787842db6fea351cf6929539fca70dChris Lattner#undef GET_DIAG_TABLE 4243bc172bc6a787842db6fea351cf6929539fca70dChris Lattner}; 4253bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerstatic const size_t OptionTableSize = 4263bc172bc6a787842db6fea351cf6929539fca70dChris Lattnersizeof(OptionTable) / sizeof(OptionTable[0]); 4273bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4283bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerstatic bool WarningOptionCompare(const WarningOption &LHS, 4293bc172bc6a787842db6fea351cf6929539fca70dChris Lattner const WarningOption &RHS) { 4303bc172bc6a787842db6fea351cf6929539fca70dChris Lattner return strcmp(LHS.Name, RHS.Name) < 0; 4313bc172bc6a787842db6fea351cf6929539fca70dChris Lattner} 4323bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4333bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerstatic void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, 4343bc172bc6a787842db6fea351cf6929539fca70dChris Lattner Diagnostic &Diags) { 4353bc172bc6a787842db6fea351cf6929539fca70dChris Lattner // Option exists, poke all the members of its diagnostic set. 4363bc172bc6a787842db6fea351cf6929539fca70dChris Lattner if (const short *Member = Group->Members) { 4373bc172bc6a787842db6fea351cf6929539fca70dChris Lattner for (; *Member != -1; ++Member) 4383bc172bc6a787842db6fea351cf6929539fca70dChris Lattner Diags.setDiagnosticMapping(*Member, Mapping); 4393bc172bc6a787842db6fea351cf6929539fca70dChris Lattner } 4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4413bc172bc6a787842db6fea351cf6929539fca70dChris Lattner // Enable/disable all subgroups along with this one. 4423bc172bc6a787842db6fea351cf6929539fca70dChris Lattner if (const char *SubGroups = Group->SubGroups) { 4433bc172bc6a787842db6fea351cf6929539fca70dChris Lattner for (; *SubGroups != (char)-1; ++SubGroups) 4443bc172bc6a787842db6fea351cf6929539fca70dChris Lattner MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping, Diags); 4453bc172bc6a787842db6fea351cf6929539fca70dChris Lattner } 4463bc172bc6a787842db6fea351cf6929539fca70dChris Lattner} 4473bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4483bc172bc6a787842db6fea351cf6929539fca70dChris Lattner/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. 4493bc172bc6a787842db6fea351cf6929539fca70dChris Lattner/// "unknown-pragmas" to have the specified mapping. This returns true and 4503bc172bc6a787842db6fea351cf6929539fca70dChris Lattner/// ignores the request if "Group" was unknown, false otherwise. 4513bc172bc6a787842db6fea351cf6929539fca70dChris Lattnerbool Diagnostic::setDiagnosticGroupMapping(const char *Group, 4523bc172bc6a787842db6fea351cf6929539fca70dChris Lattner diag::Mapping Map) { 4531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4543bc172bc6a787842db6fea351cf6929539fca70dChris Lattner WarningOption Key = { Group, 0, 0 }; 4553bc172bc6a787842db6fea351cf6929539fca70dChris Lattner const WarningOption *Found = 4563bc172bc6a787842db6fea351cf6929539fca70dChris Lattner std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, 4573bc172bc6a787842db6fea351cf6929539fca70dChris Lattner WarningOptionCompare); 4583bc172bc6a787842db6fea351cf6929539fca70dChris Lattner if (Found == OptionTable + OptionTableSize || 4593bc172bc6a787842db6fea351cf6929539fca70dChris Lattner strcmp(Found->Name, Group) != 0) 4603bc172bc6a787842db6fea351cf6929539fca70dChris Lattner return true; // Option not found. 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4623bc172bc6a787842db6fea351cf6929539fca70dChris Lattner MapGroupMembers(Found, Map, *this); 4633bc172bc6a787842db6fea351cf6929539fca70dChris Lattner return false; 4643bc172bc6a787842db6fea351cf6929539fca70dChris Lattner} 4653bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4663bc172bc6a787842db6fea351cf6929539fca70dChris Lattner 4670a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner/// ProcessDiag - This is the method used to report a diagnostic that is 4680a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner/// finally fully formed. 4695e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregorbool Diagnostic::ProcessDiag() { 4703cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner DiagnosticInfo Info(this); 4711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47281b747b7fcc91c2fba9a3183d8fac80adbfc1d3eDouglas Gregor if (SuppressAllDiagnostics) 47381b747b7fcc91c2fba9a3183d8fac80adbfc1d3eDouglas Gregor return false; 47481b747b7fcc91c2fba9a3183d8fac80adbfc1d3eDouglas Gregor 4755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Figure out the diagnostic level of this message. 476f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner Diagnostic::Level DiagLevel; 477f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner unsigned DiagID = Info.getID(); 4781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 479f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // ShouldEmitInSystemHeader - True if this diagnostic should be produced even 480f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // in a system header. 481f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner bool ShouldEmitInSystemHeader; 4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 483f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner if (DiagID >= diag::DIAG_UPPER_LIMIT) { 484f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // Handle custom diagnostics, which cannot be mapped. 485f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner DiagLevel = CustomDiagInfo->getLevel(DiagID); 4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 487f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // Custom diagnostics always are emitted in system headers. 488f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner ShouldEmitInSystemHeader = true; 489f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner } else { 490f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // Get the class of the diagnostic. If this is a NOTE, map it onto whatever 491f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // the diagnostic level was for the previous diagnostic so that it is 492f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // filtered the same as the previous diagnostic. 493f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner unsigned DiagClass = getBuiltinDiagClass(DiagID); 4948a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner if (DiagClass == CLASS_NOTE) { 495f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner DiagLevel = Diagnostic::Note; 496f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner ShouldEmitInSystemHeader = false; // extra consideration is needed 497f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner } else { 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // If this is not an error and we are in a system header, we ignore it. 499f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // Check the original Diag ID here, because we also want to ignore 500f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // extensions and warnings in -Werror and -pedantic-errors modes, which 501f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // *map* warnings/extensions to errors. 5028a941e0c71d318430648e24eeca91a464a46eba9Chris Lattner ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; 5031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 504f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner DiagLevel = getDiagnosticLevel(DiagID, DiagClass); 505f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner } 506f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner } 507f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner 508525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor if (DiagLevel != Diagnostic::Note) { 509525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // Record that a fatal error occurred only when we see a second 510525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // non-note diagnostic. This allows notes to be attached to the 511525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // fatal error, but suppresses any diagnostics that follow those 512525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // notes. 513525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor if (LastDiagLevel == Diagnostic::Fatal) 514525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor FatalErrorOccurred = true; 515525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor 516f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner LastDiagLevel = DiagLevel; 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 518525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor 519525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // If a fatal error has already been emitted, silence all subsequent 520525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor // diagnostics. 521525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor if (FatalErrorOccurred) 5225e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor return false; 523525c4b0d1bd1a70bf269adecf91b192f3e6c1a89Douglas Gregor 524f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // If the client doesn't care about this message, don't issue it. If this is 525f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // a note and the last real diagnostic was ignored, ignore it too. 526f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner if (DiagLevel == Diagnostic::Ignored || 527f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored)) 5285e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor return false; 5297bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber 530f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // If this diagnostic is in a system header and is not a clang error, suppress 531f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner // it. 532f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner if (SuppressSystemWarnings && !ShouldEmitInSystemHeader && 5330a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner Info.getLocation().isValid() && 534779cf424a153ca92d501af87cb50c7a701514a61John McCall Info.getLocation().getInstantiationLoc().isInSystemHeader() && 535336f26be05c30c0c65b8b518d68f04c29b43b3d2Chris Lattner (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) { 536336f26be05c30c0c65b8b518d68f04c29b43b3d2Chris Lattner LastDiagLevel = Diagnostic::Ignored; 5375e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor return false; 538336f26be05c30c0c65b8b518d68f04c29b43b3d2Chris Lattner } 539f5d2328fc849288c3a62e43d065685f516d57091Chris Lattner 5405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (DiagLevel >= Diagnostic::Error) { 5415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ErrorOccurred = true; 5420a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner ++NumErrors; 5435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Finally, report it. 5460a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner Client->HandleDiagnostic(DiagLevel, Info); 547cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics; 548ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor 549ee1828a6b5ae1bc4ea300e48f3840ac1ec5be295Douglas Gregor CurDiagID = ~0U; 5505e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor 5515e9f35c7cb61aea46f56d46c77cbcf47c0cf28baDouglas Gregor return true; 5525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 5535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 55493ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregorbool DiagnosticBuilder::Emit() { 55593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // If DiagObj is null, then its soul was stolen by the copy ctor 55693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // or the user called Emit(). 55793ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor if (DiagObj == 0) return false; 55893ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 55993ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // When emitting diagnostics, we set the final argument count into 56093ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // the Diagnostic object. 56193ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj->NumDiagArgs = NumArgs; 56293ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj->NumDiagRanges = NumRanges; 56393ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj->NumCodeModificationHints = NumCodeModificationHints; 56493ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 56593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // Process the diagnostic, sending the accumulated information to the 56693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // DiagnosticClient. 56793ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor bool Emitted = DiagObj->ProcessDiag(); 56893ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 56993ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // Clear out the current diagnostic object. 5709e2dac9c9b6bc4384c816a447cca6516a03c89f2Douglas Gregor unsigned DiagID = DiagObj->CurDiagID; 57193ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj->Clear(); 57293ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 57393ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // If there was a delayed diagnostic, emit it now. 5749e2dac9c9b6bc4384c816a447cca6516a03c89f2Douglas Gregor if (DiagObj->DelayedDiagID && DiagObj->DelayedDiagID != DiagID) 57593ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj->ReportDelayed(); 57693ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 57793ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor // This diagnostic is dead. 57893ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor DiagObj = 0; 57993ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 58093ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor return Emitted; 58193ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor} 58293ea5cb0edf8e509c5113e70cb05ee247c9bdf6bDouglas Gregor 5837bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber 5845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerDiagnosticClient::~DiagnosticClient() {} 5857bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber 586f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner 587af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// ModifierIs - Return true if the specified modifier matches specified string. 588af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattnertemplate <std::size_t StrLen> 589af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattnerstatic bool ModifierIs(const char *Modifier, unsigned ModifierLen, 590af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner const char (&Str)[StrLen]) { 591af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1); 592af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner} 593af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner 594909c182f6a0e6169475eef6a71add14555b6162cJohn McCall/// ScanForward - Scans forward, looking for the given character, skipping 595909c182f6a0e6169475eef6a71add14555b6162cJohn McCall/// nested clauses and escaped characters. 596909c182f6a0e6169475eef6a71add14555b6162cJohn McCallstatic const char *ScanFormat(const char *I, const char *E, char Target) { 597909c182f6a0e6169475eef6a71add14555b6162cJohn McCall unsigned Depth = 0; 598909c182f6a0e6169475eef6a71add14555b6162cJohn McCall 599909c182f6a0e6169475eef6a71add14555b6162cJohn McCall for ( ; I != E; ++I) { 600909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (Depth == 0 && *I == Target) return I; 601909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (Depth != 0 && *I == '}') Depth--; 602909c182f6a0e6169475eef6a71add14555b6162cJohn McCall 603909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (*I == '%') { 604909c182f6a0e6169475eef6a71add14555b6162cJohn McCall I++; 605909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (I == E) break; 606909c182f6a0e6169475eef6a71add14555b6162cJohn McCall 607909c182f6a0e6169475eef6a71add14555b6162cJohn McCall // Escaped characters get implicitly skipped here. 608909c182f6a0e6169475eef6a71add14555b6162cJohn McCall 609909c182f6a0e6169475eef6a71add14555b6162cJohn McCall // Format specifier. 610909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (!isdigit(*I) && !ispunct(*I)) { 611909c182f6a0e6169475eef6a71add14555b6162cJohn McCall for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ; 612909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (I == E) break; 613909c182f6a0e6169475eef6a71add14555b6162cJohn McCall if (*I == '{') 614909c182f6a0e6169475eef6a71add14555b6162cJohn McCall Depth++; 615909c182f6a0e6169475eef6a71add14555b6162cJohn McCall } 616909c182f6a0e6169475eef6a71add14555b6162cJohn McCall } 617909c182f6a0e6169475eef6a71add14555b6162cJohn McCall } 618909c182f6a0e6169475eef6a71add14555b6162cJohn McCall return E; 619909c182f6a0e6169475eef6a71add14555b6162cJohn McCall} 620909c182f6a0e6169475eef6a71add14555b6162cJohn McCall 621af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// HandleSelectModifier - Handle the integer 'select' modifier. This is used 622af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// like this: %select{foo|bar|baz}2. This means that the integer argument 623af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'. 624af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'. 625af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// This is very useful for certain classes of variant diagnostics. 6269f28614bf1a8387000d8df57a713fcf69e198145John McCallstatic void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo, 627af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner const char *Argument, unsigned ArgumentLen, 628af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner llvm::SmallVectorImpl<char> &OutStr) { 629af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner const char *ArgumentEnd = Argument+ArgumentLen; 6301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 631af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // Skip over 'ValNo' |'s. 632af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner while (ValNo) { 633909c182f6a0e6169475eef6a71add14555b6162cJohn McCall const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|'); 634af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(NextVal != ArgumentEnd && "Value for integer select modifier was" 635af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner " larger than the number of options in the diagnostic string!"); 636af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner Argument = NextVal+1; // Skip this string. 637af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner --ValNo; 638af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 6391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 640af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // Get the end of the value. This is either the } or the |. 641909c182f6a0e6169475eef6a71add14555b6162cJohn McCall const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|'); 6429f28614bf1a8387000d8df57a713fcf69e198145John McCall 6439f28614bf1a8387000d8df57a713fcf69e198145John McCall // Recursively format the result of the select clause into the output string. 6449f28614bf1a8387000d8df57a713fcf69e198145John McCall DInfo.FormatDiagnostic(Argument, EndPtr, OutStr); 645af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner} 646af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner 647af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the 648af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// letter 's' to the string if the value is not 1. This is used in cases like 649af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner/// this: "you idiot, you have %4 parameter%s4!". 650af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattnerstatic void HandleIntegerSModifier(unsigned ValNo, 651af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner llvm::SmallVectorImpl<char> &OutStr) { 652af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner if (ValNo != 1) 653af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner OutStr.push_back('s'); 654af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner} 655af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner 6563be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This 6573be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall/// prints the ordinal form of the given integer, with 1 corresponding 6583be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall/// to the first ordinal. Currently this is hard-coded to use the 6593be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall/// English form. 6603be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCallstatic void HandleOrdinalModifier(unsigned ValNo, 6613be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall llvm::SmallVectorImpl<char> &OutStr) { 6623be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall assert(ValNo != 0 && "ValNo must be strictly positive!"); 6633be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall 6643be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall llvm::raw_svector_ostream Out(OutStr); 6653be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall 6663be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall // We could use text forms for the first N ordinals, but the numeric 6673be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall // forms are actually nicer in diagnostics because they stand out. 6683be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall Out << ValNo; 6693be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall 6703be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall // It is critically important that we do this perfectly for 6713be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall // user-written sequences with over 100 elements. 6723be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall switch (ValNo % 100) { 6733be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 11: 6743be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 12: 6753be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 13: 6763be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall Out << "th"; return; 6773be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall default: 6783be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall switch (ValNo % 10) { 6793be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 1: Out << "st"; return; 6803be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 2: Out << "nd"; return; 6813be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall case 3: Out << "rd"; return; 6823be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall default: Out << "th"; return; 6833be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall } 6843be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall } 6853be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall} 6863be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall 687af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner 688e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// PluralNumber - Parse an unsigned integer and advance Start. 689d2aa7c90e7646c509f3493fa8548635ccf4a2d0aChris Lattnerstatic unsigned PluralNumber(const char *&Start, const char *End) { 690e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl // Programming 101: Parse a decimal number :-) 691e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned Val = 0; 692e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl while (Start != End && *Start >= '0' && *Start <= '9') { 693e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl Val *= 10; 694e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl Val += *Start - '0'; 695e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 696e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 697e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return Val; 698e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl} 699e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 700e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// TestPluralRange - Test if Val is in the parsed range. Modifies Start. 701d2aa7c90e7646c509f3493fa8548635ccf4a2d0aChris Lattnerstatic bool TestPluralRange(unsigned Val, const char *&Start, const char *End) { 702e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (*Start != '[') { 703e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned Ref = PluralNumber(Start, End); 704e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return Ref == Val; 705e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 706e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 707e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 708e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned Low = PluralNumber(Start, End); 709e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl assert(*Start == ',' && "Bad plural expression syntax: expected ,"); 710e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 711e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned High = PluralNumber(Start, End); 712e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl assert(*Start == ']' && "Bad plural expression syntax: expected )"); 713e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 714e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return Low <= Val && Val <= High; 715e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl} 716e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 717e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier. 718d2aa7c90e7646c509f3493fa8548635ccf4a2d0aChris Lattnerstatic bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { 719e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl // Empty condition? 720e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (*Start == ':') 721e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return true; 722e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 723e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl while (1) { 724e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl char C = *Start; 725e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (C == '%') { 726e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl // Modulo expression 727e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 728e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned Arg = PluralNumber(Start, End); 729e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl assert(*Start == '=' && "Bad plural expression syntax: expected ="); 730e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 731e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl unsigned ValMod = ValNo % Arg; 732e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (TestPluralRange(ValMod, Start, End)) 733e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return true; 734e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } else { 735e20653219732b03294130999415fc3aa92d2336aSebastian Redl assert((C == '[' || (C >= '0' && C <= '9')) && 736e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl "Bad plural expression syntax: unexpected character"); 737e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl // Range expression 738e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (TestPluralRange(ValNo, Start, End)) 739e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return true; 740e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 741e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 742e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl // Scan for next or-expr part. 743e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl Start = std::find(Start, End, ','); 7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (Start == End) 745e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl break; 746e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++Start; 747e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 748e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return false; 749e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl} 750e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 751e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used 752e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// for complex plural forms, or in languages where all plurals are complex. 753e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are 754e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// conditions that are tested in order, the form corresponding to the first 755e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// that applies being emitted. The empty condition is always true, making the 756e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// last form a default case. 757e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Conditions are simple boolean expressions, where n is the number argument. 758e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Here are the rules. 759e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// condition := expression | empty 760e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// empty := -> always true 761e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// expression := numeric [',' expression] -> logical or 762e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// numeric := range -> true if n in range 763e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// | '%' number '=' range -> true if n % number in range 764e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// range := number 765e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// | '[' number ',' number ']' -> ranges are inclusive both ends 766e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// 767e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Here are some examples from the GNU gettext manual written in this form: 768e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// English: 769e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {1:form0|:form1} 770e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Latvian: 771e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0} 772e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Gaeilge: 773e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {1:form0|2:form1|:form2} 774e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Romanian: 775e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {1:form0|0,%100=[1,19]:form1|:form2} 776e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Lithuanian: 777e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1} 778e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Russian (requires repeated form): 779e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2} 780e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Slovak 781e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {1:form0|[2,4]:form1|:form2} 782e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// Polish (requires repeated form): 783e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2} 784e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redlstatic void HandlePluralModifier(unsigned ValNo, 785e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl const char *Argument, unsigned ArgumentLen, 786b54b276a920246c595a0498da281821eb9d22996Chris Lattner llvm::SmallVectorImpl<char> &OutStr) { 787e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl const char *ArgumentEnd = Argument + ArgumentLen; 788e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl while (1) { 789e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl assert(Argument < ArgumentEnd && "Plural expression didn't match."); 790e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl const char *ExprEnd = Argument; 791e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl while (*ExprEnd != ':') { 792e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl assert(ExprEnd != ArgumentEnd && "Plural missing expression end"); 793e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl ++ExprEnd; 794e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 795e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl if (EvalPluralExpr(ValNo, Argument, ExprEnd)) { 796e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl Argument = ExprEnd + 1; 797909c182f6a0e6169475eef6a71add14555b6162cJohn McCall ExprEnd = ScanFormat(Argument, ArgumentEnd, '|'); 798e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl OutStr.append(Argument, ExprEnd); 799e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl return; 800e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 801909c182f6a0e6169475eef6a71add14555b6162cJohn McCall Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1; 802e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } 803e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl} 804e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 805e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl 806f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner/// FormatDiagnostic - Format this diagnostic into a string, substituting the 807f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner/// formal arguments into the %0 slots. The result is appended onto the Str 808f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner/// array. 809f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattnervoid DiagnosticInfo:: 810f4c839657742b823cea1a95b18422f1ba74d3dddChris LattnerFormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { 811f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner const char *DiagStr = getDiags()->getDescription(getID()); 812f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner const char *DiagEnd = DiagStr+strlen(DiagStr); 8131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8149f28614bf1a8387000d8df57a713fcf69e198145John McCall FormatDiagnostic(DiagStr, DiagEnd, OutStr); 8159f28614bf1a8387000d8df57a713fcf69e198145John McCall} 8169f28614bf1a8387000d8df57a713fcf69e198145John McCall 8179f28614bf1a8387000d8df57a713fcf69e198145John McCallvoid DiagnosticInfo:: 8189f28614bf1a8387000d8df57a713fcf69e198145John McCallFormatDiagnostic(const char *DiagStr, const char *DiagEnd, 8199f28614bf1a8387000d8df57a713fcf69e198145John McCall llvm::SmallVectorImpl<char> &OutStr) const { 8209f28614bf1a8387000d8df57a713fcf69e198145John McCall 821b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner /// FormattedArgs - Keep track of all of the arguments formatted by 822b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner /// ConvertArgToString and pass them into subsequent calls to 823b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner /// ConvertArgToString, allowing the implementation to avoid redundancies in 824b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner /// obvious cases. 825b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs; 826b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner 827f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner while (DiagStr != DiagEnd) { 828f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner if (DiagStr[0] != '%') { 829f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner // Append non-%0 substrings to Str if we have one. 830f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner const char *StrEnd = std::find(DiagStr, DiagEnd, '%'); 831f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner OutStr.append(DiagStr, StrEnd); 832f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner DiagStr = StrEnd; 833af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner continue; 834909c182f6a0e6169475eef6a71add14555b6162cJohn McCall } else if (ispunct(DiagStr[1])) { 835909c182f6a0e6169475eef6a71add14555b6162cJohn McCall OutStr.push_back(DiagStr[1]); // %% -> %. 836f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner DiagStr += 2; 837af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner continue; 838af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 8391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 840af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // Skip the %. 841af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ++DiagStr; 8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 843af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // This must be a placeholder for a diagnostic argument. The format for a 844af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0". 845af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // The digit is a number from 0-9 indicating which argument this comes from. 846af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // The modifier is a string of digits from the set [-a-z]+, arguments is a 847af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // brace enclosed string. 848af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner const char *Modifier = 0, *Argument = 0; 849af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner unsigned ModifierLen = 0, ArgumentLen = 0; 8501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 851af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // Check to see if we have a modifier. If so eat it. 852af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner if (!isdigit(DiagStr[0])) { 853af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner Modifier = DiagStr; 854af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner while (DiagStr[0] == '-' || 855af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner (DiagStr[0] >= 'a' && DiagStr[0] <= 'z')) 856af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ++DiagStr; 857af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ModifierLen = DiagStr-Modifier; 858f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner 859af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner // If we have an argument, get it next. 860af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner if (DiagStr[0] == '{') { 861af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ++DiagStr; // Skip {. 862af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner Argument = DiagStr; 8631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 864909c182f6a0e6169475eef6a71add14555b6162cJohn McCall DiagStr = ScanFormat(DiagStr, DiagEnd, '}'); 865909c182f6a0e6169475eef6a71add14555b6162cJohn McCall assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!"); 866af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ArgumentLen = DiagStr-Argument; 867af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner ++DiagStr; // Skip }. 868f4c839657742b823cea1a95b18422f1ba74d3dddChris Lattner } 869af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 8701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 871af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); 87222caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner unsigned ArgNo = *DiagStr++ - '0'; 873af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner 874b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner Diagnostic::ArgumentKind Kind = getArgKind(ArgNo); 875b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner 876b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner switch (Kind) { 87708631c5fa053867146b5ee8be658c229f6bf127cChris Lattner // ---- STRINGS ---- 8783cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner case Diagnostic::ak_std_string: { 87922caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner const std::string &S = getArgStdStr(ArgNo); 880af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(ModifierLen == 0 && "No modifiers for strings yet"); 881af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner OutStr.append(S.begin(), S.end()); 882af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner break; 883af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 8843cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner case Diagnostic::ak_c_string: { 88522caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner const char *S = getArgCStr(ArgNo); 886af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(ModifierLen == 0 && "No modifiers for strings yet"); 887e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar 888e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar // Don't crash if get passed a null pointer by accident. 889e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar if (!S) 890e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar S = "(null)"; 8911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 892af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner OutStr.append(S, S + strlen(S)); 893af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner break; 894af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 89508631c5fa053867146b5ee8be658c229f6bf127cChris Lattner // ---- INTEGERS ---- 8963cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner case Diagnostic::ak_sint: { 89722caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner int Val = getArgSInt(ArgNo); 8981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 899af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner if (ModifierIs(Modifier, ModifierLen, "select")) { 9009f28614bf1a8387000d8df57a713fcf69e198145John McCall HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen, OutStr); 901af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } else if (ModifierIs(Modifier, ModifierLen, "s")) { 902af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner HandleIntegerSModifier(Val, OutStr); 903e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 904e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); 9053be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { 9063be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall HandleOrdinalModifier((unsigned)Val, OutStr); 907af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } else { 908af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(ModifierLen == 0 && "Unknown integer modifier"); 90923e47c6b6e8ccdd8daa378ab2a879644425c72d8Daniel Dunbar llvm::raw_svector_ostream(OutStr) << Val; 91030bc96544346bea42921cf6837e66cef80d664b4Chris Lattner } 911af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner break; 912af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 9133cbfe2c4159e0a219ae660d50625c013aa4afbd0Chris Lattner case Diagnostic::ak_uint: { 91422caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner unsigned Val = getArgUInt(ArgNo); 9151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 916af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner if (ModifierIs(Modifier, ModifierLen, "select")) { 9179f28614bf1a8387000d8df57a713fcf69e198145John McCall HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr); 918af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } else if (ModifierIs(Modifier, ModifierLen, "s")) { 919af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner HandleIntegerSModifier(Val, OutStr); 920e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 921e4c452c4c7b9124fe94a96f559ff077d59cdf996Sebastian Redl HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); 9223be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { 9233be16b7d9d0ab075461ed3498b4c01b30b517c0eJohn McCall HandleOrdinalModifier(Val, OutStr); 924af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } else { 925af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner assert(ModifierLen == 0 && "Unknown integer modifier"); 92623e47c6b6e8ccdd8daa378ab2a879644425c72d8Daniel Dunbar llvm::raw_svector_ostream(OutStr) << Val; 92730bc96544346bea42921cf6837e66cef80d664b4Chris Lattner } 92822caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner break; 929af7ae4e8160fc5c23e471f2125b3fe5911e3532aChris Lattner } 93008631c5fa053867146b5ee8be658c229f6bf127cChris Lattner // ---- NAMES and TYPES ---- 93108631c5fa053867146b5ee8be658c229f6bf127cChris Lattner case Diagnostic::ak_identifierinfo: { 93208631c5fa053867146b5ee8be658c229f6bf127cChris Lattner const IdentifierInfo *II = getArgIdentifier(ArgNo); 93308631c5fa053867146b5ee8be658c229f6bf127cChris Lattner assert(ModifierLen == 0 && "No modifiers for strings yet"); 934e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar 935e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar // Don't crash if get passed a null pointer by accident. 936e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar if (!II) { 937e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar const char *S = "(null)"; 938e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar OutStr.append(S, S + strlen(S)); 939e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar continue; 940e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar } 941e46e354ecb9a04c8d3724ae2b0f95f4424e3f69cDaniel Dunbar 94201eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\''; 94308631c5fa053867146b5ee8be658c229f6bf127cChris Lattner break; 94408631c5fa053867146b5ee8be658c229f6bf127cChris Lattner } 94522caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner case Diagnostic::ak_qualtype: 946011bb4edf731d529da1cbf71c7c2696aaf5a054fChris Lattner case Diagnostic::ak_declarationname: 94747b9a1ca55e61e37f5a368740e29de190345acc6Douglas Gregor case Diagnostic::ak_nameddecl: 948dacd434c49658286c380c7b4c357d76d53cb4aa1Douglas Gregor case Diagnostic::ak_nestednamespec: 9493f09327b26033d0a9676d52d80cf92c48f581affDouglas Gregor case Diagnostic::ak_declcontext: 950b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), 9513fdf4b071dc79fae778fb5f376485480756c76a3Chris Lattner Modifier, ModifierLen, 952b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner Argument, ArgumentLen, 953b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner FormattedArgs.data(), FormattedArgs.size(), 954b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner OutStr); 95522caddc91d2f6186739c6b20ec58ed38cd68e595Chris Lattner break; 9567bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber } 957b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner 958b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner // Remember this argument info for subsequent formatting operations. Turn 959b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner // std::strings into a null terminated string to make it be the same case as 960b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner // all the other ones. 961b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner if (Kind != Diagnostic::ak_std_string) 962b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); 963b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner else 964b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string, 965b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner (intptr_t)getArgStdStr(ArgNo).c_str())); 966b54d8af9a66cc20a6a9a9219c7eaea8df7ee7fd4Chris Lattner 9677bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber } 9687bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber} 969cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek 970a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic::StoredDiagnostic() { } 971a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 972a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, 973a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor llvm::StringRef Message) 9740a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor : Level(Level), Loc(), Message(Message) { } 975a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 976a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, 977a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor const DiagnosticInfo &Info) 978a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor : Level(Level), Loc(Info.getLocation()) 979a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor{ 980a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor llvm::SmallString<64> Message; 981a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Info.FormatDiagnostic(Message); 982a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor this->Message.assign(Message.begin(), Message.end()); 983a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 984a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Ranges.reserve(Info.getNumRanges()); 985a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I) 986a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Ranges.push_back(Info.getRange(I)); 987a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 988a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor FixIts.reserve(Info.getNumCodeModificationHints()); 989a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (unsigned I = 0, N = Info.getNumCodeModificationHints(); I != N; ++I) 990a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor FixIts.push_back(Info.getCodeModificationHint(I)); 991a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor} 992a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 993a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic::~StoredDiagnostic() { } 994a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 995d93256e55673a17d18543397ec462416acb13792Douglas Gregorstatic void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { 996d93256e55673a17d18543397ec462416acb13792Douglas Gregor OS.write((const char *)&Value, sizeof(unsigned)); 997d93256e55673a17d18543397ec462416acb13792Douglas Gregor} 998d93256e55673a17d18543397ec462416acb13792Douglas Gregor 999d93256e55673a17d18543397ec462416acb13792Douglas Gregorstatic void WriteString(llvm::raw_ostream &OS, llvm::StringRef String) { 1000d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, String.size()); 1001d93256e55673a17d18543397ec462416acb13792Douglas Gregor OS.write(String.data(), String.size()); 1002d93256e55673a17d18543397ec462416acb13792Douglas Gregor} 1003d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1004d93256e55673a17d18543397ec462416acb13792Douglas Gregorstatic void WriteSourceLocation(llvm::raw_ostream &OS, 1005d93256e55673a17d18543397ec462416acb13792Douglas Gregor SourceManager *SM, 1006d93256e55673a17d18543397ec462416acb13792Douglas Gregor SourceLocation Location) { 1007d93256e55673a17d18543397ec462416acb13792Douglas Gregor if (!SM || Location.isInvalid()) { 1008d93256e55673a17d18543397ec462416acb13792Douglas Gregor // If we don't have a source manager or this location is invalid, 1009d93256e55673a17d18543397ec462416acb13792Douglas Gregor // just write an invalid location. 1010d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, 0); 1011d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, 0); 1012d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, 0); 1013d93256e55673a17d18543397ec462416acb13792Douglas Gregor return; 1014d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1015d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1016d93256e55673a17d18543397ec462416acb13792Douglas Gregor Location = SM->getInstantiationLoc(Location); 1017d93256e55673a17d18543397ec462416acb13792Douglas Gregor std::pair<FileID, unsigned> Decomposed = SM->getDecomposedLoc(Location); 1018d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1019d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteString(OS, SM->getFileEntryForID(Decomposed.first)->getName()); 1020d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, SM->getLineNumber(Decomposed.first, Decomposed.second)); 1021d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, SM->getColumnNumber(Decomposed.first, Decomposed.second)); 1022d93256e55673a17d18543397ec462416acb13792Douglas Gregor} 1023d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1024a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregorvoid StoredDiagnostic::Serialize(llvm::raw_ostream &OS) const { 1025d93256e55673a17d18543397ec462416acb13792Douglas Gregor SourceManager *SM = 0; 1026d93256e55673a17d18543397ec462416acb13792Douglas Gregor if (getLocation().isValid()) 1027d93256e55673a17d18543397ec462416acb13792Douglas Gregor SM = &const_cast<SourceManager &>(getLocation().getManager()); 1028d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1029b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor // Write a short header to help identify diagnostics. 1030b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor OS << (char)0x06 << (char)0x07; 1031b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1032d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Write the diagnostic level and location. 1033a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteUnsigned(OS, (unsigned)Level); 1034d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteSourceLocation(OS, SM, getLocation()); 1035d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1036d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Write the diagnostic message. 1037d93256e55673a17d18543397ec462416acb13792Douglas Gregor llvm::SmallString<64> Message; 1038a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteString(OS, getMessage()); 1039d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1040d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Count the number of ranges that don't point into macros, since 1041d93256e55673a17d18543397ec462416acb13792Douglas Gregor // only simple file ranges serialize well. 1042d93256e55673a17d18543397ec462416acb13792Douglas Gregor unsigned NumNonMacroRanges = 0; 1043a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (range_iterator R = range_begin(), REnd = range_end(); R != REnd; ++R) { 1044a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (R->getBegin().isMacroID() || R->getEnd().isMacroID()) 1045d93256e55673a17d18543397ec462416acb13792Douglas Gregor continue; 1046d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1047d93256e55673a17d18543397ec462416acb13792Douglas Gregor ++NumNonMacroRanges; 1048d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1049d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1050d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Write the ranges. 1051d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, NumNonMacroRanges); 1052d93256e55673a17d18543397ec462416acb13792Douglas Gregor if (NumNonMacroRanges) { 1053a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (range_iterator R = range_begin(), REnd = range_end(); R != REnd; ++R) { 1054a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (R->getBegin().isMacroID() || R->getEnd().isMacroID()) 1055d93256e55673a17d18543397ec462416acb13792Douglas Gregor continue; 1056d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1057a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteSourceLocation(OS, SM, R->getBegin()); 1058a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteSourceLocation(OS, SM, R->getEnd()); 1059d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1060d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1061d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1062d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Determine if all of the fix-its involve rewrites with simple file 1063d93256e55673a17d18543397ec462416acb13792Douglas Gregor // locations (not in macro instantiations). If so, we can write 1064d93256e55673a17d18543397ec462416acb13792Douglas Gregor // fix-it information. 1065a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned NumFixIts = 0; 1066a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (fixit_iterator F = fixit_begin(), FEnd = fixit_end(); F != FEnd; ++F) { 1067a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (F->RemoveRange.isValid() && 1068a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor (F->RemoveRange.getBegin().isMacroID() || 1069a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor F->RemoveRange.getEnd().isMacroID())) { 1070d93256e55673a17d18543397ec462416acb13792Douglas Gregor NumFixIts = 0; 1071d93256e55673a17d18543397ec462416acb13792Douglas Gregor break; 1072d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1073d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1074a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (F->InsertionLoc.isValid() && F->InsertionLoc.isMacroID()) { 1075d93256e55673a17d18543397ec462416acb13792Douglas Gregor NumFixIts = 0; 1076d93256e55673a17d18543397ec462416acb13792Douglas Gregor break; 1077d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1078a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1079a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ++NumFixIts; 1080d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1081d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1082d93256e55673a17d18543397ec462416acb13792Douglas Gregor // Write the fix-its. 1083d93256e55673a17d18543397ec462416acb13792Douglas Gregor WriteUnsigned(OS, NumFixIts); 1084a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (fixit_iterator F = fixit_begin(), FEnd = fixit_end(); F != FEnd; ++F) { 1085a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteSourceLocation(OS, SM, F->RemoveRange.getBegin()); 1086a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteSourceLocation(OS, SM, F->RemoveRange.getEnd()); 1087a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteSourceLocation(OS, SM, F->InsertionLoc); 1088a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor WriteString(OS, F->CodeToInsert); 1089a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 1090a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor} 1091a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1092a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregorstatic bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 1093a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned &Value) { 1094a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (Memory + sizeof(unsigned) > MemoryEnd) 1095a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return true; 1096a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1097a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor memmove(&Value, Memory, sizeof(unsigned)); 1098a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory += sizeof(unsigned); 1099a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return false; 1100a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor} 1101a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1102a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregorstatic bool ReadSourceLocation(FileManager &FM, SourceManager &SM, 1103a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor const char *&Memory, const char *MemoryEnd, 1104a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor SourceLocation &Location) { 1105a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the filename. 1106a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned FileNameLen = 0; 1107a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, FileNameLen) || 1108a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory + FileNameLen > MemoryEnd) 1109a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return true; 1110a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1111a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor llvm::StringRef FileName(Memory, FileNameLen); 1112a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory += FileNameLen; 1113a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1114a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the line, column. 1115a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned Line = 0, Column = 0; 1116a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, Line) || 1117a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ReadUnsigned(Memory, MemoryEnd, Column)) 1118a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return true; 1119a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1120a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (FileName.empty()) { 1121a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Location = SourceLocation(); 1122a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return false; 1123a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 1124a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1125a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor const FileEntry *File = FM.getFile(FileName); 1126a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (!File) 1127a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return true; 1128a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1129a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Make sure that this file has an entry in the source manager. 1130a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (!SM.hasFileInfo(File)) 1131a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor SM.createFileID(File, SourceLocation(), SrcMgr::C_User); 1132a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1133a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Location = SM.getLocation(File, Line, Column); 1134a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return false; 1135a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor} 1136a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1137a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic 1138a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas GregorStoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM, 1139a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor const char *&Memory, const char *MemoryEnd) { 1140b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor while (true) { 1141b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor if (Memory == MemoryEnd) 1142b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor return StoredDiagnostic(); 1143b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1144b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor if (*Memory != 0x06) { 1145b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor ++Memory; 1146b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor continue; 1147b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor } 1148b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1149b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor ++Memory; 1150b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor if (Memory == MemoryEnd) 1151b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor return StoredDiagnostic(); 1152b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1153b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor if (*Memory != 0x07) { 1154b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor ++Memory; 1155b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor continue; 1156b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor } 1157b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1158b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor // We found the header. We're done. 1159b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor ++Memory; 1160b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor break; 1161b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor } 1162b9c903bc7c11adf86b1f1e68ad35cd49703dc654Douglas Gregor 1163a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the severity level. 1164a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned Level = 0; 1165a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, Level) || Level > Diagnostic::Fatal) 1166a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return StoredDiagnostic(); 1167a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1168a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the source location. 1169a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor SourceLocation Location; 1170a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Location)) 1171a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return StoredDiagnostic(); 1172a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1173a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the diagnostic text. 1174a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (Memory == MemoryEnd) 1175a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return StoredDiagnostic(); 1176a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1177a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned MessageLen = 0; 1178a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, MessageLen) || 1179a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory + MessageLen > MemoryEnd) 1180a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return StoredDiagnostic(); 1181a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1182a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor llvm::StringRef Message(Memory, MessageLen); 1183a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory += MessageLen; 1184a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1185a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1186a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // At this point, we have enough information to form a diagnostic. Do so. 1187a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor StoredDiagnostic Diag; 1188a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.Level = (Diagnostic::Level)Level; 1189a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.Loc = FullSourceLoc(Location, SM); 1190a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.Message = Message; 1191a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (Memory == MemoryEnd) 1192a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1193a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1194a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the source ranges. 1195a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned NumSourceRanges = 0; 1196a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, NumSourceRanges)) 1197a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1198a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor for (unsigned I = 0; I != NumSourceRanges; ++I) { 1199a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor SourceLocation Begin, End; 1200a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Begin) || 1201a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ReadSourceLocation(FM, SM, Memory, MemoryEnd, End)) 1202a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1203a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1204a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.Ranges.push_back(SourceRange(Begin, End)); 1205a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 1206a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1207a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor // Read the fix-it hints. 1208a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned NumFixIts = 0; 1209a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadUnsigned(Memory, MemoryEnd, NumFixIts)) 1210a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1211d93256e55673a17d18543397ec462416acb13792Douglas Gregor for (unsigned I = 0; I != NumFixIts; ++I) { 1212a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor SourceLocation RemoveBegin, RemoveEnd, InsertionLoc; 1213a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor unsigned InsertLen = 0; 1214a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveBegin) || 1215a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveEnd) || 1216a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ReadSourceLocation(FM, SM, Memory, MemoryEnd, InsertionLoc) || 1217a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor ReadUnsigned(Memory, MemoryEnd, InsertLen) || 1218a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory + InsertLen > MemoryEnd) { 1219a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.FixIts.clear(); 1220a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1221a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor } 1222a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1223a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor CodeModificationHint Hint; 1224a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Hint.RemoveRange = SourceRange(RemoveBegin, RemoveEnd); 1225a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Hint.InsertionLoc = InsertionLoc; 1226a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Hint.CodeToInsert.assign(Memory, Memory + InsertLen); 1227a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Memory += InsertLen; 1228a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor Diag.FixIts.push_back(Hint); 1229d93256e55673a17d18543397ec462416acb13792Douglas Gregor } 1230a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor 1231a88084b78fd4ca5d3d858c14b02414f8cc399f02Douglas Gregor return Diag; 1232d93256e55673a17d18543397ec462416acb13792Douglas Gregor} 1233d93256e55673a17d18543397ec462416acb13792Douglas Gregor 1234cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek/// IncludeInDiagnosticCounts - This method (whose default implementation 1235cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek/// returns true) indicates whether the diagnostics handled by this 1236cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek/// DiagnosticClient should be included in the number of diagnostics 1237cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenek/// reported by Diagnostic. 1238cabe66811fe43835b8c5a0854552768fc53261e3Ted Kremenekbool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; } 1239