Changeset View
Changeset View
Standalone View
Standalone View
lib/Sema/SemaExpr.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 12,437 Lines • ▼ Show 20 Lines | case BO_Assign: | ||||
if (getLangOpts().CPlusPlus && | if (getLangOpts().CPlusPlus && | ||||
LHS.get()->getObjectKind() != OK_ObjCProperty) { | LHS.get()->getObjectKind() != OK_ObjCProperty) { | ||||
VK = LHS.get()->getValueKind(); | VK = LHS.get()->getValueKind(); | ||||
OK = LHS.get()->getObjectKind(); | OK = LHS.get()->getObjectKind(); | ||||
} | } | ||||
if (!ResultTy.isNull()) { | if (!ResultTy.isNull()) { | ||||
DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true); | DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true); | ||||
DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc); | DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc); | ||||
// Avoid copying a block to the heap if the block is assigned to a local | |||||
// auto variable that is declared in the same scope as the block. This | |||||
// optimization is unsafe if the local variable is declared in an outer | |||||
// scope. For example: | |||||
// | |||||
// BlockTy b; | |||||
// { | |||||
// b = ^{...}; | |||||
// } | |||||
// // It is unsafe to invoke the block here if it wasn't copied to the | |||||
// // heap. | |||||
// b(); | |||||
if (auto *BE = dyn_cast<BlockExpr>(RHS.get()->IgnoreParens())) | |||||
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS.get()->IgnoreParens())) | |||||
rjmccall: You should `IgnoreParens` on the LHS as well. In general, you should always `IgnoreParens`. | |||||
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) | |||||
if (VD->hasLocalStorage() && getCurScope()->isDeclScope(VD)) | |||||
BE->getBlockDecl()->setCanAvoidCopyToHeap(); | |||||
} | } | ||||
RecordModifiableNonNullParam(*this, LHS.get()); | RecordModifiableNonNullParam(*this, LHS.get()); | ||||
break; | break; | ||||
case BO_PtrMemD: | case BO_PtrMemD: | ||||
case BO_PtrMemI: | case BO_PtrMemI: | ||||
ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc, | ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc, | ||||
Opc == BO_PtrMemI); | Opc == BO_PtrMemI); | ||||
break; | break; | ||||
case BO_Mul: | case BO_Mul: | ||||
case BO_Div: | case BO_Div: | ||||
ConvertHalfVec = true; | ConvertHalfVec = true; | ||||
ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false, | ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false, | ||||
Opc == BO_Div); | Opc == BO_Div); | ||||
break; | break; | ||||
case BO_Rem: | case BO_Rem: | ||||
ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc); | ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc); | ||||
break; | break; | ||||
case BO_Add: | case BO_Add: | ||||
ConvertHalfVec = true; | ConvertHalfVec = true; | ||||
ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc); | ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc); | ||||
break; | break; | ||||
Please check for a block-expression RHS first, it is far more likely to short-circuit this check than anything else. Also, I think the right place for this check is up with the calls to DiagnoseSelfAssignment and DiagnoseSelfMove. rjmccall: Please check for a block-expression RHS first, it is far more likely to short-circuit this… | |||||
case BO_Sub: | case BO_Sub: | ||||
ConvertHalfVec = true; | ConvertHalfVec = true; | ||||
ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc); | ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc); | ||||
break; | break; | ||||
case BO_Shl: | case BO_Shl: | ||||
case BO_Shr: | case BO_Shr: | ||||
ResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc); | ResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 4,477 Lines • Show Last 20 Lines |
You should IgnoreParens on the LHS as well. In general, you should always IgnoreParens.