Commit fb39526159

Andrew Kelley <andrew@ziglang.org>
2021-05-11 23:50:39
AstGen: support emitting multiple compile errors
1 parent bcf15e3
src/AstGen.zig
@@ -3317,20 +3317,32 @@ fn structDeclInner(
                 switch (node_tags[fn_proto]) {
                     .fn_proto_simple => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_multi => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_one => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     else => unreachable,
@@ -3338,50 +3350,83 @@ fn structDeclInner(
             },
             .fn_proto_simple => {
                 var params: [1]ast.Node.Index = undefined;
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto_multi => {
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto_one => {
                 var params: [1]ast.Node.Index = undefined;
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto => {
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
 
             .global_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .local_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .simple_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .aligned_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
 
             .@"comptime" => {
-                try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
+                astgen.comptimeDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .@"usingnamespace" => {
-                try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
+                astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .test_decl => {
-                try astgen.testDecl(gz, scope, &wip_decls, member_node);
+                astgen.testDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             else => unreachable,
@@ -3530,20 +3575,32 @@ fn unionDeclInner(
                 switch (node_tags[fn_proto]) {
                     .fn_proto_simple => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_multi => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_one => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto));
+                        astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     else => unreachable,
@@ -3551,50 +3608,83 @@ fn unionDeclInner(
             },
             .fn_proto_simple => {
                 var params: [1]ast.Node.Index = undefined;
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto_multi => {
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto_one => {
                 var params: [1]ast.Node.Index = undefined;
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .fn_proto => {
-                try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node));
+                astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
 
             .global_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .local_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .simple_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .aligned_var_decl => {
-                try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
+                astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
 
             .@"comptime" => {
-                try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
+                astgen.comptimeDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .@"usingnamespace" => {
-                try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
+                astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             .test_decl => {
-                try astgen.testDecl(gz, scope, &wip_decls, member_node);
+                astgen.testDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.AnalysisFail => {},
+                };
                 continue;
             },
             else => unreachable,
@@ -3878,20 +3968,32 @@ fn containerDecl(
                         switch (node_tags[fn_proto]) {
                             .fn_proto_simple => {
                                 var params: [1]ast.Node.Index = undefined;
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto_multi => {
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto_one => {
                                 var params: [1]ast.Node.Index = undefined;
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto => {
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             else => unreachable,
@@ -3899,50 +4001,83 @@ fn containerDecl(
                     },
                     .fn_proto_simple => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_multi => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_one => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
 
                     .global_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .local_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .simple_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .aligned_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
 
                     .@"comptime" => {
-                        try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
+                        astgen.comptimeDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .@"usingnamespace" => {
-                        try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
+                        astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .test_decl => {
-                        try astgen.testDecl(gz, scope, &wip_decls, member_node);
+                        astgen.testDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     else => unreachable,
@@ -4044,20 +4179,32 @@ fn containerDecl(
                         switch (node_tags[fn_proto]) {
                             .fn_proto_simple => {
                                 var params: [1]ast.Node.Index = undefined;
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto_multi => {
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto_one => {
                                 var params: [1]ast.Node.Index = undefined;
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             .fn_proto => {
-                                try astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto));
+                                astgen.fnDecl(gz, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
+                                    error.OutOfMemory => return error.OutOfMemory,
+                                    error.AnalysisFail => {},
+                                };
                                 continue;
                             },
                             else => unreachable,
@@ -4065,50 +4212,83 @@ fn containerDecl(
                     },
                     .fn_proto_simple => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_multi => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto_one => {
                         var params: [1]ast.Node.Index = undefined;
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .fn_proto => {
-                        try astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node));
+                        astgen.fnDecl(gz, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
 
                     .global_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .local_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .simple_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .aligned_var_decl => {
-                        try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
+                        astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
 
                     .@"comptime" => {
-                        try astgen.comptimeDecl(gz, scope, &wip_decls, member_node);
+                        astgen.comptimeDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .@"usingnamespace" => {
-                        try astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node);
+                        astgen.usingnamespaceDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     .test_decl => {
-                        try astgen.testDecl(gz, scope, &wip_decls, member_node);
+                        astgen.testDecl(gz, scope, &wip_decls, member_node) catch |err| switch (err) {
+                            error.OutOfMemory => return error.OutOfMemory,
+                            error.AnalysisFail => {},
+                        };
                         continue;
                     },
                     else => unreachable,
src/Compilation.zig
@@ -1676,8 +1676,21 @@ pub fn totalErrorCount(self: *Compilation) usize {
 
     if (self.bin_file.options.module) |module| {
         total += module.failed_exports.items().len +
-            module.failed_files.items().len +
             @boolToInt(module.failed_root_src_file != null);
+
+        for (module.failed_files.items()) |entry| {
+            if (entry.value) |_| {
+                total += 1;
+            } else {
+                const file = entry.key;
+                assert(file.zir_loaded);
+                const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)];
+                assert(payload_index != 0);
+                const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index);
+                total += header.data.items_len;
+            }
+        }
+
         // Skip errors for Decls within files that failed parsing.
         // When a parse error is introduced, we keep all the semantic analysis for
         // the previous parse success, including compile errors, but we cannot
BRANCH_TODO
@@ -44,9 +44,6 @@
 
  * sort compile errors before presenting them to eliminate nondeterministic error reporting
 
- * when handling decls, catch the error and continue, so that
-   AstGen can report more than one compile error.
-
  * AstGen: add result location pointers to function calls
  * nested function decl: how to refer to params?
 
@@ -66,3 +63,5 @@
 
  * better anonymous Decl naming convention
    - avoid the global atomic integer for the number because of contention
+
+ * AstGen memory leak with `block_gz.labeled_store_to_block_ptr_list.append`