|
30 | 30 | #include "clang/AST/Attr.h"
|
31 | 31 | #include "clang/AST/DeclObjC.h"
|
32 | 32 | #include "clang/AST/NSAPI.h"
|
| 33 | +#include "clang/AST/ParentMapContext.h" |
33 | 34 | #include "clang/AST/StmtVisitor.h"
|
34 | 35 | #include "clang/Basic/Builtins.h"
|
35 | 36 | #include "clang/Basic/CodeGenOptions.h"
|
@@ -1353,6 +1354,115 @@ void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, QualType AllocType) {
|
1353 | 1354 | CB->setMetadata(llvm::LLVMContext::MD_alloc_token, MDN);
|
1354 | 1355 | }
|
1355 | 1356 |
|
| 1357 | +namespace { |
| 1358 | +/// Infer type from a simple sizeof expression. |
| 1359 | +QualType inferTypeFromSizeofExpr(const Expr *E) { |
| 1360 | + const Expr *Arg = E->IgnoreParenImpCasts(); |
| 1361 | + if (const auto *UET = dyn_cast<UnaryExprOrTypeTraitExpr>(Arg)) { |
| 1362 | + if (UET->getKind() == UETT_SizeOf) { |
| 1363 | + if (UET->isArgumentType()) |
| 1364 | + return UET->getArgumentTypeInfo()->getType(); |
| 1365 | + else |
| 1366 | + return UET->getArgumentExpr()->getType(); |
| 1367 | + } |
| 1368 | + } |
| 1369 | + return QualType(); |
| 1370 | +} |
| 1371 | + |
| 1372 | +/// Infer type from an arithmetic expression involving a sizeof. For example: |
| 1373 | +/// |
| 1374 | +/// malloc(sizeof(MyType) + padding); // infers 'MyType' |
| 1375 | +/// malloc(sizeof(MyType) * 32); // infers 'MyType' |
| 1376 | +/// malloc(32 * sizeof(MyType)); // infers 'MyType' |
| 1377 | +/// malloc(sizeof(MyType) << 1); // infers 'MyType' |
| 1378 | +/// ... |
| 1379 | +/// |
| 1380 | +/// More complex arithmetic expressions are supported, but are a heuristic, e.g. |
| 1381 | +/// when considering allocations for structs with flexible array members: |
| 1382 | +/// |
| 1383 | +/// malloc(sizeof(HasFlexArray) + sizeof(int) * 32); // infers 'HasFlexArray' |
| 1384 | +/// |
| 1385 | +QualType inferPossibleTypeFromArithSizeofExpr(const Expr *E) { |
| 1386 | + const Expr *Arg = E->IgnoreParenImpCasts(); |
| 1387 | + // The argument is a lone sizeof expression. |
| 1388 | + if (QualType T = inferTypeFromSizeofExpr(Arg); !T.isNull()) |
| 1389 | + return T; |
| 1390 | + if (const auto *BO = dyn_cast<BinaryOperator>(Arg)) { |
| 1391 | + // Argument is an arithmetic expression. Cover common arithmetic patterns |
| 1392 | + // involving sizeof. |
| 1393 | + switch (BO->getOpcode()) { |
| 1394 | + case BO_Add: |
| 1395 | + case BO_Div: |
| 1396 | + case BO_Mul: |
| 1397 | + case BO_Shl: |
| 1398 | + case BO_Shr: |
| 1399 | + case BO_Sub: |
| 1400 | + if (QualType T = inferPossibleTypeFromArithSizeofExpr(BO->getLHS()); |
| 1401 | + !T.isNull()) |
| 1402 | + return T; |
| 1403 | + if (QualType T = inferPossibleTypeFromArithSizeofExpr(BO->getRHS()); |
| 1404 | + !T.isNull()) |
| 1405 | + return T; |
| 1406 | + break; |
| 1407 | + default: |
| 1408 | + break; |
| 1409 | + } |
| 1410 | + } |
| 1411 | + return QualType(); |
| 1412 | +} |
| 1413 | + |
| 1414 | +/// If the expression E is a reference to a variable, infer the type from a |
| 1415 | +/// variable's initializer if it contains a sizeof. Beware, this is a heuristic |
| 1416 | +/// and ignores if a variable is later reassigned. For example: |
| 1417 | +/// |
| 1418 | +/// size_t my_size = sizeof(MyType); |
| 1419 | +/// void *x = malloc(my_size); // infers 'MyType' |
| 1420 | +/// |
| 1421 | +QualType inferPossibleTypeFromVarInitSizeofExpr(const Expr *E) { |
| 1422 | + const Expr *Arg = E->IgnoreParenImpCasts(); |
| 1423 | + if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) { |
| 1424 | + if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) { |
| 1425 | + if (const Expr *Init = VD->getInit()) |
| 1426 | + return inferPossibleTypeFromArithSizeofExpr(Init); |
| 1427 | + } |
| 1428 | + } |
| 1429 | + return QualType(); |
| 1430 | +} |
| 1431 | + |
| 1432 | +/// Deduces the allocated type by checking if the allocation call's result |
| 1433 | +/// is immediately used in a cast expression. For example: |
| 1434 | +/// |
| 1435 | +/// MyType *x = (MyType *)malloc(4096); // infers 'MyType' |
| 1436 | +/// |
| 1437 | +QualType inferPossibleTypeFromCastExpr(const CallExpr *CallE, |
| 1438 | + const CastExpr *CastE) { |
| 1439 | + if (!CastE) |
| 1440 | + return QualType(); |
| 1441 | + QualType PtrType = CastE->getType(); |
| 1442 | + if (PtrType->isPointerType()) |
| 1443 | + return PtrType->getPointeeType(); |
| 1444 | + return QualType(); |
| 1445 | +} |
| 1446 | +} // end anonymous namespace |
| 1447 | + |
| 1448 | +void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, const CallExpr *E) { |
| 1449 | + QualType AllocType; |
| 1450 | + // First check arguments. |
| 1451 | + for (const Expr *Arg : E->arguments()) { |
| 1452 | + AllocType = inferPossibleTypeFromArithSizeofExpr(Arg); |
| 1453 | + if (AllocType.isNull()) |
| 1454 | + AllocType = inferPossibleTypeFromVarInitSizeofExpr(Arg); |
| 1455 | + if (!AllocType.isNull()) |
| 1456 | + break; |
| 1457 | + } |
| 1458 | + // Then check later casts. |
| 1459 | + if (AllocType.isNull()) |
| 1460 | + AllocType = inferPossibleTypeFromCastExpr(E, CurCast); |
| 1461 | + // Emit if we were able to infer the type. |
| 1462 | + if (!AllocType.isNull()) |
| 1463 | + EmitAllocToken(CB, AllocType); |
| 1464 | +} |
| 1465 | + |
1356 | 1466 | CodeGenFunction::ComplexPairTy CodeGenFunction::
|
1357 | 1467 | EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
|
1358 | 1468 | bool isInc, bool isPre) {
|
@@ -5723,6 +5833,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue(
|
5723 | 5833 | /// are permitted with aggregate result, including noop aggregate casts, and
|
5724 | 5834 | /// cast from scalar to union.
|
5725 | 5835 | LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
|
| 5836 | + auto RestoreCurCast = |
| 5837 | + llvm::make_scope_exit([this, Prev = CurCast] { CurCast = Prev; }); |
| 5838 | + CurCast = E; |
5726 | 5839 | switch (E->getCastKind()) {
|
5727 | 5840 | case CK_ToVoid:
|
5728 | 5841 | case CK_BitCast:
|
@@ -6668,16 +6781,24 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
|
6668 | 6781 | RValue Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &LocalCallOrInvoke,
|
6669 | 6782 | E == MustTailCall, E->getExprLoc());
|
6670 | 6783 |
|
6671 |
| - // Generate function declaration DISuprogram in order to be used |
6672 |
| - // in debug info about call sites. |
6673 |
| - if (CGDebugInfo *DI = getDebugInfo()) { |
6674 |
| - if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) { |
| 6784 | + if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) { |
| 6785 | + // Generate function declaration DISuprogram in order to be used |
| 6786 | + // in debug info about call sites. |
| 6787 | + if (CGDebugInfo *DI = getDebugInfo()) { |
6675 | 6788 | FunctionArgList Args;
|
6676 | 6789 | QualType ResTy = BuildFunctionArgList(CalleeDecl, Args);
|
6677 | 6790 | DI->EmitFuncDeclForCallSite(LocalCallOrInvoke,
|
6678 | 6791 | DI->getFunctionType(CalleeDecl, ResTy, Args),
|
6679 | 6792 | CalleeDecl);
|
6680 | 6793 | }
|
| 6794 | + if (CalleeDecl->hasAttr<RestrictAttr>() || |
| 6795 | + CalleeDecl->hasAttr<AllocSizeAttr>()) { |
| 6796 | + // Function has 'malloc' (aka. 'restrict') or 'alloc_size' attribute. |
| 6797 | + if (SanOpts.has(SanitizerKind::AllocToken)) { |
| 6798 | + // Set !alloc_token metadata. |
| 6799 | + EmitAllocToken(LocalCallOrInvoke, E); |
| 6800 | + } |
| 6801 | + } |
6681 | 6802 | }
|
6682 | 6803 | if (CallOrInvoke)
|
6683 | 6804 | *CallOrInvoke = LocalCallOrInvoke;
|
|
0 commit comments