2020template <typename Producer> class H5TemplateCallback : public clang ::ast_matchers::MatchFinder::MatchCallback {
2121public :
2222
23- H5TemplateCallback (const std::string& path){
24- io.open ( path );
23+ H5TemplateCallback (const std::string& path) : path_(path) {
2524 producer.file_begin ();
2625 }
2726
2827 ~H5TemplateCallback (){
2928 producer.file_end ();
29+ io.open (path_);
3030 io << producer;
3131 io.close ();
3232 }
@@ -56,6 +56,18 @@ public :
5656 if ( tier == utils::tier::pod ){
5757 // --- tier 1: standard register_struct emission ---
5858 topological_order ( node );
59+ // collect header files for all records before emitting preamble
60+ if ( Result.Context ) {
61+ for ( const auto & item : store ) {
62+ if ( item.first == utils::type::record ) {
63+ auto rec = utils::as<const clang::CXXRecordDecl*>( item.second );
64+ std::string hdr = get_header_name (rec, Result.Context ->getSourceManager ());
65+ if ( !hdr.empty () )
66+ producer.add_include (hdr);
67+ }
68+ }
69+ }
70+
5971 producer.template_decl ( rn, doc, alias, version );
6072
6173 std::string var, type;
@@ -74,6 +86,11 @@ public :
7486 break ;
7587 case utils::type::record:
7688 re = utils::as<const clang::CXXRecordDecl*>( node.second );
89+ if ( Result.Context ) {
90+ std::string hdr = get_header_name (re, Result.Context ->getSourceManager ());
91+ if ( !hdr.empty () )
92+ producer.add_include (hdr);
93+ }
7794 var = producer.record_decl ( utils::type_name ( re ) );
7895 for (clang::FieldDecl* fld: re->fields () ){
7996 // Issue #32: skip fields annotated with [[h5::ignore]]
@@ -98,7 +115,7 @@ public :
98115 default :
99116 break ;
100117 }
101- store.pop ();
118+ store.pop_front ();
102119 }
103120 producer.type_release ();
104121 producer.return_type ( var );
@@ -150,6 +167,11 @@ public :
150167 compress_algo = compress_strs.empty () ? " gzip" : compress_strs[0 ];
151168 }
152169
170+ if (Result.Context ) {
171+ std::string hdr = get_header_name (node, Result.Context ->getSourceManager ());
172+ if (!hdr.empty ())
173+ producer.add_include (hdr);
174+ }
153175 producer.scatter_type (rn, fields, chunk_size, compress_algo, compress_level, doc, alias, version, on_missing);
154176 }
155177 }
@@ -160,7 +182,7 @@ public :
160182 topological_order ( utils::as<const clang::QualType>( fld ) );
161183 auto it = unique.insert ( node );
162184 if ( it.second )
163- store.push ( {utils::type::record, node} );
185+ store.push_back ( {utils::type::record, node} );
164186 }
165187
166188 void topological_order (const clang::QualType& qt){
@@ -173,7 +195,7 @@ public :
173195 topological_order ( ar->getElementType () );
174196 it = unique.insert ( ar );
175197 if ( it.second )
176- store.push ({utils::type::array, ar});
198+ store.push_back ({utils::type::array, ar});
177199 break ;
178200
179201 case utils::type::record:
@@ -184,8 +206,23 @@ public :
184206 }
185207 }
186208
209+ static std::string get_header_name (const clang::CXXRecordDecl* decl, const clang::SourceManager& sm){
210+ if ( !decl ) return " " ;
211+ clang::SourceLocation loc = decl->getLocation ();
212+ if ( !loc.isValid () ) return " " ;
213+ llvm::StringRef path = sm.getFilename (loc);
214+ if ( path.size () < 3 ) return " " ;
215+ if ( !(path.ends_with (" .h" ) || path.ends_with (" .hpp" ) || path.ends_with (" .hxx" ) || path.ends_with (" .hh" )) )
216+ return " " ;
217+ size_t pos = path.rfind (' /' );
218+ if ( pos == llvm::StringRef::npos )
219+ return path.str ();
220+ return path.substr (pos + 1 ).str ();
221+ }
222+
187223 std::ofstream io;
224+ std::string path_;
188225 Producer producer;
189226 std::set<const void *> unique, nodes;
190- std::queue <std::pair<utils::type, const void *>> store;
227+ std::deque <std::pair<utils::type, const void *>> store;
191228};
0 commit comments