Index: src/ControlStruct/LabelGenerator.cc
===================================================================
--- src/ControlStruct/LabelGenerator.cc	(revision a0ad7dc9c1fb88ba2a6f635f0b103f2eb1380169)
+++ src/ControlStruct/LabelGenerator.cc	(revision c51b5a353e99148805d261773a65c571cb6fb639)
@@ -20,4 +20,5 @@
 #include "SynTree/Label.h"
 #include "SynTree/Attribute.h"
+#include "SynTree/Statement.h"
 
 namespace ControlStruct {
@@ -31,7 +32,10 @@
 	}
 
-	Label LabelGenerator::newLabel( std::string suffix ) {
+	Label LabelGenerator::newLabel( std::string suffix, Statement * stmt ) {
 		std::ostringstream os;
 		os << "__L" << current++ << "__" << suffix;
+		if ( stmt && ! stmt->get_labels().empty() ) {
+			os << "_" << stmt->get_labels().front() << "__";
+		}
 		std::string ret = os.str();
 		Label l( ret );
Index: src/ControlStruct/LabelGenerator.h
===================================================================
--- src/ControlStruct/LabelGenerator.h	(revision a0ad7dc9c1fb88ba2a6f635f0b103f2eb1380169)
+++ src/ControlStruct/LabelGenerator.h	(revision c51b5a353e99148805d261773a65c571cb6fb639)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// LabelGenerator.h -- 
+// LabelGenerator.h --
 //
 // Author           : Rodolfo G. Esteves
@@ -24,5 +24,5 @@
 	  public:
 		static LabelGenerator *getGenerator();
-		Label newLabel(std::string suffix = "");
+		Label newLabel(std::string suffix, Statement * stmt = nullptr);
 		void reset() { current = 0; }
 		void rewind() { current--; }
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision a0ad7dc9c1fb88ba2a6f635f0b103f2eb1380169)
+++ src/ControlStruct/MLEMutator.cc	(revision c51b5a353e99148805d261773a65c571cb6fb639)
@@ -56,5 +56,5 @@
 		bool labeledBlock = !(cmpndStmt->get_labels().empty());
 		if ( labeledBlock ) {
-			Label brkLabel = generator->newLabel("blockBreak");
+			Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
 			enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
 		} // if
@@ -80,9 +80,10 @@
 		// whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
 		// loops
-		Label brkLabel = generator->newLabel("loopBreak");
-		Label contLabel = generator->newLabel("loopContinue");
+		Label brkLabel = generator->newLabel("loopBreak", loopStmt);
+		Label contLabel = generator->newLabel("loopContinue", loopStmt);
 		enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
 		loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
 
+		assert( ! enclosingControlStructures.empty() );
 		Entry &e = enclosingControlStructures.back();
 		// sanity check that the enclosing loops have been popped correctly
@@ -108,10 +109,10 @@
 		bool labeledBlock = !(ifStmt->get_labels().empty());
 		if ( labeledBlock ) {
-			Label brkLabel = generator->newLabel("blockBreak");
+			Label brkLabel = generator->newLabel("blockBreak", ifStmt);
 			enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
 		} // if
 
 		Parent::mutate( ifStmt );
-		
+
 		if ( labeledBlock ) {
 			if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
@@ -126,5 +127,5 @@
 	Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
 		// generate a label for breaking out of a labeled switch
-		Label brkLabel = generator->newLabel("switchBreak");
+		Label brkLabel = generator->newLabel("switchBreak", switchStmt);
 		enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
 		mutateAll( switchStmt->get_statements(), *this );
@@ -158,27 +159,33 @@
 
 		std::list< Entry >::reverse_iterator targetEntry;
-		if ( branchStmt->get_type() == BranchStmt::Goto ) {
-			return branchStmt;
-		} else if ( branchStmt->get_type() == BranchStmt::Continue) {
-			// continue target must be a loop
-			if ( branchStmt->get_target() == "" ) {
-				targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
-			} else {
-				// labelled continue - lookup label in table ot find attached control structure
-				targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
-			} // if
-			if ( targetEntry == enclosingControlStructures.rend() || ! isLoop( targetEntry->get_controlStructure() ) ) {
-				throw SemanticError( "'continue' target must be an enclosing loop: " + originalTarget );
-			} // if
-		} else if ( branchStmt->get_type() == BranchStmt::Break ) {
-			if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
-			targetEntry = enclosingControlStructures.rbegin();
-		} else {
-			assert( false );
-		} // if
-
-		if ( branchStmt->get_target() != "" && targetTable->find( branchStmt->get_target() ) == targetTable->end() ) {
-			throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
-		} // if
+		switch ( branchStmt->get_type() ) {
+			case BranchStmt::Goto:
+				return branchStmt;
+			case BranchStmt::Continue:
+			case BranchStmt::Break: {
+				bool isContinue = branchStmt->get_type() == BranchStmt::Continue;
+				// unlabeled break/continue
+				if ( branchStmt->get_target() == "" ) {
+					if ( isContinue ) {
+						// continue target is outermost loop
+						targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
+					} else {
+						// break target is outmost control structure
+						if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
+						targetEntry = enclosingControlStructures.rbegin();
+					} // if
+				} else {
+					// labeled break/continue - lookup label in table to find attached control structure
+					targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
+				} // if
+				// ensure that selected target is valid
+				if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
+					throw SemanticError( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
+				} // if
+				break;
+			}
+			default:
+				assert( false );
+		} // switch
 
 		// branch error checks, get the appropriate label name and create a goto
@@ -197,14 +204,7 @@
 		} // switch
 
-		if ( branchStmt->get_target() == "" && branchStmt->get_type() != BranchStmt::Continue ) {
-			// unlabelled break/continue - can keep branch as break/continue for extra semantic information, but add
-			// exitLabel as its destination so that label passes can easily determine where the break/continue goes to
-			branchStmt->set_target( exitLabel );
-			return branchStmt;
-		} else {
-			// labelled break/continue - can't easily emulate this with break and continue, so transform into a goto
-			delete branchStmt;
-			return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
-		} // if
+		// transform break/continue statements into goto to simplify later handling of branches
+		delete branchStmt;
+		return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
 	}
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision a0ad7dc9c1fb88ba2a6f635f0b103f2eb1380169)
+++ src/SymTab/Validate.cc	(revision c51b5a353e99148805d261773a65c571cb6fb639)
@@ -208,4 +208,18 @@
 	};
 
