Reapply "[clang] Fix some static initialization race-conditions" (#182020)
This reverts d4b574266132e08ff585facf2e0e01995082999f, and reapplies d7f32f1fbf83da2faa4acdcaf2a4d4885a2d068c. Original commit message: - clang/StaticAnalyzer: fix static init in findKnownClass. Prior to this patch two threads running in findKnownClass could result in a race condition. - clang/Stmt: fix StmtClassNameTable array initialization: prior to this patch there was a race condition when two threads check `if(Initialized)` at the same time. - clang/ParsedAttrInfo: fix race condition in getAttributePluginInstances. Prior to this patch two threads could enter `if(empty())` check. - clang/CodeGen: correctly restore diagnostic handler in HandleTranslationUnit. Prior to this patch an early exit from HandleTranslationUnit could result in not restoring previous diagnostic handler.
This commit is contained in:
parent
537e09b70d
commit
5fbbd41342
@ -40,6 +40,7 @@
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
@ -57,25 +58,23 @@ using namespace clang;
|
||||
#define ABSTRACT_STMT(STMT)
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
static struct StmtClassNameTable {
|
||||
struct StmtClassNameTable {
|
||||
const char *Name;
|
||||
unsigned Counter;
|
||||
unsigned Size;
|
||||
} StmtClassInfo[Stmt::lastStmtConstant+1];
|
||||
};
|
||||
|
||||
static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
|
||||
static bool Initialized = false;
|
||||
if (Initialized)
|
||||
return StmtClassInfo[E];
|
||||
|
||||
// Initialize the table on the first use.
|
||||
Initialized = true;
|
||||
static std::array<StmtClassNameTable, Stmt::lastStmtConstant + 1>
|
||||
StmtClassInfo = [] {
|
||||
std::array<StmtClassNameTable, Stmt::lastStmtConstant + 1> Table{};
|
||||
#define ABSTRACT_STMT(STMT)
|
||||
#define STMT(CLASS, PARENT) \
|
||||
StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
|
||||
StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
|
||||
#define STMT(CLASS, PARENT) \
|
||||
Table[static_cast<unsigned>(Stmt::CLASS##Class)].Name = #CLASS; \
|
||||
Table[static_cast<unsigned>(Stmt::CLASS##Class)].Size = sizeof(CLASS);
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
return Table;
|
||||
}();
|
||||
return StmtClassInfo[E];
|
||||
}
|
||||
|
||||
@ -85,7 +84,7 @@ void *Stmt::operator new(size_t bytes, const ASTContext& C,
|
||||
}
|
||||
|
||||
const char *Stmt::getStmtClassName() const {
|
||||
return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
|
||||
return getStmtInfoTableEntry(static_cast<StmtClass>(StmtBits.sClass)).Name;
|
||||
}
|
||||
|
||||
// Check that no statement / expression class is polymorphic. LLVM style RTTI
|
||||
@ -113,19 +112,25 @@ void Stmt::PrintStats() {
|
||||
unsigned sum = 0;
|
||||
llvm::errs() << "\n*** Stmt/Expr Stats:\n";
|
||||
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
|
||||
if (StmtClassInfo[i].Name == nullptr) continue;
|
||||
sum += StmtClassInfo[i].Counter;
|
||||
const StmtClassNameTable &Entry =
|
||||
getStmtInfoTableEntry(static_cast<Stmt::StmtClass>(i));
|
||||
if (Entry.Name == nullptr)
|
||||
continue;
|
||||
sum += Entry.Counter;
|
||||
}
|
||||
llvm::errs() << " " << sum << " stmts/exprs total.\n";
|
||||
sum = 0;
|
||||
for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
|
||||
if (StmtClassInfo[i].Name == nullptr) continue;
|
||||
if (StmtClassInfo[i].Counter == 0) continue;
|
||||
llvm::errs() << " " << StmtClassInfo[i].Counter << " "
|
||||
<< StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
|
||||
<< " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
|
||||
const StmtClassNameTable &Entry =
|
||||
getStmtInfoTableEntry(static_cast<Stmt::StmtClass>(i));
|
||||
if (Entry.Name == nullptr)
|
||||
continue;
|
||||
if (Entry.Counter == 0)
|
||||
continue;
|
||||
llvm::errs() << " " << Entry.Counter << " " << Entry.Name << ", "
|
||||
<< Entry.Size << " each (" << Entry.Counter * Entry.Size
|
||||
<< " bytes)\n";
|
||||
sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
|
||||
sum += Entry.Counter * Entry.Size;
|
||||
}
|
||||
|
||||
llvm::errs() << "Total bytes = " << sum << "\n";
|
||||
|
||||
@ -20,13 +20,16 @@ using namespace clang;
|
||||
|
||||
LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
|
||||
|
||||
static std::list<std::unique_ptr<ParsedAttrInfo>> instantiateEntries() {
|
||||
std::list<std::unique_ptr<ParsedAttrInfo>> Instances;
|
||||
for (const auto &It : ParsedAttrInfoRegistry::entries())
|
||||
Instances.emplace_back(It.instantiate());
|
||||
return Instances;
|
||||
}
|
||||
|
||||
const std::list<std::unique_ptr<ParsedAttrInfo>> &
|
||||
clang::getAttributePluginInstances() {
|
||||
static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
|
||||
PluginAttrInstances;
|
||||
if (PluginAttrInstances->empty())
|
||||
for (const auto &It : ParsedAttrInfoRegistry::entries())
|
||||
PluginAttrInstances->emplace_back(It.instantiate());
|
||||
|
||||
return *PluginAttrInstances;
|
||||
static std::list<std::unique_ptr<ParsedAttrInfo>> Instances =
|
||||
instantiateEntries();
|
||||
return Instances;
|
||||
}
|
||||
|
||||
@ -248,6 +248,8 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
|
||||
LLVMContext &Ctx = getModule()->getContext();
|
||||
std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler =
|
||||
Ctx.getDiagnosticHandler();
|
||||
llvm::scope_exit RestoreDiagnosticHandler(
|
||||
[&]() { Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); });
|
||||
Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>(
|
||||
CodeGenOpts, this));
|
||||
|
||||
@ -311,8 +313,6 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
|
||||
C.getTargetInfo().getDataLayoutString(), getModule(),
|
||||
Action, FS, std::move(AsmOutStream), this);
|
||||
|
||||
Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
|
||||
|
||||
if (OptRecordFile)
|
||||
OptRecordFile->keep();
|
||||
}
|
||||
|
||||
@ -70,16 +70,12 @@ enum FoundationClass {
|
||||
|
||||
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID,
|
||||
bool IncludeSuperclasses = true) {
|
||||
static llvm::StringMap<FoundationClass> Classes;
|
||||
if (Classes.empty()) {
|
||||
Classes["NSArray"] = FC_NSArray;
|
||||
Classes["NSDictionary"] = FC_NSDictionary;
|
||||
Classes["NSEnumerator"] = FC_NSEnumerator;
|
||||
Classes["NSNull"] = FC_NSNull;
|
||||
Classes["NSOrderedSet"] = FC_NSOrderedSet;
|
||||
Classes["NSSet"] = FC_NSSet;
|
||||
Classes["NSString"] = FC_NSString;
|
||||
}
|
||||
static const llvm::StringMap<FoundationClass> Classes{
|
||||
{"NSArray", FC_NSArray}, {"NSDictionary", FC_NSDictionary},
|
||||
{"NSEnumerator", FC_NSEnumerator}, {"NSNull", FC_NSNull},
|
||||
{"NSOrderedSet", FC_NSOrderedSet}, {"NSSet", FC_NSSet},
|
||||
{"NSString", FC_NSString},
|
||||
};
|
||||
|
||||
// FIXME: Should we cache this at all?
|
||||
FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user