From 731cb2cf52bf1b577c1d3533f93c2f64e96b402c Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 12 Dec 2023 00:05:13 -0500 Subject: [PATCH 1/3] Fix docs for the sus_class_never_value_field macro The way it works has changed since they were written. --- sus/mem/never_value.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sus/mem/never_value.h b/sus/mem/never_value.h index 564700406..80611584f 100644 --- a/sus/mem/never_value.h +++ b/sus/mem/never_value.h @@ -19,12 +19,12 @@ #include #include +#include "sus/cmp/eq.h" #include "sus/macros/inline.h" #include "sus/macros/pure.h" #include "sus/marker/unsafe.h" #include "sus/mem/forward.h" #include "sus/mem/relocate.h" -#include "sus/cmp/eq.h" namespace sus::mem { @@ -105,7 +105,9 @@ struct NeverValueAccess { t_._sus_Unsafe_NeverValueSetDestroyValue(::sus::marker::unsafe_fn); } - _sus_pure constexpr _sus_always_inline const T& as_inner() const { return t_; } + _sus_pure constexpr _sus_always_inline const T& as_inner() const { + return t_; + } _sus_pure constexpr _sus_always_inline T& as_inner_mut() { return t_; } private: @@ -138,11 +140,11 @@ concept NeverValueField = __private::NeverValueChecker::has_field; /// querying if a class is constructed in a memory location, since the class is /// constructed iff the value of the field is not the never-value. /// -/// The `never_value` will be placed in the named field after construction, and -/// the `destroy_value` will be placed in the named field just prior to -/// destruction. The latter is meant to help the destructor be a no-op when the -/// type is in a never-value state, if the never-value would be read in the -/// destructor. +/// The named field can be compared to the `never_value` to determine if the +/// object is constructed. The field must be set to the `destroy_value` just +/// prior to destruction. The latter is meant to help the destructor be a no-op +/// when the type is in a never-value state, if the never-value would be read in +/// the destructor. /// /// The macro includes `private:` which changes the class definition visibility /// to private. @@ -157,7 +159,7 @@ concept NeverValueField = __private::NeverValueChecker::has_field; template \ friend struct ::sus::mem::__private::NeverValueChecker; \ \ - _sus_pure constexpr bool _sus_Unsafe_NeverValueIsConstructed( \ + _sus_pure constexpr bool _sus_Unsafe_NeverValueIsConstructed( \ ::sus::marker::UnsafeFnMarker) const noexcept { \ static_assert( \ std::is_assignable_v, \ From ab8935ecda5a80e1c24c57614144358c5a886665 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 12 Dec 2023 00:05:51 -0500 Subject: [PATCH 2/3] Hide the _sus_eval_and_concat from docs, it's not public API --- sus/iter/iterator_ref.h | 11 +++++---- sus/macros/eval_and_concat.h | 2 +- sus/num/__private/float_consts.inc | 38 +++++++++++++++--------------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/sus/iter/iterator_ref.h b/sus/iter/iterator_ref.h index 568cebc81..ebb7527b5 100644 --- a/sus/iter/iterator_ref.h +++ b/sus/iter/iterator_ref.h @@ -19,16 +19,15 @@ #include "sus/mem/replace.h" #include "sus/num/unsigned_integer.h" -#if !defined(SUS_ITERATOR_INVALIDATION) -#define SUS_ITERATOR_INVALIDATION 1 -#endif +#if defined(SUS_ITERATOR_INVALIDATION) static_assert(SUS_ITERATOR_INVALIDATION == 0 || SUS_ITERATOR_INVALIDATION == 1); +#endif namespace sus::iter { struct IterRefCounter; -#if SUS_ITERATOR_INVALIDATION +#if !defined(SUS_ITERATOR_INVALIDATION) || SUS_ITERATOR_INVALIDATION /// An iterator's refcount on the owning collection, preventig mutation while /// the iterator is alive. @@ -131,7 +130,9 @@ struct [[_sus_trivial_abi]] IterRefCounter final { union { /// The `count` member is active in owning collections like `Vec`. - mutable usize count; // TODO: should be uptr. + // TODO: This needs to be atomic: a container can be iterated on multiple + // threads. + mutable usize count; /// The `count_ptr` member is active in view collections like `Slice`. It /// points to he owning collection. The presence of a `count_ptr` must also /// indicate an increment in the `count` it points to, lest the `count_ptr` diff --git a/sus/macros/eval_and_concat.h b/sus/macros/eval_and_concat.h index 3c796a5bd..cd9ba65d7 100644 --- a/sus/macros/eval_and_concat.h +++ b/sus/macros/eval_and_concat.h @@ -17,6 +17,6 @@ /// Evaluates and concatenates two macro expressions. /// /// `x##y` will concatenate without evaluating. -#define sus_eval_and_concat(x, y) _sus__eval_and_concat_impl(x, y) +#define _sus_eval_and_concat(x, y) _sus__eval_and_concat_impl(x, y) #define _sus__eval_and_concat_impl(x, y) x##y diff --git a/sus/num/__private/float_consts.inc b/sus/num/__private/float_consts.inc index 7b52d93cf..e9307f16d 100644 --- a/sus/num/__private/float_consts.inc +++ b/sus/num/__private/float_consts.inc @@ -52,43 +52,43 @@ inline constexpr _self _self::NEG_INFINITY = _self(__private::negative_infinity<_primitive>()); inline constexpr _self _self::consts::E = - _self(sus_eval_and_concat(2.718281828459045235360287471352662, _suffix)); + _self(_sus_eval_and_concat(2.718281828459045235360287471352662, _suffix)); inline constexpr _self _self::consts::FRAC_1_PI = - _self(sus_eval_and_concat(0.318309886183790671537767526745028, _suffix)); + _self(_sus_eval_and_concat(0.318309886183790671537767526745028, _suffix)); inline constexpr _self _self::consts::FRAC_1_SQRT_2 = - _self(sus_eval_and_concat(0.7071067811865476, _suffix)); + _self(_sus_eval_and_concat(0.7071067811865476, _suffix)); inline constexpr _self _self::consts::FRAC_2_PI = - _self(sus_eval_and_concat(0.6366197723675814, _suffix)); + _self(_sus_eval_and_concat(0.6366197723675814, _suffix)); inline constexpr _self _self::consts::FRAC_2_SQRT_PI = - _self(sus_eval_and_concat(1.1283791670955126, _suffix)); + _self(_sus_eval_and_concat(1.1283791670955126, _suffix)); inline constexpr _self _self::consts::FRAC_PI_2 = - _self(sus_eval_and_concat(1.5707963267948966, _suffix)); + _self(_sus_eval_and_concat(1.5707963267948966, _suffix)); inline constexpr _self _self::consts::FRAC_PI_3 = - _self(sus_eval_and_concat(1.0471975511965979, _suffix)); + _self(_sus_eval_and_concat(1.0471975511965979, _suffix)); inline constexpr _self _self::consts::FRAC_PI_4 = - _self(sus_eval_and_concat(0.7853981633974483, _suffix)); + _self(_sus_eval_and_concat(0.7853981633974483, _suffix)); inline constexpr _self _self::consts::FRAC_PI_6 = - _self(sus_eval_and_concat(0.5235987755982989, _suffix)); + _self(_sus_eval_and_concat(0.5235987755982989, _suffix)); inline constexpr _self _self::consts::FRAC_PI_8 = - _self(sus_eval_and_concat(0.39269908169872414, _suffix)); + _self(_sus_eval_and_concat(0.39269908169872414, _suffix)); inline constexpr _self _self::consts::LN_2 = - _self(sus_eval_and_concat(0.693147180559945309417232121458176, _suffix)); + _self(_sus_eval_and_concat(0.693147180559945309417232121458176, _suffix)); inline constexpr _self _self::consts::LN_10 = - _self(sus_eval_and_concat(2.302585092994045684017991454684364, _suffix)); + _self(_sus_eval_and_concat(2.302585092994045684017991454684364, _suffix)); inline constexpr _self _self::consts::LOG2_10 = - _self(sus_eval_and_concat(3.321928094887362, _suffix)); + _self(_sus_eval_and_concat(3.321928094887362, _suffix)); inline constexpr _self _self::consts::LOG2_E = - _self(sus_eval_and_concat(1.4426950408889634, _suffix)); + _self(_sus_eval_and_concat(1.4426950408889634, _suffix)); inline constexpr _self _self::consts::LOG10_2 = - _self(sus_eval_and_concat(0.3010299956639812, _suffix)); + _self(_sus_eval_and_concat(0.3010299956639812, _suffix)); inline constexpr _self _self::consts::LOG10_E = - _self(sus_eval_and_concat(0.4342944819032518, _suffix)); + _self(_sus_eval_and_concat(0.4342944819032518, _suffix)); inline constexpr _self _self::consts::PI = - _self(sus_eval_and_concat(3.141592653589793238462643383279502, _suffix)); + _self(_sus_eval_and_concat(3.141592653589793238462643383279502, _suffix)); inline constexpr _self _self::consts::SQRT_2 = - _self(sus_eval_and_concat(1.414213562373095048801688724209698, _suffix)); + _self(_sus_eval_and_concat(1.414213562373095048801688724209698, _suffix)); inline constexpr _self _self::consts::TAU = - _self(sus_eval_and_concat(6.283185307179586, _suffix)); + _self(_sus_eval_and_concat(6.283185307179586, _suffix)); #undef sus__literal From 85cb8c17c86137a44786ac8597aab32baeae30f2 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 12 Dec 2023 00:06:09 -0500 Subject: [PATCH 3/3] Include macros without comments in the generated docs --- subdoc/lib/visit.cc | 82 +++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/subdoc/lib/visit.cc b/subdoc/lib/visit.cc index cd746f55e..e2e4636be 100644 --- a/subdoc/lib/visit.cc +++ b/subdoc/lib/visit.cc @@ -208,50 +208,52 @@ class Visitor : public clang::RecursiveASTVisitor { const std::map* comments_in_file = ast_comments.getCommentsInFile(file); if (comments_in_file == nullptr) continue; - if (comments_in_file->empty()) continue; const u32 macro_start = decomposed_loc.second; - if (macro_start == 0u) continue; // Find the nearest comment above the macro definition. - auto it = comments_in_file->lower_bound(macro_start); - if (it == comments_in_file->begin()) { - continue; - } - --it; - clang::RawComment* raw_comment = it->second; - - // The comment should be docs and be above the macro. - if (!raw_comment->isDocumentation()) continue; - if (raw_comment->isTrailingComment()) continue; - - // Now we know the offset into the file for the end of the macro and the - // start of the comment. - const u32 comment_end = ast_comments.getCommentEndOffset(raw_comment); - - // Make sure the comment is actually against the macro. Read the - // original buffer. - bool invalid = false; - const char* buffer = sm.getBufferData(file, &invalid).data(); - if (invalid) continue; - llvm::StringRef between(buffer + comment_end, macro_start - comment_end); - - // Drop the #define for this macro. - while (between.endswith(" ")) - between = between.substr(0u, between.size() - 1u); - if (between.endswith("define")) - between = between.substr(0u, between.size() - strlen("define")); - while (between.endswith(" ")) - between = between.substr(0u, between.size() - 1u); - if (between.endswith("#")) - between = between.substr(0u, between.size() - strlen("#")); - - // There should be no other declarations or macros between the comment and - // this macro. This pattern is copied from - // clang::ASTContext::getRawCommentForDeclNoCacheImpl(). - if (between.find_last_of(";{}#@") != llvm::StringRef::npos) { - continue; - } + clang::RawComment* raw_comment = [&]() -> clang::RawComment* { + if (comments_in_file->empty()) return nullptr; + + auto it = comments_in_file->lower_bound(macro_start); + if (it == comments_in_file->begin()) return nullptr; + --it; + clang::RawComment* raw_comment = it->second; + + // The comment should be docs and be above the macro. + if (!raw_comment->isDocumentation()) return nullptr; + if (raw_comment->isTrailingComment()) return nullptr; + + // Now we know the offset into the file for the end of the macro and the + // start of the comment. + const u32 comment_end = ast_comments.getCommentEndOffset(raw_comment); + + // Make sure the comment is actually against the macro. Read the + // original buffer. + bool invalid = false; + const char* buffer = sm.getBufferData(file, &invalid).data(); + if (invalid) return nullptr; + llvm::StringRef between(buffer + comment_end, + macro_start - comment_end); + + // Drop the #define for this macro. + while (between.endswith(" ")) + between = between.substr(0u, between.size() - 1u); + if (between.endswith("define")) + between = between.substr(0u, between.size() - strlen("define")); + while (between.endswith(" ")) + between = between.substr(0u, between.size() - 1u); + if (between.endswith("#")) + between = between.substr(0u, between.size() - strlen("#")); + + // There should be no other declarations or macros between the comment and + // this macro. This pattern is copied from + // clang::ASTContext::getRawCommentForDeclNoCacheImpl(). + if (between.find_last_of(";{}#@") != llvm::StringRef::npos) { + return nullptr; + } + return raw_comment; + }(); auto params = sus::Option>(); if (info->isFunctionLike()) {