Author: aaronballman Date: Tue Jan 9 05:07:03 2018 New Revision: 322074 URL: http://llvm.org/viewvc/llvm-project?rev=322074&view=rev Log: Track in the AST whether the operand to a UnaryOperator can overflow and then use that logic when evaluating constant expressions and emitting codegen.
Modified: cfe/trunk/include/clang/AST/Expr.h cfe/trunk/lib/AST/ASTDumper.cpp cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Analysis/BodyFarm.cpp cfe/trunk/lib/CodeGen/CGExprScalar.cpp cfe/trunk/lib/CodeGen/CGObjC.cpp cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaExprObjC.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/lib/Sema/SemaPseudoObject.cpp cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/test/Misc/ast-dump-stmt.c Modified: cfe/trunk/include/clang/AST/Expr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Expr.h (original) +++ cfe/trunk/include/clang/AST/Expr.h Tue Jan 9 05:07:03 2018 @@ -1720,19 +1720,19 @@ public: private: unsigned Opc : 5; + unsigned CanOverflow : 1; SourceLocation Loc; Stmt *Val; public: - - UnaryOperator(Expr *input, Opcode opc, QualType type, - ExprValueKind VK, ExprObjectKind OK, SourceLocation l) - : Expr(UnaryOperatorClass, type, VK, OK, - input->isTypeDependent() || type->isDependentType(), - input->isValueDependent(), - (input->isInstantiationDependent() || - type->isInstantiationDependentType()), - input->containsUnexpandedParameterPack()), - Opc(opc), Loc(l), Val(input) {} + UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, bool CanOverflow) + : Expr(UnaryOperatorClass, type, VK, OK, + input->isTypeDependent() || type->isDependentType(), + input->isValueDependent(), + (input->isInstantiationDependent() || + type->isInstantiationDependentType()), + input->containsUnexpandedParameterPack()), + Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input) {} /// \brief Build an empty unary operator. explicit UnaryOperator(EmptyShell Empty) @@ -1748,6 +1748,15 @@ public: SourceLocation getOperatorLoc() const { return Loc; } void setOperatorLoc(SourceLocation L) { Loc = L; } + /// Returns true if the unary operator can cause an overflow. For instance, + /// signed int i = INT_MAX; i++; + /// signed char c = CHAR_MAX; c++; + /// Due to integer promotions, c++ is promoted to an int before the postfix + /// increment, and the result is an int that cannot overflow. However, i++ + /// can overflow. + bool canOverflow() const { return CanOverflow; } + void setCanOverflow(bool C) { CanOverflow = C; } + /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { return Op == UO_PostInc || Op == UO_PostDec; Modified: cfe/trunk/lib/AST/ASTDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDumper.cpp (original) +++ cfe/trunk/lib/AST/ASTDumper.cpp Tue Jan 9 05:07:03 2018 @@ -2214,12 +2214,14 @@ void ASTDumper::VisitArrayInitIndexExpr( } void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { - VisitExpr(Node); - OS << " " << (Node->isPostfix() ? "postfix" : "prefix") - << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; -} - -void ASTDumper::VisitUnaryExprOrTypeTraitExpr( + VisitExpr(Node); + OS << " " << (Node->isPostfix() ? "postfix" : "prefix") + << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; + if (!Node->canOverflow()) + OS << " cannot overflow"; +} + +void ASTDumper::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *Node) { VisitExpr(Node); switch(Node->getKind()) { Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jan 9 05:07:03 2018 @@ -5120,14 +5120,13 @@ Expr *ASTNodeImporter::VisitUnaryOperato if (!SubExpr) return nullptr; - return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(), - T, E->getValueKind(), - E->getObjectKind(), - Importer.Import(E->getOperatorLoc())); + return new (Importer.getToContext()) UnaryOperator( + SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), + Importer.Import(E->getOperatorLoc()), E->canOverflow()); } -Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( - UnaryExprOrTypeTraitExpr *E) { +Expr * +ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { QualType ResultType = Importer.Import(E->getType()); if (E->isArgumentType()) { Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Jan 9 05:07:03 2018 @@ -3244,17 +3244,12 @@ static bool handleAssignment(EvalInfo &I } CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); - return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val); -} - -static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) { - return T->isSignedIntegerType() && - Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy); -} - -namespace { -struct CompoundAssignSubobjectHandler { - EvalInfo &Info; + return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val); +} + +namespace { +struct CompoundAssignSubobjectHandler { + EvalInfo &Info; const Expr *E; QualType PromotedLHSType; BinaryOperatorKind Opcode; @@ -3370,13 +3365,13 @@ static bool handleCompoundAssignment( return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); } -namespace { -struct IncDecSubobjectHandler { - EvalInfo &Info; - const Expr *E; - AccessKinds AccessKind; - APValue *Old; - +namespace { +struct IncDecSubobjectHandler { + EvalInfo &Info; + const UnaryOperator *E; + AccessKinds AccessKind; + APValue *Old; + typedef bool result_type; bool checkConst(QualType QT) { @@ -3442,22 +3437,20 @@ struct IncDecSubobjectHandler { } bool WasNegative = Value.isNegative(); - if (AccessKind == AK_Increment) { - ++Value; - - if (!WasNegative && Value.isNegative() && - isOverflowingIntegerType(Info.Ctx, SubobjType)) { - APSInt ActualValue(Value, /*IsUnsigned*/true); - return HandleOverflow(Info, E, ActualValue, SubobjType); - } - } else { - --Value; - - if (WasNegative && !Value.isNegative() && - isOverflowingIntegerType(Info.Ctx, SubobjType)) { - unsigned BitWidth = Value.getBitWidth(); - APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); - ActualValue.setBit(BitWidth); + if (AccessKind == AK_Increment) { + ++Value; + + if (!WasNegative && Value.isNegative() && E->canOverflow()) { + APSInt ActualValue(Value, /*IsUnsigned*/true); + return HandleOverflow(Info, E, ActualValue, SubobjType); + } + } else { + --Value; + + if (WasNegative && !Value.isNegative() && E->canOverflow()) { + unsigned BitWidth = Value.getBitWidth(); + APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); + ActualValue.setBit(BitWidth); return HandleOverflow(Info, E, ActualValue, SubobjType); } } @@ -3512,13 +3505,13 @@ static bool handleIncDec(EvalInfo &Info, Info.FFDiag(E); return false; } - - AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement; - CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType); - IncDecSubobjectHandler Handler = { Info, E, AK, Old }; - return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); -} - + + AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement; + CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType); + IncDecSubobjectHandler Handler = {Info, cast<UnaryOperator>(E), AK, Old}; + return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); +} + /// Build an lvalue for the object argument of a member function call. static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, LValue &This) { @@ -8875,13 +8868,13 @@ bool IntExprEvaluator::VisitUnaryOperato return Visit(E->getSubExpr()); case UO_Minus: { if (!Visit(E->getSubExpr())) - return false; - if (!Result.isInt()) return Error(E); - const APSInt &Value = Result.getInt(); - if (Value.isSigned() && Value.isMinSignedValue() && - !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), - E->getType())) - return false; + return false; + if (!Result.isInt()) return Error(E); + const APSInt &Value = Result.getInt(); + if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() && + !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), + E->getType())) + return false; return Success(-Value, E); } case UO_Not: { Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original) +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Tue Jan 9 05:07:03 2018 @@ -149,7 +149,8 @@ DeclRefExpr *ASTMaker::makeDeclRefExpr( UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty, - VK_LValue, OK_Ordinary, SourceLocation()); + VK_LValue, OK_Ordinary, SourceLocation(), + /*CanOverflow*/ false); } ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { @@ -441,7 +442,8 @@ static Stmt *create_call_once(ASTContext /* opc=*/ UO_LNot, /* QualType=*/ C.IntTy, /* ExprValueKind=*/ VK_RValue, - /* ExprObjectKind=*/ OK_Ordinary, SourceLocation()); + /* ExprObjectKind=*/ OK_Ordinary, SourceLocation(), + /* CanOverflow*/ false); // Create assignment. BinaryOperator *FlagAssignment = M.makeAssignment( @@ -505,7 +507,8 @@ static Stmt *create_dispatch_once(ASTCon // (2) Create the assignment to the predicate. Expr *DoneValue = new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy, - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), + /*CanOverflow*/false); BinaryOperator *B = M.makeAssignment( Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Jan 9 05:07:03 2018 @@ -162,13 +162,13 @@ static bool CanElideOverflowCheck(const // we can elide the overflow check. if (!Op.mayHaveIntegerOverflow()) return true; - - // If a unary op has a widened operand, the op cannot overflow. - if (const auto *UO = dyn_cast<UnaryOperator>(Op.E)) - return IsWidenedIntegerOp(Ctx, UO->getSubExpr()); - - // We usually don't need overflow checks for binops with widened operands. - // Multiplication with promoted unsigned operands is a special case. + + // If a unary op has a widened operand, the op cannot overflow. + if (const auto *UO = dyn_cast<UnaryOperator>(Op.E)) + return !UO->canOverflow(); + + // We usually don't need overflow checks for binops with widened operands. + // Multiplication with promoted unsigned operands is a special case. const auto *BO = cast<BinaryOperator>(Op.E); auto OptionalLHSTy = getUnwidenedIntegerType(Ctx, BO->getLHS()); if (!OptionalLHSTy) @@ -1870,13 +1870,13 @@ llvm::Value *ScalarExprEmitter::EmitIncD return Builder.CreateAdd(InVal, Amount, Name); case LangOptions::SOB_Undefined: if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) - return Builder.CreateNSWAdd(InVal, Amount, Name); - // Fall through. - case LangOptions::SOB_Trapping: - if (IsWidenedIntegerOp(CGF.getContext(), E->getSubExpr())) - return Builder.CreateNSWAdd(InVal, Amount, Name); - return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc)); - } + return Builder.CreateNSWAdd(InVal, Amount, Name); + // Fall through. + case LangOptions::SOB_Trapping: + if (!E->canOverflow()) + return Builder.CreateNSWAdd(InVal, Amount, Name); + return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, InVal, IsInc)); + } llvm_unreachable("Unknown SignedOverflowBehaviorTy"); } @@ -1952,17 +1952,15 @@ ScalarExprEmitter::EmitScalarPrePostIncD value = Builder.getTrue(); // Most common case by far: integer increment. - } else if (type->isIntegerType()) { - // Note that signed integer inc/dec with width less than int can't - // overflow because of promotion rules; we're just eliding a few steps here. - bool CanOverflow = value->getType()->getIntegerBitWidth() >= - CGF.IntTy->getIntegerBitWidth(); - if (CanOverflow && type->isSignedIntegerOrEnumerationType()) { - value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); - } else if (CanOverflow && type->isUnsignedIntegerType() && - CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) { - value = - EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc)); + } else if (type->isIntegerType()) { + // Note that signed integer inc/dec with width less than int can't + // overflow because of promotion rules; we're just eliding a few steps here. + if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) { + value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); + } else if (E->canOverflow() && type->isUnsignedIntegerType() && + CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) { + value = + EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(E, value, isInc)); } else { llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true); value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec"); Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Jan 9 05:07:03 2018 @@ -3268,12 +3268,12 @@ CodeGenFunction::GenerateObjCAtomicSette DeclRefExpr DstExpr(&DstDecl, false, DestTy, VK_RValue, SourceLocation()); UnaryOperator DST(&DstExpr, UO_Deref, DestTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation()); + VK_LValue, OK_Ordinary, SourceLocation(), false); DeclRefExpr SrcExpr(&SrcDecl, false, SrcTy, VK_RValue, SourceLocation()); UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation()); + VK_LValue, OK_Ordinary, SourceLocation(), false); Expr *Args[2] = { &DST, &SRC }; CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment()); @@ -3351,7 +3351,7 @@ CodeGenFunction::GenerateObjCAtomicGette VK_RValue, SourceLocation()); UnaryOperator SRC(&SrcExpr, UO_Deref, SrcTy->getPointeeType(), - VK_LValue, OK_Ordinary, SourceLocation()); + VK_LValue, OK_Ordinary, SourceLocation(), false); CXXConstructExpr *CXXConstExpr = cast<CXXConstructExpr>(PID->getGetterCXXConstructor()); Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original) +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Tue Jan 9 05:07:03 2018 @@ -2483,7 +2483,7 @@ void CodeGenFunction::EmitSections(const OK_Ordinary, S.getLocStart(), FPOptions()); // Increment for loop counter. UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, - S.getLocStart()); + S.getLocStart(), true); auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) { // Iterate through all sections and emit a switch construct: // switch (IV) { Modified: cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp (original) +++ cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp Tue Jan 9 05:07:03 2018 @@ -2590,7 +2590,7 @@ Stmt *RewriteModernObjC::RewriteObjCStri Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); // cast to NSConstantString * CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), CK_CPointerToObjCPointerCast, Unop); @@ -3295,7 +3295,7 @@ Stmt *RewriteModernObjC::SynthMessageExp SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -3313,7 +3313,7 @@ Stmt *RewriteModernObjC::SynthMessageExp SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); } MsgExprs.push_back(SuperRep); break; @@ -3389,7 +3389,7 @@ Stmt *RewriteModernObjC::SynthMessageExp SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -4720,7 +4720,7 @@ Stmt *RewriteModernObjC::RewriteLocalVar return DRE; Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), VK_LValue, OK_Ordinary, - DRE->getLocation()); + DRE->getLocation(), false); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), Exp); @@ -5314,7 +5314,7 @@ Stmt *RewriteModernObjC::SynthBlockInitE UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); InitExprs.push_back(DescRefExpr); // Add initializers for any closure decl refs. @@ -5332,7 +5332,8 @@ Stmt *RewriteModernObjC::SynthBlockInitE QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getName()); @@ -5348,7 +5349,8 @@ Stmt *RewriteModernObjC::SynthBlockInitE QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } @@ -5388,7 +5390,8 @@ Stmt *RewriteModernObjC::SynthBlockInitE if (!isNestedCapturedVar) Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), + false); Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); InitExprs.push_back(Exp); } @@ -5414,7 +5417,7 @@ Stmt *RewriteModernObjC::SynthBlockInitE NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, NewRep); // Put Paren around the call. @@ -7558,7 +7561,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvar Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT, VK_LValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); PE = new (Context) ParenExpr(OldRange.getBegin(), OldRange.getEnd(), Exp); Modified: cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp (original) +++ cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp Tue Jan 9 05:07:03 2018 @@ -2511,7 +2511,7 @@ Stmt *RewriteObjC::RewriteObjCStringLite Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); // cast to NSConstantString * CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), CK_CPointerToObjCPointerCast, Unop); @@ -2712,7 +2712,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjC SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -2730,7 +2730,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjC SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); } MsgExprs.push_back(SuperRep); break; @@ -2806,7 +2806,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjC SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -3045,7 +3045,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolEx VK_LValue, SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), CK_BitCast, DerefExpr); @@ -3875,7 +3875,7 @@ Stmt *RewriteObjC::RewriteLocalVariableE return DRE; Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), VK_LValue, OK_Ordinary, - DRE->getLocation()); + DRE->getLocation(), false); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), Exp); @@ -4438,7 +4438,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(Bl UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); InitExprs.push_back(DescRefExpr); // Add initializers for any closure decl refs. @@ -4456,7 +4456,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(Bl QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getName()); @@ -4472,7 +4473,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(Bl QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } InitExprs.push_back(Exp); @@ -4509,9 +4511,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(Bl // captured nested byref variable has its address passed. Do not take // its address again. if (!isNestedCapturedVar) - Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, - Context->getPointerType(Exp->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + Exp = new (Context) UnaryOperator( + Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), VK_RValue, + OK_Ordinary, SourceLocation(), false); Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); InitExprs.push_back(Exp); } @@ -4529,7 +4531,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(Bl FType, VK_LValue, SourceLocation()); NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, NewRep); BlockDeclRefs.clear(); Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jan 9 05:07:03 2018 @@ -10990,11 +10990,11 @@ buildMemcpyForAssignmentOp(Sema &S, Sour Expr *From = FromB.build(S, Loc); From = new (S.Context) UnaryOperator(From, UO_AddrOf, S.Context.getPointerType(From->getType()), - VK_RValue, OK_Ordinary, Loc); + VK_RValue, OK_Ordinary, Loc, false); Expr *To = ToB.build(S, Loc); To = new (S.Context) UnaryOperator(To, UO_AddrOf, S.Context.getPointerType(To->getType()), - VK_RValue, OK_Ordinary, Loc); + VK_RValue, OK_Ordinary, Loc, false); const Type *E = T->getBaseElementTypeUnsafe(); bool NeedsCollectableMemCpy = @@ -11230,16 +11230,18 @@ buildSingleCopyAssignRecursively(Sema &S Expr *Comparison = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), - BO_NE, S.Context.BoolTy, - VK_RValue, OK_Ordinary, Loc, FPOptions()); - - // Create the pre-increment of the iteration variable. - Expr *Increment - = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, - SizeType, VK_LValue, OK_Ordinary, Loc); - - // Construct the loop that copies all elements of this array. - return S.ActOnForStmt( + BO_NE, S.Context.BoolTy, + VK_RValue, OK_Ordinary, Loc, FPOptions()); + + // Create the pre-increment of the iteration variable. We can determine + // whether the increment will overflow based on the value of the array + // bound. + Expr *Increment = new (S.Context) + UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType, + VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue()); + + // Construct the loop that copies all elements of this array. + return S.ActOnForStmt( Loc, Loc, InitStmt, S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean), S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get()); Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jan 9 05:07:03 2018 @@ -12178,6 +12178,16 @@ ExprResult Sema::BuildBinOp(Scope *S, So return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); } +static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) { + if (T.isNull() || T->isDependentType()) + return false; + + if (!T->isPromotableIntegerType()) + return true; + + return Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy); +} + ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr) { @@ -12185,6 +12195,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(So ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; + bool CanOverflow = false; + bool ConvertHalfVec = false; if (getLangOpts().OpenCL) { QualType Ty = InputExpr->getType(); @@ -12210,6 +12222,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(So Opc == UO_PostInc, Opc == UO_PreInc || Opc == UO_PreDec); + CanOverflow = isOverflowingIntegerType(Context, resultType); break; case UO_AddrOf: resultType = CheckAddressOfOperand(Input, OpLoc); @@ -12223,6 +12236,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(So } case UO_Plus: case UO_Minus: + CanOverflow = Opc == UO_Minus && + isOverflowingIntegerType(Context, Input.get()->getType()); Input = UsualUnaryConversions(Input.get()); if (Input.isInvalid()) return ExprError(); // Unary plus and minus require promoting an operand of half vector to a @@ -12259,6 +12274,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(So if (Input.isInvalid()) return ExprError(); resultType = Input.get()->getType(); + if (resultType->isDependentType()) break; // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. @@ -12373,7 +12389,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(So CheckArrayAccess(Input.get()); auto *UO = new (Context) - UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc); + UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow); // Convert the result back to a half vector. if (ConvertHalfVec) return convertVector(UO, Context.HalfTy, *this); Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jan 9 05:07:03 2018 @@ -4276,9 +4276,9 @@ Expr *Sema::stripARCUnbridgedCast(Expr * } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) { assert(uo->getOpcode() == UO_Extension); Expr *sub = stripARCUnbridgedCast(uo->getSubExpr()); - return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(), - sub->getValueKind(), sub->getObjectKind(), - uo->getOperatorLoc()); + return new (Context) + UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(), + sub->getObjectKind(), uo->getOperatorLoc(), false); } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { assert(!gse->isResultDependent()); Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jan 9 05:07:03 2018 @@ -12022,7 +12022,7 @@ Sema::CreateOverloadedUnaryOp(SourceLoca if (Input->isTypeDependent()) { if (Fns.empty()) return new (Context) UnaryOperator(Input, Opc, Context.DependentTy, - VK_RValue, OK_Ordinary, OpLoc); + VK_RValue, OK_Ordinary, OpLoc, false); CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators UnresolvedLookupExpr *Fn @@ -13552,7 +13552,7 @@ Expr *Sema::FixOverloadedFunctionReferen return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary, - UnOp->getOperatorLoc()); + UnOp->getOperatorLoc(), false); } } Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), @@ -13563,7 +13563,7 @@ Expr *Sema::FixOverloadedFunctionReferen return new (Context) UnaryOperator(SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()), VK_RValue, OK_Ordinary, - UnOp->getOperatorLoc()); + UnOp->getOperatorLoc(), false); } // C++ [except.spec]p17: Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original) +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Jan 9 05:07:03 2018 @@ -132,7 +132,8 @@ namespace { uop->getType(), uop->getValueKind(), uop->getObjectKind(), - uop->getOperatorLoc()); + uop->getOperatorLoc(), + uop->canOverflow()); } if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { @@ -524,15 +525,18 @@ PseudoOpBuilder::buildIncDecOperation(Sc addSemanticExpr(result.get()); if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() && !result.get()->getType()->isVoidType() && - (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) - setResultToLastSemantic(); - - UnaryOperator *syntactic = - new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, - VK_LValue, OK_Ordinary, opcLoc); - return complete(syntactic); -} - + (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) + setResultToLastSemantic(); + + UnaryOperator *syntactic = new (S.Context) UnaryOperator( + syntacticOp, opcode, resultType, VK_LValue, OK_Ordinary, opcLoc, + !resultType->isDependentType() + ? S.Context.getTypeSize(resultType) >= + S.Context.getTypeSize(S.Context.IntTy) + : false); + return complete(syntactic); +} + //===----------------------------------------------------------------------===// // Objective-C @property and implicit property references @@ -1550,7 +1554,7 @@ ExprResult Sema::checkPseudoObjectIncDec // Do nothing if the operand is dependent. if (op->isTypeDependent()) return new (Context) UnaryOperator(op, opcode, Context.DependentTy, - VK_RValue, OK_Ordinary, opcLoc); + VK_RValue, OK_Ordinary, opcLoc, false); assert(UnaryOperator::isIncrementDecrementOp(opcode)); Expr *opaqueRef = op->IgnoreParens(); @@ -1630,15 +1634,15 @@ static Expr *stripOpaqueValuesFromPseudo /// capable of rebuilding a tree without stripping implicit /// operations. Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { - Expr *syntax = E->getSyntacticForm(); - if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { - Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); - return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), - uop->getValueKind(), uop->getObjectKind(), - uop->getOperatorLoc()); - } else if (CompoundAssignOperator *cop - = dyn_cast<CompoundAssignOperator>(syntax)) { - Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); + Expr *syntax = E->getSyntacticForm(); + if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { + Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); + return new (Context) UnaryOperator( + op, uop->getOpcode(), uop->getType(), uop->getValueKind(), + uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow()); + } else if (CompoundAssignOperator *cop + = dyn_cast<CompoundAssignOperator>(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), cop->getType(), Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jan 9 05:07:03 2018 @@ -550,12 +550,13 @@ void ASTStmtReader::VisitParenListExpr(P void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) { VisitExpr(E); - E->setSubExpr(Record.readSubExpr()); - E->setOpcode((UnaryOperator::Opcode)Record.readInt()); - E->setOperatorLoc(ReadSourceLocation()); -} - -void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { + E->setSubExpr(Record.readSubExpr()); + E->setOpcode((UnaryOperator::Opcode)Record.readInt()); + E->setOperatorLoc(ReadSourceLocation()); + E->setCanOverflow(Record.readInt()); +} + +void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { VisitExpr(E); assert(E->getNumComponents() == Record.peekInt()); Record.skipInts(1); Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Jan 9 05:07:03 2018 @@ -506,12 +506,13 @@ void ASTStmtWriter::VisitParenListExpr(P void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) { VisitExpr(E); - Record.AddStmt(E->getSubExpr()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Record.AddSourceLocation(E->getOperatorLoc()); - Code = serialization::EXPR_UNARY_OPERATOR; -} - + Record.AddStmt(E->getSubExpr()); + Record.push_back(E->getOpcode()); // FIXME: stable encoding + Record.AddSourceLocation(E->getOperatorLoc()); + Record.push_back(E->canOverflow()); + Code = serialization::EXPR_UNARY_OPERATOR; +} + void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { VisitExpr(E); Record.push_back(E->getNumComponents()); Modified: cfe/trunk/test/Misc/ast-dump-stmt.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-stmt.c?rev=322074&r1=322073&r2=322074&view=diff ============================================================================== --- cfe/trunk/test/Misc/ast-dump-stmt.c (original) +++ cfe/trunk/test/Misc/ast-dump-stmt.c Tue Jan 9 05:07:03 2018 @@ -30,6 +30,38 @@ int TestOpaqueValueExpr = 0 ?: 1; // CHECK-NEXT: IntegerLiteral // CHECK-NEXT: OpaqueValueExpr // CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: OpaqueValueExpr -// CHECK-NEXT: IntegerLiteral -// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: OpaqueValueExpr +// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: IntegerLiteral + +void TestUnaryOperatorExpr(void) { + char T1 = 1; + int T2 = 1; + + T1++; + T2++; + // CHECK: UnaryOperator{{.*}}postfix '++' cannot overflow + // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char' + // CHECK-NOT: UnaryOperator{{.*}}postfix '++' cannot overflow + // CHECK: DeclRefExpr{{.*}}'T2' 'int' + + -T1; + -T2; + // CHECK: UnaryOperator{{.*}}prefix '-' cannot overflow + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char' + // CHECK-NOT: UnaryOperator{{.*}}prefix '-' cannot overflow + // CHECK: ImplicitCastExpr + // CHECK: DeclRefExpr{{.*}}'T2' 'int' + + ~T1; + ~T2; + // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'T1' 'char' + // CHECK: UnaryOperator{{.*}}prefix '~' cannot overflow + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'T2' 'int' +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits