diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/OSLog.cpp | 18 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/BackendUtil.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 29 | ||||
-rw-r--r-- | clang/lib/CodeGen/SanitizerHandler.h | 88 | ||||
-rw-r--r-- | clang/lib/Driver/SanitizerArgs.cpp | 6 |
9 files changed, 141 insertions, 48 deletions
diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp index b777d4d..91f8410 100644 --- a/clang/lib/AST/OSLog.cpp +++ b/clang/lib/AST/OSLog.cpp @@ -1,4 +1,16 @@ -// TODO: header template +//===--- OSLog.cpp - OS log format string analysis ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements analysis functions for OS log format strings and +/// buffer layout computation for __builtin_os_log_format and related builtins. +/// +//===----------------------------------------------------------------------===// #include "clang/AST/OSLog.h" #include "clang/AST/Attr.h" @@ -137,8 +149,8 @@ public: for (auto &Data : ArgsData) { if (!Data.MaskType.empty()) { CharUnits Size = CharUnits::fromQuantity(8); - Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, - Size, 0, Data.MaskType); + Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr, Size, 0, + Data.MaskType); } if (Data.FieldWidth) { diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index d8459b4..51aab95 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -438,8 +438,7 @@ void AggExprEmitter::visitCXXParenListOrInitListExpr( // Push a destructor if necessary. // FIXME: if we have an array of structures, all explicitly // initialized, we can end up pushing a linear number of cleanups. - if (QualType::DestructionKind dtorKind = - field->getType().isDestructedType()) { + if (field->getType().isDestructedType()) { cgf.cgm.errorNYI(e->getSourceRange(), "visitCXXParenListOrInitListExpr destructor"); return; diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 9c36a43..2213c75 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -339,7 +339,7 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, } if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr, - cir::ConstComplexAttr>(attrType)) + cir::ConstComplexAttr, cir::PoisonAttr>(attrType)) return success(); assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?"); @@ -629,6 +629,11 @@ static Value tryFoldCastChain(cir::CastOp op) { } OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) { + if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) { + // Propagate poison value + return cir::PoisonAttr::get(getContext(), getType()); + } + if (getSrc().getType() == getType()) { switch (getKind()) { case cir::CastKind::integral: { @@ -1783,6 +1788,12 @@ static bool isBoolNot(cir::UnaryOp op) { // // and the argument of the first one (%0) will be used instead. OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { + if (auto poison = + mlir::dyn_cast_if_present<cir::PoisonAttr>(adaptor.getInput())) { + // Propagate poison values + return poison; + } + if (isBoolNot(*this)) if (auto previous = dyn_cast_or_null<UnaryOp>(getInput().getDefiningOp())) if (isBoolNot(previous)) @@ -2239,16 +2250,18 @@ static OpFoldResult foldUnaryBitOp(mlir::Attribute inputAttr, llvm::function_ref<llvm::APInt(const llvm::APInt &)> func, bool poisonZero = false) { + if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) { + // Propagate poison value + return inputAttr; + } + auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr); if (!input) return nullptr; llvm::APInt inputValue = input.getValue(); - if (poisonZero && inputValue.isZero()) { - // TODO(cir): maybe we should return a poison value here? - assert(!MissingFeatures::poisonAttr()); - return nullptr; - } + if (poisonZero && inputValue.isZero()) + return cir::PoisonAttr::get(input.getType()); llvm::APInt resultValue = func(inputValue); return IntAttr::get(input.getType(), resultValue); @@ -2307,6 +2320,12 @@ OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) { } OpFoldResult RotateOp::fold(FoldAdaptor adaptor) { + if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) || + mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) { + // Propagate poison values + return cir::PoisonAttr::get(getType()); + } + auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput()); auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount()); if (!input && !amount) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 3cd7de0..c27b889 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1027,6 +1027,12 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite( mlir::ConversionPatternRewriter &rewriter) const { mlir::Attribute attr = op.getValue(); + if (mlir::isa<cir::PoisonAttr>(attr)) { + rewriter.replaceOpWithNewOp<mlir::LLVM::PoisonOp>( + op, getTypeConverter()->convertType(op.getType())); + return mlir::success(); + } + if (mlir::isa<mlir::IntegerType>(op.getType())) { // Verified cir.const operations cannot actually be of these types, but the // lowering pass may generate temporary cir.const operations with these diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 1b72578..0b8b824 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1027,12 +1027,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline( MPM.addPass( createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); }); - PB.registerPipelineEarlySimplificationEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level, - ThinOrFullLTOPhase) { - if (Level != OptimizationLevel::O0) - MPM.addPass(ObjCARCAPElimPass()); - }); PB.registerScalarOptimizerLateEPCallback( [](FunctionPassManager &FPM, OptimizationLevel Level) { if (Level != OptimizationLevel::O0) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a371b67..77fc3a2 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -6435,7 +6435,7 @@ CodeGenFunction::LexicalScope::~LexicalScope() { static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) { std::string Label; switch (Handler) { -#define SANITIZER_CHECK(Enum, Name, Version) \ +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ case Enum: \ Label = "__ubsan_check_" #Name; \ break; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c7688..90aed79 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -85,6 +85,16 @@ enum VariableTypeDescriptorKind : uint16_t { // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// +static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { + switch (ID) { +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ + case SanitizerHandler::Enum: \ + return Msg; + LIST_SANITIZER_CHECKS +#undef SANITIZER_CHECK + } +} + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. RawAddress @@ -3649,7 +3659,7 @@ struct SanitizerHandlerInfo { } const SanitizerHandlerInfo SanitizerHandlers[] = { -#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version}, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) {#Name, Version}, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; @@ -3954,6 +3964,8 @@ void CodeGenFunction::EmitCfiCheckFail() { StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, SourceLocation()); + ApplyDebugLocation ADL = ApplyDebugLocation::CreateArtificial(*this); + // This function is not affected by NoSanitizeList. This function does // not have a source location, but "src:*" would still apply. Revert any // changes to SanOpts made in StartFunction. @@ -4051,6 +4063,15 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; + llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); + llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID); + + if (getDebugInfo() && !TrapMessage.empty() && + CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) { + TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor( + TrapLocation, "Undefined Behavior Sanitizer", TrapMessage); + } + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); @@ -4059,8 +4080,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, auto Call = TrapBB->begin(); assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB"); - Call->applyMergedLocation(Call->getDebugLoc(), - Builder.getCurrentDebugLocation()); + Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation); + Builder.CreateCondBr(Checked, Cont, TrapBB, MDHelper.createLikelyBranchWeights()); } else { @@ -4069,6 +4090,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, MDHelper.createLikelyBranchWeights()); EmitBlock(TrapBB); + ApplyDebugLocation applyTrapDI(*this, TrapLocation); + llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID)); diff --git a/clang/lib/CodeGen/SanitizerHandler.h b/clang/lib/CodeGen/SanitizerHandler.h index bb42e39..a66e7ab 100644 --- a/clang/lib/CodeGen/SanitizerHandler.h +++ b/clang/lib/CodeGen/SanitizerHandler.h @@ -14,35 +14,69 @@ #define LLVM_CLANG_LIB_CODEGEN_SANITIZER_HANDLER_H #define LIST_SANITIZER_CHECKS \ - SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ - SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \ - SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \ - SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ - SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ - SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ - SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ - SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ - SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ - SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ - SANITIZER_CHECK(MissingReturn, missing_return, 0) \ - SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ - SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ - SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ - SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \ - SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ - SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \ - SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ - SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ - SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ - SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ - SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ - SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) \ - SANITIZER_CHECK(BoundsSafety, bounds_safety, 0) + SANITIZER_CHECK(AddOverflow, add_overflow, 0, "Integer addition overflowed") \ + SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0, \ + "_builtin_unreachable(), execution reached an unreachable " \ + "program point") \ + SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0, \ + "Control flow integrity check failed") \ + SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0, \ + "Integer divide or remainder overflowed") \ + SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0, \ + "Dynamic type cache miss, member call made on an object " \ + "whose dynamic type differs from the expected type") \ + SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0, \ + "Floating-point to integer conversion overflowed") \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0, \ + "Function called with mismatched signature") \ + SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0, \ + "Implicit integer conversion overflowed or lost data") \ + SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0, \ + "Invalid use of builtin function") \ + SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0, \ + "Invalid Objective-C cast") \ + SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0, \ + "Loaded an invalid or uninitialized value for the type") \ + SANITIZER_CHECK(MissingReturn, missing_return, 0, \ + "Execution reached the end of a value-returning function " \ + "without returning a value") \ + SANITIZER_CHECK(MulOverflow, mul_overflow, 0, \ + "Integer multiplication overflowed") \ + SANITIZER_CHECK(NegateOverflow, negate_overflow, 0, \ + "Integer negation overflowed") \ + SANITIZER_CHECK( \ + NullabilityArg, nullability_arg, 0, \ + "Passing null as an argument which is annotated with _Nonnull") \ + SANITIZER_CHECK(NullabilityReturn, nullability_return, 1, \ + "Returning null from a function with a return type " \ + "annotated with _Nonnull") \ + SANITIZER_CHECK(NonnullArg, nonnull_arg, 0, \ + "Passing null pointer as an argument which is declared to " \ + "never be null") \ + SANITIZER_CHECK(NonnullReturn, nonnull_return, 1, \ + "Returning null pointer from a function which is declared " \ + "to never return null") \ + SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0, "Array index out of bounds") \ + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0, \ + "Pointer arithmetic overflowed bounds") \ + SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0, \ + "Shift exponent is too large for the type") \ + SANITIZER_CHECK(SubOverflow, sub_overflow, 0, \ + "Integer subtraction overflowed") \ + SANITIZER_CHECK(TypeMismatch, type_mismatch, 1, \ + "Type mismatch in operation") \ + SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0, \ + "Alignment assumption violated") \ + SANITIZER_CHECK( \ + VLABoundNotPositive, vla_bound_not_positive, 0, \ + "Variable length array bound evaluates to non-positive value") \ + SANITIZER_CHECK(BoundsSafety, bounds_safety, 0, \ + "") // BoundsSafety Msg is empty because it is not considered + // part of UBSan; therefore, no trap reason is emitted for + // this case. enum SanitizerHandler { -#define SANITIZER_CHECK(Enum, Name, Version) Enum, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) Enum, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 21e4cff..98793a5 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1382,6 +1382,12 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" + toString(AnnotateDebugInfo))); + if (const Arg *A = + Args.getLastArg(options::OPT_fsanitize_debug_trap_reasons, + options::OPT_fno_sanitize_debug_trap_reasons)) { + CmdArgs.push_back(Args.MakeArgString(A->getAsString(Args))); + } + addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-ignorelist=", UserIgnorelistFiles); addSpecialCaseListOpt(Args, CmdArgs, |