Skip to content

Commit de57e89

Browse files
committed
Merge remote-tracking branch 'origin/main' into pr/vfnrclip
2 parents 4b83ebc + 71b6f6b commit de57e89

File tree

30 files changed

+902
-188
lines changed

30 files changed

+902
-188
lines changed

clang/docs/RealtimeSanitizer.rst

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C+
1111
projects. RTSan can be used to detect real-time violations, i.e. calls to methods
1212
that are not safe for use in functions with deterministic run time requirements.
1313
RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
14-
to be a real-time function. If RTSan detects a call to ``malloc``, ``free``,
15-
``pthread_mutex_lock``, or anything else that could have a non-deterministic
16-
execution time in a function marked ``[[clang::nonblocking]]``
14+
to be a real-time function. At run-time, if RTSan detects a call to ``malloc``,
15+
``free``, ``pthread_mutex_lock``, or anything else that could have a
16+
non-deterministic execution time in a function marked ``[[clang::nonblocking]]``
1717
RTSan raises an error.
1818

19+
RTSan performs its analysis at run-time but shares the ``[[clang::nonblocking]]``
20+
attribute with the :doc:`FunctionEffectAnalysis` system, which operates at
21+
compile-time to detect potential real-time safety violations. For comprehensive
22+
detection of real-time safety issues, it is recommended to use both systems together.
23+
1924
The runtime slowdown introduced by RealtimeSanitizer is negligible.
2025

