Skip to content

Commit 0d4250f

Browse files
Merge branch 'main' into users/yuxuanchen1997/coro-respect-noinline
2 parents 2603db7 + 53e49f1 commit 0d4250f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1580
-640
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,6 +3774,74 @@ type-generic alternative to the ``__builtin_clz{,l,ll}`` (respectively
37743774
``__builtin_ctz{,l,ll}``) builtins, with support for other integer types, such
37753775
as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``.
37763776
3777+
``__builtin_counted_by_ref``
3778+
----------------------------
3779+
3780+
``__builtin_counted_by_ref`` returns a pointer to the count field from the
3781+
``counted_by`` attribute.
3782+
3783+
The argument must be a flexible array member. If the argument isn't a flexible
3784+
array member or doesn't have the ``counted_by`` attribute, the builtin returns
3785+
``(void *)0``.
3786+
3787+
**Syntax**:
3788+
3789+
.. code-block:: c
3790+
3791+
T *__builtin_counted_by_ref(void *array)
3792+
3793+
**Examples**:
3794+
3795+
.. code-block:: c
3796+
3797+
#define alloc(P, FAM, COUNT) ({ \
3798+
size_t __ignored_assignment; \
3799+
typeof(P) __p = NULL; \
3800+
__p = malloc(MAX(sizeof(*__p), \
3801+
sizeof(*__p) + sizeof(*__p->FAM) * COUNT)); \
3802+
\
3803+
*_Generic( \
3804+
__builtin_counted_by_ref(__p->FAM), \
3805+
void *: &__ignored_assignment, \
3806+
default: __builtin_counted_by_ref(__p->FAM)) = COUNT; \
3807+
\
3808+
__p; \
3809+
})
3810+
3811+
**Description**:
3812+
3813+
The ``__builtin_counted_by_ref`` builtin allows the programmer to prevent a
3814+
common error associated with the ``counted_by`` attribute. When using the
3815+
``counted_by`` attribute, the ``count`` field **must** be set before the
3816+
flexible array member can be accessed. Otherwise, the sanitizers may view such
3817+
accesses as false positives. For instance, it's not uncommon for programmers to
3818+
initialize the flexible array before setting the ``count`` field:
3819+
3820+
.. code-block:: c
3821+
3822+
struct s {
3823+
int dummy;
3824+
short count;
3825+
long array[] __attribute__((counted_by(count)));
3826+
};
3827+
3828+
struct s *ptr = malloc(sizeof(struct s) + sizeof(long) * COUNT);
3829+
3830+
for (int i = 0; i < COUNT; ++i)
3831+
ptr->array[i] = i;
3832+
3833+
ptr->count = COUNT;
3834+
3835+
Enforcing the rule that ``ptr->count = COUNT;`` must occur after every
3836+
allocation of a struct with a flexible array member with the ``counted_by``
3837+
attribute is prone to failure in large code bases. This builtin mitigates this
3838+
for allocators (like in Linux) that are implemented in a way where the counter
3839+
assignment can happen automatically.
3840+
3841+
**Note:** The value returned by ``__builtin_counted_by_ref`` cannot be assigned
3842+
to a variable, have its address taken, or passed into or returned from a
3843+
function, because doing so violates bounds safety conventions.
3844+
37773845
Multiprecision Arithmetic Builtins
37783846
----------------------------------
37793847

clang/docs/ReleaseNotes.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,29 @@ Non-comprehensive list of changes in this release
313313
as well as declarations.
314314
- ``__builtin_abs`` function can now be used in constant expressions.
315315

316+
- The new builtin ``__builtin_counted_by_ref`` was added. In contexts where the
317+
programmer needs access to the ``counted_by`` attribute's field, but it's not
318+
available --- e.g. in macros. For instace, it can be used to automatically
319+
set the counter during allocation in the Linux kernel:
320+
321+
.. code-block:: c
322+
323+
/* A simplified version of Linux allocation macros */
324+
#define alloc(PTR, FAM, COUNT) ({ \
325+
sizeof_t __ignored_assignment; \
326+
typeof(P) __p; \
327+
size_t __size = sizeof(*P) + sizeof(*P->FAM) * COUNT; \
328+
__p = malloc(__size); \
329+
*_Generic( \
330+
__builtin_counted_by_ref(__p->FAM), \
331+
void *: &__ignored_assignment, \
332+
default: __builtin_counted_by_ref(__p->FAM)) = COUNT; \
333+
__p; \
334+
})
335+
336+
The flexible array member (FAM) can now be accessed immediately without causing
337+
issues with the sanitizer because the counter is automatically set.
338+
316339
New Compiler Flags
317340
------------------
318341

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4932,3 +4932,9 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
49324932
let Attributes = [CustomTypeChecking, Constexpr];
49334933
let Prototype = "void(...)";
49344934
}
4935+
4936+
def CountedByRef : Builtin {
4937+
let Spellings = ["__builtin_counted_by_ref"];
4938+
let Attributes = [NoThrow, CustomTypeChecking];
4939+
let Prototype = "int(...)";
4940+
}

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6652,6 +6652,18 @@ def warn_counted_by_attr_elt_type_unknown_size :
66526652
Warning<err_counted_by_attr_pointee_unknown_size.Summary>,
66536653
InGroup<BoundsSafetyCountedByEltTyUnknownSize>;
66546654

6655+
// __builtin_counted_by_ref diagnostics:
6656+
def err_builtin_counted_by_ref_must_be_flex_array_member : Error<
6657+
"'__builtin_counted_by_ref' argument must reference a flexible array member">;
6658+
def err_builtin_counted_by_ref_cannot_leak_reference : Error<
6659+
"value returned by '__builtin_counted_by_ref' cannot be assigned to a "
6660+
"variable, have its address taken, or passed into or returned from a function">;
6661+
def err_builtin_counted_by_ref_invalid_lhs_use : Error<
6662+
"value returned by '__builtin_counted_by_ref' cannot be used in "
6663+
"%select{an array subscript|a binary}0 expression">;
6664+
def err_builtin_counted_by_ref_has_side_effects : Error<
6665+
"'__builtin_counted_by_ref' argument cannot have side-effects">;
6666+
66556667
let CategoryName = "ARC Semantic Issue" in {
66566668

66576669
// ARC-mode diagnostics.

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,8 @@ class Sema final : public SemaBase {
25102510

25112511
bool BuiltinNonDeterministicValue(CallExpr *TheCall);
25122512

2513+
bool BuiltinCountedByRef(CallExpr *TheCall);
2514+
25132515
// Matrix builtin handling.
25142516
ExprResult BuiltinMatrixTranspose(CallExpr *TheCall, ExprResult CallResult);
25152517
ExprResult BuiltinMatrixColumnMajorLoad(CallExpr *TheCall,

clang/include/clang/Serialization/ASTRecordWriter.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ class ASTRecordWriter
6060

6161
public:
6262
/// Construct a ASTRecordWriter that uses the default encoding scheme.
63-
ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record)
64-
: DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {}
63+
ASTRecordWriter(ASTContext &Context, ASTWriter &W,
64+
ASTWriter::RecordDataImpl &Record)
65+
: DataStreamBasicWriter(Context), Writer(&W), Record(&Record) {}
6566

6667
/// Construct a ASTRecordWriter that uses the same encoding scheme as another
6768
/// ASTRecordWriter.
@@ -208,7 +209,7 @@ class ASTRecordWriter
208209

209210
/// Emit a reference to a type.
210211
void AddTypeRef(QualType T) {
211-
return Writer->AddTypeRef(T, *Record);
212+
return Writer->AddTypeRef(getASTContext(), T, *Record);
212213
}
213214
void writeQualType(QualType T) {
214215
AddTypeRef(T);

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@ class ASTWriter : public ASTDeserializationListener,
119119
/// The PCM manager which manages memory buffers for pcm files.
120120
InMemoryModuleCache &ModuleCache;
121121

122-
/// The ASTContext we're writing.
123-
ASTContext *Context = nullptr;
124-
125122
/// The preprocessor we're writing.
126123
Preprocessor *PP = nullptr;
127124

@@ -545,7 +542,7 @@ class ASTWriter : public ASTDeserializationListener,
545542
unsigned getSubmoduleID(Module *Mod);
546543

547544
/// Write the given subexpression to the bitstream.
548-
void WriteSubStmt(Stmt *S);
545+
void WriteSubStmt(ASTContext &Context, Stmt *S);
549546

550547
void WriteBlockInfoBlock();
551548
void WriteControlBlock(Preprocessor &PP, StringRef isysroot);
@@ -564,34 +561,36 @@ class ASTWriter : public ASTDeserializationListener,
564561
void WriteHeaderSearch(const HeaderSearch &HS);
565562
void WritePreprocessorDetail(PreprocessingRecord &PPRec,
566563
uint64_t MacroOffsetsBase);
567-
void WriteSubmodules(Module *WritingModule);
564+
void WriteSubmodules(Module *WritingModule, ASTContext &Context);
568565

569566
void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
570567
bool isModule);
571568

572569
unsigned TypeExtQualAbbrev = 0;
573570
void WriteTypeAbbrevs();
574-
void WriteType(QualType T);
571+
void WriteType(ASTContext &Context, QualType T);
575572

576573
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
577574

578-
void GenerateNameLookupTable(const DeclContext *DC,
575+
void GenerateNameLookupTable(ASTContext &Context, const DeclContext *DC,
579576
llvm::SmallVectorImpl<char> &LookupTable);
580577
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context,
581578
const DeclContext *DC);
582579
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
583580
void WriteTypeDeclOffsets();
584581
void WriteFileDeclIDsMap();
585-
void WriteComments();
582+
void WriteComments(ASTContext &Context);
586583
void WriteSelectors(Sema &SemaRef);
587584
void WriteReferencedSelectorsPool(Sema &SemaRef);
588585
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
589586
bool IsModule);
590587
void WriteDeclAndTypes(ASTContext &Context);
591588
void PrepareWritingSpecialDecls(Sema &SemaRef);
592589
void WriteSpecialDeclRecords(Sema &SemaRef);
593-
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
594-
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
590+
void WriteDeclUpdatesBlocks(ASTContext &Context,
591+
RecordDataImpl &OffsetsRecord);
592+
void WriteDeclContextVisibleUpdate(ASTContext &Context,
593+
const DeclContext *DC);
595594
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
596595
void WriteOpenCLExtensions(Sema &SemaRef);
597596
void WriteCUDAPragmas(Sema &SemaRef);
@@ -653,11 +652,6 @@ class ASTWriter : public ASTDeserializationListener,
653652
bool GeneratingReducedBMI = false);
654653
~ASTWriter() override;
655654

