Skip to content

Commit f03cb00

Browse files
dougsonosDoug WyattshafikAaronBallmanSirraide
authored
[Clang] Introduce nonblocking/nonallocating attributes (#84983)
Introduce `nonblocking` and `nonallocating` attributes. RFC is here: https://discourse.llvm.org/t/rfc-nolock-and-noalloc-attributes/76837 This PR introduces the attributes, with some changes in Sema to deal with them as extensions to function (proto)types. There are some basic type checks, most importantly, a warning when trying to spoof the attribute (implicitly convert a function without the attribute to one that has it). A second, follow-on pull request will introduce new caller/callee verification. --------- Co-authored-by: Doug Wyatt <[email protected]> Co-authored-by: Shafik Yaghmour <[email protected]> Co-authored-by: Aaron Ballman <[email protected]> Co-authored-by: Sirraide <[email protected]>
1 parent 5a997c1 commit f03cb00

24 files changed

+1850
-11
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,11 @@ Attribute Changes in Clang
511511
};
512512
513513
514+
- Introduced new function type attributes ``[[clang::nonblocking]]``, ``[[clang::nonallocating]]``,
515+
``[[clang::blocking]]``, and ``[[clang::allocating]]``, with GNU-style variants as well.
516+
The attributes declare constraints about a function's behavior pertaining to blocking and
517+
heap memory allocation.
518+
514519
Improvements to Clang's diagnostics
515520
-----------------------------------
516521
- Clang now applies syntax highlighting to the code snippets it

clang/include/clang/AST/AbstractBasicReader.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,15 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
244244
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
245245
}
246246

247+
FunctionEffect readFunctionEffect() {
248+
uint32_t value = asImpl().readUInt32();
249+
return FunctionEffect::fromOpaqueInt32(value);
250+
}
251+
252+
EffectConditionExpr readEffectConditionExpr() {
253+
return EffectConditionExpr{asImpl().readExprRef()};
254+
}
255+
247256
NestedNameSpecifier *readNestedNameSpecifier() {
248257
auto &ctx = getASTContext();
249258

clang/include/clang/AST/AbstractBasicWriter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
222222
asImpl().writeUInt32(epi.getOpaqueValue());
223223
}
224224

225+
void writeFunctionEffect(FunctionEffect E) {
226+
asImpl().writeUInt32(E.toOpaqueInt32());
227+
}
228+
229+
void writeEffectConditionExpr(EffectConditionExpr CE) {
230+
asImpl().writeExprRef(CE.getCondition());
231+
}
232+
225233
void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
226234
// Nested name specifiers usually aren't too long. I think that 8 would
227235
// typically accommodate the vast majority.

clang/include/clang/AST/Decl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,6 +3042,16 @@ class FunctionDecl : public DeclaratorDecl,
30423042
/// computed and stored.
30433043
unsigned getODRHash() const;
30443044

3045+
FunctionEffectsRef getFunctionEffects() const {
3046+
// Effects may differ between declarations, but they should be propagated
3047+
// from old to new on any redeclaration, so it suffices to look at
3048+
// getMostRecentDecl().
3049+
if (const auto *FPT =
3050+
getMostRecentDecl()->getType()->getAs<FunctionProtoType>())
3051+
return FPT->getFunctionEffects();
3052+
return {};
3053+
}
3054+
30453055
// Implement isa/cast/dyncast/etc.
30463056
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
30473057
static bool classofKind(Kind K) {
@@ -4670,6 +4680,13 @@ class BlockDecl : public Decl, public DeclContext {
46704680

46714681
SourceRange getSourceRange() const override LLVM_READONLY;
46724682

4683+
FunctionEffectsRef getFunctionEffects() const {
4684+
if (const TypeSourceInfo *TSI = getSignatureAsWritten())
4685+
if (const auto *FPT = TSI->getType()->getAs<FunctionProtoType>())
4686+
return FPT->getFunctionEffects();
4687+
return {};
4688+
}
4689+
46734690
// Implement isa/cast/dyncast/etc.
46744691
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
46754692
static bool classofKind(Kind K) { return K == Block; }

clang/include/clang/AST/PropertiesBase.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
117117
def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
118118
let PassByReference = 1;
119119
}
120+
def FunctionEffect : PropertyType<"FunctionEffect">;
121+
def EffectConditionExpr : PropertyType<"EffectConditionExpr">;
120122
def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
121123
def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
122124
def LValuePathSerializationHelper :

0 commit comments

Comments
 (0)