ObjCBoxedExpr can't be evaluated by the constant expression evaluator.

A boxed expression evaluates its subexpr and then calls an objc method to transform it into another value with pointer type. The objc method can never be constexpr and therefore this expression can never be evaluated. Fixes a miscompile boxing expressions with side-effects.

Also make ObjCBoxedExpr handling a normal part of the expression evaluator instead of being the only case besides full-expression where we check for integer overflow.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301721 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky 2017-04-29 00:07:27 +00:00
parent acf47c79de
commit 538445b124
4 changed files with 20 additions and 3 deletions

View File

@ -5481,8 +5481,11 @@ public:
bool VisitUnaryAddrOf(const UnaryOperator *E);
bool VisitObjCStringLiteral(const ObjCStringLiteral *E)
{ return Success(E); }
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E)
{ return Success(E); }
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
if (Info.noteFailure())
EvaluateIgnoredValue(Info, E->getSubExpr());
return Error(E);
}
bool VisitAddrLabelExpr(const AddrLabelExpr *E)
{ return Success(E); }
bool VisitCallExpr(const CallExpr *E);

View File

@ -9882,6 +9882,9 @@ void Sema::CheckForIntOverflow (Expr *E) {
if (auto InitList = dyn_cast<InitListExpr>(E))
Exprs.append(InitList->inits().begin(), InitList->inits().end());
if (isa<ObjCBoxedExpr>(E))
E->IgnoreParenCasts()->EvaluateForOverflow(Context);
} while (!Exprs.empty());
}

View File

@ -595,7 +595,6 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
break;
}
}
CheckForIntOverflow(ValueExpr);
// FIXME: Do I need to do anything special with BoolTy expressions?
// Look for the appropriate method within NSNumber.

View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
@interface NSNumber
+ (id)numberWithInt:(int)n;
@end
int n = 1;
int m = (@(n++), 0);
// CHECK: define {{.*}} @__cxx_global_var_init()
// CHECK: load i32, i32* @n
// CHECK: store i32 %{{.*}}, i32* @n