656-
ASTContext &getASTContext() const {
657-
assert(Context && "requested AST context when not writing AST");
658-
return *Context;
659-
}
660-
661655
const LangOptions &getLangOpts() const;
662656

663657
/// Get a timestamp for output into the AST file. The actual timestamp
@@ -723,10 +717,10 @@ class ASTWriter : public ASTDeserializationListener,
723717
uint32_t getMacroDirectivesOffset(const IdentifierInfo *Name);
724718

725719
/// Emit a reference to a type.
726-
void AddTypeRef(QualType T, RecordDataImpl &Record);
720+
void AddTypeRef(ASTContext &Context, QualType T, RecordDataImpl &Record);
727721

728722
/// Force a type to be emitted and get its ID.
729-
serialization::TypeID GetOrCreateTypeID(QualType T);
723+
serialization::TypeID GetOrCreateTypeID(ASTContext &Context, QualType T);
730724

731725
/// Find the first local declaration of a given local redeclarable
732726
/// decl.

clang/lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3657,6 +3657,10 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
36573657
(!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>()))
36583658
return 0;
36593659

3660+
if (getASTContext().getLangOpts().CPlusPlus &&
3661+
BuiltinID == Builtin::BI__builtin_counted_by_ref)
3662+
return 0;
3663+
36603664
const ASTContext &Context = getASTContext();
36613665
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
36623666
return BuiltinID;

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3691,6 +3691,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
36913691
return RValue::get(emitBuiltinObjectSize(E->getArg(0), Type, ResType,
36923692
/*EmittedE=*/nullptr, IsDynamic));
36933693
}
3694+
case Builtin::BI__builtin_counted_by_ref: {
3695+
// Default to returning '(void *) 0'.
3696+
llvm::Value *Result = llvm::ConstantPointerNull::get(
3697+
llvm::PointerType::getUnqual(getLLVMContext()));
3698+
3699+
const Expr *Arg = E->getArg(0)->IgnoreParenImpCasts();
3700+
3701+
if (auto *UO = dyn_cast<UnaryOperator>(Arg);
3702+
UO && UO->getOpcode() == UO_AddrOf) {
3703+
Arg = UO->getSubExpr()->IgnoreParenImpCasts();
3704+
3705+
if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Arg))
3706+
Arg = ASE->getBase()->IgnoreParenImpCasts();
3707+
}
3708+
3709+
if (const MemberExpr *ME = dyn_cast_if_present<MemberExpr>(Arg)) {
3710+
if (auto *CATy =
3711+
ME->getMemberDecl()->getType()->getAs<CountAttributedType>();
3712+
CATy && CATy->getKind() == CountAttributedType::CountedBy) {
3713+
const auto *FAMDecl = cast<FieldDecl>(ME->getMemberDecl());
3714+
if (const FieldDecl *CountFD = FAMDecl->findCountedByField())
3715+
Result = GetCountedByFieldExprGEP(Arg, FAMDecl, CountFD);
3716+
else
3717+
llvm::report_fatal_error("Cannot find the counted_by 'count' field");
3718+
}
3719+
}
3720+
3721+
return RValue::get(Result);
3722+
}
36943723
case Builtin::BI__builtin_prefetch: {
36953724
Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
36963725
// FIXME: Technically these constants should of type 'int', yes?

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,15 +1145,7 @@ static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD,
11451145
return false;
11461146
}
11471147

