@@ -176,7 +176,13 @@ void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx,
176176
177177bool DylibVerifier::shouldIgnoreObsolete (const Record *R, SymbolContext &SymCtx,
178178 const Record *DR) {
179- return SymCtx.FA ->Avail .isObsoleted ();
179+ if (!SymCtx.FA ->Avail .isObsoleted ())
180+ return false ;
181+
182+ if (Zippered)
183+ DeferredZipperedSymbols[SymCtx.SymbolName ].emplace_back (ZipperedDeclSource{
184+ SymCtx.FA , &Ctx.Diag ->getSourceManager (), Ctx.Target });
185+ return true ;
180186}
181187
182188bool DylibVerifier::shouldIgnoreReexport (const Record *R,
@@ -195,6 +201,28 @@ bool DylibVerifier::shouldIgnoreReexport(const Record *R,
195201 return false ;
196202}
197203
204+ bool DylibVerifier::shouldIgnoreInternalZipperedSymbol (
205+ const Record *R, const SymbolContext &SymCtx) const {
206+ if (!Zippered)
207+ return false ;
208+
209+ return Exports->findSymbol (SymCtx.Kind , SymCtx.SymbolName ,
210+ SymCtx.ObjCIFKind ) != nullptr ;
211+ }
212+
213+ bool DylibVerifier::shouldIgnoreZipperedAvailability (const Record *R,
214+ SymbolContext &SymCtx) {
215+ if (!(Zippered && SymCtx.FA ->Avail .isUnavailable ()))
216+ return false ;
217+
218+ // Collect source location incase there is an exported symbol to diagnose
219+ // during `verifyRemainingSymbols`.
220+ DeferredZipperedSymbols[SymCtx.SymbolName ].emplace_back (
221+ ZipperedDeclSource{SymCtx.FA , SourceManagers.back ().get (), Ctx.Target });
222+
223+ return true ;
224+ }
225+
198226bool DylibVerifier::compareObjCInterfaceSymbols (const Record *R,
199227 SymbolContext &SymCtx,
200228 const ObjCInterfaceRecord *DR) {
@@ -294,6 +322,9 @@ DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R,
294322 if (shouldIgnorePrivateExternAttr (SymCtx.FA ->D ))
295323 return Result::Ignore;
296324
325+ if (shouldIgnoreInternalZipperedSymbol (R, SymCtx))
326+ return Result::Ignore;
327+
297328 unsigned ID;
298329 Result Outcome;
299330 if (Mode == VerificationMode::ErrorsAndWarnings) {
@@ -321,6 +352,9 @@ DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R,
321352 if (!SymCtx.FA ->Avail .isUnavailable ())
322353 return Result::Valid;
323354
355+ if (shouldIgnoreZipperedAvailability (R, SymCtx))
356+ return Result::Ignore;
357+
324358 const bool IsDeclAvailable = SymCtx.FA ->Avail .isUnavailable ();
325359
326360 switch (Mode) {
@@ -588,13 +622,58 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
588622 }
589623 }
590624
625+ const bool IsLinkerSymbol = SymbolName.starts_with (" $ld$" );
626+
627+ if (R.isVerified ()) {
628+ // Check for unavailable symbols.
629+ // This should only occur in the zippered case where we ignored
630+ // availability until all headers have been parsed.
631+ auto It = DeferredZipperedSymbols.find (SymCtx.SymbolName );
632+ if (It == DeferredZipperedSymbols.end ()) {
633+ updateState (Result::Valid);
634+ return ;
635+ }
636+
637+ ZipperedDeclSources Locs;
638+ for (const ZipperedDeclSource &ZSource : It->second ) {
639+ if (ZSource.FA ->Avail .isObsoleted ()) {
640+ updateState (Result::Ignore);
641+ return ;
642+ }
643+ if (ZSource.T .Arch != Ctx.Target .Arch )
644+ continue ;
645+ Locs.emplace_back (ZSource);
646+ }
647+ assert (Locs.size () == 2 && " Expected two decls for zippered symbol" );
648+
649+ // Print violating declarations per platform.
650+ for (const ZipperedDeclSource &ZSource : Locs) {
651+ unsigned DiagID = 0 ;
652+ if (Mode == VerificationMode::Pedantic || IsLinkerSymbol) {
653+ updateState (Result::Invalid);
654+ DiagID = diag::err_header_availability_mismatch;
655+ } else if (Mode == VerificationMode::ErrorsAndWarnings) {
656+ updateState (Result::Ignore);
657+ DiagID = diag::warn_header_availability_mismatch;
658+ } else {
659+ updateState (Result::Ignore);
660+ return ;
661+ }
662+ // Bypass emitDiag banner and print the target everytime.
663+ Ctx.Diag ->setSourceManager (ZSource.SrcMgr );
664+ Ctx.Diag ->Report (diag::warn_target) << getTargetTripleName (ZSource.T );
665+ Ctx.Diag ->Report (ZSource.FA ->Loc , DiagID)
666+ << getAnnotatedName (&R, SymCtx) << ZSource.FA ->Avail .isUnavailable ()
667+ << ZSource.FA ->Avail .isUnavailable ();
668+ }
669+ return ;
670+ }
671+
591672 if (shouldIgnoreCpp (SymbolName, R.isWeakDefined ())) {
592673 updateState (Result::Valid);
593674 return ;
594675 }
595676
596- const bool IsLinkerSymbol = SymbolName.starts_with (" $ld$" );
597-
598677 // All checks at this point classify as some kind of violation.
599678 // The different verification modes dictate whether they are reported to the
600679 // user.
@@ -647,8 +726,6 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
647726}
648727
649728void DylibVerifier::visitGlobal (const GlobalRecord &R) {
650- if (R.isVerified ())
651- return ;
652729 SymbolContext SymCtx;
653730 SimpleSymbol Sym = parseSymbol (R.getName ());
654731 SymCtx.SymbolName = Sym.Name ;
@@ -658,8 +735,6 @@ void DylibVerifier::visitGlobal(const GlobalRecord &R) {
658735
659736void DylibVerifier::visitObjCIVar (const ObjCIVarRecord &R,
660737 const StringRef Super) {
661- if (R.isVerified ())
662- return ;
663738 SymbolContext SymCtx;
664739 SymCtx.SymbolName = ObjCIVarRecord::createScopedName (Super, R.getName ());
665740 SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable;
@@ -679,8 +754,6 @@ void DylibVerifier::accumulateSrcLocForDylibSymbols() {
679754}
680755
681756void DylibVerifier::visitObjCInterface (const ObjCInterfaceRecord &R) {
682- if (R.isVerified ())
683- return ;
684757 SymbolContext SymCtx;
685758 SymCtx.SymbolName = R.getName ();
686759 SymCtx.ObjCIFKind = assignObjCIFSymbolKind (&R);
@@ -713,9 +786,12 @@ DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() {
713786
714787 DWARFContext DWARFInfo;
715788 DWARFCtx = &DWARFInfo;
716- Ctx.DiscoveredFirstError = false ;
717- Ctx.PrintArch = true ;
789+ Ctx.Target = Target (Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN);
718790 for (std::shared_ptr<RecordsSlice> Slice : Dylib) {
791+ if (Ctx.Target .Arch == Slice->getTarget ().Arch )
792+ continue ;
793+ Ctx.DiscoveredFirstError = false ;
794+ Ctx.PrintArch = true ;
719795 Ctx.Target = Slice->getTarget ();
720796 Ctx.DylibSlice = Slice.get ();
721797 Slice->visit (*this );
0 commit comments