r179053 - <rdar://problem/13540921> Fix a crasher when an Objective-C for-in loop gets a non-variable iteration declaration.
Douglas Gregor
dgregor at apple.com
Mon Apr 8 13:52:24 PDT 2013
Author: dgregor
Date: Mon Apr 8 15:52:24 2013
New Revision: 179053
URL: http://llvm.org/viewvc/llvm-project?rev=179053&view=rev
Log:
<rdar://problem/13540921> Fix a crasher when an Objective-C for-in loop gets a non-variable iteration declaration.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/SemaObjCXX/foreach.mm
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179053&r1=179052&r2=179053&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 8 15:52:24 2013
@@ -6029,8 +6029,10 @@ def ext_mixed_decls_code : Extension<
"ISO C90 forbids mixing declarations and code">,
InGroup<DiagGroup<"declaration-after-statement">>;
-def err_non_variable_decl_in_for : Error<
+def err_non_local_variable_decl_in_for : Error<
"declaration of non-local variable in 'for' loop">;
+def err_non_variable_decl_in_for : Error<
+ "non-variable declaration in 'for' loop">;
def err_toomany_element_decls : Error<
"only one element declaration is allowed">;
def err_selector_element_not_lvalue : Error<
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=179053&r1=179052&r2=179053&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Apr 8 15:52:24 2013
@@ -1527,14 +1527,23 @@ Parser::DeclGroupPtrTy Parser::ParseDecl
// C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we
// must parse and analyze the for-range-initializer before the declaration is
// analyzed.
- if (FRI && Tok.is(tok::colon)) {
- FRI->ColonLoc = ConsumeToken();
- if (Tok.is(tok::l_brace))
- FRI->RangeExpr = ParseBraceInitializer();
- else
- FRI->RangeExpr = ParseExpression();
+ //
+ // Handle the Objective-C for-in loop variable similarly, although we
+ // don't need to parse the container in advance.
+ if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
+ bool IsForRangeLoop = false;
+ if (Tok.is(tok::colon)) {
+ IsForRangeLoop = true;
+ FRI->ColonLoc = ConsumeToken();
+ if (Tok.is(tok::l_brace))
+ FRI->RangeExpr = ParseBraceInitializer();
+ else
+ FRI->RangeExpr = ParseExpression();
+ }
+
Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
- Actions.ActOnCXXForRangeDecl(ThisDecl);
+ if (IsForRangeLoop)
+ Actions.ActOnCXXForRangeDecl(ThisDecl);
Actions.FinalizeDeclaration(ThisDecl);
D.complete(ThisDecl);
return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1);
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=179053&r1=179052&r2=179053&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Apr 8 15:52:24 2013
@@ -76,10 +76,23 @@ StmtResult Sema::ActOnDeclStmt(DeclGroup
void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+ // If we don't have a declaration, or we have an invalid declaration,
+ // just return.
+ if (DG.isNull() || !DG.isSingleDecl())
+ return;
+
+ Decl *decl = DG.getSingleDecl();
+ if (!decl || decl->isInvalidDecl())
+ return;
- // If we have an invalid decl, just return.
- if (DG.isNull() || !DG.isSingleDecl()) return;
- VarDecl *var = cast<VarDecl>(DG.getSingleDecl());
+ // Only variable declarations are permitted.
+ VarDecl *var = dyn_cast<VarDecl>(decl);
+ if (!var) {
+ Diag(decl->getLocation(), diag::err_non_variable_decl_in_for);
+ decl->setInvalidDecl();
+ return;
+ }
// suppress any potential 'unused variable' warning.
var->setUsed();
@@ -1426,9 +1439,10 @@ Sema::ActOnForStmt(SourceLocation ForLoc
VarDecl *VD = dyn_cast<VarDecl>(*DI);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
VD = 0;
- if (VD == 0)
- Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for);
- // FIXME: mark decl erroneous!
+ if (VD == 0) {
+ Diag((*DI)->getLocation(), diag::err_non_local_variable_decl_in_for);
+ (*DI)->setInvalidDecl();
+ }
}
}
}
@@ -1562,14 +1576,17 @@ Sema::ActOnObjCForCollectionStmt(SourceL
return StmtError(Diag((*DS->decl_begin())->getLocation(),
diag::err_toomany_element_decls));
- VarDecl *D = cast<VarDecl>(DS->getSingleDecl());
+ VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!D || D->isInvalidDecl())
+ return StmtError();
+
FirstType = D->getType();
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
if (!D->hasLocalStorage())
return StmtError(Diag(D->getLocation(),
- diag::err_non_variable_decl_in_for));
+ diag::err_non_local_variable_decl_in_for));
// If the type contained 'auto', deduce the 'auto' to 'id'.
if (FirstType->getContainedAutoType()) {
Modified: cfe/trunk/test/SemaObjCXX/foreach.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/foreach.mm?rev=179053&r1=179052&r2=179053&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/foreach.mm (original)
+++ cfe/trunk/test/SemaObjCXX/foreach.mm Mon Apr 8 15:52:24 2013
@@ -69,3 +69,9 @@ void test2(NSObject<NSFastEnumeration> *
// expected-warning {{property access result unused - getters should not be used for side effects}}
}
}
+
+void testErrors(NSArray *array) {
+ typedef int fn(int);
+
+ for (fn x in array) { } // expected-error{{non-variable declaration in 'for' loop}}
+}
More information about the cfe-commits
mailing list