2126
How to build

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ class CXXNameMangler {
468468
void mangleLambdaSig(const CXXRecordDecl *Lambda);
469469
void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
470470
void mangleVendorQualifier(StringRef Name);
471+
void mangleVendorType(StringRef Name);
471472

472473
private:
473474

@@ -2891,6 +2892,10 @@ void CXXNameMangler::mangleVendorQualifier(StringRef name) {
28912892
Out << 'U' << name.size() << name;
28922893
}
28932894

2895+
void CXXNameMangler::mangleVendorType(StringRef name) {
2896+
Out << 'u' << name.size() << name;
2897+
}
2898+
28942899
void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
28952900
// <ref-qualifier> ::= R # lvalue reference
28962901
// ::= O # rvalue-reference
@@ -3413,8 +3418,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
34133418
if (T->getKind() == BuiltinType::SveBFloat16 && \
34143419
isCompatibleWith(LangOptions::ClangABI::Ver17)) { \
34153420
/* Prior to Clang 18.0 we used this incorrect mangled name */ \
3416-
type_name = "__SVBFloat16_t"; \
3417-
Out << "u" << type_name.size() << type_name; \
3421+
mangleVendorType("__SVBFloat16_t"); \
34183422
} else { \
34193423
type_name = MangledName; \
34203424
Out << (type_name == Name ? "u" : "") << type_name.size() << type_name; \
@@ -3436,35 +3440,30 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
34363440
Out << (type_name == Name ? "u" : "") << type_name.size() << type_name; \
34373441
break;
34383442
#include "clang/Basic/AArch64SVEACLETypes.def"
3439-
#define PPC_VECTOR_TYPE(Name, Id, Size) \
3440-
case BuiltinType::Id: \
3441-
type_name = #Name; \
3442-
Out << 'u' << type_name.size() << type_name; \
3443+
#define PPC_VECTOR_TYPE(Name, Id, Size) \
3444+
case BuiltinType::Id: \
3445+
mangleVendorType(#Name); \
34433446
break;
34443447
#include "clang/Basic/PPCTypes.def"
34453448
// TODO: Check the mangling scheme for RISC-V V.
34463449
#define RVV_TYPE(Name, Id, SingletonId) \
34473450
case BuiltinType::Id: \
3448-
type_name = Name; \
3449-
Out << 'u' << type_name.size() << type_name; \
3451+
mangleVendorType(Name); \
34503452
break;
34513453
#include "clang/Basic/RISCVVTypes.def"
34523454
#define WASM_REF_TYPE(InternalName, MangledName, Id, SingletonId, AS) \
34533455
case BuiltinType::Id: \
3454-
type_name = MangledName; \
3455-
Out << 'u' << type_name.size() << type_name; \
3456+
mangleVendorType(MangledName); \
34563457
break;
34573458
#include "clang/Basic/WebAssemblyReferenceTypes.def"
34583459
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
34593460
case BuiltinType::Id: \
3460-
type_name = Name; \
3461-
Out << 'u' << type_name.size() << type_name; \
3461+
mangleVendorType(Name); \
34623462
break;
34633463
#include "clang/Basic/AMDGPUTypes.def"
34643464
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
34653465
case BuiltinType::Id: \
3466-
type_name = #Name; \
3467-
Out << 'u' << type_name.size() << type_name; \
3466+
mangleVendorType(#Name); \
34683467
break;
34693468
#include "clang/Basic/HLSLIntangibleTypes.def"
34703469
}
@@ -4035,8 +4034,9 @@ void CXXNameMangler::mangleAArch64FixedSveVectorType(const VectorType *T) {
40354034
if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)
40364035
VecSizeInBits *= 8;
40374036

4038-
Out << "9__SVE_VLSI" << 'u' << TypeName.size() << TypeName << "Lj"
4039-
<< VecSizeInBits << "EE";
4037+
Out << "9__SVE_VLSI";
4038+
mangleVendorType(TypeName);
4039+
Out << "Lj" << VecSizeInBits << "EE";
40404040
}
40414041

40424042
void CXXNameMangler::mangleAArch64FixedSveVectorType(
@@ -4136,8 +4136,9 @@ void CXXNameMangler::mangleRISCVFixedRVVVectorType(const VectorType *T) {
41364136
}
41374137
TypeNameOS << "_t";
41384138

4139-
Out << "9__RVV_VLSI" << 'u' << TypeNameStr.size() << TypeNameStr << "Lj"
4140-
<< VecSizeInBits << "EE";
4139+
Out << "9__RVV_VLSI";
4140+
mangleVendorType(TypeNameStr);
4141+
Out << "Lj" << VecSizeInBits << "EE";
41414142
}
41424143

41434144
void CXXNameMangler::mangleRISCVFixedRVVVectorType(
@@ -4236,8 +4237,7 @@ void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
42364237
// Mangle matrix types as a vendor extended type:
42374238
// u<Len>matrix_typeI<Rows><Columns><element type>E
42384239

4239-
StringRef VendorQualifier = "matrix_type";
4240-
Out << "u" << VendorQualifier.size() << VendorQualifier;
4240+
mangleVendorType("matrix_type");
42414241

42424242
Out << "I";
42434243
auto &ASTCtx = getASTContext();
@@ -4255,8 +4255,7 @@ void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
42554255
void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) {
42564256
// Mangle matrix types as a vendor extended type:
42574257
// u<Len>matrix_typeI<row expr><column expr><element type>E
4258-
StringRef VendorQualifier = "matrix_type";
4259-
Out << "u" << VendorQualifier.size() << VendorQualifier;
4258+
mangleVendorType("matrix_type");
42604259

42614260
Out << "I";
42624261
mangleTemplateArgExpr(T->getRowExpr());
@@ -4302,7 +4301,7 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) {
43024301
StringRef name = I->getName();
43034302
QualOS << name.size() << name;
43044303
}
4305-
Out << 'U' << QualStr.size() << QualStr;
4304+
mangleVendorQualifier(QualStr);
43064305
}
43074306

43084307
mangleType(T->getBaseType());
@@ -4436,8 +4435,6 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
44364435
// If this is dependent, we need to record that. If not, we simply
44374436
// mangle it as the underlying type since they are equivalent.
44384437
if (T->isDependentType()) {
4439-
Out << "u";
4440-
44414438
StringRef BuiltinName;
44424439
switch (T->getUTTKind()) {
44434440
#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
@@ -4446,7 +4443,7 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
44464443
break;
44474444
#include "clang/Basic/TransformTypeTraits.def"
44484445
}
4449-
Out << BuiltinName.size() << BuiltinName;
4446+
mangleVendorType(BuiltinName);
44504447
}
44514448

44524449
Out << "I";
@@ -5311,9 +5308,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
53115308
// <expression> ::= u <source-name> <template-arg>* E # vendor extension
53125309
const TypeTraitExpr *TTE = cast<TypeTraitExpr>(E);
53135310
NotPrimaryExpr();
5314-
Out << 'u';
53155311
llvm::StringRef Spelling = getTraitSpelling(TTE->getTrait());
5316-
Out << Spelling.size() << Spelling;
5312+
mangleVendorType(Spelling);
53175313
for (TypeSourceInfo *TSI : TTE->getArgs()) {
53185314
mangleType(TSI->getType());
53195315
}

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 82 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ class MatchDescendantVisitor
171171
return VisitorBase::TraverseCXXTypeidExpr(Node);
172172
}
173173

174+
bool TraverseCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
175+
if (!TraverseStmt(Node->getExpr()))
176+
return false;
177+
return VisitorBase::TraverseCXXDefaultInitExpr(Node);
178+
}
179+
174180
bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) {
175181
if (!Node)
176182
return true;
@@ -1972,14 +1978,18 @@ class DerefSimplePtrArithFixableGadget : public FixableGadget {
19721978
};
19731979

19741980
/// Scan the function and return a list of gadgets found with provided kits.
1975-
static std::tuple<FixableGadgetList, WarningGadgetList, DeclUseTracker>
1976-
findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
1977-
bool EmitSuggestions) {
1981+
static void findGadgets(const Stmt *S, ASTContext &Ctx,
1982+
const UnsafeBufferUsageHandler &Handler,
1983+
bool EmitSuggestions, FixableGadgetList &FixableGadgets,
1984+
WarningGadgetList &WarningGadgets,
1985+
DeclUseTracker &Tracker) {
19781986

19791987
struct GadgetFinderCallback : MatchFinder::MatchCallback {
1980-
FixableGadgetList FixableGadgets;
1981-
WarningGadgetList WarningGadgets;
1982-
DeclUseTracker Tracker;
1988+
GadgetFinderCallback(FixableGadgetList &FixableGadgets,
1989+
WarningGadgetList &WarningGadgets,
1990+
DeclUseTracker &Tracker)
1991+
: FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets),
1992+
Tracker(Tracker) {}
19831993

19841994
void run(const MatchFinder::MatchResult &Result) override {
19851995
// In debug mode, assert that we've found exactly one gadget.
@@ -2020,10 +2030,14 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
20202030
assert(numFound >= 1 && "Gadgets not found in match result!");
20212031
assert(numFound <= 1 && "Conflicting bind tags in gadgets!");
20222032
}
2033+
2034+
FixableGadgetList &FixableGadgets;
2035+
WarningGadgetList &WarningGadgets;
2036+
DeclUseTracker &Tracker;
20232037
};
20242038

20252039
MatchFinder M;
2026-
GadgetFinderCallback CB;
2040+
GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker};
20272041

20282042
// clang-format off
20292043
M.addMatcher(
@@ -2068,9 +2082,7 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler,
20682082
// clang-format on
20692083
}
20702084

2071-
M.match(*D->getBody(), D->getASTContext());
2072-
return {std::move(CB.FixableGadgets), std::move(CB.WarningGadgets),
2073-
std::move(CB.Tracker)};
2085+
M.match(*S, Ctx);
20742086
}
20752087

20762088
// Compares AST nodes by source locations.
@@ -3614,39 +3626,9 @@ class VariableGroupsManagerImpl : public VariableGroupsManager {
36143626
}
36153627
};
36163628

