Skip to content

Commit 313ff2b

Browse files
author
z1_cciauto
authored
merge main into amd-staging (llvm#3725)
2 parents 3205d53 + 269a426 commit 313ff2b

File tree

129 files changed

+3315
-2694
lines changed

Some content is hidden

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

129 files changed

+3315
-2694
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ Improvements to Clang's diagnostics
485485
specializations in th same way as it already did for other declarators.
486486
(#GH147333)
487487

488+
- A new warning ``-Walloc-size`` has been added to detect calls to functions
489+
decorated with the ``alloc_size`` attribute don't allocate enough space for
490+
the target pointer type.
491+
488492
Improvements to Clang's time-trace
489493
----------------------------------
490494

clang/include/clang/AST/Expr.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <optional>
4141

4242
namespace clang {
43+
class AllocSizeAttr;
4344
class APValue;
4445
class ASTContext;
4546
class BlockDecl;
@@ -3261,6 +3262,14 @@ class CallExpr : public Expr {
32613262
setDependence(getDependence() | ExprDependence::TypeValueInstantiation);
32623263
}
32633264

3265+
/// Try to get the alloc_size attribute of the callee. May return null.
3266+
const AllocSizeAttr *getCalleeAllocSizeAttr() const;
3267+
3268+
/// Get the total size in bytes allocated by calling a function decorated with
3269+
/// alloc_size. Returns std::nullopt if the the result cannot be evaluated.
3270+
std::optional<llvm::APInt>
3271+
getBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const;
3272+
32643273
bool isCallToStdMove() const;
32653274

32663275
static bool classof(const Stmt *T) {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,21 @@ An example of how to use ``alloc_size``
973973
assert(__builtin_object_size(a, 0) == 100);
974974
}
975975

976+
When ``-Walloc-size`` is enabled, this attribute allows the compiler to
977+
diagnose cases when the allocated memory is insufficient for the size of the
978+
type the returned pointer is cast to.
979+
980+
.. code-block:: c
981+
982+
void *my_malloc(int a) __attribute__((alloc_size(1)));
983+
void consumer_func(int *);
984+
985+
int main() {
986+
int *ptr = my_malloc(sizeof(int)); // no warning
987+
int *w = my_malloc(1); // warning: allocation of insufficient size '1' for type 'int' with size '4'
988+
consumer_func(my_malloc(1)); // warning: allocation of insufficient size '1' for type 'int' with size '4'
989+
}
990+
976991
.. Note:: This attribute works differently in clang than it does in GCC.
977992
Specifically, clang will only trace ``const`` pointers (as above); we give up
978993
on pointers that are not marked as ``const``. In the vast majority of cases,

clang/include/clang/Basic/BuiltinsPPC.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,10 @@ UNALIASED_CUSTOM_BUILTIN(mma_dmmr, "vW1024*W1024*", false,
11001100
"mma,isa-future-instructions")
11011101
UNALIASED_CUSTOM_BUILTIN(mma_dmxor, "vW1024*W1024*", true,
11021102
"mma,isa-future-instructions")
1103+
UNALIASED_CUSTOM_BUILTIN(mma_disassemble_dmr, "vv*W1024*", false,
1104+
"mma,isa-future-instructions")
1105+
UNALIASED_CUSTOM_BUILTIN(mma_build_dmr, "vW1024*VVVVVVVV", false,
1106+
"mma,isa-future-instructions")
11031107

11041108
// MMA builtins with positive/negative multiply/accumulate.
11051109
UNALIASED_CUSTOM_MMA_BUILTIN(mma_xvf16ger2, "vW512*VV",

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3683,6 +3683,10 @@ def warn_alloca_align_alignof : Warning<
36833683
"second argument to __builtin_alloca_with_align is supposed to be in bits">,
36843684
InGroup<DiagGroup<"alloca-with-align-alignof">>;
36853685

3686+
def warn_alloc_size : Warning<
3687+
"allocation of insufficient size '%0' for type %1 with size '%2'">,
3688+
InGroup<DiagGroup<"alloc-size">>;
3689+
36863690
def err_alignment_too_small : Error<
36873691
"requested alignment must be %0 or greater">;
36883692
def err_alignment_too_big : Error<

clang/lib/AST/Expr.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,6 +3533,56 @@ bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const {
35333533
Arg->EvaluateAsBooleanCondition(ArgVal, Ctx) && !ArgVal;
35343534
}
35353535

3536+
const AllocSizeAttr *CallExpr::getCalleeAllocSizeAttr() const {
3537+
if (const FunctionDecl *DirectCallee = getDirectCallee())
3538+
return DirectCallee->getAttr<AllocSizeAttr>();
3539+
if (const Decl *IndirectCallee = getCalleeDecl())
3540+
return IndirectCallee->getAttr<AllocSizeAttr>();
3541+
return nullptr;
3542+
}
3543+
3544+
std::optional<llvm::APInt>
3545+
CallExpr::getBytesReturnedByAllocSizeCall(const ASTContext &Ctx) const {
3546+
const AllocSizeAttr *AllocSize = getCalleeAllocSizeAttr();
3547+
3548+
assert(AllocSize && AllocSize->getElemSizeParam().isValid());
3549+
unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex();
3550+
unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
3551+
if (getNumArgs() <= SizeArgNo)
3552+
return {};
3553+
3554+
auto EvaluateAsSizeT = [&](const Expr *E, llvm::APSInt &Into) {
3555+
Expr::EvalResult ExprResult;
3556+
if (E->isValueDependent() ||
3557+
!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects))
3558+
return false;
3559+
Into = ExprResult.Val.getInt();
3560+
if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
3561+
return false;
3562+
Into = Into.zext(BitsInSizeT);
3563+
return true;
3564+
};
3565+
3566+
llvm::APSInt SizeOfElem;
3567+
if (!EvaluateAsSizeT(getArg(SizeArgNo), SizeOfElem))
3568+
return {};
3569+
3570+
if (!AllocSize->getNumElemsParam().isValid())
3571+
return SizeOfElem;
3572+
3573+
llvm::APSInt NumberOfElems;
3574+
unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex();
3575+
if (!EvaluateAsSizeT(getArg(NumArgNo), NumberOfElems))
3576+
return {};
3577+
3578+
bool Overflow;
3579+
llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow);
3580+
if (Overflow)
3581+
return {};
3582+
3583+
return BytesAvailable;
3584+
}
3585+
35363586
bool CallExpr::isCallToStdMove() const {
35373587
return getBuiltinCallee() == Builtin::BImove;
35383588
}

clang/lib/AST/ExprConstant.cpp

Lines changed: 8 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,6 @@ namespace {
114114
return Ctx.getLValueReferenceType(E->getType());
115115
}
116116

117-
/// Given a CallExpr, try to get the alloc_size attribute. May return null.
118-
static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) {
119-
if (const FunctionDecl *DirectCallee = CE->getDirectCallee())
120-
return DirectCallee->getAttr<AllocSizeAttr>();
121-
if (const Decl *IndirectCallee = CE->getCalleeDecl())
122-
return IndirectCallee->getAttr<AllocSizeAttr>();
123-
return nullptr;
124-
}
125-
126117
/// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr.
127118
/// This will look through a single cast.
128119
///
@@ -142,7 +133,7 @@ namespace {
142133
E = Cast->getSubExpr()->IgnoreParens();
143134

144135
if (const auto *CE = dyn_cast<CallExpr>(E))
145-
return getAllocSizeAttr(CE) ? CE : nullptr;
136+
return CE->getCalleeAllocSizeAttr() ? CE : nullptr;
146137
return nullptr;
147138
}
148139

@@ -9466,57 +9457,6 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
94669457
// Pointer Evaluation
94679458
//===----------------------------------------------------------------------===//
94689459

9469-
/// Attempts to compute the number of bytes available at the pointer
9470-
/// returned by a function with the alloc_size attribute. Returns true if we
9471-
/// were successful. Places an unsigned number into `Result`.
9472-
///
9473-
/// This expects the given CallExpr to be a call to a function with an
9474-
/// alloc_size attribute.
9475-
static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
9476-
const CallExpr *Call,
9477-
llvm::APInt &Result) {
9478-
const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call);
9479-
9480-
assert(AllocSize && AllocSize->getElemSizeParam().isValid());
9481-
unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex();
9482-
unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
9483-
if (Call->getNumArgs() <= SizeArgNo)
9484-
return false;
9485-
9486-
auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {
9487-
Expr::EvalResult ExprResult;
9488-
if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects))
9489-
return false;
9490-
Into = ExprResult.Val.getInt();
9491-
if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
9492-
return false;
9493-
Into = Into.zext(BitsInSizeT);
9494-
return true;
9495-
};
9496-
9497-
APSInt SizeOfElem;
9498-
if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem))
9499-
return false;
9500-
9501-
if (!AllocSize->getNumElemsParam().isValid()) {
9502-
Result = std::move(SizeOfElem);
9503-
return true;
9504-
}
9505-
9506-
APSInt NumberOfElems;
9507-
unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex();
9508-
if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems))
9509-
return false;
9510-
9511-
bool Overflow;
9512-
llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow);
9513-
if (Overflow)
9514-
return false;
9515-
9516-
Result = std::move(BytesAvailable);
9517-
return true;
9518-
}
9519-
95209460
/// Convenience function. LVal's base must be a call to an alloc_size
95219461
/// function.
95229462
static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
@@ -9526,7 +9466,12 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
95269466
"Can't get the size of a non alloc_size function");
95279467
const auto *Base = LVal.getLValueBase().get<const Expr *>();
95289468
const CallExpr *CE = tryUnwrapAllocSizeCall(Base);
9529-
return getBytesReturnedByAllocSizeCall(Ctx, CE, Result);
9469+
std::optional<llvm::APInt> Size = CE->getBytesReturnedByAllocSizeCall(Ctx);
9470+
if (!Size)
9471+
return false;
9472+
9473+
Result = std::move(*Size);
9474+
return true;
95309475
}
95319476

