Handle function decls in Structured CFG analysis (#2474)

Fixes #2451

* Structured cfg analysis now handles functions with no basic blocks
* Added a test
diff --git a/source/opt/struct_cfg_analysis.cpp b/source/opt/struct_cfg_analysis.cpp
index d78ec56..dcfd4a5 100644
--- a/source/opt/struct_cfg_analysis.cpp
+++ b/source/opt/struct_cfg_analysis.cpp
@@ -19,7 +19,7 @@
 namespace {
 const uint32_t kMergeNodeIndex = 0;
 const uint32_t kContinueNodeIndex = 1;
-}
+}  // namespace
 
 namespace spvtools {
 namespace opt {
@@ -37,6 +37,8 @@
 }
 
 void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
+  if (func->begin() == func->end()) return;
+
   std::list<BasicBlock*> order;
   context_->cfg()->ComputeStructuredOrder(func, &*func->begin(), &order);
 
diff --git a/test/opt/struct_cfg_analysis_test.cpp b/test/opt/struct_cfg_analysis_test.cpp
index 13f9022..3a980fe 100644
--- a/test/opt/struct_cfg_analysis_test.cpp
+++ b/test/opt/struct_cfg_analysis_test.cpp
@@ -461,6 +461,26 @@
   }
 }
 
+TEST_F(StructCFGAnalysisTest, EmptyFunctionTest) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpDecorate %func LinkageAttributes "x" Import
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%func = OpFunction %void None %void_fn
+OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  // #2451: This segfaulted on empty functions.
+  StructuredCFGAnalysis analysis(context.get());
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools