aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h')
-rw-r--r--contrib/llvm-project/clang/include/clang/AST/ODRDiagsEmitter.h203
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