Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:38

0001 //===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_AST_ODRDIAGSEMITTER_H
0010 #define LLVM_CLANG_AST_ODRDIAGSEMITTER_H
0011 
0012 #include "clang/AST/ASTContext.h"
0013 #include "clang/AST/DeclCXX.h"
0014 #include "clang/AST/DeclObjC.h"
0015 #include "clang/Basic/Diagnostic.h"
0016 #include "clang/Basic/LangOptions.h"
0017 
0018 namespace clang {
0019 
0020 class ODRDiagsEmitter {
0021 public:
0022   ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context,
0023                   const LangOptions &LangOpts)
0024       : Diags(Diags), Context(Context), LangOpts(LangOpts) {}
0025 
0026   /// Diagnose ODR mismatch between 2 FunctionDecl.
0027   ///
0028   /// Returns true if found a mismatch and diagnosed it.
0029   bool diagnoseMismatch(const FunctionDecl *FirstFunction,
0030                         const FunctionDecl *SecondFunction) const;
0031 
0032   /// Diagnose ODR mismatch between 2 EnumDecl.
0033   ///
0034   /// Returns true if found a mismatch and diagnosed it.
0035   bool diagnoseMismatch(const EnumDecl *FirstEnum,
0036                         const EnumDecl *SecondEnum) const;
0037 
0038   /// Diagnose ODR mismatch between 2 CXXRecordDecl.
0039   ///
0040   /// Returns true if found a mismatch and diagnosed it.
0041   /// To compare 2 declarations with merged and identical definition data
0042   /// you need to provide pre-merge definition data in \p SecondDD.
0043   bool
0044   diagnoseMismatch(const CXXRecordDecl *FirstRecord,
0045                    const CXXRecordDecl *SecondRecord,
0046                    const struct CXXRecordDecl::DefinitionData *SecondDD) const;
0047 
0048   /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl.
0049   ///
0050   /// Returns true if found a mismatch and diagnosed it.
0051   bool diagnoseMismatch(const RecordDecl *FirstRecord,
0052                         const RecordDecl *SecondRecord) const;
0053 
0054   /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl.
0055   ///
0056   /// Returns true if found a mismatch and diagnosed it.
0057   bool diagnoseMismatch(
0058       const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
0059       const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const;
0060 
0061   /// Diagnose ODR mismatch between ObjCInterfaceDecl with different
0062   /// definitions.
0063   bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID,
0064                         const ObjCInterfaceDecl *SecondID) const {
0065     assert(FirstID->data().Definition != SecondID->data().Definition &&
0066            "Don't diagnose differences when definitions are merged already");
0067     return diagnoseMismatch(FirstID, SecondID, &SecondID->data());
0068   }
0069 
0070   /// Diagnose ODR mismatch between 2 ObjCProtocolDecl.
0071   ///
0072   /// Returns true if found a mismatch and diagnosed it.
0073   /// To compare 2 declarations with merged and identical definition data
0074   /// you need to provide pre-merge definition data in \p SecondDD.
0075   bool diagnoseMismatch(
0076       const ObjCProtocolDecl *FirstProtocol,
0077       const ObjCProtocolDecl *SecondProtocol,
0078       const struct ObjCProtocolDecl::DefinitionData *SecondDD) const;
0079 
0080   /// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions.
0081   bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol,
0082                         const ObjCProtocolDecl *SecondProtocol) const {
0083     assert(FirstProtocol->data().Definition !=
0084                SecondProtocol->data().Definition &&
0085            "Don't diagnose differences when definitions are merged already");
0086     return diagnoseMismatch(FirstProtocol, SecondProtocol,
0087                             &SecondProtocol->data());
0088   }
0089 
0090   /// Get the best name we know for the module that owns the given
0091   /// declaration, or an empty string if the declaration is not from a module.
0092   static std::string getOwningModuleNameForDiagnostic(const Decl *D);
0093 
0094 private:
0095   using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>;
0096 
0097   // Used with err_module_odr_violation_mismatch_decl,
0098   // note_module_odr_violation_mismatch_decl,
0099   // err_module_odr_violation_mismatch_decl_unknown,
0100   // and note_module_odr_violation_mismatch_decl_unknown
0101   // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed
0102   enum ODRMismatchDecl {
0103     EndOfClass,
0104     PublicSpecifer,
0105     PrivateSpecifer,
0106     ProtectedSpecifer,
0107     StaticAssert,
0108     Field,
0109     CXXMethod,
0110     TypeAlias,
0111     TypeDef,
0112     Var,
0113     Friend,
0114     FunctionTemplate,
0115     ObjCMethod,
0116     ObjCIvar,
0117     ObjCProperty,
0118     Other
0119   };
0120 
0121   struct DiffResult {
0122     const Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
0123     ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
0124   };
0125 
0126   // If there is a diagnoseable difference, FirstDiffType and
0127   // SecondDiffType will not be Other and FirstDecl and SecondDecl will be
0128   // filled in if not EndOfClass.
0129   static DiffResult FindTypeDiffs(DeclHashes &FirstHashes,
0130                                   DeclHashes &SecondHashes);
0131 
0132   DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const {
0133     return Diags.Report(Loc, DiagID);
0134   }
0135 
0136   // Use this to diagnose that an unexpected Decl was encountered
0137   // or no difference was detected. This causes a generic error
0138   // message to be emitted.
0139   void diagnoseSubMismatchUnexpected(DiffResult &DR,
0140                                      const NamedDecl *FirstRecord,
0141                                      StringRef FirstModule,
0142                                      const NamedDecl *SecondRecord,
0143                                      StringRef SecondModule) const;
0144 
0145   void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR,
0146                                              const NamedDecl *FirstRecord,
0147                                              StringRef FirstModule,
0148                                              const NamedDecl *SecondRecord,
0149                                              StringRef SecondModule) const;
0150 
0151   bool diagnoseSubMismatchField(const NamedDecl *FirstRecord,
0152                                 StringRef FirstModule, StringRef SecondModule,
0153                                 const FieldDecl *FirstField,
0154                                 const FieldDecl *SecondField) const;
0155 
0156   bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord,
0157                                   StringRef FirstModule, StringRef SecondModule,
0158                                   const TypedefNameDecl *FirstTD,
0159                                   const TypedefNameDecl *SecondTD,
0160                                   bool IsTypeAlias) const;
0161 
0162   bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord,
0163                               StringRef FirstModule, StringRef SecondModule,
0164                               const VarDecl *FirstVD,
0165                               const VarDecl *SecondVD) const;
0166 
0167   /// Check if protocol lists are the same and diagnose if they are different.
0168   ///
0169   /// Returns true if found a mismatch and diagnosed it.
0170   bool diagnoseSubMismatchProtocols(const ObjCProtocolList &FirstProtocols,
0171                                     const ObjCContainerDecl *FirstContainer,
0172                                     StringRef FirstModule,
0173                                     const ObjCProtocolList &SecondProtocols,
0174                                     const ObjCContainerDecl *SecondContainer,
0175                                     StringRef SecondModule) const;
0176 
0177   /// Check if Objective-C methods are the same and diagnose if different.
0178   ///
0179   /// Returns true if found a mismatch and diagnosed it.
0180   bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer,
0181                                      StringRef FirstModule,
0182                                      StringRef SecondModule,
0183                                      const ObjCMethodDecl *FirstMethod,
0184                                      const ObjCMethodDecl *SecondMethod) const;
0185 
0186   /// Check if Objective-C properties are the same and diagnose if different.
0187   ///
0188   /// Returns true if found a mismatch and diagnosed it.
0189   bool
0190   diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer,
0191                                   StringRef FirstModule, StringRef SecondModule,
0192                                   const ObjCPropertyDecl *FirstProp,
0193                                   const ObjCPropertyDecl *SecondProp) const;
0194 
0195 private:
0196   DiagnosticsEngine &Diags;
0197   const ASTContext &Context;
0198   const LangOptions &LangOpts;
0199 };
0200 
0201 } // namespace clang
0202 
0203 #endif