Index: tools/clang/translation_unit/TranslationUnitGenerator.cpp |
diff --git a/tools/clang/translation_unit/TranslationUnitGenerator.cpp b/tools/clang/translation_unit/TranslationUnitGenerator.cpp |
index 5db8d640b74c5c6e5b6328c9ee7ab49e6f8cbe95..3590b0c4ea30d7a1719e1a16348e42b2397070e9 100644 |
--- a/tools/clang/translation_unit/TranslationUnitGenerator.cpp |
+++ b/tools/clang/translation_unit/TranslationUnitGenerator.cpp |
@@ -23,6 +23,7 @@ |
#include "clang/Basic/SourceManager.h" |
#include "clang/Frontend/CompilerInstance.h" |
#include "clang/Frontend/FrontendActions.h" |
+#include "clang/Lex/HeaderSearchOptions.h" |
#include "clang/Lex/PPCallbacks.h" |
#include "clang/Lex/Preprocessor.h" |
#include "clang/Tooling/CommonOptionsParser.h" |
@@ -31,6 +32,7 @@ |
#include "clang/Tooling/Tooling.h" |
#include "llvm/Support/CommandLine.h" |
+using clang::HeaderSearchOptions; |
using clang::tooling::CommonOptionsParser; |
using std::set; |
using std::stack; |
@@ -43,10 +45,8 @@ class IncludeFinderPPCallbacks : public clang::PPCallbacks { |
public: |
IncludeFinderPPCallbacks(clang::SourceManager* source_manager, |
string* main_source_file, |
- set<string>* source_file_paths) |
- : source_manager_(source_manager), |
- main_source_file_(main_source_file), |
- source_file_paths_(source_file_paths) {} |
+ set<string>* source_file_paths, |
+ const HeaderSearchOptions* header_search_options); |
void FileChanged(clang::SourceLocation /*loc*/, |
clang::PPCallbacks::FileChangeReason reason, |
clang::SrcMgr::CharacteristicKind /*file_type*/, |
@@ -64,9 +64,13 @@ class IncludeFinderPPCallbacks : public clang::PPCallbacks { |
void EndOfMainFile() override; |
private: |
+ string DoubleSlashSystemHeaders(const string& search_path, |
+ const string& relative_path) const; |
+ |
clang::SourceManager* const source_manager_; |
string* const main_source_file_; |
set<string>* const source_file_paths_; |
+ set<string> system_header_prefixes_; |
// The path of the file that was last referenced by an inclusion directive, |
// normalized for includes that are relative to a different source file. |
string last_inclusion_directive_; |
@@ -74,6 +78,39 @@ class IncludeFinderPPCallbacks : public clang::PPCallbacks { |
stack<string> current_files_; |
}; |
+IncludeFinderPPCallbacks::IncludeFinderPPCallbacks( |
+ clang::SourceManager* source_manager, |
+ string* main_source_file, |
+ set<string>* source_file_paths, |
+ const HeaderSearchOptions* header_search_options) |
+ : source_manager_(source_manager), |
+ main_source_file_(main_source_file), |
+ source_file_paths_(source_file_paths) { |
+ // In practice this list seems to be empty, but add it anyway just in case. |
+ for (const auto& prefix : header_search_options->SystemHeaderPrefixes) { |
+ system_header_prefixes_.insert(prefix.Prefix); |
+ } |
+ |
+ // This list contains all the include directories of different type. We add |
+ // all system headers to the set - excluding the Quoted and Angled groups |
+ // which are from -iquote and -I flags. |
+ for (const auto& entry : header_search_options->UserEntries) { |
+ switch (entry.Group) { |
+ case clang::frontend::System: |
+ case clang::frontend::ExternCSystem: |
+ case clang::frontend::CSystem: |
+ case clang::frontend::CXXSystem: |
+ case clang::frontend::ObjCSystem: |
+ case clang::frontend::ObjCXXSystem: |
+ case clang::frontend::After: |
+ system_header_prefixes_.insert(entry.Path); |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+} |
+ |
void IncludeFinderPPCallbacks::FileChanged( |
clang::SourceLocation /*loc*/, |
clang::PPCallbacks::FileChangeReason reason, |
@@ -135,21 +172,30 @@ void IncludeFinderPPCallbacks::InclusionDirective( |
// Otherwise we take the literal path as we stored it for the current |
// file, and append the relative path. |
- last_inclusion_directive_ = parent + "/" + relative_path.str(); |
+ last_inclusion_directive_ = |
+ DoubleSlashSystemHeaders(parent, relative_path.str()); |
} else if (!search_path.empty()) { |
- // We want to be able to extract the search path relative to which the |
- // include statement is defined. Therefore if search_path is an absolute |
- // path (indicating it is most likely a system header) we use "//" as a |
- // separator between the search path and the relative path. |
- last_inclusion_directive_ = search_path.str() + |
- (llvm::sys::path::is_absolute(search_path) ? "//" : "/") + |
- relative_path.str(); |
+ last_inclusion_directive_ = |
+ DoubleSlashSystemHeaders(search_path.str(), relative_path.str()); |
} else { |
last_inclusion_directive_ = file_name.str(); |
} |
AddFile(last_inclusion_directive_); |
} |
+string IncludeFinderPPCallbacks::DoubleSlashSystemHeaders( |
+ const string& search_path, |
+ const string& relative_path) const { |
+ // We want to be able to extract the search path relative to which the |
+ // include statement is defined. Therefore if search_path is a system header |
+ // we use "//" as a separator between the search path and the relative path. |
+ const bool is_system_header = |
+ system_header_prefixes_.find(search_path) != |
+ system_header_prefixes_.end(); |
+ |
+ return search_path + (is_system_header ? "//" : "/") + relative_path; |
+} |
+ |
void IncludeFinderPPCallbacks::EndOfMainFile() { |
const clang::FileEntry* main_file = |
source_manager_->getFileEntryForID(source_manager_->getMainFileID()); |
@@ -190,7 +236,8 @@ void CompilationIndexerAction::Preprocess() { |
preprocessor.addPPCallbacks(llvm::make_unique<IncludeFinderPPCallbacks>( |
&getCompilerInstance().getSourceManager(), |
&main_source_file_, |
- &source_file_paths_)); |
+ &source_file_paths_, |
+ &getCompilerInstance().getHeaderSearchOpts())); |
preprocessor.getDiagnostics().setIgnoreAllWarnings(true); |
preprocessor.SetSuppressIncludeNotFoundError(true); |
preprocessor.EnterMainSourceFile(); |
@@ -202,7 +249,7 @@ void CompilationIndexerAction::Preprocess() { |
void CompilationIndexerAction::EndSourceFileAction() { |
std::ofstream out(main_source_file_ + ".filepaths"); |
- for (string path : source_file_paths_) { |
+ for (const string& path : source_file_paths_) { |
dcheng
2016/02/03 05:18:33
Oops.
|
out << path << std::endl; |
} |
} |