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:
getDescriptionmcld::__anon0a5653a50111::DiagStaticInfo33   llvm::StringRef getDescription() const {
34     return llvm::StringRef(DescriptionStr, DescriptionLen);
35   }
36 
operator <mcld::__anon0a5653a50111::DiagStaticInfo37   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 
getDiagInfo(unsigned int pID,bool pInLoC=false)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 //===----------------------------------------------------------------------===//
DiagnosticInfos(const LinkerConfig & pConfig)100 DiagnosticInfos::DiagnosticInfos(const LinkerConfig& pConfig)
101     : m_Config(pConfig) {
102 }
103 
~DiagnosticInfos()104 DiagnosticInfos::~DiagnosticInfos() {
105 }
106 
getDescription(unsigned int pID,bool pInLoC) const107 llvm::StringRef DiagnosticInfos::getDescription(unsigned int pID,
108                                                 bool pInLoC) const {
109   return getDiagInfo(pID, pInLoC)->getDescription();
110 }
111 
process(DiagnosticEngine & pEngine) const112 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