aboutsummaryrefslogtreecommitdiff
path: root/syntax/improper.rs
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-11-02 12:57:57 -0800
committerDavid Tolnay <dtolnay@gmail.com>2020-11-02 18:20:08 -0800
commit7953a11d0c9466103344c15a56569a0aa7f45c9d (patch)
treeeba74278e6771d72510e621d123edfc5e15b4536 /syntax/improper.rs
parentfa1f15b2d700af64980747a0824725965056123b (diff)
downloadcxx-7953a11d0c9466103344c15a56569a0aa7f45c9d.tar.gz
Implement improper ctypes check without infinite loop on cyclic structs
Diffstat (limited to 'syntax/improper.rs')
-rw-r--r--syntax/improper.rs36
1 files changed, 36 insertions, 0 deletions
diff --git a/syntax/improper.rs b/syntax/improper.rs
new file mode 100644
index 00000000..6fd31629
--- /dev/null
+++ b/syntax/improper.rs
@@ -0,0 +1,36 @@
+use self::ImproperCtype::*;
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{Type, Types};
+use proc_macro2::Ident;
+
+pub enum ImproperCtype<'a> {
+ Definite(bool),
+ Depends(&'a Ident),
+}
+
+impl<'a> Types<'a> {
+ // yes, no, maybe
+ pub fn determine_improper_ctype(&self, ty: &Type) -> ImproperCtype<'a> {
+ match ty {
+ Type::Ident(ident) => {
+ let ident = &ident.rust;
+ if let Some(atom) = Atom::from(ident) {
+ Definite(atom == RustString)
+ } else if let Some(strct) = self.structs.get(ident) {
+ Depends(&strct.name.rust) // iterate to fixed-point
+ } else {
+ Definite(self.rust.contains(ident))
+ }
+ }
+ Type::RustBox(_)
+ | Type::RustVec(_)
+ | Type::Str(_)
+ | Type::Fn(_)
+ | Type::Void(_)
+ | Type::Slice(_)
+ | Type::SliceRefU8(_) => Definite(true),
+ Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
+ Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+ }
+ }
+}