diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h b/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h new file mode 100644 index 000000000000..1f7faaa06e54 --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h @@ -0,0 +1,203 @@ +//===- ODRDiagsEmitter.h - Emits diagnostic for ODR mismatches --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ODRDIAGSEMITTER_H +#define LLVM_CLANG_AST_ODRDIAGSEMITTER_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LangOptions.h" + +namespace clang { + +class ODRDiagsEmitter { +public: + ODRDiagsEmitter(DiagnosticsEngine &Diags, const ASTContext &Context, + const LangOptions &LangOpts) + : Diags(Diags), Context(Context), LangOpts(LangOpts) {} + + /// Diagnose ODR mismatch between 2 FunctionDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const FunctionDecl *FirstFunction, + const FunctionDecl *SecondFunction) const; + + /// Diagnose ODR mismatch between 2 EnumDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const EnumDecl *FirstEnum, + const EnumDecl *SecondEnum) const; + + /// Diagnose ODR mismatch between 2 CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool + diagnoseMismatch(const CXXRecordDecl *FirstRecord, + const CXXRecordDecl *SecondRecord, + const struct CXXRecordDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const RecordDecl *FirstRecord, + const RecordDecl *SecondRecord) const; + + /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch( + const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, + const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between ObjCInterfaceDecl with different + /// definitions. + bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID, + const ObjCInterfaceDecl *SecondID) const { + assert(FirstID->data().Definition != SecondID->data().Definition && + "Don't diagnose differences when definitions are merged already"); + return diagnoseMismatch(FirstID, SecondID, &SecondID->data()); + } + + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool diagnoseMismatch( + const ObjCProtocolDecl *FirstProtocol, + const ObjCProtocolDecl *SecondProtocol, + const struct ObjCProtocolDecl::DefinitionData *SecondDD) const; + + /// Diagnose ODR mismatch between ObjCProtocolDecl with different definitions. + bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol, + const ObjCProtocolDecl *SecondProtocol) const { + assert(FirstProtocol->data().Definition != + SecondProtocol->data().Definition && + "Don't diagnose differences when definitions are merged already"); + return diagnoseMismatch(FirstProtocol, SecondProtocol, + &SecondProtocol->data()); + } + + /// Get the best name we know for the module that owns the given + /// declaration, or an empty string if the declaration is not from a module. + static std::string getOwningModuleNameForDiagnostic(const Decl *D); + +private: + using DeclHashes = llvm::SmallVector<std::pair<const Decl *, unsigned>, 4>; + + // Used with err_module_odr_violation_mismatch_decl, + // note_module_odr_violation_mismatch_decl, + // err_module_odr_violation_mismatch_decl_unknown, + // and note_module_odr_violation_mismatch_decl_unknown + // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed + enum ODRMismatchDecl { + EndOfClass, + PublicSpecifer, + PrivateSpecifer, + ProtectedSpecifer, + StaticAssert, + Field, + CXXMethod, + TypeAlias, + TypeDef, + Var, + Friend, + FunctionTemplate, + ObjCMethod, + ObjCIvar, + ObjCProperty, + Other + }; + + struct DiffResult { + const Decl *FirstDecl = nullptr, *SecondDecl = nullptr; + ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other; + }; + + // If there is a diagnoseable difference, FirstDiffType and + // SecondDiffType will not be Other and FirstDecl and SecondDecl will be + // filled in if not EndOfClass. + static DiffResult FindTypeDiffs(DeclHashes &FirstHashes, + DeclHashes &SecondHashes); + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const { + return Diags.Report(Loc, DiagID); + } + + // Use this to diagnose that an unexpected Decl was encountered + // or no difference was detected. This causes a generic error + // message to be emitted. + void diagnoseSubMismatchUnexpected(DiffResult &DR, + const NamedDecl *FirstRecord, + StringRef FirstModule, + const NamedDecl *SecondRecord, + StringRef SecondModule) const; + + void diagnoseSubMismatchDifferentDeclKinds(DiffResult &DR, + const NamedDecl *FirstRecord, + StringRef FirstModule, + const NamedDecl *SecondRecord, + StringRef SecondModule) const; + + bool diagnoseSubMismatchField(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const FieldDecl *FirstField, + const FieldDecl *SecondField) const; + + bool diagnoseSubMismatchTypedef(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const TypedefNameDecl *FirstTD, + const TypedefNameDecl *SecondTD, + bool IsTypeAlias) const; + + bool diagnoseSubMismatchVar(const NamedDecl *FirstRecord, + StringRef FirstModule, StringRef SecondModule, + const VarDecl *FirstVD, + const VarDecl *SecondVD) const; + + /// Check if protocol lists are the same and diagnose if they are different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchProtocols(const ObjCProtocolList &FirstProtocols, + const ObjCContainerDecl *FirstContainer, + StringRef FirstModule, + const ObjCProtocolList &SecondProtocols, + const ObjCContainerDecl *SecondContainer, + StringRef SecondModule) const; + + /// Check if Objective-C methods are the same and diagnose if different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, + StringRef SecondModule, + const ObjCMethodDecl *FirstMethod, + const ObjCMethodDecl *SecondMethod) const; + + /// Check if Objective-C properties are the same and diagnose if different. + /// + /// Returns true if found a mismatch and diagnosed it. + bool + diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, StringRef SecondModule, + const ObjCPropertyDecl *FirstProp, + const ObjCPropertyDecl *SecondProp) const; + +private: + DiagnosticsEngine &Diags; + const ASTContext &Context; + const LangOptions &LangOpts; +}; + +} // namespace clang + +#endif |