3617-
void clang::checkUnsafeBufferUsage(const Decl *D,
3618-
UnsafeBufferUsageHandler &Handler,
3619-
bool EmitSuggestions) {
3620-
#ifndef NDEBUG
3621-
Handler.clearDebugNotes();
3622-
#endif
3623-
3624-
assert(D && D->getBody());
3625-
// We do not want to visit a Lambda expression defined inside a method
3626-
// independently. Instead, it should be visited along with the outer method.
3627-
// FIXME: do we want to do the same thing for `BlockDecl`s?
3628-
if (const auto *fd = dyn_cast<CXXMethodDecl>(D)) {
3629-
if (fd->getParent()->isLambda() && fd->getParent()->isLocalClass())
3630-
return;
3631-
}
3632-
3633-
// Do not emit fixit suggestions for functions declared in an
3634-
// extern "C" block.
3635-
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3636-
for (FunctionDecl *FReDecl : FD->redecls()) {
3637-
if (FReDecl->isExternC()) {
3638-
EmitSuggestions = false;
3639-
break;
3640-
}
3641-
}
3642-
}
3643-
3644-
WarningGadgetSets UnsafeOps;
3645-
FixableGadgetSets FixablesForAllVars;
3646-
3647-
auto [FixableGadgets, WarningGadgets, Tracker] =
3648-
findGadgets(D, Handler, EmitSuggestions);
3649-
3629+
void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets,
3630+
WarningGadgetList WarningGadgets, DeclUseTracker Tracker,
3631+
UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) {
36503632
if (!EmitSuggestions) {
36513633
// Our job is very easy without suggestions. Just warn about
36523634
// every problematic operation and consider it done. No need to deal
@@ -3690,8 +3672,10 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
36903672
if (WarningGadgets.empty())
36913673
return;
36923674

3693-
UnsafeOps = groupWarningGadgetsByVar(std::move(WarningGadgets));
3694-
FixablesForAllVars = groupFixablesByVar(std::move(FixableGadgets));
3675+
WarningGadgetSets UnsafeOps =
3676+
groupWarningGadgetsByVar(std::move(WarningGadgets));
3677+
FixableGadgetSets FixablesForAllVars =
3678+
groupFixablesByVar(std::move(FixableGadgets));
36953679

36963680
std::map<const VarDecl *, FixItList> FixItsForVariableGroup;
36973681

@@ -3912,3 +3896,56 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
39123896
}
39133897
}
39143898
}
3899+
3900+
void clang::checkUnsafeBufferUsage(const Decl *D,
3901+
UnsafeBufferUsageHandler &Handler,
3902+
bool EmitSuggestions) {
3903+
#ifndef NDEBUG
3904+
Handler.clearDebugNotes();
3905+
#endif
3906+
3907+
assert(D);
3908+
3909+
SmallVector<Stmt *> Stmts;
3910+
3911+
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3912+
// We do not want to visit a Lambda expression defined inside a method
3913+
// independently. Instead, it should be visited along with the outer method.
3914+
// FIXME: do we want to do the same thing for `BlockDecl`s?
3915+
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3916+
if (MD->getParent()->isLambda() && MD->getParent()->isLocalClass())
3917+
return;
3918+
}
3919+
3920+
for (FunctionDecl *FReDecl : FD->redecls()) {
3921+
if (FReDecl->isExternC()) {
3922+
// Do not emit fixit suggestions for functions declared in an
3923+
// extern "C" block.
3924+
EmitSuggestions = false;
3925+
break;
3926+
}
3927+
}
3928+
3929+
Stmts.push_back(FD->getBody());
3930+
3931+
if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
3932+
for (const CXXCtorInitializer *CI : ID->inits()) {
3933+
Stmts.push_back(CI->getInit());
3934+
}
3935+
}
3936+
} else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
3937+
Stmts.push_back(D->getBody());
3938+
}
3939+
3940+
assert(!Stmts.empty());
3941+
3942+
FixableGadgetList FixableGadgets;
3943+
WarningGadgetList WarningGadgets;
3944+
DeclUseTracker Tracker;
3945+
for (Stmt *S : Stmts) {
3946+
findGadgets(S, D->getASTContext(), Handler, EmitSuggestions, FixableGadgets,
3947+
WarningGadgets, Tracker);
3948+
}
3949+
applyGadgets(D, std::move(FixableGadgets), std::move(WarningGadgets),
3950+
std::move(Tracker), Handler, EmitSuggestions);
3951+
}

clang/lib/Driver/ToolChain.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
109109
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
110110
ToolChain::executeToolChainProgram(StringRef Executable) const {
111111
llvm::SmallString<64> OutputFile;
112-
llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
112+
llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile,
113+
llvm::sys::fs::OF_Text);
113114
llvm::FileRemover OutputRemover(OutputFile.c_str());
114115
std::optional<llvm::StringRef> Redirects[] = {
115116
{""},
@@ -128,7 +129,8 @@ ToolChain::executeToolChainProgram(StringRef Executable) const {
128129
*Str + "'");
129130
SecondsToWait = std::max(SecondsToWait, 0); // infinite
130131
}
131-
if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait,
132+
if (llvm::sys::ExecuteAndWait(Executable, {Executable}, {}, Redirects,
133+
SecondsToWait,
132134
/*MemoryLimit=*/0, &ErrorMessage))
133135
return llvm::createStringError(std::error_code(),
134136
Executable + ": " + ErrorMessage);

0 commit comments

Comments
 (0)