clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
204 lines
8.3 KiB
C++
204 lines
8.3 KiB
C++
//===- 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
|