1 //===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_AST_ODRDIAGSEMITTER_H
10 #define LLVM_CLANG_AST_ODRDIAGSEMITTER_H
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"
20 class ODRDiagsEmitter {
22 ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context,
23 const LangOptions &LangOpts)
24 : Diags(Diags), Context(Context), LangOpts(LangOpts) {}
26 /// Diagnose ODR mismatch between 2 FunctionDecl.
28 /// Returns true if found a mismatch and diagnosed it.
29 bool diagnoseMismatch(const FunctionDecl *FirstFunction,
30 const FunctionDecl *SecondFunction) const;
32 /// Diagnose ODR mismatch between 2 EnumDecl.
34 /// Returns true if found a mismatch and diagnosed it.
35 bool diagnoseMismatch(const EnumDecl *FirstEnum,
36 const EnumDecl *SecondEnum) const;
38 /// Diagnose ODR mismatch between 2 CXXRecordDecl.
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.
44 diagnoseMismatch(const CXXRecordDecl *FirstRecord,
45 const CXXRecordDecl *SecondRecord,
46 const struct CXXRecordDecl::DefinitionData *SecondDD) const;
48 /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl.
50 /// Returns true if found a mismatch and diagnosed it.
51 bool diagnoseMismatch(const RecordDecl *FirstRecord,
52 const RecordDecl *SecondRecord) const;
54 /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl.
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;
61 /// Diagnose ODR mismatch between ObjCInterfaceDecl with different
63 bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID,
64 const ObjCInterfaceDecl *SecondID) const {
65 assert(FirstID->data().Definition != SecondID->data().Definition &&
66 "Don't diagnose differences when definitions are merged already");
67 return diagnoseMismatch(FirstID, SecondID, &SecondID->data());
70 /// Diagnose ODR mismatch between 2 ObjCProtocolDecl.
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;
80 /// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions.
81 bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol,
82 const ObjCProtocolDecl *SecondProtocol) const {
83 assert(FirstProtocol->data().Definition !=
84 SecondProtocol->data().Definition &&
85 "Don't diagnose differences when definitions are merged already");
86 return diagnoseMismatch(FirstProtocol, SecondProtocol,
87 &SecondProtocol->data());
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);
95 using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>;
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 {
122 const Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
123 ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
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);
132 DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const {
133 return Diags.Report(Loc, DiagID);
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;
145 void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR,
146 const NamedDecl *FirstRecord,
147 StringRef FirstModule,
148 const NamedDecl *SecondRecord,
149 StringRef SecondModule) const;
151 bool diagnoseSubMismatchField(const NamedDecl *FirstRecord,
152 StringRef FirstModule, StringRef SecondModule,
153 const FieldDecl *FirstField,
154 const FieldDecl *SecondField) const;
156 bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord,
157 StringRef FirstModule, StringRef SecondModule,
158 const TypedefNameDecl *FirstTD,
159 const TypedefNameDecl *SecondTD,
160 bool IsTypeAlias) const;
162 bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord,
163 StringRef FirstModule, StringRef SecondModule,
164 const VarDecl *FirstVD,
165 const VarDecl *SecondVD) const;
167 /// Check if protocol lists are the same and diagnose if they are different.
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;
177 /// Check if Objective-C methods are the same and diagnose if different.
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;
186 /// Check if Objective-C properties are the same and diagnose if different.
188 /// Returns true if found a mismatch and diagnosed it.
190 diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer,
191 StringRef FirstModule, StringRef SecondModule,
192 const ObjCPropertyDecl *FirstProp,
193 const ObjCPropertyDecl *SecondProp) const;
196 DiagnosticsEngine &Diags;
197 const ASTContext &Context;
198 const LangOptions &LangOpts;