Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 43cedfb1c58861bac53c5290364eabefc16820a9)
+++ src/Concurrency/Keywords.cc	(revision 92b99582f2cac55ec8dec114c10fa83e9b366054)
@@ -42,6 +42,9 @@
 
 namespace Concurrency {
+	inline static std::string getTypeIdName( std::string const & exception_name ) {
+		return exception_name.empty() ? std::string() : Virtual::typeIdType( exception_name );
+	}
 	inline static std::string getVTableName( std::string const & exception_name ) {
-		return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
+		return exception_name.empty() ? std::string() : Virtual::vtableTypeName( exception_name );
 	}
 
@@ -75,4 +78,5 @@
 		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
 		  context_error( context_error ), exception_name( exception_name ),
+		  typeid_name( getTypeIdName( exception_name ) ),
 		  vtable_name( getVTableName( exception_name ) ),
 		  needs_main( needs_main ), cast_target( cast_target ) {}
@@ -84,4 +88,5 @@
 
 		void handle( StructDecl * );
+		void addTypeId( StructDecl * );
 		void addVtableForward( StructDecl * );
 		FunctionDecl * forwardDeclare( StructDecl * );
@@ -99,4 +104,5 @@
 		const std::string context_error;
 		const std::string exception_name;
+		const std::string typeid_name;
 		const std::string vtable_name;
 		bool needs_main;
@@ -106,4 +112,5 @@
 		FunctionDecl * dtor_decl = nullptr;
 		StructDecl * except_decl = nullptr;
+		StructDecl * typeid_decl = nullptr;
 		StructDecl * vtable_decl = nullptr;
 	};
@@ -392,4 +399,7 @@
 		else if ( !except_decl && exception_name == decl->name && decl->body ) {
 			except_decl = decl;
+		}
+		else if ( !typeid_decl && typeid_name == decl->name && decl->body ) {
+			typeid_decl = decl;
 		}
 		else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
@@ -448,5 +458,11 @@
 		if( !dtor_decl ) SemanticError( decl, context_error );
 
-		addVtableForward( decl );
+		if ( !exception_name.empty() ) {
+			if( !typeid_decl ) SemanticError( decl, context_error );
+			if( !vtable_decl ) SemanticError( decl, context_error );
+
+			addTypeId( decl );
+			addVtableForward( decl );
+		}
 		FunctionDecl * func = forwardDeclare( decl );
 		ObjectDecl * field = addField( decl );
@@ -454,19 +470,24 @@
 	}
 
+	void ConcurrentSueKeyword::addTypeId( StructDecl * decl ) {
+		assert( typeid_decl );
+		StructInstType typeid_type( Type::Const, typeid_decl );
+		typeid_type.parameters.push_back( new TypeExpr(
+			new StructInstType( noQualifiers, decl )
+			) );
+		declsToAddBefore.push_back( Virtual::makeTypeIdInstance( &typeid_type ) );
+	}
+
 	void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
-		if ( vtable_decl ) {
-			std::list< Expression * > poly_args = {
-				new TypeExpr( new StructInstType( noQualifiers, decl ) ),
-			};
-			declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
-				vtable_decl->makeInst( poly_args ),
-				except_decl->makeInst( poly_args )
-			) );
-			declsToAddBefore.push_back( Virtual::makeVtableForward(
-				vtable_decl->makeInst( move( poly_args ) ) ) );
-		// Its only an error if we want a vtable and don't have one.
-		} else if ( ! vtable_name.empty() ) {
-			SemanticError( decl, context_error );
-		}
+		assert( vtable_decl );
+		std::list< Expression * > poly_args = {
+			new TypeExpr( new StructInstType( noQualifiers, decl ) ),
+		};
+		declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
+			vtable_decl->makeInst( poly_args ),
+			except_decl->makeInst( poly_args )
+		) );
+		declsToAddBefore.push_back( Virtual::makeVtableForward(
+			vtable_decl->makeInst( move( poly_args ) ) ) );
 	}
 