+	class ArrayLength : public Visitor {
+	public:
+		/// for array types without an explicit length, compute the length and store it so that it
+		/// is known to the rest of the phases. For example,
+		///   int x[] = { 1, 2, 3 };
+		///   int y[][2] = { { 1, 2, 3 }, { 1, 2, 3 } };
+		/// here x and y are known at compile-time to have length 3, so change this into
+		///   int x[3] = { 1, 2, 3 };
+		///   int y[3][2] = { { 1, 2, 3 }, { 1, 2, 3 } };
+		static void computeLength( std::list< Declaration * > & translationUnit );
+
+		virtual void visit( ObjectDecl * objDecl );
+	};
+
 	class CompoundLiteral final : public GenPoly::DeclMutator {
 		Type::StorageClasses storageClasses;
@@ -235,4 +249,5 @@
 		acceptAll( translationUnit, pass3 );
 		VerifyCtorDtorAssign::verify( translationUnit );
+		ArrayLength::computeLength( translationUnit );
 	}
 
@@ -869,4 +884,18 @@
 		}
 	}
+
+	void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
+		ArrayLength len;
+		acceptAll( translationUnit, len );
+	}
+
+	void ArrayLength::visit( ObjectDecl * objDecl ) {
+		if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
+			if ( at->get_dimension() != nullptr ) return;
+			if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->get_init() ) ) {
+				at->set_dimension( new ConstantExpr( Constant::from_ulong( init->get_initializers().size() ) ) );
+			}
+		}
+	}
 } // namespace SymTab
 
