/// \brief Print a template integral argument value. /// /// \param TemplArg the TemplateArgument instance to print. /// /// \param Out the raw_ostream instance to use for printing. static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); if (T->isBooleanType()) { Out << (Val.getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { const char Ch = Val.getZExtValue(); Out << ((Ch == '\'') ? "'\\" : "'"); Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); Out << "'"; } else { Out << Val; } }
void DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { DataExtractor debug_str_data(cu->getStringSection(), true, 0); DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0); uint64_t uvalue = Value.uval; bool cu_relative_offset = false; switch (Form) { case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; case DW_FORM_GNU_addr_index: { OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); uint64_t Address; if (cu->getAddrOffsetSectionItem(uvalue, Address)) OS << format("0x%016" PRIx64, Address); else OS << "<no .debug_addr section>"; break; } case DW_FORM_flag_present: OS << "true"; break; case DW_FORM_flag: case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break; case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break; case DW_FORM_ref_sig8: case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break; case DW_FORM_string: OS << '"'; OS.write_escaped(Value.cstr); OS << '"'; break; case DW_FORM_exprloc: case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: if (uvalue > 0) { switch (Form) { case DW_FORM_exprloc: case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break; case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; default: break; } const uint8_t* data_ptr = Value.data; if (data_ptr) { // uvalue contains size of block const uint8_t* end_data_ptr = data_ptr + uvalue; while (data_ptr < end_data_ptr) { OS << format("%2.2x ", *data_ptr); ++data_ptr; } } else OS << "NULL"; } break; case DW_FORM_sdata: OS << Value.sval; break; case DW_FORM_udata: OS << Value.uval; break; case DW_FORM_strp: { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); Optional<const char *> DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { OS << '"'; OS.write_escaped(DbgStr.getValue()); OS << '"'; } break; } case DW_FORM_GNU_str_index: { OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); Optional<const char *> DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { OS << '"'; OS.write_escaped(DbgStr.getValue()); OS << '"'; } break; } case DW_FORM_ref_addr: OS << format("0x%016" PRIx64, uvalue); break; case DW_FORM_ref1: cu_relative_offset = true; OS << format("cu + 0x%2.2x", (uint8_t)uvalue); break; case DW_FORM_ref2: cu_relative_offset = true; OS << format("cu + 0x%4.4x", (uint16_t)uvalue); break; case DW_FORM_ref4: cu_relative_offset = true; OS << format("cu + 0x%4.4x", (uint32_t)uvalue); break; case DW_FORM_ref8: cu_relative_offset = true; OS << format("cu + 0x%8.8" PRIx64, uvalue); break; case DW_FORM_ref_udata: cu_relative_offset = true; OS << format("cu + 0x%" PRIx64, uvalue); break; // All DW_FORM_indirect attributes should be resolved prior to calling // this function case DW_FORM_indirect: OS << "DW_FORM_indirect"; break; // Should be formatted to 64-bit for DWARF64. case DW_FORM_sec_offset: OS << format("0x%08x", (uint32_t)uvalue); break; default: OS << format("DW_FORM(0x%4.4x)", Form); break; } if (cu_relative_offset) OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0)); }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer()); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { const AsmToken &Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: OS << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: OS << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: OS << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: OS << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: OS << "Amp"; break; case AsmToken::AmpAmp: OS << "AmpAmp"; break; case AsmToken::At: OS << "At"; break; case AsmToken::Caret: OS << "Caret"; break; case AsmToken::Colon: OS << "Colon"; break; case AsmToken::Comma: OS << "Comma"; break; case AsmToken::Dollar: OS << "Dollar"; break; case AsmToken::Dot: OS << "Dot"; break; case AsmToken::EndOfStatement: OS << "EndOfStatement"; break; case AsmToken::Eof: OS << "Eof"; break; case AsmToken::Equal: OS << "Equal"; break; case AsmToken::EqualEqual: OS << "EqualEqual"; break; case AsmToken::Exclaim: OS << "Exclaim"; break; case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break; case AsmToken::Greater: OS << "Greater"; break; case AsmToken::GreaterEqual: OS << "GreaterEqual"; break; case AsmToken::GreaterGreater: OS << "GreaterGreater"; break; case AsmToken::Hash: OS << "Hash"; break; case AsmToken::LBrac: OS << "LBrac"; break; case AsmToken::LCurly: OS << "LCurly"; break; case AsmToken::LParen: OS << "LParen"; break; case AsmToken::Less: OS << "Less"; break; case AsmToken::LessEqual: OS << "LessEqual"; break; case AsmToken::LessGreater: OS << "LessGreater"; break; case AsmToken::LessLess: OS << "LessLess"; break; case AsmToken::Minus: OS << "Minus"; break; case AsmToken::Percent: OS << "Percent"; break; case AsmToken::Pipe: OS << "Pipe"; break; case AsmToken::PipePipe: OS << "PipePipe"; break; case AsmToken::Plus: OS << "Plus"; break; case AsmToken::RBrac: OS << "RBrac"; break; case AsmToken::RCurly: OS << "RCurly"; break; case AsmToken::RParen: OS << "RParen"; break; case AsmToken::Slash: OS << "Slash"; break; case AsmToken::Star: OS << "Star"; break; case AsmToken::Tilde: OS << "Tilde"; break; } // Print the token string. OS << " (\""; OS.write_escaped(Tok.getString()); OS << "\")\n"; } return Error; }
void Module::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (IsFramework) OS << "framework "; if (IsExplicit) OS << "explicit "; OS << "module " << Name; if (IsSystem) { OS.indent(Indent + 2); OS << " [system]"; } OS << " {\n"; if (!Requirements.empty()) { OS.indent(Indent + 2); OS << "requires "; for (unsigned I = 0, N = Requirements.size(); I != N; ++I) { if (I) OS << ", "; if (!Requirements[I].second) OS << "!"; OS << Requirements[I].first; } OS << "\n"; } if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; OS.write_escaped(UmbrellaHeader->getName()); OS << "\"\n"; } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(UmbrellaDir->getName()); OS << "\"\n"; } if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { OS.indent(Indent + 2); OS << "config_macros "; if (ConfigMacrosExhaustive) OS << "[exhaustive]"; for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { if (I) OS << ", "; OS << ConfigMacros[I]; } OS << "\n"; } for (unsigned I = 0, N = NormalHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "header \""; OS.write_escaped(NormalHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "exclude header \""; OS.write_escaped(ExcludedHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = PrivateHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "private header \""; OS.write_escaped(PrivateHeaders[I]->getName()); OS << "\"\n"; } for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) // Print inferred subframework modules so that we don't need to re-infer // them (requires expensive directory iteration + stat calls) when we build // the module. Regular inferred submodules are OK, as we need to look at all // those header files anyway. if (!(*MI)->IsInferred || (*MI)->IsFramework) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; if (Module *Restriction = Exports[I].getPointer()) { OS << Restriction->getFullModuleName(); if (Exports[I].getInt()) OS << ".*"; } else { OS << "*"; } OS << "\n"; } for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; printModuleId(OS, UnresolvedExports[I].Id); if (UnresolvedExports[I].Wildcard) { if (UnresolvedExports[I].Id.empty()) OS << "*"; else OS << ".*"; } OS << "\n"; } for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; OS << DirectUses[I]->getFullModuleName(); OS << "\n"; } for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; printModuleId(OS, UnresolvedDirectUses[I]); OS << "\n"; } for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "link "; if (LinkLibraries[I].IsFramework) OS << "framework "; OS << "\""; OS.write_escaped(LinkLibraries[I].Library); OS << "\""; } for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; printModuleId(OS, UnresolvedConflicts[I].Id); OS << ", \""; OS.write_escaped(UnresolvedConflicts[I].Message); OS << "\"\n"; } for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; OS << Conflicts[I].Other->getFullModuleName(); OS << ", \""; OS.write_escaped(Conflicts[I].Message); OS << "\"\n"; } if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) OS << "explicit "; OS << "module * {\n"; if (InferExportWildcard) { OS.indent(Indent + 4); OS << "export *\n"; } OS.indent(Indent + 2); OS << "}\n"; } OS.indent(Indent); OS << "}\n"; }
void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { uint64_t UValue = Value.uval; bool CURelativeOffset = false; raw_ostream &AddrOS = DumpOpts.ShowAddresses ? WithColor(OS, syntax::Address).get() : nulls(); switch (Form) { case DW_FORM_addr: AddrOS << format("0x%016" PRIx64, UValue); break; case DW_FORM_GNU_addr_index: { AddrOS << format(" indexed (%8.8x) address = ", (uint32_t)UValue); uint64_t Address; if (U == nullptr) OS << "<invalid dwarf unit>"; else if (U->getAddrOffsetSectionItem(UValue, Address)) AddrOS << format("0x%016" PRIx64, Address); else OS << "<no .debug_addr section>"; break; } case DW_FORM_flag_present: OS << "true"; break; case DW_FORM_flag: case DW_FORM_data1: OS << format("0x%02x", (uint8_t)UValue); break; case DW_FORM_data2: OS << format("0x%04x", (uint16_t)UValue); break; case DW_FORM_data4: OS << format("0x%08x", (uint32_t)UValue); break; case DW_FORM_ref_sig8: AddrOS << format("0x%016" PRIx64, UValue); break; case DW_FORM_data8: OS << format("0x%016" PRIx64, UValue); break; case DW_FORM_data16: OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), None, 16, 16); break; case DW_FORM_string: OS << '"'; OS.write_escaped(Value.cstr); OS << '"'; break; case DW_FORM_exprloc: case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: if (UValue > 0) { switch (Form) { case DW_FORM_exprloc: case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", UValue); break; case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)UValue); break; case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)UValue); break; case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)UValue); break; default: break; } const uint8_t *DataPtr = Value.data; if (DataPtr) { // UValue contains size of block const uint8_t *EndDataPtr = DataPtr + UValue; while (DataPtr < EndDataPtr) { OS << format("%2.2x ", *DataPtr); ++DataPtr; } } else OS << "NULL"; } break; case DW_FORM_sdata: OS << Value.sval; break; case DW_FORM_udata: OS << Value.uval; break; case DW_FORM_strp: if (DumpOpts.Verbose) OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue); dumpString(OS); break; case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2: case DW_FORM_strx3: case DW_FORM_strx4: case DW_FORM_GNU_str_index: if (DumpOpts.Verbose) OS << format(" indexed (%8.8x) string = ", (uint32_t)UValue); dumpString(OS); break; case DW_FORM_GNU_strp_alt: if (DumpOpts.Verbose) OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue); dumpString(OS); break; case DW_FORM_ref_addr: AddrOS << format("0x%016" PRIx64, UValue); break; case DW_FORM_ref1: CURelativeOffset = true; AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue); break; case DW_FORM_ref2: CURelativeOffset = true; AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue); break; case DW_FORM_ref4: CURelativeOffset = true; AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue); break; case DW_FORM_ref8: CURelativeOffset = true; AddrOS << format("cu + 0x%8.8" PRIx64, UValue); break; case DW_FORM_ref_udata: CURelativeOffset = true; AddrOS << format("cu + 0x%" PRIx64, UValue); break; case DW_FORM_GNU_ref_alt: AddrOS << format("<alt 0x%" PRIx64 ">", UValue); break; // All DW_FORM_indirect attributes should be resolved prior to calling // this function case DW_FORM_indirect: OS << "DW_FORM_indirect"; break; // Should be formatted to 64-bit for DWARF64. case DW_FORM_sec_offset: AddrOS << format("0x%08x", (uint32_t)UValue); break; default: OS << format("DW_FORM(0x%4.4x)", Form); break; } if (CURelativeOffset && DumpOpts.Verbose) { OS << " => {"; WithColor(OS, syntax::Address).get() << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0)); OS << "}"; } }
void DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0); uint64_t uvalue = getUnsigned(); bool cu_relative_offset = false; switch (Form) { case DW_FORM_addr: OS << format("0x%016x", uvalue); break; case DW_FORM_flag: case DW_FORM_data1: OS << format("0x%02x", uvalue); break; case DW_FORM_data2: OS << format("0x%04x", uvalue); break; case DW_FORM_data4: OS << format("0x%08x", uvalue); break; case DW_FORM_data8: OS << format("0x%016x", uvalue); break; case DW_FORM_string: OS << '"'; OS.write_escaped(getAsCString(NULL)); OS << '"'; break; case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: if (uvalue > 0) { switch (Form) { case DW_FORM_block: OS << format("<0x%llx> ", uvalue); break; case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; default: break; } const uint8_t* data_ptr = Value.data; if (data_ptr) { // uvalue contains size of block const uint8_t* end_data_ptr = data_ptr + uvalue; while (data_ptr < end_data_ptr) { OS << format("%2.2x ", *data_ptr); ++data_ptr; } } else OS << "NULL"; } break; case DW_FORM_sdata: OS << getSigned(); break; case DW_FORM_udata: OS << getUnsigned(); break; case DW_FORM_strp: { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); const char* dbg_str = getAsCString(&debug_str_data); if (dbg_str) { OS << '"'; OS.write_escaped(dbg_str); OS << '"'; } break; } case DW_FORM_ref_addr: OS << format("0x%016x", uvalue); break; case DW_FORM_ref1: cu_relative_offset = true; OS << format("cu + 0x%2.2x", (uint8_t)uvalue); break; case DW_FORM_ref2: cu_relative_offset = true; OS << format("cu + 0x%4.4x", (uint16_t)uvalue); break; case DW_FORM_ref4: cu_relative_offset = true; OS << format("cu + 0x%4.4x", (uint32_t)uvalue); break; case DW_FORM_ref8: cu_relative_offset = true; OS << format("cu + 0x%8.8llx", uvalue); break; case DW_FORM_ref_udata: cu_relative_offset = true; OS << format("cu + 0x%llx", uvalue); break; // All DW_FORM_indirect attributes should be resolved prior to calling // this function case DW_FORM_indirect: OS << "DW_FORM_indirect"; break; default: OS << format("DW_FORM(0x%4.4x)", Form); break; } if (cu_relative_offset) OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0))); }
void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, const std::string &Component) { // Write the #if guard if (!Component.empty()) { std::string ComponentName = StringRef(Component).upper(); OS << "#ifdef " << ComponentName << "START\n"; OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName << ",\n"; OS << "#undef " << ComponentName << "START\n"; OS << "#endif\n\n"; } const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); std::map<std::string, GroupInfo> DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); DiagCategoryIDMap CategoryIDs(Records); DiagGroupParentMap DGParentMap(Records); // Compute the set of diagnostics that are in -Wpedantic. RecordSet DiagsInPedantic; InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; // Check if this is an error that is accidentally in a warning // group. if (isError(R)) { if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) { const Record *GroupRec = Group->getDef(); const std::string &GroupName = GroupRec->getValueAsString("GroupName"); PrintFatalError(R.getLoc(), "Error " + R.getName() + " cannot be in a warning group [" + GroupName + "]"); } } // Check that all remarks have an associated diagnostic group. if (isRemark(R)) { if (!isa<DefInit>(R.getValueInit("Group"))) { PrintFatalError(R.getLoc(), "Error " + R.getName() + " not in any diagnostic group"); } } // Filter by component. if (!Component.empty() && Component != R.getValueAsString("Component")) continue; OS << "DIAG(" << R.getName() << ", "; OS << R.getValueAsDef("Class")->getName(); OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName(); // Description string. OS << ", \""; OS.write_escaped(R.getValueAsString("Text")) << '"'; // Warning associated with the diagnostic. This is stored as an index into // the alphabetically sorted warning table. if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName")); assert(I != DiagsInGroup.end()); OS << ", " << I->second.IDNo; } else if (DiagsInPedantic.count(&R)) { std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find("pedantic"); assert(I != DiagsInGroup.end() && "pedantic group not defined"); OS << ", " << I->second.IDNo; } else { OS << ", 0"; } // SFINAE response. OS << ", " << R.getValueAsDef("SFINAE")->getName(); // Default warning has no Werror bit. if (R.getValueAsBit("WarningNoWerror")) OS << ", true"; else OS << ", false"; // Default warning show in system header bit. if (R.getValueAsBit("WarningShowInSystemHeader")) OS << ", true"; else OS << ", false"; // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); OS << ")\n"; } }
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker"); llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap; for (unsigned i = 0, e = checkers.size(); i != e; ++i) checkerRecIndexMap[checkers[i]] = i; // Invert the mapping of checkers to package/group into a one to many // mapping of packages/groups to checkers. std::map<std::string, GroupInfo> groupInfoByName; llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap; std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package"); for (unsigned i = 0, e = packages.size(); i != e; ++i) { Record *R = packages[i]; std::string fullName = getPackageFullName(R); if (!fullName.empty()) { GroupInfo &info = groupInfoByName[fullName]; info.Hidden = isHidden(*R); recordGroupMap[R] = &info; } } std::vector<Record*> checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup"); for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) { Record *R = checkerGroups[i]; std::string name = R->getValueAsString("GroupName"); if (!name.empty()) { GroupInfo &info = groupInfoByName[name]; recordGroupMap[R] = &info; } } for (unsigned i = 0, e = checkers.size(); i != e; ++i) { Record *R = checkers[i]; Record *package = 0; if (DefInit * DI = dyn_cast<DefInit>(R->getValueInit("ParentPackage"))) package = DI->getDef(); if (!isCheckerNamed(R) && !package) PrintFatalError(R->getLoc(), "Checker '" + R->getName() + "' is neither named, nor in a package!"); if (isCheckerNamed(R)) { // Create a pseudo-group to hold this checker. std::string fullName = getCheckerFullName(R); GroupInfo &info = groupInfoByName[fullName]; info.Hidden = R->getValueAsBit("Hidden"); recordGroupMap[R] = &info; info.Checkers.insert(R); } else { recordGroupMap[package]->Checkers.insert(R); } Record *currR = isCheckerNamed(R) ? R : package; // Insert the checker and its parent packages into the subgroups set of // the corresponding parent package. while (DefInit *DI = dyn_cast<DefInit>(currR->getValueInit("ParentPackage"))) { Record *parentPackage = DI->getDef(); recordGroupMap[parentPackage]->SubGroups.insert(currR); currR = parentPackage; } // Insert the checker into the set of its group. if (DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"))) recordGroupMap[DI->getDef()]->Checkers.insert(R); } // If a package is in group, add all its checkers and its sub-packages // checkers into the group. for (unsigned i = 0, e = packages.size(); i != e; ++i) if (DefInit *DI = dyn_cast<DefInit>(packages[i]->getValueInit("Group"))) addPackageToCheckerGroup(packages[i], DI->getDef(), recordGroupMap); typedef std::map<std::string, const Record *> SortedRecords; typedef llvm::DenseMap<const Record *, unsigned> RecToSortIndex; SortedRecords sortedGroups; RecToSortIndex groupToSortIndex; OS << "\n#ifdef GET_GROUPS\n"; { for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) sortedGroups[checkerGroups[i]->getValueAsString("GroupName")] = checkerGroups[i]; unsigned sortIndex = 0; for (SortedRecords::iterator I = sortedGroups.begin(), E = sortedGroups.end(); I != E; ++I) { const Record *R = I->second; OS << "GROUP(" << "\""; OS.write_escaped(R->getValueAsString("GroupName")) << "\""; OS << ")\n"; groupToSortIndex[R] = sortIndex++; } } OS << "#endif // GET_GROUPS\n\n"; OS << "\n#ifdef GET_PACKAGES\n"; { SortedRecords sortedPackages; for (unsigned i = 0, e = packages.size(); i != e; ++i) sortedPackages[getPackageFullName(packages[i])] = packages[i]; for (SortedRecords::iterator I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) { const Record &R = *I->second; OS << "PACKAGE(" << "\""; OS.write_escaped(getPackageFullName(&R)) << "\", "; // Group index if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) OS << groupToSortIndex[DI->getDef()] << ", "; else OS << "-1, "; // Hidden bit if (isHidden(R)) OS << "true"; else OS << "false"; OS << ")\n"; } } OS << "#endif // GET_PACKAGES\n\n"; OS << "\n#ifdef GET_CHECKERS\n"; for (unsigned i = 0, e = checkers.size(); i != e; ++i) { const Record &R = *checkers[i]; OS << "CHECKER(" << "\""; std::string name; if (isCheckerNamed(&R)) name = getCheckerFullName(&R); OS.write_escaped(name) << "\", "; OS << R.getName() << ", "; OS << getStringValue(R, "DescFile") << ", "; OS << "\""; OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; // Group index if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) OS << groupToSortIndex[DI->getDef()] << ", "; else OS << "-1, "; // Hidden bit if (isHidden(R)) OS << "true"; else OS << "false"; OS << ")\n"; } OS << "#endif // GET_CHECKERS\n\n"; unsigned index = 0; for (std::map<std::string, GroupInfo>::iterator I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) I->second.Index = index++; // Walk through the packages/groups/checkers emitting an array for each // set of checkers and an array for each set of subpackages. OS << "\n#ifdef GET_MEMBER_ARRAYS\n"; unsigned maxLen = 0; for (std::map<std::string, GroupInfo>::iterator I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) { maxLen = std::max(maxLen, (unsigned)I->first.size()); llvm::DenseSet<const Record *> &checkers = I->second.Checkers; if (!checkers.empty()) { OS << "static const short CheckerArray" << I->second.Index << "[] = { "; // Make the output order deterministic. std::map<int, const Record *> sorted; for (llvm::DenseSet<const Record *>::iterator I = checkers.begin(), E = checkers.end(); I != E; ++I) sorted[(*I)->getID()] = *I; for (std::map<int, const Record *>::iterator I = sorted.begin(), E = sorted.end(); I != E; ++I) OS << checkerRecIndexMap[I->second] << ", "; OS << "-1 };\n"; } llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups; if (!subGroups.empty()) { OS << "static const short SubPackageArray" << I->second.Index << "[] = { "; // Make the output order deterministic. std::map<int, const Record *> sorted; for (llvm::DenseSet<const Record *>::iterator I = subGroups.begin(), E = subGroups.end(); I != E; ++I) sorted[(*I)->getID()] = *I; for (std::map<int, const Record *>::iterator I = sorted.begin(), E = sorted.end(); I != E; ++I) { OS << recordGroupMap[I->second]->Index << ", "; } OS << "-1 };\n"; } } OS << "#endif // GET_MEMBER_ARRAYS\n\n"; OS << "\n#ifdef GET_CHECKNAME_TABLE\n"; for (std::map<std::string, GroupInfo>::iterator I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) { // Group option string. OS << " { \""; OS.write_escaped(I->first) << "\"," << std::string(maxLen-I->first.size()+1, ' '); if (I->second.Checkers.empty()) OS << "0, "; else OS << "CheckerArray" << I->second.Index << ", "; // Subgroups. if (I->second.SubGroups.empty()) OS << "0, "; else OS << "SubPackageArray" << I->second.Index << ", "; OS << (I->second.Hidden ? "true" : "false"); OS << " },\n"; } OS << "#endif // GET_CHECKNAME_TABLE\n\n"; }
void ClangDiagGroupsEmitter::run(raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. DiagGroupParentMap DGParentMap(Records); // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of // groups to diags in the group. std::map<std::string, GroupInfo> DiagsInGroup; std::vector<Record*> Diags = Records.getAllDerivedDefinitions("Diagnostic"); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record *R = Diags[i]; DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group")); if (DI == 0) continue; std::string GroupName = DI->getDef()->getValueAsString("GroupName"); DiagsInGroup[GroupName].DiagsInGroup.push_back(R); } // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty // groups (these are warnings that GCC supports that clang never produces). std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { Record *Group = DiagGroups[i]; GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups"); for (unsigned j = 0, e = SubGroups.size(); j != e; ++j) GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName")); } // Assign unique ID numbers to the groups. unsigned IDNo = 0; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo) I->second.IDNo = IDNo; // Walk through the groups emitting an array for each diagnostic of the diags // that are mapped to. OS << "\n#ifdef GET_DIAG_ARRAYS\n"; unsigned MaxLen = 0; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { MaxLen = std::max(MaxLen, (unsigned)I->first.size()); std::vector<const Record*> &V = I->second.DiagsInGroup; if (!V.empty()) { OS << "static const short DiagArray" << I->second.IDNo << "[] = { "; for (unsigned i = 0, e = V.size(); i != e; ++i) OS << "diag::" << V[i]->getName() << ", "; OS << "-1 };\n"; } const std::vector<std::string> &SubGroups = I->second.SubGroups; if (!SubGroups.empty()) { OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { "; for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) { std::map<std::string, GroupInfo>::iterator RI = DiagsInGroup.find(SubGroups[i]); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } OS << "-1 };\n"; } } OS << "#endif // GET_DIAG_ARRAYS\n\n"; // Emit the table now. OS << "\n#ifdef GET_DIAG_TABLE\n"; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { // Group option string. OS << " { "; OS << I->first.size() << ", "; OS << "\""; OS.write_escaped(I->first) << "\"," << std::string(MaxLen-I->first.size()+1, ' '); // Diagnostics in the group. if (I->second.DiagsInGroup.empty()) OS << "0, "; else OS << "DiagArray" << I->second.IDNo << ", "; // Subgroups. if (I->second.SubGroups.empty()) OS << 0; else OS << "DiagSubGroup" << I->second.IDNo; OS << " },\n"; } OS << "#endif // GET_DIAG_TABLE\n\n"; // Emit the category table next. DiagCategoryIDMap CategoriesByID(Records); OS << "\n#ifdef GET_CATEGORY_TABLE\n"; for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(), E = CategoriesByID.end(); I != E; ++I) OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; }
void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Write the #if guard if (!Component.empty()) { std::string ComponentName = UppercaseString(Component); OS << "#ifdef " << ComponentName << "START\n"; OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName << ",\n"; OS << "#undef " << ComponentName << "START\n"; OS << "#endif\n\n"; } const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); DiagCategoryIDMap CategoryIDs(Records); DiagGroupParentMap DGParentMap(Records); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; // Filter by component. if (!Component.empty() && Component != R.getValueAsString("Component")) continue; OS << "DIAG(" << R.getName() << ", "; OS << R.getValueAsDef("Class")->getName(); OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName(); // Description string. OS << ", \""; OS.write_escaped(R.getValueAsString("Text")) << '"'; // Warning associated with the diagnostic. if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) { OS << ", \""; OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"'; } else { OS << ", \"\""; } // SFINAE bit if (R.getValueAsBit("SFINAE")) OS << ", true"; else OS << ", false"; // Access control bit if (R.getValueAsBit("AccessControl")) OS << ", true"; else OS << ", false"; // FIXME: This condition is just to avoid temporary revlock, it can be // removed. if (R.getValue("WarningNoWerror")) { // Default warning has no Werror bit. if (R.getValueAsBit("WarningNoWerror")) OS << ", true"; else OS << ", false"; // Default warning show in system header bit. if (R.getValueAsBit("WarningShowInSystemHeader")) OS << ", true"; else OS << ", false"; } // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); // Brief OS << ", \""; OS.write_escaped(R.getValueAsString("Brief")) << '"'; // Explanation OS << ", \""; OS.write_escaped(R.getValueAsString("Explanation")) << '"'; OS << ")\n"; } }
void Module::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (IsFramework) OS << "framework "; if (IsExplicit) OS << "explicit "; OS << "module " << Name; if (IsSystem) { OS.indent(Indent + 2); OS << " [system]"; } OS << " {\n"; if (!Requires.empty()) { OS.indent(Indent + 2); OS << "requires "; for (unsigned I = 0, N = Requires.size(); I != N; ++I) { if (I) OS << ", "; OS << Requires[I]; } OS << "\n"; } if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; OS.write_escaped(UmbrellaHeader->getName()); OS << "\"\n"; } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(UmbrellaDir->getName()); OS << "\"\n"; } if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { OS.indent(Indent + 2); OS << "config_macros "; if (ConfigMacrosExhaustive) OS << "[exhaustive]"; for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { if (I) OS << ", "; OS << ConfigMacros[I]; } OS << "\n"; } for (unsigned I = 0, N = NormalHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "header \""; OS.write_escaped(NormalHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "exclude header \""; OS.write_escaped(ExcludedHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = PrivateHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "private header \""; OS.write_escaped(PrivateHeaders[I]->getName()); OS << "\"\n"; } for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; if (Module *Restriction = Exports[I].getPointer()) { OS << Restriction->getFullModuleName(); if (Exports[I].getInt()) OS << ".*"; } else { OS << "*"; } OS << "\n"; } for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; printModuleId(OS, UnresolvedExports[I].Id); if (UnresolvedExports[I].Wildcard) { if (UnresolvedExports[I].Id.empty()) OS << "*"; else OS << ".*"; } OS << "\n"; } for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "link "; if (LinkLibraries[I].IsFramework) OS << "framework "; OS << "\""; OS.write_escaped(LinkLibraries[I].Library); OS << "\""; } for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; printModuleId(OS, UnresolvedConflicts[I].Id); OS << ", \""; OS.write_escaped(UnresolvedConflicts[I].Message); OS << "\"\n"; } for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; OS << Conflicts[I].Other->getFullModuleName(); OS << ", \""; OS.write_escaped(Conflicts[I].Message); OS << "\"\n"; } if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) OS << "explicit "; OS << "module * {\n"; if (InferExportWildcard) { OS.indent(Indent + 4); OS << "export *\n"; } OS.indent(Indent + 2); OS << "}\n"; } OS.indent(Indent); OS << "}\n"; }
void Module::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (IsFramework) OS << "framework "; if (IsExplicit) OS << "explicit "; OS << "module " << Name; if (IsSystem || IsExternC) { OS.indent(Indent + 2); if (IsSystem) OS << " [system]"; if (IsExternC) OS << " [extern_c]"; } OS << " {\n"; if (!Requirements.empty()) { OS.indent(Indent + 2); OS << "requires "; for (unsigned I = 0, N = Requirements.size(); I != N; ++I) { if (I) OS << ", "; if (!Requirements[I].second) OS << "!"; OS << Requirements[I].first; } OS << "\n"; } if (Header H = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; OS.write_escaped(H.NameAsWritten); OS << "\"\n"; } else if (DirectoryName D = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(D.NameAsWritten); OS << "\"\n"; } if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { OS.indent(Indent + 2); OS << "config_macros "; if (ConfigMacrosExhaustive) OS << "[exhaustive]"; for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { if (I) OS << ", "; OS << ConfigMacros[I]; } OS << "\n"; } struct { StringRef Prefix; HeaderKind Kind; } Kinds[] = {{"", HK_Normal}, {"textual ", HK_Textual}, {"private ", HK_Private}, {"private textual ", HK_PrivateTextual}, {"exclude ", HK_Excluded}}; for (auto &K : Kinds) { for (auto &H : Headers[K.Kind]) { OS.indent(Indent + 2); OS << K.Prefix << "header \""; OS.write_escaped(H.NameAsWritten); OS << "\"\n"; } } for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) // Print inferred subframework modules so that we don't need to re-infer // them (requires expensive directory iteration + stat calls) when we build // the module. Regular inferred submodules are OK, as we need to look at all // those header files anyway. if (!(*MI)->IsInferred || (*MI)->IsFramework) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; if (Module *Restriction = Exports[I].getPointer()) { OS << Restriction->getFullModuleName(); if (Exports[I].getInt()) OS << ".*"; } else { OS << "*"; } OS << "\n"; } for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; printModuleId(OS, UnresolvedExports[I].Id); if (UnresolvedExports[I].Wildcard) OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*"); OS << "\n"; } for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; OS << DirectUses[I]->getFullModuleName(); OS << "\n"; } for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; printModuleId(OS, UnresolvedDirectUses[I]); OS << "\n"; } for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "link "; if (LinkLibraries[I].IsFramework) OS << "framework "; OS << "\""; OS.write_escaped(LinkLibraries[I].Library); OS << "\""; } for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; printModuleId(OS, UnresolvedConflicts[I].Id); OS << ", \""; OS.write_escaped(UnresolvedConflicts[I].Message); OS << "\"\n"; } for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; OS << Conflicts[I].Other->getFullModuleName(); OS << ", \""; OS.write_escaped(Conflicts[I].Message); OS << "\"\n"; } if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) OS << "explicit "; OS << "module * {\n"; if (InferExportWildcard) { OS.indent(Indent + 4); OS << "export *\n"; } OS.indent(Indent + 2); OS << "}\n"; } OS.indent(Indent); OS << "}\n"; }
void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. DiagGroupParentMap DGParentMap(Records); std::vector<Record*> Diags = Records.getAllDerivedDefinitions("Diagnostic"); std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); std::map<std::string, GroupInfo> DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); // All extensions are implicitly in the "pedantic" group. Record the // implicit set of groups in the "pedantic" group, and use this information // later when emitting the group information for Pedantic. RecordVec DiagsInPedantic; RecordVec GroupsInPedantic; InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); // Walk through the groups emitting an array for each diagnostic of the diags // that are mapped to. OS << "\n#ifdef GET_DIAG_ARRAYS\n"; unsigned MaxLen = 0; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { MaxLen = std::max(MaxLen, (unsigned)I->first.size()); const bool IsPedantic = I->first == "pedantic"; std::vector<const Record*> &V = I->second.DiagsInGroup; if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) { OS << "static const short DiagArray" << I->second.IDNo << "[] = { "; for (unsigned i = 0, e = V.size(); i != e; ++i) OS << "diag::" << V[i]->getName() << ", "; // Emit the diagnostics implicitly in "pedantic". if (IsPedantic) { for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i) OS << "diag::" << DiagsInPedantic[i]->getName() << ", "; } OS << "-1 };\n"; } const std::vector<std::string> &SubGroups = I->second.SubGroups; if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) { OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { "; for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) { std::map<std::string, GroupInfo>::iterator RI = DiagsInGroup.find(SubGroups[i]); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } // Emit the groups implicitly in "pedantic". if (IsPedantic) { for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) { const std::string &GroupName = GroupsInPedantic[i]->getValueAsString("GroupName"); std::map<std::string, GroupInfo>::iterator RI = DiagsInGroup.find(GroupName); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } } OS << "-1 };\n"; } } OS << "#endif // GET_DIAG_ARRAYS\n\n"; // Emit the table now. OS << "\n#ifdef GET_DIAG_TABLE\n"; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { // Group option string. OS << " { "; OS << I->first.size() << ", "; OS << "\""; if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789!@#$%^*-+=:?")!=std::string::npos) PrintFatalError("Invalid character in diagnostic group '" + I->first + "'"); OS.write_escaped(I->first) << "\"," << std::string(MaxLen-I->first.size()+1, ' '); // Special handling for 'pedantic'. const bool IsPedantic = I->first == "pedantic"; // Diagnostics in the group. const bool hasDiags = !I->second.DiagsInGroup.empty() || (IsPedantic && !DiagsInPedantic.empty()); if (!hasDiags) OS << "0, "; else OS << "DiagArray" << I->second.IDNo << ", "; // Subgroups. const bool hasSubGroups = !I->second.SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty()); if (!hasSubGroups) OS << 0; else OS << "DiagSubGroup" << I->second.IDNo; OS << " },\n"; } OS << "#endif // GET_DIAG_TABLE\n\n"; // Emit the category table next. DiagCategoryIDMap CategoriesByID(Records); OS << "\n#ifdef GET_CATEGORY_TABLE\n"; for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(), E = CategoriesByID.end(); I != E; ++I) OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; }
void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, const std::string &Component) { // Write the #if guard if (!Component.empty()) { std::string ComponentName = StringRef(Component).upper(); OS << "#ifdef " << ComponentName << "START\n"; OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName << ",\n"; OS << "#undef " << ComponentName << "START\n"; OS << "#endif\n\n"; } const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); std::map<std::string, GroupInfo> DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); DiagCategoryIDMap CategoryIDs(Records); DiagGroupParentMap DGParentMap(Records); // Compute the set of diagnostics that are in -Wpedantic. RecordSet DiagsInPedantic; InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; // Filter by component. if (!Component.empty() && Component != R.getValueAsString("Component")) continue; OS << "DIAG(" << R.getName() << ", "; OS << R.getValueAsDef("Class")->getName(); OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName(); // Description string. OS << ", \""; OS.write_escaped(R.getValueAsString("Text")) << '"'; // Warning associated with the diagnostic. This is stored as an index into // the alphabetically sorted warning table. if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) { std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName")); assert(I != DiagsInGroup.end()); OS << ", " << I->second.IDNo; } else if (DiagsInPedantic.count(&R)) { std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find("pedantic"); assert(I != DiagsInGroup.end() && "pedantic group not defined"); OS << ", " << I->second.IDNo; } else { OS << ", 0"; } // SFINAE bit if (R.getValueAsBit("SFINAE")) OS << ", true"; else OS << ", false"; // Access control bit if (R.getValueAsBit("AccessControl")) OS << ", true"; else OS << ", false"; // FIXME: This condition is just to avoid temporary revlock, it can be // removed. if (R.getValue("WarningNoWerror")) { // Default warning has no Werror bit. if (R.getValueAsBit("WarningNoWerror")) OS << ", true"; else OS << ", false"; // Default warning show in system header bit. if (R.getValueAsBit("WarningShowInSystemHeader")) OS << ", true"; else OS << ", false"; } // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); OS << ")\n"; } }