|
24 | 24 | #include "clang/AST/Attr.h" |
25 | 25 | #include "clang/AST/DeclObjC.h" |
26 | 26 | #include "clang/AST/Expr.h" |
| 27 | +#include "clang/AST/ParentMapContext.h" |
27 | 28 | #include "clang/AST/RecordLayout.h" |
28 | 29 | #include "clang/AST/StmtVisitor.h" |
29 | 30 | #include "clang/Basic/CodeGenOptions.h" |
@@ -195,13 +196,24 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { |
195 | 196 | if (!Op.mayHaveIntegerOverflow()) |
196 | 197 | return true; |
197 | 198 |
|
| 199 | + const UnaryOperator *UO = dyn_cast<UnaryOperator>(Op.E); |
| 200 | + |
| 201 | + if (UO && UO->getOpcode() == UO_Minus && |
| 202 | + Ctx.getLangOpts().isOverflowPatternExcluded( |
| 203 | + LangOptions::OverflowPatternExclusionKind::NegUnsignedConst) && |
| 204 | + UO->isIntegerConstantExpr(Ctx)) |
| 205 | + return true; |
| 206 | + |
198 | 207 | // If a unary op has a widened operand, the op cannot overflow. |
199 | | - if (const auto *UO = dyn_cast<UnaryOperator>(Op.E)) |
| 208 | + if (UO) |
200 | 209 | return !UO->canOverflow(); |
201 | 210 |
|
202 | 211 | // We usually don't need overflow checks for binops with widened operands. |
203 | 212 | // Multiplication with promoted unsigned operands is a special case. |
204 | 213 | const auto *BO = cast<BinaryOperator>(Op.E); |
| 214 | + if (BO->hasExcludedOverflowPattern()) |
| 215 | + return true; |
| 216 | + |
205 | 217 | auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS()); |
206 | 218 | if (!OptionalLHSTy) |
207 | 219 | return false; |
@@ -2766,6 +2778,26 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior( |
2766 | 2778 | llvm_unreachable("Unknown SignedOverflowBehaviorTy"); |
2767 | 2779 | } |
2768 | 2780 |
|
| 2781 | +/// For the purposes of overflow pattern exclusion, does this match the |
| 2782 | +/// "while(i--)" pattern? |
| 2783 | +static bool matchesPostDecrInWhile(const UnaryOperator *UO, bool isInc, |
| 2784 | + bool isPre, ASTContext &Ctx) { |
| 2785 | + if (isInc || isPre) |
| 2786 | + return false; |
| 2787 | + |
| 2788 | + // -fsanitize-undefined-ignore-overflow-pattern=post-decr-while |
| 2789 | + if (!Ctx.getLangOpts().isOverflowPatternExcluded( |
| 2790 | + LangOptions::OverflowPatternExclusionKind::PostDecrInWhile)) |
| 2791 | + return false; |
| 2792 | + |
| 2793 | + // all Parents (usually just one) must be a WhileStmt |
| 2794 | + for (const auto &Parent : Ctx.getParentMapContext().getParents(*UO)) |
| 2795 | + if (!Parent.get<WhileStmt>()) |
| 2796 | + return false; |
| 2797 | + |
| 2798 | + return true; |
| 2799 | +} |
| 2800 | + |
2769 | 2801 | namespace { |
2770 | 2802 | /// Handles check and update for lastprivate conditional variables. |
2771 | 2803 | class OMPLastprivateConditionalUpdateRAII { |
@@ -2877,6 +2909,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, |
2877 | 2909 | } else if (type->isIntegerType()) { |
2878 | 2910 | QualType promotedType; |
2879 | 2911 | bool canPerformLossyDemotionCheck = false; |
| 2912 | + |
| 2913 | + bool excludeOverflowPattern = |
| 2914 | + matchesPostDecrInWhile(E, isInc, isPre, CGF.getContext()); |
| 2915 | + |
2880 | 2916 | if (CGF.getContext().isPromotableIntegerType(type)) { |
2881 | 2917 | promotedType = CGF.getContext().getPromotedIntegerType(type); |
2882 | 2918 | assert(promotedType != type && "Shouldn't promote to the same type."); |
@@ -2936,7 +2972,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, |
2936 | 2972 | } else if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) { |
2937 | 2973 | value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); |
2938 | 2974 | } else if (E->canOverflow() && type->isUnsignedIntegerType() && |
2939 | | - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) { |
| 2975 | + CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && |
| 2976 | + !excludeOverflowPattern) { |
2940 | 2977 | value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( |
2941 | 2978 | E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); |
2942 | 2979 | } else { |
|
0 commit comments