1148-
/// This method is typically called in contexts where we can't generate
1149-
/// side-effects, like in __builtin_dynamic_object_size. When finding
1150-
/// expressions, only choose those that have either already been emitted or can
1151-
/// be loaded without side-effects.
1152-
///
1153-
/// - \p FAMDecl: the \p Decl for the flexible array member. It may not be
1154-
/// within the top-level struct.
1155-
/// - \p CountDecl: must be within the same non-anonymous struct as \p FAMDecl.
1156-
llvm::Value *CodeGenFunction::EmitLoadOfCountedByField(
1148+
llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP(
11571149
const Expr *Base, const FieldDecl *FAMDecl, const FieldDecl *CountDecl) {
11581150
const RecordDecl *RD = CountDecl->getParent()->getOuterLexicalRecordContext();
11591151

@@ -1182,12 +1174,25 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField(
11821174
return nullptr;
11831175

11841176
Indices.push_back(Builder.getInt32(0));
1185-
Res = Builder.CreateInBoundsGEP(
1177+
return Builder.CreateInBoundsGEP(
11861178
ConvertType(QualType(RD->getTypeForDecl(), 0)), Res,
11871179
RecIndicesTy(llvm::reverse(Indices)), "..counted_by.gep");
1180+
}
11881181

1189-
return Builder.CreateAlignedLoad(ConvertType(CountDecl->getType()), Res,
1190-
getIntAlign(), "..counted_by.load");
1182+
/// This method is typically called in contexts where we can't generate
1183+
/// side-effects, like in __builtin_dynamic_object_size. When finding
1184+
/// expressions, only choose those that have either already been emitted or can
1185+
/// be loaded without side-effects.
1186+
///
1187+
/// - \p FAMDecl: the \p Decl for the flexible array member. It may not be
1188+
/// within the top-level struct.
1189+
/// - \p CountDecl: must be within the same non-anonymous struct as \p FAMDecl.
1190+
llvm::Value *CodeGenFunction::EmitLoadOfCountedByField(
1191+
const Expr *Base, const FieldDecl *FAMDecl, const FieldDecl *CountDecl) {
1192+
if (llvm::Value *GEP = GetCountedByFieldExprGEP(Base, FAMDecl, CountDecl))
1193+
return Builder.CreateAlignedLoad(ConvertType(CountDecl->getType()), GEP,
1194+
getIntAlign(), "..counted_by.load");
1195+
return nullptr;
11911196
}
11921197

11931198
void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,

0 commit comments

Comments
 (0)