/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h
Line | Count | Source |
1 | | //===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLVM_CLANG_AST_ODRDIAGSEMITTER_H |
10 | | #define LLVM_CLANG_AST_ODRDIAGSEMITTER_H |
11 | | |
12 | | #include "clang/AST/ASTContext.h" |
13 | | #include "clang/AST/DeclCXX.h" |
14 | | #include "clang/AST/DeclObjC.h" |
15 | | #include "clang/Basic/Diagnostic.h" |
16 | | #include "clang/Basic/LangOptions.h" |
17 | | |
18 | | namespace clang { |
19 | | |
20 | | class ODRDiagsEmitter { |
21 | | public: |
22 | | ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context, |
23 | | const LangOptions &LangOpts) |
24 | 399 | : Diags(Diags), Context(Context), LangOpts(LangOpts) {} |
25 | | |
26 | | /// Diagnose ODR mismatch between 2 FunctionDecl. |
27 | | /// |
28 | | /// Returns true if found a mismatch and diagnosed it. |
29 | | bool diagnoseMismatch(const FunctionDecl *FirstFunction, |
30 | | const FunctionDecl *SecondFunction) const; |
31 | | |
32 | | /// Diagnose ODR mismatch between 2 EnumDecl. |
33 | | /// |
34 | | /// Returns true if found a mismatch and diagnosed it. |
35 | | bool diagnoseMismatch(const EnumDecl *FirstEnum, |
36 | | const EnumDecl *SecondEnum) const; |
37 | | |
38 | | /// Diagnose ODR mismatch between 2 CXXRecordDecl. |
39 | | /// |
40 | | /// Returns true if found a mismatch and diagnosed it. |
41 | | /// To compare 2 declarations with merged and identical definition data |
42 | | /// you need to provide pre-merge definition data in \p SecondDD. |
43 | | bool |
44 | | diagnoseMismatch(const CXXRecordDecl *FirstRecord, |
45 | | const CXXRecordDecl *SecondRecord, |
46 | | const struct CXXRecordDecl::DefinitionData *SecondDD) const; |
47 | | |
48 | | /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl. |
49 | | /// |
50 | | /// Returns true if found a mismatch and diagnosed it. |
51 | | bool diagnoseMismatch(const RecordDecl *FirstRecord, |
52 | | const RecordDecl *SecondRecord) const; |
53 | | |
54 | | /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl. |
55 | | /// |
56 | | /// Returns true if found a mismatch and diagnosed it. |
57 | | bool diagnoseMismatch( |
58 | | const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, |
59 | | const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const; |
60 | | |
61 | | /// Diagnose ODR mismatch between ObjCInterfaceDecl with different |
62 | | /// definitions. |
63 | | bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID, |
64 | 31 | const ObjCInterfaceDecl *SecondID) const { |
65 | 31 | assert(FirstID->data().Definition != SecondID->data().Definition && |
66 | 31 | "Don't diagnose differences when definitions are merged already"); |
67 | 31 | return diagnoseMismatch(FirstID, SecondID, &SecondID->data()); |
68 | 31 | } |
69 | | |
70 | | /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. |
71 | | /// |
72 | | /// Returns true if found a mismatch and diagnosed it. |
73 | | /// To compare 2 declarations with merged and identical definition data |
74 | | /// you need to provide pre-merge definition data in \p SecondDD. |
75 | | bool diagnoseMismatch( |
76 | | const ObjCProtocolDecl *FirstProtocol, |
77 | | const ObjCProtocolDecl *SecondProtocol, |
78 | | const struct ObjCProtocolDecl::DefinitionData *SecondDD) const; |
79 | | |
80 | | /// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions. |
81 | | bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol, |
82 | 22 | const ObjCProtocolDecl *SecondProtocol) const { |
83 | 22 | assert(FirstProtocol->data().Definition != |
84 | 22 | SecondProtocol->data().Definition && |
85 | 22 | "Don't diagnose differences when definitions are merged already"); |
86 | 22 | return diagnoseMismatch(FirstProtocol, SecondProtocol, |
87 | 22 | &SecondProtocol->data()); |
88 | 22 | } |
89 | | |
90 | | /// Get the best name we know for the module that owns the given |
91 | | /// declaration, or an empty string if the declaration is not from a module. |
92 | | static std::string getOwningModuleNameForDiagnostic(const Decl *D); |
93 | | |
94 | | private: |
95 | | using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>; |
96 | | |
97 | | // Used with err_module_odr_violation_mismatch_decl, |
98 | | // note_module_odr_violation_mismatch_decl, |
99 | | // err_module_odr_violation_mismatch_decl_unknown, |
100 | | // and note_module_odr_violation_mismatch_decl_unknown |
101 | | // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed |
102 | | enum ODRMismatchDecl { |
103 | | EndOfClass, |
104 | | PublicSpecifer, |
105 | | PrivateSpecifer, |
106 | | ProtectedSpecifer, |
107 | | StaticAssert, |
108 | | Field, |
109 | | CXXMethod, |
110 | | TypeAlias, |
111 | | TypeDef, |
112 | | Var, |
113 | | Friend, |
114 | | FunctionTemplate, |
115 | | ObjCMethod, |
116 | | ObjCIvar, |
117 | | ObjCProperty, |
118 | | Other |
119 | | }; |
120 | | |
121 | | struct DiffResult { |
122 | | const Decl *FirstDecl = nullptr, *SecondDecl = nullptr; |
123 | | ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other; |
124 | | }; |
125 | | |
126 | | // If there is a diagnoseable difference, FirstDiffType and |
127 | | // SecondDiffType will not be Other and FirstDecl and SecondDecl will be |
128 | | // filled in if not EndOfClass. |
129 | | static DiffResult FindTypeDiffs(DeclHashes &FirstHashes, |
130 | | DeclHashes &SecondHashes); |
131 | | |
132 | 618 | DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const { |
133 | 618 | return Diags.Report(Loc, DiagID); |
134 | 618 | } |
135 | | |
136 | | // Use this to diagnose that an unexpected Decl was encountered |
137 | | // or no difference was detected. This causes a generic error |
138 | | // message to be emitted. |
139 | | void diagnoseSubMismatchUnexpected(DiffResult &DR, |
140 | | const NamedDecl *FirstRecord, |
141 | | StringRef FirstModule, |
142 | | const NamedDecl *SecondRecord, |
143 | | StringRef SecondModule) const; |
144 | | |
145 | | void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR, |
146 | | const NamedDecl *FirstRecord, |
147 | | StringRef FirstModule, |
148 | | const NamedDecl *SecondRecord, |
149 | | StringRef SecondModule) const; |
150 | | |
151 | | bool diagnoseSubMismatchField(const NamedDecl *FirstRecord, |
152 | | StringRef FirstModule, StringRef SecondModule, |
153 | | const FieldDecl *FirstField, |
154 | | const FieldDecl *SecondField) const; |
155 | | |
156 | | bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord, |
157 | | StringRef FirstModule, StringRef SecondModule, |
158 | | const TypedefNameDecl *FirstTD, |
159 | | const TypedefNameDecl *SecondTD, |
160 | | bool IsTypeAlias) const; |
161 | | |
162 | | bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord, |
163 | | StringRef FirstModule, StringRef SecondModule, |
164 | | const VarDecl *FirstVD, |
165 | | const VarDecl *SecondVD) const; |
166 | | |
167 | | /// Check if protocol lists are the same and diagnose if they are different. |
168 | | /// |
169 | | /// Returns true if found a mismatch and diagnosed it. |
170 | | bool diagnoseSubMismatchProtocols(const ObjCProtocolList &FirstProtocols, |
171 | | const ObjCContainerDecl *FirstContainer, |
172 | | StringRef FirstModule, |
173 | | const ObjCProtocolList &SecondProtocols, |
174 | | const ObjCContainerDecl *SecondContainer, |
175 | | StringRef SecondModule) const; |
176 | | |
177 | | /// Check if Objective-C methods are the same and diagnose if different. |
178 | | /// |
179 | | /// Returns true if found a mismatch and diagnosed it. |
180 | | bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer, |
181 | | StringRef FirstModule, |
182 | | StringRef SecondModule, |
183 | | const ObjCMethodDecl *FirstMethod, |
184 | | const ObjCMethodDecl *SecondMethod) const; |
185 | | |
186 | | /// Check if Objective-C properties are the same and diagnose if different. |
187 | | /// |
188 | | /// Returns true if found a mismatch and diagnosed it. |
189 | | bool |
190 | | diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer, |
191 | | StringRef FirstModule, StringRef SecondModule, |
192 | | const ObjCPropertyDecl *FirstProp, |
193 | | const ObjCPropertyDecl *SecondProp) const; |
194 | | |
195 | | private: |
196 | | DiagnosticsEngine &Diags; |
197 | | const ASTContext &Context; |
198 | | const LangOptions &LangOpts; |
199 | | }; |
200 | | |
201 | | } // namespace clang |
202 | | |
203 | | #endif |