diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 34 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp | 1 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp | 8 |
4 files changed, 56 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c73a6e1b061..54566aa7e51 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1147,6 +1147,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, AI->setAlignment(SuitableAlignmentInBytes); return RValue::get(AI); } + + case Builtin::BI__builtin_alloca_with_align: { + Value *Size = EmitScalarExpr(E->getArg(0)); + Value *AlignmentValue = EmitScalarExpr(E->getArg(1)); + auto *AlignmentCI = cast<ConstantInt>(AlignmentValue); + unsigned Alignment = AlignmentCI->getZExtValue(); + const TargetInfo &TI = getContext().getTargetInfo(); + unsigned AlignmentInBytes = Alignment / TI.getCharWidth(); + AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); + AI->setAlignment(AlignmentInBytes); + return RValue::get(AI); + } + case Builtin::BIbzero: case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c73bd4c6ed2..a4e3c5b8b24 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -791,6 +791,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinPrefetch(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_alloca_with_align: + if (SemaBuiltinAllocaWithAlign(TheCall)) + return ExprError(); + break; case Builtin::BI__assume: case Builtin::BI__builtin_assume: if (SemaBuiltinAssume(TheCall)) @@ -3904,6 +3908,36 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { } /// Handle __builtin_assume_aligned. This is declared +/// as (size_t, size_t) where the second size_t must be a power of 2 greater +/// than 8. +bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) { + // The alignment must be a constant integer. + Expr *Arg = TheCall->getArg(1); + + // We can't check the value of a dependent argument. + if (!Arg->isTypeDependent() && !Arg->isValueDependent()) { + llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context); + + if (!Result.isPowerOf2()) + return Diag(TheCall->getLocStart(), + diag::err_alignment_not_power_of_two) + << Arg->getSourceRange(); + + if (Result < Context.getCharWidth()) + return Diag(TheCall->getLocStart(), diag::err_alignment_too_small) + << (unsigned)Context.getCharWidth() + << Arg->getSourceRange(); + + if (Result > INT32_MAX) + return Diag(TheCall->getLocStart(), diag::err_alignment_too_big) + << INT32_MAX + << Arg->getSourceRange(); + } + + return false; +} + +/// Handle __builtin_assume_aligned. This is declared /// as (const void*, size_t, ...) and can take one optional constant int arg. bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index dab2f61229a..8c2aef21b3c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -55,6 +55,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, return true; } + case Builtin::BI__builtin_alloca_with_align: case Builtin::BI__builtin_alloca: { // FIXME: Refactor into StoreManager itself? MemRegionManager& RM = C.getStoreManager().getRegionManager(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 4b78c205834..c9dafb518c4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -43,6 +43,7 @@ public: void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const; void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const; void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const; + void CheckAllocaWithAlignZero(CheckerContext &C, const CallExpr *CE) const; void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const; typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &, @@ -337,6 +338,11 @@ void UnixAPIChecker::CheckAllocaZero(CheckerContext &C, BasicAllocationCheck(C, CE, 1, 0, "alloca"); } +void UnixAPIChecker::CheckAllocaWithAlignZero(CheckerContext &C, + const CallExpr *CE) const { + BasicAllocationCheck(C, CE, 2, 0, "__builtin_alloca_with_align"); +} + void UnixAPIChecker::CheckVallocZero(CheckerContext &C, const CallExpr *CE) const { BasicAllocationCheck(C, CE, 1, 0, "valloc"); @@ -366,6 +372,8 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE, .Case("realloc", &UnixAPIChecker::CheckReallocZero) .Case("reallocf", &UnixAPIChecker::CheckReallocfZero) .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero) + .Case("__builtin_alloca_with_align", + &UnixAPIChecker::CheckAllocaWithAlignZero) .Case("valloc", &UnixAPIChecker::CheckVallocZero) .Default(nullptr); |