[cfe-dev] Obtaining translation unit file names from plugins

Tom Honermann thonermann at coverity.com
Tue Jul 10 07:39:38 PDT 2012


On 7/10/2012 9:30 AM, Florian Weimer wrote:
> I've got a PluginASTAction which runs and produces some extra
> diagnostics which are stored in an SQLite database, together with file
> identification information.  If the user changes the file in such a way
> that the plugin does not report any diagnostics, the reporting tool
> cannot tell this scenario from the case where the plugin has not run at
> all on the changed file.  So I would like to gather all file names which
> contribute to the translation unit and mark them as processed in the
> database.  I could transverse the entire AST to collect all file names,
> but surely there is a simpler way to do it?

Assuming you care only about the source files that are directly read by 
Clang when compiling the TU and not files referenced by preprocessing 
line control directives, a loop like the following will work:

     const clang::SourceManager &source_manager = ...
     clang::SourceManager::fileinfo_iterator fi_iter;
     for (fi_iter = source_manager.fileinfo_begin();
          fi_iter != source_manager.fileinfo_end();
          ++fi_iter)
     {
         const clang::SrcMgr::ContentCache *content_cache = fi_iter->second;
         const clang::FileEntry *file_entry =
             content_cache->ContentsEntry;
         if (!file_entry)
             file_entry = content_cache->OrigEntry;
         if (!file_entry)
             continue;
         const char *file_name = file_entry->getName();
         // Do something with file_name and/or file_entry
     }

If you are loading a .ast file (typically a pre-compiled header), then 
add the following loops before the loop above.  This is necessary to 
coerce the source manager into fully populating its FileInfos map. 
Without this, only a subset of all source files contributing to the TU 
will be enumerated.

     for (unsigned i = 0; i < source_manager.local_sloc_entry_size(); ++i) {
         source_manager.getLocalSLocEntry(i);
     }
     for (unsigned i = 0; i < source_manager.loaded_sloc_entry_size(); 
++i) {
         source_manager.getLoadedSLocEntry(i);
     }

Tom.




More information about the cfe-dev mailing list