Don't import private structs, even indirectly as part of template instantiation!

PiperOrigin-RevId: 478948147
diff --git a/rs_bindings_from_cc/importer.cc b/rs_bindings_from_cc/importer.cc
index 2a319e4..54f2fea 100644
--- a/rs_bindings_from_cc/importer.cc
+++ b/rs_bindings_from_cc/importer.cc
@@ -564,7 +564,34 @@
   return result;
 }
 
+/// Returns true if a decl is inside a private section, or is inside a
+/// RecordDecl which is IsTransitivelyInPrivate.
+bool IsTransitivelyInPrivate(clang::Decl* decl_to_check) {
+  while (true) {
+    auto* parent =
+        llvm::dyn_cast<clang::CXXRecordDecl>(decl_to_check->getDeclContext());
+    if (parent == nullptr) {
+      return false;
+    }
+    switch (decl_to_check->getAccess()) {
+      case clang::AccessSpecifier::AS_public:
+        break;
+      case clang::AccessSpecifier::AS_none:
+        if (!parent->isClass()) {
+          break;
+        }
+        [[fallthrough]];
+      case clang::AccessSpecifier::AS_private:
+      case clang::AccessSpecifier::AS_protected:
+        return true;
+    }
+
+    decl_to_check = parent;
+  }
+}
+
 std::optional<IR::Item> Importer::ImportDecl(clang::Decl* decl) {
+  if (IsTransitivelyInPrivate(decl)) return std::nullopt;
   std::optional<IR::Item> result;
   for (auto& importer : decl_importers_) {
     if (importer->CanImport(decl)) {
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index ac8f005..2745e15 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -7431,6 +7431,30 @@
     }
 
     #[test]
+    fn test_private_struct_not_present() -> Result<()> {
+        let ir = ir_from_cc(&with_lifetime_macros(
+            r#"#pragma clang lifetime_elision
+            template <typename T> class MyTemplate {};
+            class HasPrivateType {
+             private:
+              struct PrivateType {
+                using Foo = MyTemplate<PrivateType>;
+                Foo* get();
+              };
+             protected:
+              HasPrivateType(MyTemplate<PrivateType> x) {}
+            };"#,
+        ))?;
+        let rs_api = generate_bindings_tokens(ir)?.rs_api;
+
+        assert_rs_not_matches!(
+            rs_api,
+            quote! { __CcTemplateInst10MyTemplateIN14HasPrivateType11PrivateTypeEE }
+        );
+        Ok(())
+    }
+
+    #[test]
     fn test_implicit_template_specializations_are_sorted_by_mangled_name() -> Result<()> {
         let bindings = generate_bindings_tokens(ir_from_cc(
             r#"
diff --git a/rs_bindings_from_cc/test/golden/private_method_rs_api.rs b/rs_bindings_from_cc/test/golden/private_method_rs_api.rs
index d311c0e..7ea7b98 100644
--- a/rs_bindings_from_cc/test/golden/private_method_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/private_method_rs_api.rs
@@ -46,10 +46,6 @@
 // Error while generating bindings for item 'Outer::operator=':
 // Parameter #0 is not supported: Unsupported type 'class Outer &&': Unsupported type: && without lifetime
 
-// rs_bindings_from_cc/test/golden/private_method.h;l=19
-// Error while generating bindings for item 'Outer::Inner':
-// Nested classes are not supported yet
-
 // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_GOLDEN_PRIVATE_METHOD_H_
 
 const _: () = assert!(::std::mem::size_of::<Option<&i32>>() == ::std::mem::size_of::<&i32>());
diff --git a/rs_bindings_from_cc/test/golden/templates.h b/rs_bindings_from_cc/test/golden/templates.h
index 615e09d..9976140 100644
--- a/rs_bindings_from_cc/test/golden/templates.h
+++ b/rs_bindings_from_cc/test/golden/templates.h
@@ -126,4 +126,18 @@
 
 }  // namespace forward_declared_template
 
+namespace private_classes {
+
+class HasPrivateType {
+ private:
+  struct PrivateType {
+    using Foo = test_namespace_bindings::MyTemplate<PrivateType>;
+    Foo* get();
+  };
+
+ protected:
+  HasPrivateType(test_namespace_bindings::MyTemplate<PrivateType> x) {}
+};
+}  // namespace private_classes
+
 #endif  // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_GOLDEN_TEMPLATES_H_
diff --git a/rs_bindings_from_cc/test/golden/templates_rs_api.rs b/rs_bindings_from_cc/test/golden/templates_rs_api.rs
index 16f2d25..5b8e06e 100644
--- a/rs_bindings_from_cc/test/golden/templates_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/templates_rs_api.rs
@@ -193,6 +193,116 @@
 
 // namespace forward_declared_template
 
+pub mod private_classes {
+    #[::ctor::recursively_pinned]
+    #[repr(C)]
+    pub struct HasPrivateType {
+        __non_field_data: [::std::mem::MaybeUninit<u8>; 1],
+    }
+    forward_declare::unsafe_define!(
+        forward_declare::symbol!("HasPrivateType"),
+        crate::private_classes::HasPrivateType
+    );
+
+    impl<'b> ::ctor::CtorNew<&'b crate::private_classes::HasPrivateType> for HasPrivateType {
+        type CtorType = impl ::ctor::Ctor<Output = Self> + ::ctor::Captures<'b>;
+        #[inline(always)]
+        fn ctor_new(args: &'b crate::private_classes::HasPrivateType) -> Self::CtorType {
+            let __param_0 = args;
+            unsafe {
+                ::ctor::FnCtor::new(
+                    move |dest: ::std::pin::Pin<
+                        &mut ::std::mem::MaybeUninit<crate::private_classes::HasPrivateType>,
+                    >| {
+                        crate::detail::__rust_thunk___ZN15private_classes14HasPrivateTypeC1ERKS0_(
+                            ::std::pin::Pin::into_inner_unchecked(dest),
+                            __param_0,
+                        );
+                    },
+                )
+            }
+        }
+    }
+    impl<'b> ::ctor::CtorNew<(&'b crate::private_classes::HasPrivateType,)> for HasPrivateType {
+        type CtorType = impl ::ctor::Ctor<Output = Self> + ::ctor::Captures<'b>;
+        #[inline(always)]
+        fn ctor_new(args: (&'b crate::private_classes::HasPrivateType,)) -> Self::CtorType {
+            let (arg,) = args;
+            <Self as ::ctor::CtorNew<&'b crate::private_classes::HasPrivateType>>::ctor_new(arg)
+        }
+    }
+
+    impl<'b> ::ctor::CtorNew<::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>>
+        for HasPrivateType
+    {
+        type CtorType = impl ::ctor::Ctor<Output = Self> + ::ctor::Captures<'b>;
+        #[inline(always)]
+        fn ctor_new(
+            args: ::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,
+        ) -> Self::CtorType {
+            let __param_0 = args;
+            unsafe {
+                ::ctor::FnCtor::new(
+                    move |dest: ::std::pin::Pin<
+                        &mut ::std::mem::MaybeUninit<crate::private_classes::HasPrivateType>,
+                    >| {
+                        crate::detail::__rust_thunk___ZN15private_classes14HasPrivateTypeC1EOS0_(
+                            ::std::pin::Pin::into_inner_unchecked(dest),
+                            __param_0,
+                        );
+                    },
+                )
+            }
+        }
+    }
+    impl<'b> ::ctor::CtorNew<(::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,)>
+        for HasPrivateType
+    {
+        type CtorType = impl ::ctor::Ctor<Output = Self> + ::ctor::Captures<'b>;
+        #[inline(always)]
+        fn ctor_new(
+            args: (::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,),
+        ) -> Self::CtorType {
+            let (arg,) = args;
+            <Self as ::ctor::CtorNew<
+                ::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,
+            >>::ctor_new(arg)
+        }
+    }
+
+    impl<'b> ::ctor::Assign<&'b crate::private_classes::HasPrivateType> for HasPrivateType {
+        #[inline(always)]
+        fn assign<'a>(
+            self: ::std::pin::Pin<&'a mut Self>,
+            __param_0: &'b crate::private_classes::HasPrivateType,
+        ) {
+            unsafe {
+                crate::detail::__rust_thunk___ZN15private_classes14HasPrivateTypeaSERKS0_(
+                    self, __param_0,
+                );
+            }
+        }
+    }
+
+    impl<'b> ::ctor::Assign<::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>>
+        for HasPrivateType
+    {
+        #[inline(always)]
+        fn assign<'a>(
+            self: ::std::pin::Pin<&'a mut Self>,
+            __param_0: ::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,
+        ) {
+            unsafe {
+                crate::detail::__rust_thunk___ZN15private_classes14HasPrivateTypeaSEOS0_(
+                    self, __param_0,
+                );
+            }
+        }
+    }
+}
+
+// namespace private_classes
+
 // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_GOLDEN_TEMPLATES_H_
 
 #[derive(Clone, Copy)]
@@ -966,6 +1076,22 @@
         >(
             i: Option<::std::pin::Pin<&'a mut crate::__CcTemplateInst18MyTopLevelTemplateIiE>>,
         );
+        pub(crate) fn __rust_thunk___ZN15private_classes14HasPrivateTypeC1ERKS0_<'a, 'b>(
+            __this: &'a mut ::std::mem::MaybeUninit<crate::private_classes::HasPrivateType>,
+            __param_0: &'b crate::private_classes::HasPrivateType,
+        );
+        pub(crate) fn __rust_thunk___ZN15private_classes14HasPrivateTypeC1EOS0_<'a, 'b>(
+            __this: &'a mut ::std::mem::MaybeUninit<crate::private_classes::HasPrivateType>,
+            __param_0: ::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,
+        );
+        pub(crate) fn __rust_thunk___ZN15private_classes14HasPrivateTypeaSERKS0_<'a, 'b>(
+            __this: ::std::pin::Pin<&'a mut crate::private_classes::HasPrivateType>,
+            __param_0: &'b crate::private_classes::HasPrivateType,
+        ) -> ::std::pin::Pin<&'a mut crate::private_classes::HasPrivateType>;
+        pub(crate) fn __rust_thunk___ZN15private_classes14HasPrivateTypeaSEOS0_<'a, 'b>(
+            __this: ::std::pin::Pin<&'a mut crate::private_classes::HasPrivateType>,
+            __param_0: ::ctor::RvalueReference<'b, crate::private_classes::HasPrivateType>,
+        ) -> ::std::pin::Pin<&'a mut crate::private_classes::HasPrivateType>;
         pub(crate) fn __rust_thunk___ZN23test_namespace_bindings10MyTemplateI14DifferentScopeEC1Ev__2f_2fthird_5fparty_2fcrubit_2frs_5fbindings_5ffrom_5fcc_2ftest_2fgolden_3atemplates_5fcc<
             'a,
         >(
@@ -1238,6 +1364,15 @@
     static_assertions::assert_not_impl_any!(crate::test_namespace_bindings::TemplateParam: Drop);
 };
 
+const _: () = assert!(::std::mem::size_of::<crate::private_classes::HasPrivateType>() == 1);
+const _: () = assert!(::std::mem::align_of::<crate::private_classes::HasPrivateType>() == 1);
+const _: () = {
+    static_assertions::assert_not_impl_any!(crate::private_classes::HasPrivateType: Copy);
+};
+const _: () = {
+    static_assertions::assert_not_impl_any!(crate::private_classes::HasPrivateType: Drop);
+};
+
 const _: () = assert!(
     ::std::mem::size_of::<
         crate::__CcTemplateInstN23test_namespace_bindings10MyTemplateI14DifferentScopeEE,
diff --git a/rs_bindings_from_cc/test/golden/templates_rs_api_impl.cc b/rs_bindings_from_cc/test/golden/templates_rs_api_impl.cc
index 47db5d8..9d871bb 100644
--- a/rs_bindings_from_cc/test/golden/templates_rs_api_impl.cc
+++ b/rs_bindings_from_cc/test/golden/templates_rs_api_impl.cc
@@ -217,6 +217,28 @@
   return template_template_params::MyTemplate<
       template_template_params::Policy>::GetPolicy();
 }
+extern "C" void __rust_thunk___ZN15private_classes14HasPrivateTypeC1ERKS0_(
+    class private_classes::HasPrivateType* __this,
+    const class private_classes::HasPrivateType* __param_0) {
+  crubit::construct_at(__this, *__param_0);
+}
+extern "C" void __rust_thunk___ZN15private_classes14HasPrivateTypeC1EOS0_(
+    class private_classes::HasPrivateType* __this,
+    class private_classes::HasPrivateType* __param_0) {
+  crubit::construct_at(__this, std::move(*__param_0));
+}
+extern "C" class private_classes::HasPrivateType*
+__rust_thunk___ZN15private_classes14HasPrivateTypeaSERKS0_(
+    class private_classes::HasPrivateType* __this,
+    const class private_classes::HasPrivateType* __param_0) {
+  return &__this->operator=(*__param_0);
+}
+extern "C" class private_classes::HasPrivateType*
+__rust_thunk___ZN15private_classes14HasPrivateTypeaSEOS0_(
+    class private_classes::HasPrivateType* __this,
+    class private_classes::HasPrivateType* __param_0) {
+  return &__this->operator=(std::move(*__param_0));
+}
 
 static_assert(sizeof(struct DifferentScope) == 1);
 static_assert(alignof(struct DifferentScope) == 1);
@@ -312,4 +334,7 @@
 static_assert(alignof(class template_template_params::MyTemplate<
                       template_template_params::Policy>) == 1);
 
+static_assert(sizeof(class private_classes::HasPrivateType) == 1);
+static_assert(alignof(class private_classes::HasPrivateType) == 1);
+
 #pragma clang diagnostic pop