aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorVolodymyr Sapsai <vsapsai@apple.com>2022-07-08 13:10:31 -0700
committerVolodymyr Sapsai <vsapsai@apple.com>2022-11-17 18:31:32 -0800
commita65d5309d5b73527efcbdec49a3ba9bba0fd873d (patch)
tree5cb02a9ebdeeb2b6a4b06ecf53feb8a8a05e59b4 /clang/lib
parent7059a6c32cfad8f272fad47265e3890cd7a1a7e1 (diff)
downloadllvm-a65d5309d5b73527efcbdec49a3ba9bba0fd873d.zip
llvm-a65d5309d5b73527efcbdec49a3ba9bba0fd873d.tar.gz
llvm-a65d5309d5b73527efcbdec49a3ba9bba0fd873d.tar.bz2
[ODRHash] Detect duplicate `ObjCProtocolDecl` ODR mismatches during parsing.
When during parsing we encountered a duplicate `ObjCProtocolDecl`, we were always emitting an error. With this change we accept * when a previous `ObjCProtocolDecl` is in a hidden [sub]module; * parsed `ObjCProtocolDecl` is the same as the previous one. And in case of mismatches we provide more detailed error messages. rdar://93069080 Differential Revision: https://reviews.llvm.org/D130327
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/DeclObjC.cpp11
-rw-r--r--clang/lib/AST/ODRDiagsEmitter.cpp22
-rw-r--r--clang/lib/Parse/ParseObjc.cpp17
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp20
4 files changed, 53 insertions, 17 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index 64e9f3c..2ba8daa 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -1997,6 +1997,17 @@ void ObjCProtocolDecl::startDefinition() {
RD->Data = this->Data;
}
+void ObjCProtocolDecl::startDuplicateDefinitionForComparison() {
+ Data.setPointer(nullptr);
+ allocateDefinitionData();
+ // Don't propagate data to other redeclarations.
+}
+
+void ObjCProtocolDecl::mergeDuplicateDefinitionWithCommon(
+ const ObjCProtocolDecl *Definition) {
+ Data = Definition->Data;
+}
+
void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const {
if (const ObjCProtocolDecl *PDecl = getDefinition()) {
for (auto *Prop : PDecl->properties()) {
diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp
index dfc2157..6e0f122 100644
--- a/clang/lib/AST/ODRDiagsEmitter.cpp
+++ b/clang/lib/AST/ODRDiagsEmitter.cpp
@@ -90,8 +90,9 @@ static bool diagnoseSubMismatchMethodParameters(DiagnosticsEngine &Diags,
DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod);
return Diags.Report(SecondMethod->getLocation(),
diag::note_module_odr_violation_method_params)
- << SecondModule << SecondMethod->getSourceRange() << DiffType
- << SecondMethodType << SecondName;
+ << SecondModule.empty() << SecondModule
+ << SecondMethod->getSourceRange() << DiffType << SecondMethodType
+ << SecondName;
};
const unsigned FirstNumParameters = FirstMethod->param_size();
@@ -378,7 +379,7 @@ bool ODRDiagsEmitter::diagnoseSubMismatchProtocols(
this](SourceLocation Loc, SourceRange Range,
ODRReferencedProtocolDifference DiffType) {
return Diag(Loc, diag::note_module_odr_violation_referenced_protocols)
- << SecondModule << Range << DiffType;
+ << SecondModule.empty() << SecondModule << Range << DiffType;
};
auto GetProtoListSourceRange = [](const ObjCProtocolList &PL) {
if (PL.empty())
@@ -440,7 +441,8 @@ bool ODRDiagsEmitter::diagnoseSubMismatchObjCMethod(
this](ODRMethodDifference DiffType) {
return Diag(SecondMethod->getLocation(),
diag::note_module_odr_violation_objc_method)
- << SecondModule << SecondMethod->getSourceRange() << DiffType;
+ << SecondModule.empty() << SecondModule
+ << SecondMethod->getSourceRange() << DiffType;
};
if (computeODRHash(FirstMethod->getReturnType()) !=
@@ -517,7 +519,8 @@ bool ODRDiagsEmitter::diagnoseSubMismatchObjCProperty(
auto DiagNote = [SecondModule, SecondProp,
this](SourceLocation Loc, ODRPropertyDifference DiffType) {
return Diag(Loc, diag::note_module_odr_violation_objc_property)
- << SecondModule << SecondProp->getSourceRange() << DiffType;
+ << SecondModule.empty() << SecondModule
+ << SecondProp->getSourceRange() << DiffType;
};
IdentifierInfo *FirstII = FirstProp->getIdentifier();
@@ -690,7 +693,8 @@ void ODRDiagsEmitter::diagnoseSubMismatchDifferentDeclKinds(
auto SecondDiagInfo =
GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl);
Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl)
- << SecondModule << SecondDiagInfo.second << DR.SecondDiffType;
+ << SecondModule.empty() << SecondModule << SecondDiagInfo.second
+ << DR.SecondDiffType;
}
bool ODRDiagsEmitter::diagnoseMismatch(
@@ -1538,7 +1542,8 @@ bool ODRDiagsEmitter::diagnoseMismatch(
<< FirstDecl->getSourceRange();
Diag(SecondDecl->getLocation(),
diag::note_module_odr_violation_mismatch_decl_unknown)
- << SecondModule << FirstDiffType << SecondDecl->getSourceRange();
+ << SecondModule.empty() << SecondModule << FirstDiffType
+ << SecondDecl->getSourceRange();
return true;
}
@@ -1908,6 +1913,7 @@ bool ODRDiagsEmitter::diagnoseMismatch(
<< FirstDecl->getSourceRange();
Diag(SecondDecl->getLocation(),
diag::note_module_odr_violation_mismatch_decl_unknown)
- << SecondModule << FirstDiffType << SecondDecl->getSourceRange();
+ << SecondModule.empty() << SecondModule << FirstDiffType
+ << SecondDecl->getSourceRange();
return true;
}
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 734c66f..7404eba 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ODRDiagsEmitter.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/TargetInfo.h"
@@ -2088,11 +2089,23 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
/*consumeLastToken=*/true))
return nullptr;
- Decl *ProtoType = Actions.ActOnStartProtocolInterface(
+ Sema::SkipBodyInfo SkipBody;
+ ObjCProtocolDecl *ProtoType = Actions.ActOnStartProtocolInterface(
AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),
- ProtocolLocs.data(), EndProtoLoc, attrs);
+ ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody);
ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
+ if (SkipBody.CheckSameAsPrevious) {
+ auto *PreviousDef = cast<ObjCProtocolDecl>(SkipBody.Previous);
+ if (Actions.ActOnDuplicateODRHashDefinition(ProtoType, PreviousDef)) {
+ ProtoType->mergeDuplicateDefinitionWithCommon(
+ PreviousDef->getDefinition());
+ } else {
+ ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),
+ getPreprocessor().getLangOpts());
+ DiagsEmitter.diagnoseMismatch(PreviousDef, ProtoType);
+ }
+ }
return Actions.ConvertDeclToDeclGroup(ProtoType);
}
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index c55cb78..97dff49 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -1213,7 +1213,7 @@ ObjCProtocolDecl *Sema::ActOnStartProtocolInterface(
SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
- const ParsedAttributesView &AttrList) {
+ const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {
bool err = false;
// FIXME: Deal with AttrList.
assert(ProtocolName && "Missing protocol identifier");
@@ -1221,23 +1221,29 @@ ObjCProtocolDecl *Sema::ActOnStartProtocolInterface(
forRedeclarationInCurContext());
ObjCProtocolDecl *PDecl = nullptr;
if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
- // If we already have a definition, complain.
- Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
- Diag(Def->getLocation(), diag::note_previous_definition);
-
// Create a new protocol that is completely distinct from previous
// declarations, and do not make this protocol available for name lookup.
// That way, we'll end up completely ignoring the duplicate.
// FIXME: Can we turn this into an error?
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
- /*PrevDecl=*/nullptr);
+ /*PrevDecl=*/Def);
+
+ if (SkipBody && !hasVisibleDefinition(Def)) {
+ SkipBody->CheckSameAsPrevious = true;
+ SkipBody->New = PDecl;
+ SkipBody->Previous = Def;
+ } else {
+ // If we already have a definition, complain.
+ Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ }
// If we are using modules, add the decl to the context in order to
// serialize something meaningful.
if (getLangOpts().Modules)
PushOnScopeChains(PDecl, TUScope);
- PDecl->startDefinition();
+ PDecl->startDuplicateDefinitionForComparison();
} else {
if (PrevDecl) {
// Check for circular dependencies among protocol declarations. This can