Skip to content

[InstallAPI] Tie lifetime of FE objects to DylibVerifier #88189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/InstallAPI/MachO.h"

namespace clang {
Expand Down Expand Up @@ -99,11 +100,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
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);
}
void setSourceManager(IntrusiveRefCntPtr<SourceManager> SourceMgr);

private:
/// Determine whether to compare declaration to symbol in binary.
Expand Down Expand Up @@ -190,6 +187,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {

// Track DWARF provided source location for dylibs.
DWARFContext *DWARFCtx = nullptr;

// Source manager for each unique compiler instance.
llvm::SmallVector<IntrusiveRefCntPtr<SourceManager>, 12> SourceManagers;
};

} // namespace installapi
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/InstallAPI/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ 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());
Ctx.Verifier->setSourceManager(CI.getSourceManagerPtr());
return std::make_unique<InstallAPIVisitor>(
CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor());
}
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/FrontendRecords.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace installapi {
struct FrontendAttrs {
const AvailabilityInfo Avail;
const Decl *D;
const SourceLocation Loc;
const HeaderType Access;
};

Expand Down
47 changes: 23 additions & 24 deletions clang/lib/InstallAPI/DylibVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,16 +214,16 @@ bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R,
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)
Ctx.Diag->Report(SymCtx.FA->Loc, 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)
Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning
? diag::warn_library_hidden_symbol
: diag::err_library_hidden_symbol)
<< SymName;
});
};
Expand Down Expand Up @@ -270,16 +270,14 @@ DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R,
if (R->isExported()) {
if (!DR) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_library_missing_symbol)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_missing_symbol)
<< getAnnotatedName(R, SymCtx);
});
return Result::Invalid;
}
if (DR->isInternal()) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_library_hidden_symbol)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_hidden_symbol)
<< getAnnotatedName(R, SymCtx);
});
return Result::Invalid;
Expand All @@ -306,8 +304,7 @@ DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R,
Outcome = Result::Invalid;
}
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(), ID)
<< getAnnotatedName(R, SymCtx);
Ctx.Diag->Report(SymCtx.FA->Loc, ID) << getAnnotatedName(R, SymCtx);
});
return Outcome;
}
Expand All @@ -329,15 +326,13 @@ DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R,
switch (Mode) {
case VerificationMode::ErrorsAndWarnings:
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::warn_header_availability_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::warn_header_availability_mismatch)
<< getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
});
return Result::Ignore;
case VerificationMode::Pedantic:
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_header_availability_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_availability_mismatch)
<< getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
});
return Result::Invalid;
Expand All @@ -353,33 +348,29 @@ bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx,
const Record *DR) {
if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_dylib_symbol_flags_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
<< getAnnotatedName(DR, SymCtx) << DR->isThreadLocalValue();
});
return false;
}
if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_header_symbol_flags_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
<< getAnnotatedName(R, SymCtx) << R->isThreadLocalValue();
});
return false;
}

if (DR->isWeakDefined() && !R->isWeakDefined()) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_dylib_symbol_flags_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
<< getAnnotatedName(DR, SymCtx) << R->isWeakDefined();
});
return false;
}
if (!DR->isWeakDefined() && R->isWeakDefined()) {
Ctx.emitDiag([&]() {
Ctx.Diag->Report(SymCtx.FA->D->getLocation(),
diag::err_header_symbol_flags_mismatch)
Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
<< getAnnotatedName(R, SymCtx) << R->isWeakDefined();
});
return false;
Expand Down Expand Up @@ -487,6 +478,14 @@ void DylibVerifier::setTarget(const Target &T) {
assignSlice(T);
}

void DylibVerifier::setSourceManager(
IntrusiveRefCntPtr<SourceManager> SourceMgr) {
if (!Ctx.Diag)
return;
SourceManagers.push_back(std::move(SourceMgr));
Ctx.Diag->setSourceManager(SourceManagers.back().get());
}

DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R,
const FrontendAttrs *FA,
const StringRef SuperClass) {
Expand Down
15 changes: 8 additions & 7 deletions clang/lib/InstallAPI/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ std::pair<GlobalRecord *, FrontendAttrs *> FrontendRecordsSlice::addGlobal(

GlobalRecord *GR =
llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined);
auto Result = FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}});
auto Result = FrontendRecords.insert(
{GR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
return {GR, &(Result.first->second)};
}

Expand All @@ -39,8 +40,8 @@ FrontendRecordsSlice::addObjCInterface(StringRef Name, RecordLinkage Linkage,

ObjCInterfaceRecord *ObjCR =
llvm::MachO::RecordsSlice::addObjCInterface(Name, Linkage, SymType);
auto Result =
FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
auto Result = FrontendRecords.insert(
{ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
return {ObjCR, &(Result.first->second)};
}

Expand All @@ -51,8 +52,8 @@ FrontendRecordsSlice::addObjCCategory(StringRef ClassToExtend,
const Decl *D, HeaderType Access) {
ObjCCategoryRecord *ObjCR =
llvm::MachO::RecordsSlice::addObjCCategory(ClassToExtend, CategoryName);
auto Result =
FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
auto Result = FrontendRecords.insert(
{ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
return {ObjCR, &(Result.first->second)};
}

Expand All @@ -67,8 +68,8 @@ std::pair<ObjCIVarRecord *, FrontendAttrs *> FrontendRecordsSlice::addObjCIVar(
Linkage = RecordLinkage::Internal;
ObjCIVarRecord *ObjCR =
llvm::MachO::RecordsSlice::addObjCIVar(Container, IvarName, Linkage);
auto Result =
FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
auto Result = FrontendRecords.insert(
{ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});

return {ObjCR, &(Result.first->second)};
}
Expand Down
2 changes: 2 additions & 0 deletions clang/tools/clang-installapi/ClangInstallAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
// Execute, verify and gather AST results.
// An invocation is ran for each unique target triple and for each header
// access level.
Records FrontendRecords;
for (const auto &[Targ, Trip] : Opts.DriverOpts.Targets) {
Ctx.Verifier->setTarget(Targ);
Ctx.Slice = std::make_shared<FrontendRecordsSlice>(Trip);
Expand All @@ -131,6 +132,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
InMemoryFileSystem.get(), Opts.getClangFrontendArgs()))
return EXIT_FAILURE;
}
FrontendRecords.emplace_back(std::move(Ctx.Slice));
}

if (Ctx.Verifier->verifyRemainingSymbols() == DylibVerifier::Result::Invalid)
Expand Down