95329477
/// Attempts to evaluate the given LValueBase as the result of a call to
@@ -10017,7 +9962,7 @@ bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {
100179962
if (ExprEvaluatorBaseTy::VisitCallExpr(E))
100189963
return true;
100199964

10020-
if (!(InvalidBaseOK && getAllocSizeAttr(E)))
9965+
if (!(InvalidBaseOK && E->getCalleeAllocSizeAttr()))
100219966
return false;
100229967

100239968
Result.setInvalid(E);

clang/lib/Basic/Targets/SPIR.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,11 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
219219
setAddressSpaceMap(
220220
/*DefaultIsGeneric=*/Opts.SYCLIsDevice ||
221221
// The address mapping from HIP/CUDA language for device code is only
222-
// defined for SPIR-V.
223-
(getTriple().isSPIRV() && Opts.CUDAIsDevice));
222+
// defined for SPIR-V, and all Intel SPIR-V code should have the default
223+
// AS as generic.
224+
(getTriple().isSPIRV() &&
225+
(Opts.CUDAIsDevice ||
226+
getTriple().getVendor() == llvm::Triple::Intel)));
224227
}
225228

226229
void setSupportedOpenCLOpts() override {

clang/lib/CIR/CodeGen/CIRGenVTables.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -144,33 +144,28 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp &vtableOp,
144144
layout.getAddressPointIndices();
145145
unsigned nextVTableThunkIndex = 0;
146146

147-
if (layout.getNumVTables() > 1)
148-
cgm.errorNYI("emitVTableDefinitions: multiple vtables");
149-
150-
// We'll need a loop here to handle multiple vtables, but for now we only
151-
// support one.
152-
unsigned vtableIndex = 0;
153-
size_t vtableStart = layout.getVTableOffset(vtableIndex);
154-
size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
155-
156-
// Build a ConstArrayAttr of the vtable components.
157-
llvm::SmallVector<mlir::Attribute> components;
158-
for (size_t componentIndex = vtableStart; componentIndex < vtableEnd;
159-
++componentIndex) {
160-
components.push_back(
161-
getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
162-
addressPoints[vtableIndex], vtableHasLocalLinkage));
163-
}
164-
165147
mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
166148

167-
// Create a ConstArrayAttr to hold the components.
168-
auto arr = cir::ConstArrayAttr::get(
169-
cir::ArrayType::get(componentType, components.size()),
170-
mlir::ArrayAttr::get(mlirContext, components));
149+
SmallVector<mlir::Attribute> vtables;
150+
for (auto [vtableIndex, addressPoint] : llvm::enumerate(addressPoints)) {
151+
// Build a ConstArrayAttr of the vtable components.
152+
size_t vtableStart = layout.getVTableOffset(vtableIndex);
153+
size_t vtableEnd = vtableStart + layout.getVTableSize(vtableIndex);
154+
llvm::SmallVector<mlir::Attribute> components;
155+
components.reserve(vtableEnd - vtableStart);
156+
for (size_t componentIndex : llvm::seq(vtableStart, vtableEnd))
157+
components.push_back(
158+
getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
159+
addressPoint, vtableHasLocalLinkage));
160+
// Create a ConstArrayAttr to hold the components.
161+
auto arr = cir::ConstArrayAttr::get(
162+
cir::ArrayType::get(componentType, components.size()),
163+
mlir::ArrayAttr::get(mlirContext, components));
164+
vtables.push_back(arr);
165+
}
171166

172167
// Create a ConstRecordAttr to hold the component array.
173-
const auto members = mlir::ArrayAttr::get(mlirContext, {arr});
168+
const auto members = mlir::ArrayAttr::get(mlirContext, vtables);
174169
cir::ConstRecordAttr record = cgm.getBuilder().getAnonConstRecord(members);
175170

176171
// Create a VTableAttr

0 commit comments

Comments
 (0)