https://github.com/cyndyishida updated https://github.com/llvm/llvm-project/pull/85348
>From d45081b0270f20a1313a35bd4ae12343e265ce7b Mon Sep 17 00:00:00 2001 From: Cyndy Ishida <cyndy_ish...@apple.com> Date: Wed, 13 Mar 2024 18:57:14 -0700 Subject: [PATCH 1/2] [InstallAPI] Verify that declarations in header map to symbols found in dylib * This patch completes support for verifying every declaration found in a header is discovered in the dylib. Diagnostics are reported for each class for differences that is representable in TBD files. * This patch also now captures unavailable attributes that depend on target triples. This is needed for proper tbd file generation. --- clang/include/clang/AST/Availability.h | 13 +- .../clang/Basic/DiagnosticInstallAPIKinds.td | 23 + .../include/clang/InstallAPI/DylibVerifier.h | 57 +- clang/include/clang/InstallAPI/Frontend.h | 3 + clang/include/clang/InstallAPI/MachO.h | 1 + clang/lib/AST/Availability.cpp | 6 +- clang/lib/InstallAPI/DylibVerifier.cpp | 326 ++++++++- clang/lib/InstallAPI/Visitor.cpp | 2 +- clang/test/InstallAPI/availability.test | 626 ++++++++++++++++++ clang/test/InstallAPI/diagnostics-cpp.test | 461 +++++++++++++ clang/test/InstallAPI/hiddens.test | 262 ++++++++ .../clang-installapi/ClangInstallAPI.cpp | 6 +- clang/tools/clang-installapi/Options.cpp | 4 +- 13 files changed, 1766 insertions(+), 24 deletions(-) create mode 100644 clang/test/InstallAPI/availability.test create mode 100644 clang/test/InstallAPI/diagnostics-cpp.test create mode 100644 clang/test/InstallAPI/hiddens.test diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 5cfbaf0cdfbd21..2ccc607d4b63dc 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -67,6 +67,7 @@ struct AvailabilityInfo { VersionTuple Introduced; VersionTuple Deprecated; VersionTuple Obsoleted; + bool Unavailable = false; bool UnconditionallyDeprecated = false; bool UnconditionallyUnavailable = false; @@ -78,6 +79,9 @@ struct AvailabilityInfo { /// Check if the symbol has been obsoleted. bool isObsoleted() const { return !Obsoleted.empty(); } + /// Check if the symbol is unavailable for the active platform and os version. + bool isUnavailable() const { return Unavailable; } + /// Check if the symbol is unconditionally deprecated. /// /// i.e. \code __attribute__((deprecated)) \endcode @@ -91,9 +95,10 @@ struct AvailabilityInfo { } AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, - VersionTuple O, bool UD, bool UU) + VersionTuple O, bool U, bool UD, bool UU) : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), - UnconditionallyDeprecated(UD), UnconditionallyUnavailable(UU) {} + Unavailable(U), UnconditionallyDeprecated(UD), + UnconditionallyUnavailable(UU) {} friend bool operator==(const AvailabilityInfo &Lhs, const AvailabilityInfo &Rhs); @@ -105,10 +110,10 @@ struct AvailabilityInfo { inline bool operator==(const AvailabilityInfo &Lhs, const AvailabilityInfo &Rhs) { return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted, - Lhs.UnconditionallyDeprecated, + Lhs.Unavailable, Lhs.UnconditionallyDeprecated, Lhs.UnconditionallyUnavailable) == std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted, - Rhs.UnconditionallyDeprecated, + Rhs.Unavailable, Rhs.UnconditionallyDeprecated, Rhs.UnconditionallyUnavailable); } diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 31be4f09cf3a1c..5ed2e23425dc5f 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -17,4 +17,27 @@ def err_no_install_name : Error<"no install name specified: add -install_name <p def err_no_output_file: Error<"no output file specified">; } // end of command line category. +let CategoryName = "Verification" in { +def warn_target: Warning<"violations found for %0">; +def err_library_missing_symbol : Error<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">; +def warn_library_missing_symbol : Warning<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">; +def err_library_hidden_symbol : Error<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">; +def warn_library_hidden_symbol : Warning<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">; +def warn_header_hidden_symbol : Warning<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; +def err_header_hidden_symbol : Error<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; +def err_header_symbol_missing : Error<"no declaration found for exported symbol '%0' in dynamic library">; +def warn_header_availability_mismatch : Warning<"declaration '%0' is marked %select{available|unavailable}1," + " but symbol is %select{not |}2exported in dynamic library">; +def err_header_availability_mismatch : Error<"declaration '%0' is marked %select{available|unavailable}1," + " but symbol is %select{not |}2exported in dynamic library">; +def warn_dylib_symbol_flags_mismatch : Warning<"dynamic library symbol '%0' is " + "%select{weak defined|thread local}1, but its declaration is not">; +def warn_header_symbol_flags_mismatch : Warning<"declaration '%0' is " + "%select{weak defined|thread local}1, but symbol is not in dynamic library">; +def err_dylib_symbol_flags_mismatch : Error<"dynamic library symbol '%0' is " + "%select{weak defined|thread local}1, but its declaration is not">; +def err_header_symbol_flags_mismatch : Error<"declaration '%0' is " + "%select{weak defined|thread local}1, but symbol is not in dynamic library">; +} // end of Verification category. + } // end of InstallAPI component diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h index 72c4743fdf65e0..2094548ced8d5f 100644 --- a/clang/include/clang/InstallAPI/DylibVerifier.h +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -38,19 +38,34 @@ class DylibVerifier { // Current target being verified against the AST. llvm::MachO::Target Target; + // Target specific API from binary. + RecordsSlice *DylibSlice; + // Query state of verification after AST has been traversed. Result FrontendState; // First error for AST traversal, which is tied to the target triple. bool DiscoveredFirstError; + + // Determines what kind of banner to print a violation for. + bool PrintArch = false; + + // Engine for reporting violations. + DiagnosticsEngine *Diag = nullptr; + + // Handle diagnostics reporting for target level violations. + void emitDiag(llvm::function_ref<void()> Report); + + VerifierContext() = default; + VerifierContext(DiagnosticsEngine *Diag) : Diag(Diag) {} }; DylibVerifier() = default; DylibVerifier(llvm::MachO::Records &&Dylib, DiagnosticsEngine *Diag, VerificationMode Mode, bool Demangle) - : Dylib(std::move(Dylib)), Diag(Diag), Mode(Mode), Demangle(Demangle), - Exports(std::make_unique<SymbolSet>()) {} + : Dylib(std::move(Dylib)), Mode(Mode), Demangle(Demangle), + Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {} Result verify(GlobalRecord *R, const FrontendAttrs *FA); Result verify(ObjCInterfaceRecord *R, const FrontendAttrs *FA); @@ -66,6 +81,13 @@ class DylibVerifier { /// Get result of verification. Result getState() const { return Ctx.FrontendState; } + /// Set different source managers to the same diagnostics engine. + void setSourceManager(SourceManager &SourceMgr) const { + if (!Ctx.Diag) + return; + Ctx.Diag->setSourceManager(&SourceMgr); + } + private: /// Determine whether to compare declaration to symbol in binary. bool canVerify(); @@ -73,6 +95,29 @@ class DylibVerifier { /// Shared implementation for verifying exported symbols. Result verifyImpl(Record *R, SymbolContext &SymCtx); + /// Check if declaration is marked as obsolete, they are + // expected to result in a symbol mismatch. + bool shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// Compare the visibility declarations to the linkage of symbol found in + /// dylib. + Result compareVisibility(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// An ObjCInterfaceRecord can represent up to three symbols. When verifying, + // account for this granularity. + bool compareObjCInterfaceSymbols(const Record *R, SymbolContext &SymCtx, + const ObjCInterfaceRecord *DR); + + /// Validate availability annotations against dylib. + Result compareAvailability(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// Compare and validate matching symbol flags. + bool compareSymbolFlags(const Record *R, SymbolContext &SymCtx, + const Record *DR); + /// Update result state on each call to `verify`. void updateState(Result State); @@ -80,14 +125,14 @@ class DylibVerifier { void addSymbol(const Record *R, SymbolContext &SymCtx, TargetList &&Targets = {}); + /// Find matching dylib slice for target triple that is being parsed. + void assignSlice(const Target &T); + // Symbols in dylib. llvm::MachO::Records Dylib; - // Engine for reporting violations. - [[maybe_unused]] DiagnosticsEngine *Diag = nullptr; - // Controls what class of violations to report. - [[maybe_unused]] VerificationMode Mode = VerificationMode::Invalid; + VerificationMode Mode = VerificationMode::Invalid; // Attempt to demangle when reporting violations. bool Demangle = false; diff --git a/clang/include/clang/InstallAPI/Frontend.h b/clang/include/clang/InstallAPI/Frontend.h index 660fc8cd69a59d..5cccd891c58093 100644 --- a/clang/include/clang/InstallAPI/Frontend.h +++ b/clang/include/clang/InstallAPI/Frontend.h @@ -17,6 +17,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/InstallAPI/Context.h" +#include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/Visitor.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" @@ -34,6 +35,8 @@ class InstallAPIAction : public ASTFrontendAction { std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { + Ctx.Diags->getClient()->BeginSourceFile(CI.getLangOpts()); + Ctx.Verifier->setSourceManager(CI.getSourceManager()); return std::make_unique<InstallAPIVisitor>( CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor()); } diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h index 6dee6f22420381..a77766511fa3e5 100644 --- a/clang/include/clang/InstallAPI/MachO.h +++ b/clang/include/clang/InstallAPI/MachO.h @@ -32,6 +32,7 @@ using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord; using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord; using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord; using Records = llvm::MachO::Records; +using RecordsSlice = llvm::MachO::RecordsSlice; using BinaryAttrs = llvm::MachO::RecordsSlice::BinaryAttrs; using SymbolSet = llvm::MachO::SymbolSet; using SimpleSymbol = llvm::MachO::SimpleSymbol; diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp index d0054e37e4dcd2..238359a2dedfcf 100644 --- a/clang/lib/AST/Availability.cpp +++ b/clang/lib/AST/Availability.cpp @@ -28,9 +28,9 @@ AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) { if (A->getPlatform()->getName() != PlatformName) continue; - Availability = - AvailabilityInfo(A->getPlatform()->getName(), A->getIntroduced(), - A->getDeprecated(), A->getObsoleted(), false, false); + Availability = AvailabilityInfo( + A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(), + A->getObsoleted(), A->getUnavailable(), false, false); break; } diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp index b7dd85d63fa14f..700763b3fee0db 100644 --- a/clang/lib/InstallAPI/DylibVerifier.cpp +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -1,5 +1,6 @@ #include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/FrontendRecords.h" +#include "clang/InstallAPI/InstallAPIDiagnostic.h" #include "llvm/Demangle/Demangle.h" using namespace llvm::MachO; @@ -24,6 +25,9 @@ struct DylibVerifier::SymbolContext { // The ObjCInterface symbol type, if applicable. ObjCIFSymbolKind ObjCIFKind = ObjCIFSymbolKind::None; + + // Whether Decl is inlined. + bool Inlined = false; }; static std::string @@ -80,10 +84,11 @@ getAnnotatedName(const Record *R, EncodeKind Kind, StringRef Name, } static std::string demangle(StringRef Name) { - // Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'. - if (!(Name.starts_with("_Z") || Name.starts_with("___Z"))) + // InstallAPI currently only supports itanium manglings. + if (!(Name.starts_with("_Z") || Name.starts_with("__Z") || + Name.starts_with("___Z"))) return Name.str(); - char *Result = llvm::itaniumDemangle(Name.data()); + char *Result = llvm::itaniumDemangle(Name); if (!Result) return Name.str(); @@ -109,6 +114,30 @@ static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev, return Curr; } +// __private_extern__ is a deprecated specifier that clang does not +// respect in all contexts, it should just be considered hidden for InstallAPI. +static bool shouldIgnorePrivateExternAttr(const Decl *D) { + if (const FunctionDecl *FD = cast<FunctionDecl>(D)) + return FD->getStorageClass() == StorageClass::SC_PrivateExtern; + if (const VarDecl *VD = cast<VarDecl>(D)) + return VD->getStorageClass() == StorageClass::SC_PrivateExtern; + + return false; +} + +Record *findRecordFromSlice(const RecordsSlice *Slice, StringRef Name, + EncodeKind Kind) { + switch (Kind) { + case EncodeKind::GlobalSymbol: + return Slice->findGlobal(Name); + case EncodeKind::ObjectiveCInstanceVariable: + return Slice->findObjCIVar(Name.contains('.'), Name); + case EncodeKind::ObjectiveCClass: + case EncodeKind::ObjectiveCClassEHType: + return Slice->findObjCInterface(Name); + } + llvm_unreachable("unexpected end when finding record"); +} void DylibVerifier::updateState(Result State) { Ctx.FrontendState = updateResult(Ctx.FrontendState, State); @@ -122,17 +151,272 @@ void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx, Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets); } +bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, + const Record *DR) { + return SymCtx.FA->Avail.isObsoleted(); +} + +bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R, + SymbolContext &SymCtx, + const ObjCInterfaceRecord *DR) { + const bool IsDeclVersionComplete = + ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::Class) == + ObjCIFSymbolKind::Class) && + ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::MetaClass) == + ObjCIFSymbolKind::MetaClass); + + const bool IsDylibVersionComplete = DR->isCompleteInterface(); + + // The common case, a complete ObjCInterface. + if (IsDeclVersionComplete && IsDylibVersionComplete) + return true; + + auto PrintDiagnostic = [&](auto SymLinkage, const Record *Record, + StringRef SymName, bool PrintAsWarning = false) { + if (SymLinkage == RecordLinkage::Unknown) + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + PrintAsWarning ? diag::warn_library_missing_symbol + : diag::err_library_missing_symbol) + << SymName; + }); + else + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + PrintAsWarning ? diag::warn_library_hidden_symbol + : diag::err_library_hidden_symbol) + << SymName; + }); + }; + + if (IsDeclVersionComplete) { + // The decl represents a complete ObjCInterface, but the symbols in the + // dylib do not. Determine which symbol is missing. To keep older projects + // building, treat this as a warning. + if (!DR->isExportedSymbol(ObjCIFSymbolKind::Class)) + PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::Class), R, + getAnnotatedName(R, SymCtx.Kind, SymCtx.PrettyPrintName, + /*ValidSourceLoc=*/true, + ObjCIFSymbolKind::Class), + /*PrintAsWarning=*/true); + + if (!DR->isExportedSymbol(ObjCIFSymbolKind::MetaClass)) + PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass), R, + getAnnotatedName(R, SymCtx.Kind, SymCtx.PrettyPrintName, + /*ValidSourceLoc=*/true, + ObjCIFSymbolKind::MetaClass), + /*PrintAsWarning=*/true); + return true; + } + + if (DR->isExportedSymbol(SymCtx.ObjCIFKind)) { + if (!IsDylibVersionComplete) { + // Both the declaration and dylib have a non-complete interface. + SymCtx.Kind = EncodeKind::GlobalSymbol; + SymCtx.SymbolName = R->getName(); + } + return true; + } + + // At this point that means there was not a matching class symbol + // to represent the one discovered as a declaration. + PrintDiagnostic(DR->getLinkageForSymbol(SymCtx.ObjCIFKind), R, + SymCtx.PrettyPrintName); + return false; +} + +DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R, + SymbolContext &SymCtx, + const Record *DR) { + + if (R->isExported()) { + if (!DR) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_library_missing_symbol) + << SymCtx.PrettyPrintName; + }); + return Result::Invalid; + } + if (DR->isInternal()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_library_hidden_symbol) + << SymCtx.PrettyPrintName; + }); + return Result::Invalid; + } + } + + // Emit a diagnostic for hidden declarations with external symbols, except + // when theres an inlined attribute. + if ((R->isInternal() && !SymCtx.Inlined) && DR && DR->isExported()) { + + if (Mode == VerificationMode::ErrorsOnly) + return Result::Ignore; + + if (shouldIgnorePrivateExternAttr(SymCtx.FA->D)) + return Result::Ignore; + + unsigned ID; + Result Outcome; + if (Mode == VerificationMode::ErrorsAndWarnings) { + ID = diag::warn_header_hidden_symbol; + Outcome = Result::Ignore; + } else { + ID = diag::err_header_hidden_symbol; + Outcome = Result::Invalid; + } + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), ID) + << SymCtx.PrettyPrintName; + }); + return Outcome; + } + + if (R->isInternal()) + return Result::Ignore; + + return Result::Valid; +} + +DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R, + SymbolContext &SymCtx, + const Record *DR) { + if (!SymCtx.FA->Avail.isUnavailable()) + return Result::Valid; + + const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable(); + + switch (Mode) { + case VerificationMode::ErrorsAndWarnings: + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::warn_header_availability_mismatch) + << SymCtx.PrettyPrintName << IsDeclAvailable << IsDeclAvailable; + }); + return Result::Ignore; + case VerificationMode::Pedantic: + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_availability_mismatch) + << SymCtx.PrettyPrintName << IsDeclAvailable << IsDeclAvailable; + }); + return Result::Invalid; + case VerificationMode::ErrorsOnly: + return Result::Ignore; + case VerificationMode::Invalid: + llvm_unreachable("Unexpected verification mode symbol verification"); + } + llvm_unreachable("Unexpected verification mode symbol verification"); +} + +bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx, + const Record *DR) { + std::string DisplayName = + Demangle ? demangle(DR->getName()) : DR->getName().str(); + + if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_dylib_symbol_flags_mismatch) + << getAnnotatedName(DR, SymCtx.Kind, DisplayName) + << DR->isThreadLocalValue(); + }); + return false; + } + if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) { + Ctx.emitDiag([&]() { + SymCtx.FA->D->getLocation(), + Ctx.Diag->Report(diag::err_header_symbol_flags_mismatch) + << SymCtx.PrettyPrintName << R->isThreadLocalValue(); + }); + return false; + } + + if (DR->isWeakDefined() && !R->isWeakDefined()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_dylib_symbol_flags_mismatch) + << getAnnotatedName(DR, SymCtx.Kind, DisplayName) + << R->isWeakDefined(); + }); + return false; + } + if (!DR->isWeakDefined() && R->isWeakDefined()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_symbol_flags_mismatch) + << SymCtx.PrettyPrintName << R->isWeakDefined(); + }); + return false; + } + + return true; +} + DylibVerifier::Result DylibVerifier::verifyImpl(Record *R, SymbolContext &SymCtx) { R->setVerify(); if (!canVerify()) { // Accumulate symbols when not in verifying against dylib. - if (R->isExported() && !SymCtx.FA->Avail.isUnconditionallyUnavailable() && + if (R->isExported() && !SymCtx.FA->Avail.isUnavailable() && !SymCtx.FA->Avail.isObsoleted()) { addSymbol(R, SymCtx); } return Ctx.FrontendState; } + + Record *DR = + findRecordFromSlice(Ctx.DylibSlice, SymCtx.SymbolName, SymCtx.Kind); + if (DR) + DR->setVerify(); + + if (shouldIgnoreObsolete(R, SymCtx, DR)) { + updateState(Result::Ignore); + return Ctx.FrontendState; + } + + // Unavailable declarations don't need matching symbols. + if (SymCtx.FA->Avail.isUnavailable() && (!DR || DR->isInternal())) { + updateState(Result::Valid); + return Ctx.FrontendState; + } + + Result VisibilityCheck = compareVisibility(R, SymCtx, DR); + if (VisibilityCheck != Result::Valid) { + updateState(VisibilityCheck); + return Ctx.FrontendState; + } + + // All missing symbol cases to diagnose have been handled now. + if (!DR) { + updateState(Result::Ignore); + return Ctx.FrontendState; + } + + // Check for mismatching ObjC interfaces. + if (SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) { + if (!compareObjCInterfaceSymbols( + R, SymCtx, Ctx.DylibSlice->findObjCInterface(DR->getName()))) { + updateState(Result::Invalid); + return Ctx.FrontendState; + } + } + + Result AvailabilityCheck = compareAvailability(R, SymCtx, DR); + if (AvailabilityCheck != Result::Valid) { + updateState(AvailabilityCheck); + return Ctx.FrontendState; + } + + if (!compareSymbolFlags(R, SymCtx, DR)) { + updateState(Result::Invalid); + return Ctx.FrontendState; + } + + addSymbol(R, SymCtx); + updateState(Result::Valid); return Ctx.FrontendState; } @@ -140,10 +424,29 @@ bool DylibVerifier::canVerify() { return Ctx.FrontendState != Result::NoVerify; } +void DylibVerifier::assignSlice(const Target &T) { + assert(T == Ctx.Target && "Active targets should match."); + if (Dylib.empty()) + return; + + // Note: there are no reexport slices with binaries, as opposed to TBD files, + // so it can be assumed that the target match is the active top-level library. + auto It = find_if( + Dylib, [&T](const auto &Slice) { return T == Slice->getTarget(); }); + + assert(It != Dylib.end() && "Target slice should always exist."); + Ctx.DylibSlice = It->get(); +} + void DylibVerifier::setTarget(const Target &T) { Ctx.Target = T; Ctx.DiscoveredFirstError = false; - updateState(Dylib.empty() ? Result::NoVerify : Result::Ignore); + if (Dylib.empty()) { + updateState(Result::NoVerify); + return; + } + updateState(Result::Ignore); + assignSlice(T); } DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R, @@ -205,8 +508,21 @@ DylibVerifier::Result DylibVerifier::verify(GlobalRecord *R, getAnnotatedName(R, Sym.Kind, Demangle ? demangle(Sym.Name) : Sym.Name); SymCtx.Kind = Sym.Kind; SymCtx.FA = FA; + SymCtx.Inlined = R->isInlined(); return verifyImpl(R, SymCtx); } +void DylibVerifier::VerifierContext::emitDiag( + llvm::function_ref<void()> Report) { + if (!DiscoveredFirstError) { + Diag->Report(diag::warn_target) + << (PrintArch ? getArchitectureName(Target.Arch) + : getTargetTripleName(Target)); + DiscoveredFirstError = true; + } + + Report(); +} + } // namespace installapi } // namespace clang diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index 187afe59309d37..452c8f2fb1e489 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -681,7 +681,7 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { std::string Name = getMangledName(M); auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, + GlobalRecord::Kind::Function, Avail, M, *Access, getFlags(WeakDef)); Ctx.Verifier->verify(GR, FA); } diff --git a/clang/test/InstallAPI/availability.test b/clang/test/InstallAPI/availability.test new file mode 100644 index 00000000000000..5e8f7c6e509eb4 --- /dev/null +++ b/clang/test/InstallAPI/availability.test @@ -0,0 +1,626 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/Availability.yaml -o %t/System/Library/Frameworks/Availability.framework/Availability + +; RUN: clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o output.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=ErrorsOnly --filetype=tbd-v5 2>&1 | FileCheck -allow-empty -check-prefix=ERRORSONLY %s + +; RUN: clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o output-warnings.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=ErrorsAndWarnings 2>&1 | FileCheck -check-prefixes=VIOLATIONS,ERRORSANDWARNINGS %s + +; RUN: not clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o output-pedantic.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=Pedantic 2>&1 | FileCheck -check-prefixes=VIOLATIONS,PEDANTIC %s + +; ERRORSONLY-NOT: error +; ERRORSONLY-NOT: warning + +; ERRORSANDWARNINGS-NOT: error +; VIOLATIONS: warning: violations found for x86_64-apple-macos +; VIOLATIONS: declaration 'publicGlobalVariable' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: extern int publicGlobalVariable NS_AVAILABLE +; VIOLATIONS: declaration 'Foo' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: @interface Foo : NSObject +; VIOLATIONS: declaration 'privateGlobalVariable' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: extern int privateGlobalVariable; + +; ERRORSANDWARNINGS-NOT: warning +; PEDANTIC-NOT: error + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/Availability.framework/Headers/Availability.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Availability.framework/PrivateHeaders/AvailabilityPrivate.h", + "type" : "private" + } + ], + "version": "3" +} + +;--- System/Library/Frameworks/Availability.framework/Headers/AV_Defines.h +#ifndef AV_DEFINES +#define AV_DEFINES + +#define NS_AVAILABLE __attribute__((availability(macosx,introduced=NA))) + +@interface NSObject +@end + +#endif //AV_DEFINES + +;--- System/Library/Frameworks/Availability.framework/PrivateHeaders/AvailabilityPrivate.h +#import <Availability/AV_Defines.h> +// Test private global variable. +NS_AVAILABLE +extern int privateGlobalVariable; + +;--- System/Library/Frameworks/Availability.framework/Headers/Availability.h +#import <Availability/AV_Defines.h> +extern int publicGlobalVariable NS_AVAILABLE; + +// Test public ObjC class +NS_AVAILABLE +@interface Foo : NSObject +@end + +// Test unavailable attribute. +#ifdef __i386__ +#define UNAVAILABLE_I386 __attribute__((unavailable)) +#else +#define UNAVAILABLE_I386 +#endif +extern int publicGlobalVariable2 UNAVAILABLE_I386; + +extern int publicGlobalVariable3 __attribute__((unavailable)) +__attribute__((availability(macosx, introduced = 10.9))); + +// Test obsoleted with exported variable. +extern int publicGlobalVariable4 __attribute__((availability( + macosx, introduced = 10.9, deprecated = 10.10, obsoleted = 10.11))); +// Test obsoleted with non-existent variable. +extern int publicGlobalVariable5 __attribute__((availability( + macosx, introduced = 10.9, deprecated = 10.10, obsoleted = 10.11))); + +#ifdef __i386__ +#define OBSOLETE_I386 __attribute__((availability(macosx, obsoleted = 10.11))) +#else +#define OBSOLETE_I386 +#endif +extern int publicGlobalVariable6 OBSOLETE_I386; + + +/// Created from: +// int publicGlobalVariable; int privateGlobalVariable; +// +// @implementation Foo +// @end +// +// #ifndef __i386__ +// int publicGlobalVariable2; +// #endif +// +// int publicGlobalVariable3; +// int publicGlobalVariable4; +// +// #ifndef __i386__ +// int publicGlobalVariable6; +// #endif +;--- Availability.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 14 + sizeofcmds: 1312 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 8192 + fileoff: 0 + filesize: 8192 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1140 + size: 0 + offset: 0x1140 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __cstring + segname: __TEXT + addr: 0x1140 + size: 4 + offset: 0x1140 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 466F6F00 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA_CONST + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 16 + Sections: + - sectname: __objc_classlist + segname: __DATA_CONST + addr: 0x2000 + size: 8 + offset: 0x2000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: B830000000000000 + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x2008 + size: 8 + offset: 0x2008 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __DATA + vmaddr: 12288 + vmsize: 4096 + fileoff: 12288 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 3 + flags: 0 + Sections: + - sectname: __objc_const + segname: __DATA + addr: 0x3000 + size: 144 + offset: 0x3000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '010000002800000028000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + - sectname: __objc_data + segname: __DATA + addr: 0x3090 + size: 80 + offset: 0x3090 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000000000000000000000000000000000000000000000000000000003000000000000090300000000000000000000000000000000000000000000000000000000000004830000000000000' + - sectname: __common + segname: __DATA + addr: 0x30E0 + size: 24 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 16384 + vmsize: 824 + fileoff: 16384 + filesize: 824 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 16384 + rebase_size: 16 + bind_off: 16400 + bind_size: 104 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16504 + export_size: 152 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16664 + nsyms: 14 + stroff: 16888 + strsize: 320 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 2 + iextdefsym: 2 + nextdefsym: 8 + iundefsym: 10 + nundefsym: 4 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 112 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Availability.framework/Versions/A/Availability' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4470-5555-3144-A142-4EE44DA08D2F + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16656 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16664 + datasize: 0 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x0 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x40 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ULEBExtraData: [ 0x90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __objc_empty_cache + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFFF0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 17 + Name: OBJC_ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 49 + Name: 'METACLASS_$_Foo' + Flags: 0x0 + Address: 0x3090 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 54 + Name: 'CLASS_$_Foo' + Flags: 0x0 + Address: 0x30B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 59 + Name: p + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 104 + Name: rivateGlobalVariable + Flags: 0x0 + Address: 0x30E0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 109 + Name: ublicGlobalVariable + Flags: 0x0 + Address: 0x30E4 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 130 + Name: '4' + Flags: 0x0 + Address: 0x30F0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 135 + Name: '3' + Flags: 0x0 + Address: 0x30EC + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 140 + Name: '2' + Flags: 0x0 + Address: 0x30E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 145 + Name: '6' + Flags: 0x0 + Address: 0x30F4 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xE + n_sect: 5 + n_desc: 0 + n_value: 12288 + - n_strx: 28 + n_type: 0xE + n_sect: 5 + n_desc: 0 + n_value: 12360 + - n_strx: 50 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12512 + - n_strx: 73 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12516 + - n_strx: 95 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12520 + - n_strx: 118 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12524 + - n_strx: 141 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12528 + - n_strx: 164 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12532 + - n_strx: 187 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12432 + - n_strx: 209 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12472 + - n_strx: 227 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 250 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 277 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 296 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - '__OBJC_METACLASS_RO_$_Foo' + - '__OBJC_CLASS_RO_$_Foo' + - _privateGlobalVariable + - _publicGlobalVariable + - _publicGlobalVariable2 + - _publicGlobalVariable3 + - _publicGlobalVariable4 + - _publicGlobalVariable6 + - '_OBJC_METACLASS_$_Foo' + - '_OBJC_CLASS_$_Foo' + - '_OBJC_CLASS_$_NSObject' + - '_OBJC_METACLASS_$_NSObject' + - __objc_empty_cache + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + - '' +... diff --git a/clang/test/InstallAPI/diagnostics-cpp.test b/clang/test/InstallAPI/diagnostics-cpp.test new file mode 100644 index 00000000000000..f08d4f596c4fb3 --- /dev/null +++ b/clang/test/InstallAPI/diagnostics-cpp.test @@ -0,0 +1,461 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// RUN: yaml2obj %t/Mismatch.yaml -o %t/System/Library/Frameworks/MismatchCpp.framework/MismatchCpp + +// RUN: not clang-installapi --target=arm64-apple-macos13 -x objective-c++ \ +// RUN: -F %t/System/Library/Frameworks \ +// RUN: -install_name /System/Library/Frameworks/MismatchCpp.framework/Versions/A/MismatchCpp \ +// RUN: -current_version 1 -compatibility_version 1 %t/inputs.json \ +// RUN: --verify-against=%t/System/Library/Frameworks/MismatchCpp.framework/MismatchCpp \ +// RUN: --verify-mode=Pedantic -o output.tbd --demangle 2>&1 | FileCheck %s + +CHECK: warning: violations found for arm64-apple-macos13 +CHECK: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'vtable for Bar' +CHECK-NEXT: class Bar : Foo { +CHECK-NEXT: ^ +CHECK-NEXT: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'typeinfo for Bar' +CHECK-NEXT: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'typeinfo name for Bar' +CHECK-NEXT: CPP.h:6:7: error: dynamic library symbol '(weak-def) Bar::init()' is weak defined, but its declaration is not +CHECK-NEXT: int init(); +CHECK-NEXT: ^ + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/MismatchCpp.framework/Headers/CPP.h", + "type" : "public" + } + ], + "version": "3" +} + +//--- System/Library/Frameworks/MismatchCpp.framework/Headers/CPP.h +class Foo { + virtual int init() = 0; +}; + +class Bar : Foo { + int init(); +}; + +/// Created from: +// With LD flags: -exported_symbol,"__ZN3Bar4initEv" -exported_symbol,"__Z3fooIjEiT_" +// class Foo { virtual int init() = 0;}; +// +// class Bar : Foo {int init() { return 1;}}; +// Bar bar; +// +// template <typename T> int foo(T val) { return 1; } +// template <> int foo(unsigned val) { return 1; } + +//--- Mismatch.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 15 + sizeofcmds: 1224 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x10E8 + size: 16 + offset: 0x10E8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 20008052C0035FD620008052C0035FD6 + - sectname: __const + segname: __TEXT + addr: 0x10F8 + size: 10 + offset: 0x10F8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 334261720033466F6F00 + - sectname: __unwind_info + segname: __TEXT + addr: 0x1104 + size: 4152 + offset: 0x1104 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002E81000003800000038000000F81000000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA_CONST + vmaddr: 16384 + vmsize: 16384 + fileoff: 16384 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 16 + Sections: + - sectname: __const + segname: __DATA_CONST + addr: 0x4000 + size: 80 + offset: 0x4000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 00000000000000002840000000000000F0100000000000001000000000000000FD100000000000801000000000000000F810000000000080000000000100000018400000000000000000000000000000 + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x4050 + size: 8 + offset: 0x4050 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 32768 + vmsize: 16384 + fileoff: 32768 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x8000 + size: 8 + offset: 0x8000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '1040000000000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 49152 + vmsize: 1104 + fileoff: 49152 + filesize: 1104 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 49152 + rebase_size: 16 + bind_off: 49168 + bind_size: 96 + weak_bind_off: 49264 + weak_bind_size: 24 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 49288 + export_size: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 49344 + nsyms: 11 + stroff: 49520 + strsize: 192 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 6 + iextdefsym: 6 + nextdefsym: 2 + iundefsym: 8 + nundefsym: 3 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/MismatchCpp.framework/Versions/A/MismatchCpp' + ZeroPadBytes: 1 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C44F3-5555-3144-A13F-B3FE15787197 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 0 + current_version: 117985024 + compatibility_version: 65536 + Content: '/usr/lib/libc++.1.dylib' + ZeroPadBytes: 1 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 49336 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 49344 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 49712 + datasize: 544 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x3, 0x8 ] + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ExtraData: [ 0x0 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZTVN10__cxxabiv117__class_type_infoE + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x18 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 16 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZTVN10__cxxabiv121__vmi_class_type_infoE + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x8 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + WeakBindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZN3Bar4initEv + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x10 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 7 + Name: __Z + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 35 + Name: 3fooIjEiT_ + Flags: 0x0 + Address: 0x10E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 40 + Name: N3Bar4initEv + Flags: 0x4 + Address: 0x10F0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 32 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16384 + - n_strx: 42 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16408 + - n_strx: 52 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16424 + - n_strx: 62 + n_type: 0x1E + n_sect: 6 + n_desc: 0 + n_value: 32768 + - n_strx: 67 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4344 + - n_strx: 77 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4349 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4328 + - n_strx: 16 + n_type: 0xF + n_sect: 1 + n_desc: 128 + n_value: 4336 + - n_strx: 87 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 126 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 169 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - __Z3fooIjEiT_ + - __ZN3Bar4initEv + - __ZTV3Bar + - __ZTI3Foo + - __ZTI3Bar + - _bar + - __ZTS3Bar + - __ZTS3Foo + - __ZTVN10__cxxabiv117__class_type_infoE + - __ZTVN10__cxxabiv121__vmi_class_type_infoE + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x10E8, 0x10F0 ] +... diff --git a/clang/test/InstallAPI/hiddens.test b/clang/test/InstallAPI/hiddens.test new file mode 100644 index 00000000000000..b3196ef945cd12 --- /dev/null +++ b/clang/test/InstallAPI/hiddens.test @@ -0,0 +1,262 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// RUN: yaml2obj %t/Hidden.yaml -o %t/System/Library/Frameworks/Hidden.framework/Hidden + +// RUN: clang-installapi --target=x86_64-apple-macos13 -x objective-c \ +// RUN: -F %t/System/Library/Frameworks \ +// RUN: -install_name /System/Library/Frameworks/Hidden.framework/Versions/A/Hidden\ +// RUN: -current_version 1 -compatibility_version 1 %t/inputs.json \ +// RUN: --verify-against=%t/System/Library/Frameworks/Hidden.framework/Hidden \ +// RUN: --verify-mode=Pedantic -o %t/output.tbd 2>&1 | FileCheck %s + +// CHECK-NOT: error +// CHECK: warning: use of __private_extern__ + +// RUN: llvm-readtapi --compare %t/output.tbd %t/expected.tbd + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/Hidden.framework/Headers/Hidden.h", + "type" : "public" + } + ], + "version": "3" +} + +//--- System/Library/Frameworks/Hidden.framework/Headers/Hidden.h +__private_extern__ int foo(); // Clang doesn't warn on this, but should. +__private_extern__ int baz; +__attribute__((visibility("hidden"))) int bar(); + +/// Created from: +/// #import "Hidden.h" int foo(void) { return 1; } int bar(void) { return 1; } +//--- Hidden.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 12 + sizeofcmds: 920 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 0 + vmsize: 8192 + fileoff: 0 + filesize: 8192 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xBB8 + size: 22 + offset: 0xBB8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E5B8010000005DC3554889E5B8010000005DC3 + - sectname: __unwind_info + segname: __TEXT + addr: 0xBD0 + size: 4152 + offset: 0xBD0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000001B80B00003800000038000000CE0B00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x1C08 + size: 24 + offset: 0x1C08 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C070890010000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x2000 + size: 8 + offset: 0x2000 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 12288 + vmsize: 104 + fileoff: 12288 + filesize: 104 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 12288 + export_size: 16 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 12312 + nsyms: 3 + stroff: 12360 + strsize: 32 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 1 + iextdefsym: 1 + nextdefsym: 1 + iundefsym: 2 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 88 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Hidden.framework/Versions/A/Hidden' + ZeroPadBytes: 3 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C44E7-5555-3144-A133-0271E799C487 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 12304 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 12312 + datasize: 0 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 8 + Name: _foo + Flags: 0x0 + Address: 0xBB8 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 7 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 3011 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 3000 + - n_strx: 12 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - _foo + - _bar + - dyld_stub_binder + - '' + - '' + - '' + FunctionStarts: [ 0xBB8, 0xBC3 ] +... + +//--- expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ x86_64-macos ] +flags: [ not_app_extension_safe ] +install-name: '/System/Library/Frameworks/Hidden.framework/Versions/A/Hidden' +... + diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index d758f731179008..54e82d78d4d228 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -111,17 +111,15 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { // Execute and gather AST results. // An invocation is ran for each unique target triple and for each header // access level. - Records FrontendResults; for (const auto &[Targ, Trip] : Opts.DriverOpts.Targets) { + Ctx.Verifier->setTarget(Targ); + Ctx.Slice = std::make_shared<FrontendRecordsSlice>(Trip); for (const HeaderType Type : {HeaderType::Public, HeaderType::Private, HeaderType::Project}) { - Ctx.Slice = std::make_shared<FrontendRecordsSlice>(Trip); - Ctx.Verifier->setTarget(Targ); Ctx.Type = Type; if (!runFrontend(ProgName, Opts.DriverOpts.Verbose, Ctx, InMemoryFileSystem.get(), Opts.getClangFrontendArgs())) return EXIT_FAILURE; - FrontendResults.emplace_back(std::move(Ctx.Slice)); } } diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index e5ff8a1aaa4fe5..b8696bb7896d86 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -261,6 +261,9 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, if (!processFrontendOptions(ArgList)) return; + /// Force cc1 options that should always be on. + FrontendArgs = {"-fsyntax-only", "-Wprivate-extern"}; + /// Any unclaimed arguments should be handled by invoking the clang frontend. for (const Arg *A : ArgList) { if (A->isClaimed()) @@ -268,7 +271,6 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, FrontendArgs.emplace_back(A->getSpelling()); llvm::copy(A->getValues(), std::back_inserter(FrontendArgs)); } - FrontendArgs.push_back("-fsyntax-only"); } InstallAPIContext Options::createContext() { >From ac25849bbbd3aadd77c19a56da976f5f6fee5ceb Mon Sep 17 00:00:00 2001 From: Cyndy Ishida <cyndy_ish...@apple.com> Date: Sat, 16 Mar 2024 13:05:55 -0700 Subject: [PATCH 2/2] Add DiagnosticGroup for installapi warnings --- clang/include/clang/Basic/DiagnosticGroups.td | 4 ++++ .../clang/Basic/DiagnosticInstallAPIKinds.td | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index f5ff89111d1110..dee555f783cc45 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1508,3 +1508,7 @@ def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">; // Warnings and fixes to support the "safe buffers" programming model. def UnsafeBufferUsageInContainer : DiagGroup<"unsafe-buffer-usage-in-container">; def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer]>; + +// Warnings and notes InstallAPI verification. +def InstallAPIViolation : DiagGroup<"installapi-violation">; + diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 5ed2e23425dc5f..f99a5fca64cb46 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -18,22 +18,22 @@ def err_no_output_file: Error<"no output file specified">; } // end of command line category. let CategoryName = "Verification" in { -def warn_target: Warning<"violations found for %0">; +def warn_target: Warning<"violations found for %0">, InGroup<InstallAPIViolation>; def err_library_missing_symbol : Error<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">; -def warn_library_missing_symbol : Warning<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">; +def warn_library_missing_symbol : Warning<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">, InGroup<InstallAPIViolation>; def err_library_hidden_symbol : Error<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">; -def warn_library_hidden_symbol : Warning<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">; -def warn_header_hidden_symbol : Warning<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; +def warn_library_hidden_symbol : Warning<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">, InGroup<InstallAPIViolation>; +def warn_header_hidden_symbol : Warning<"symbol exported in dynamic library, but marked hidden in declaration '%0'">, InGroup<InstallAPIViolation>; def err_header_hidden_symbol : Error<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; def err_header_symbol_missing : Error<"no declaration found for exported symbol '%0' in dynamic library">; def warn_header_availability_mismatch : Warning<"declaration '%0' is marked %select{available|unavailable}1," - " but symbol is %select{not |}2exported in dynamic library">; + " but symbol is %select{not |}2exported in dynamic library">, InGroup<InstallAPIViolation>; def err_header_availability_mismatch : Error<"declaration '%0' is marked %select{available|unavailable}1," " but symbol is %select{not |}2exported in dynamic library">; def warn_dylib_symbol_flags_mismatch : Warning<"dynamic library symbol '%0' is " - "%select{weak defined|thread local}1, but its declaration is not">; + "%select{weak defined|thread local}1, but its declaration is not">, InGroup<InstallAPIViolation>; def warn_header_symbol_flags_mismatch : Warning<"declaration '%0' is " - "%select{weak defined|thread local}1, but symbol is not in dynamic library">; + "%select{weak defined|thread local}1, but symbol is not in dynamic library">, InGroup<InstallAPIViolation>; def err_dylib_symbol_flags_mismatch : Error<"dynamic library symbol '%0' is " "%select{weak defined|thread local}1, but its declaration is not">; def err_header_symbol_flags_mismatch : Error<"declaration '%0' is " _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits