1 //===- DiagnosticInfo.cpp -------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "mcld/LD/DiagnosticInfos.h" 10 11 #include "mcld/LinkerConfig.h" 12 #include "mcld/ADT/SizeTraits.h" 13 #include "mcld/LD/Diagnostic.h" 14 #include "mcld/LD/DiagnosticPrinter.h" 15 16 #include <llvm/ADT/StringRef.h> 17 #include <llvm/Support/DataTypes.h> 18 19 #include <algorithm> 20 21 namespace mcld { 22 23 namespace { 24 25 struct DiagStaticInfo { 26 public: 27 uint16_t ID; 28 DiagnosticEngine::Severity Severity; 29 uint16_t DescriptionLen; 30 const char* DescriptionStr; 31 32 public: 33 llvm::StringRef getDescription() const { 34 return llvm::StringRef(DescriptionStr, DescriptionLen); 35 } 36 37 bool operator<(const DiagStaticInfo& pRHS) const { return (ID < pRHS.ID); } 38 }; 39 40 } // anonymous namespace 41 42 static const DiagStaticInfo DiagCommonInfo[] = { 43 #define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \ 44 { diag::ENUM, CLASS, STR_SIZE(ADDRDESC, uint16_t), ADDRDESC } \ 45 , 46 #include "mcld/LD/DiagAttribute.inc" // NOLINT [build/include] [4] 47 #include "mcld/LD/DiagCommonKinds.inc" // NOLINT [build/include] [4] 48 #include "mcld/LD/DiagReaders.inc" // NOLINT [build/include] [4] 49 #include "mcld/LD/DiagSymbolResolutions.inc" // NOLINT [build/include] [4] 50 #include "mcld/LD/DiagRelocations.inc" // NOLINT [build/include] [4] 51 #include "mcld/LD/DiagLayouts.inc" // NOLINT [build/include] [4] 52 #include "mcld/LD/DiagGOTPLT.inc" // NOLINT [build/include] [4] 53 #include "mcld/LD/DiagLDScript.inc" // NOLINT [build/include] [4] 54 #include "mcld/LD/DiagMips.inc" // NOLINT [build/include] [4] 55 #undef DIAG 56 {0, DiagnosticEngine::None, 0, 0}}; 57 58 static const unsigned int DiagCommonInfoSize = 59 sizeof(DiagCommonInfo) / sizeof(DiagCommonInfo[0]) - 1; 60 61 static const DiagStaticInfo DiagLoCInfo[] = { 62 #define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \ 63 { diag::ENUM, CLASS, STR_SIZE(LOCDESC, uint16_t), LOCDESC } \ 64 , 65 #include "mcld/LD/DiagAttribute.inc" // NOLINT [build/include] [4] 66 #include "mcld/LD/DiagCommonKinds.inc" // NOLINT [build/include] [4] 67 #include "mcld/LD/DiagReaders.inc" // NOLINT [build/include] [4] 68 #include "mcld/LD/DiagSymbolResolutions.inc" // NOLINT [build/include] [4] 69 #include "mcld/LD/DiagRelocations.inc" // NOLINT [build/include] [4] 70 #include "mcld/LD/DiagLayouts.inc" // NOLINT [build/include] [4] 71 #include "mcld/LD/DiagGOTPLT.inc" // NOLINT [build/include] [4] 72 #include "mcld/LD/DiagLDScript.inc" // NOLINT [build/include] [4] 73 #include "mcld/LD/DiagMips.inc" // NOLINT [build/include] [4] 74 #undef DIAG 75 {0, DiagnosticEngine::None, 0, 0}}; 76 77 static const unsigned int DiagLoCInfoSize = 78 sizeof(DiagLoCInfo) / sizeof(DiagLoCInfo[0]) - 1; 79 80 static const DiagStaticInfo* getDiagInfo(unsigned int pID, 81 bool pInLoC = false) { 82 const DiagStaticInfo* static_info = (pInLoC) ? DiagLoCInfo : DiagCommonInfo; 83 unsigned int info_size = (pInLoC) ? DiagLoCInfoSize : DiagCommonInfoSize; 84 85 DiagStaticInfo key = { 86 static_cast<uint16_t>(pID), DiagnosticEngine::None, 0, 0}; 87 88 const DiagStaticInfo* result = 89 std::lower_bound(static_info, static_info + info_size, key); 90 91 if (result == (static_info + info_size) || result->ID != pID) 92 return NULL; 93 94 return result; 95 } 96 97 //===----------------------------------------------------------------------===// 98 // DiagnosticInfos 99 //===----------------------------------------------------------------------===// 100 DiagnosticInfos::DiagnosticInfos(const LinkerConfig& pConfig) 101 : m_Config(pConfig) { 102 } 103 104 DiagnosticInfos::~DiagnosticInfos() { 105 } 106 107 llvm::StringRef DiagnosticInfos::getDescription(unsigned int pID, 108 bool pInLoC) const { 109 return getDiagInfo(pID, pInLoC)->getDescription(); 110 } 111 112 bool DiagnosticInfos::process(DiagnosticEngine& pEngine) const { 113 Diagnostic info(pEngine); 114 115 unsigned int ID = info.getID(); 116 117 // we are not implement LineInfo, so keep pIsLoC false. 118 const DiagStaticInfo* static_info = getDiagInfo(ID); 119 120 DiagnosticEngine::Severity severity = static_info->Severity; 121 122 switch (ID) { 123 case diag::multiple_definitions: { 124 if (m_Config.options().isMulDefs()) { 125 severity = DiagnosticEngine::Ignore; 126 } 127 break; 128 } 129 case diag::undefined_reference: 130 case diag::undefined_reference_text: { 131 // we have not implement --unresolved-symbols=method yet. So far, MCLinker 132 // provides the easier --allow-shlib-undefined and --no-undefined (i.e. 133 // -z defs) 134 switch (m_Config.codeGenType()) { 135 case LinkerConfig::Object: 136 if (m_Config.options().isNoUndefined()) 137 severity = DiagnosticEngine::Error; 138 else 139 severity = DiagnosticEngine::Ignore; 140 break; 141 case LinkerConfig::DynObj: 142 if (m_Config.options().isNoUndefined()) 143 severity = DiagnosticEngine::Error; 144 else 145 severity = DiagnosticEngine::Ignore; 146 break; 147 default: 148 severity = DiagnosticEngine::Error; 149 break; 150 } 151 break; 152 } 153 case diag::debug_print_gc_sections: { 154 if (!m_Config.options().getPrintGCSections()) 155 severity = DiagnosticEngine::Ignore; 156 break; 157 } 158 default: 159 break; 160 } // end of switch 161 162 // If --fatal-warnings is turned on, then switch warnings and errors to fatal 163 if (m_Config.options().isFatalWarnings()) { 164 if (severity == DiagnosticEngine::Warning || 165 severity == DiagnosticEngine::Error) { 166 severity = DiagnosticEngine::Fatal; 167 } 168 } 169 170 // finally, report it. 171 pEngine.getPrinter()->handleDiagnostic(severity, info); 172 return true; 173 } 174 175 } // namespace mcld 176