forked from OSchip/llvm-project
Establish the iteration variable of an ObjC for-in loop before
emitting the collection expression. Fixes some really, really broken code. llvm-svn: 126193
This commit is contained in:
parent
666cf56668
commit
9e2e22f5c6
|
@ -782,10 +782,12 @@ static bool isCapturedBy(const VarDecl &var, const Expr *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
|
void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
|
||||||
|
assert(emission.Variable && "emission was not valid!");
|
||||||
|
|
||||||
// If this was emitted as a global constant, we're done.
|
// If this was emitted as a global constant, we're done.
|
||||||
if (emission.wasEmittedAsGlobal()) return;
|
if (emission.wasEmittedAsGlobal()) return;
|
||||||
|
|
||||||
const VarDecl &D = emission.Variable;
|
const VarDecl &D = *emission.Variable;
|
||||||
QualType type = D.getType();
|
QualType type = D.getType();
|
||||||
|
|
||||||
// If this local has an initializer, emit it now.
|
// If this local has an initializer, emit it now.
|
||||||
|
@ -940,10 +942,12 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
|
void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
|
||||||
|
assert(emission.Variable && "emission was not valid!");
|
||||||
|
|
||||||
// If this was emitted as a global constant, we're done.
|
// If this was emitted as a global constant, we're done.
|
||||||
if (emission.wasEmittedAsGlobal()) return;
|
if (emission.wasEmittedAsGlobal()) return;
|
||||||
|
|
||||||
const VarDecl &D = emission.Variable;
|
const VarDecl &D = *emission.Variable;
|
||||||
|
|
||||||
// Handle C++ destruction of variables.
|
// Handle C++ destruction of variables.
|
||||||
if (getLangOptions().CPlusPlus) {
|
if (getLangOptions().CPlusPlus) {
|
||||||
|
|
|
@ -663,6 +663,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The local variable comes into scope immediately.
|
||||||
|
AutoVarEmission variable = AutoVarEmission::invalid();
|
||||||
|
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
|
||||||
|
variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
|
||||||
|
|
||||||
CGDebugInfo *DI = getDebugInfo();
|
CGDebugInfo *DI = getDebugInfo();
|
||||||
if (DI) {
|
if (DI) {
|
||||||
DI->setLocation(S.getSourceRange().getBegin());
|
DI->setLocation(S.getSourceRange().getBegin());
|
||||||
|
@ -799,22 +804,23 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
|
|
||||||
// Initialize the element variable.
|
// Initialize the element variable.
|
||||||
RunCleanupsScope elementVariableScope(*this);
|
RunCleanupsScope elementVariableScope(*this);
|
||||||
bool elementIsDecl;
|
bool elementIsVariable;
|
||||||
LValue elementLValue;
|
LValue elementLValue;
|
||||||
QualType elementType;
|
QualType elementType;
|
||||||
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
|
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
|
||||||
EmitStmt(SD);
|
// Initialize the variable, in case it's a __block variable or something.
|
||||||
const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
|
EmitAutoVarInit(variable);
|
||||||
|
|
||||||
|
const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
|
||||||
DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
|
DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
|
||||||
VK_LValue, SourceLocation());
|
VK_LValue, SourceLocation());
|
||||||
elementLValue = EmitLValue(&tempDRE);
|
elementLValue = EmitLValue(&tempDRE);
|
||||||
elementType = D->getType();
|
elementType = D->getType();
|
||||||
elementIsDecl = true;
|
elementIsVariable = true;
|
||||||
} else {
|
} else {
|
||||||
elementLValue = LValue(); // suppress warning
|
elementLValue = LValue(); // suppress warning
|
||||||
elementType = cast<Expr>(S.getElement())->getType();
|
elementType = cast<Expr>(S.getElement())->getType();
|
||||||
elementIsDecl = false;
|
elementIsVariable = false;
|
||||||
}
|
}
|
||||||
const llvm::Type *convertedElementType = ConvertType(elementType);
|
const llvm::Type *convertedElementType = ConvertType(elementType);
|
||||||
|
|
||||||
|
@ -837,11 +843,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
|
|
||||||
// Make sure we have an l-value. Yes, this gets evaluated every
|
// Make sure we have an l-value. Yes, this gets evaluated every
|
||||||
// time through the loop.
|
// time through the loop.
|
||||||
if (!elementIsDecl)
|
if (!elementIsVariable)
|
||||||
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
|
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
|
||||||
|
|
||||||
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
|
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
|
||||||
|
|
||||||
|
// If we do have an element variable, this assignment is the end of
|
||||||
|
// its initialization.
|
||||||
|
if (elementIsVariable)
|
||||||
|
EmitAutoVarCleanups(variable);
|
||||||
|
|
||||||
// Perform the loop body, setting up break and continue labels.
|
// Perform the loop body, setting up break and continue labels.
|
||||||
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
|
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
|
||||||
{
|
{
|
||||||
|
@ -891,7 +902,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
||||||
// No more elements.
|
// No more elements.
|
||||||
EmitBlock(EmptyBB);
|
EmitBlock(EmptyBB);
|
||||||
|
|
||||||
if (!elementIsDecl) {
|
if (!elementIsVariable) {
|
||||||
// If the element was not a declaration, set it to be null.
|
// If the element was not a declaration, set it to be null.
|
||||||
|
|
||||||
llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
|
llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
|
||||||
|
|
|
@ -1560,7 +1560,7 @@ public:
|
||||||
class AutoVarEmission {
|
class AutoVarEmission {
|
||||||
friend class CodeGenFunction;
|
friend class CodeGenFunction;
|
||||||
|
|
||||||
const VarDecl &Variable;
|
const VarDecl *Variable;
|
||||||
|
|
||||||
/// The alignment of the variable.
|
/// The alignment of the variable.
|
||||||
CharUnits Alignment;
|
CharUnits Alignment;
|
||||||
|
@ -1578,13 +1578,18 @@ public:
|
||||||
/// initializer.
|
/// initializer.
|
||||||
bool IsConstantAggregate;
|
bool IsConstantAggregate;
|
||||||
|
|
||||||
|
struct Invalid {};
|
||||||
|
AutoVarEmission(Invalid) : Variable(0) {}
|
||||||
|
|
||||||
AutoVarEmission(const VarDecl &variable)
|
AutoVarEmission(const VarDecl &variable)
|
||||||
: Variable(variable), Address(0), NRVOFlag(0),
|
: Variable(&variable), Address(0), NRVOFlag(0),
|
||||||
IsByRef(false), IsConstantAggregate(false) {}
|
IsByRef(false), IsConstantAggregate(false) {}
|
||||||
|
|
||||||
bool wasEmittedAsGlobal() const { return Address == 0; }
|
bool wasEmittedAsGlobal() const { return Address == 0; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
|
||||||
|
|
||||||
/// Returns the address of the object within this declaration.
|
/// Returns the address of the object within this declaration.
|
||||||
/// Note that this does not chase the forwarding pointer for
|
/// Note that this does not chase the forwarding pointer for
|
||||||
/// __block decls.
|
/// __block decls.
|
||||||
|
@ -1592,8 +1597,8 @@ public:
|
||||||
if (!IsByRef) return Address;
|
if (!IsByRef) return Address;
|
||||||
|
|
||||||
return CGF.Builder.CreateStructGEP(Address,
|
return CGF.Builder.CreateStructGEP(Address,
|
||||||
CGF.getByRefValueLLVMField(&Variable),
|
CGF.getByRefValueLLVMField(Variable),
|
||||||
Variable.getNameAsString());
|
Variable->getNameAsString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
|
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
|
||||||
|
|
|
@ -42,3 +42,9 @@ void t1() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rdar://problem/9027663
|
||||||
|
void t2(NSArray *array) {
|
||||||
|
for (NSArray *array in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue