diff options
author | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-09-01 11:26:47 -0500 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2022-09-22 20:25:33 -1000 |
commit | 2251aed4d0a2422d7b94cceeafcfe9ac98a69ad6 (patch) | |
tree | 85118ce135d5273b4df7bf682365e7c8fada0ebe | |
parent | 3da6026afd5715715feeb4a8668a91024d71830e (diff) |
find all attributes in a single pass
-rw-r--r-- | src/clang.rs | 83 | ||||
-rw-r--r-- | src/ir/function.rs | 14 |
2 files changed, 55 insertions, 42 deletions
diff --git a/src/clang.rs b/src/clang.rs index 4779e0b7..05ef5d05 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -12,6 +12,27 @@ use std::hash::Hasher; use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong}; use std::{mem, ptr, slice}; +pub struct Attribute { + name: &'static [u8], + kind: CXCursorKind, + token_kind: CXTokenKind, +} + +impl Attribute { + pub const MUST_USE: Self = Self { + name: b"warn_unused_result", + // FIXME(emilio): clang-sys doesn't expose `CXCursor_WarnUnusedResultAttr` (from clang 9). + kind: 440, + token_kind: CXToken_Identifier, + }; + + pub const NO_RETURN: Self = Self { + name: b"_Noreturn", + kind: CXCursor_UnexposedAttr, + token_kind: CXToken_Keyword, + }; +} + /// A cursor into the Clang AST, pointing to an AST node. /// /// We call the AST node pointed to by the cursor the cursor's "referent". @@ -638,48 +659,38 @@ impl Cursor { } } - /// Whether this cursor has the `warn_unused_result` attribute. - pub fn has_warn_unused_result_attr(&self) -> bool { - // FIXME(emilio): clang-sys doesn't expose this (from clang 9). - const CXCursor_WarnUnusedResultAttr: CXCursorKind = 440; - self.has_attr( - "warn_unused_result", - Some(CXCursor_WarnUnusedResultAttr), - CXToken_Identifier, - ) - } - - /// Check wether this cursor has the `_Noreturn` attribute. - pub fn has_no_return_attr(&self) -> bool { - self.has_attr("_Noreturn", None, CXToken_Keyword) - } - - /// Does this cursor have the given attribute? - /// - /// `name` is checked against unexposed attributes. - fn has_attr( + pub fn has_attrs<const N: usize>( &self, - name: &str, - clang_kind: Option<CXCursorKind>, - token_kind: CXTokenKind, - ) -> bool { - let mut found_attr = false; + attrs: &[Attribute; N], + ) -> [bool; N] { + let mut found_attrs = [false; N]; + let mut found_count = 0; + self.visit(|cur| { let kind = cur.kind(); - found_attr = clang_kind.map_or(false, |k| k == kind) || - (kind == CXCursor_UnexposedAttr && - cur.tokens().iter().any(|t| { - t.kind == token_kind && t.spelling() == name.as_bytes() - })); - - if found_attr { - CXChildVisit_Break - } else { - CXChildVisit_Continue + for (idx, attr) in attrs.iter().enumerate() { + let found_attr = &mut found_attrs[idx]; + if !*found_attr { + if kind == attr.kind && + cur.tokens().iter().any(|t| { + t.kind == attr.token_kind && + t.spelling() == attr.name + }) + { + *found_attr = true; + found_count += 1; + + if found_count == N { + return CXChildVisit_Break; + } + } + } } + + CXChildVisit_Continue }); - found_attr + found_attrs } /// Given that this cursor's referent is a `typedef`, get the `Type` that is diff --git a/src/ir/function.rs b/src/ir/function.rs index b829e601..6ed3a503 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -6,7 +6,7 @@ use super::dot::DotAttributes; use super::item::Item; use super::traversal::{EdgeKind, Trace, Tracer}; use super::ty::TypeKind; -use crate::clang; +use crate::clang::{self, Attribute}; use crate::parse::{ ClangItemParser, ClangSubItemParser, ParseError, ParseResult, }; @@ -382,9 +382,6 @@ impl FunctionSig { use clang_sys::*; debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor); - let is_divergent = ctx.options().enable_function_attribute_detection && - cursor.has_no_return_attr(); - // Skip function templates let kind = cursor.kind(); if kind == CXCursor_FunctionTemplate { @@ -453,8 +450,13 @@ impl FunctionSig { } }; - let must_use = ctx.options().enable_function_attribute_detection && - cursor.has_warn_unused_result_attr(); + let [must_use, is_divergent] = + if ctx.options().enable_function_attribute_detection { + cursor.has_attrs(&[Attribute::MUST_USE, Attribute::NO_RETURN]) + } else { + Default::default() + }; + let is_method = kind == CXCursor_CXXMethod; let is_constructor = kind == CXCursor_Constructor; let is_destructor = kind == CXCursor_Destructor; |