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 21namespace mcld { 22 23namespace { 24 25struct 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 42static 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 58static const unsigned int DiagCommonInfoSize = 59 sizeof(DiagCommonInfo) / sizeof(DiagCommonInfo[0]) - 1; 60 61static 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 77static const unsigned int DiagLoCInfoSize = 78 sizeof(DiagLoCInfo) / sizeof(DiagLoCInfo[0]) - 1; 79 80static 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//===----------------------------------------------------------------------===// 100DiagnosticInfos::DiagnosticInfos(const LinkerConfig& pConfig) 101 : m_Config(pConfig) { 102} 103 104DiagnosticInfos::~DiagnosticInfos() { 105} 106 107llvm::StringRef DiagnosticInfos::getDescription(unsigned int pID, 108 bool pInLoC) const { 109 return getDiagInfo(pID, pInLoC)->getDescription(); 110} 111 112bool 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