OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This implements a Clang tool to generate compilation information that is | 5 // This implements a Clang tool to generate compilation information that is |
6 // sufficient to recompile the code with clang. For each compilation unit, all | 6 // sufficient to recompile the code with clang. For each compilation unit, all |
7 // source files which are necessary for compiling it are determined. For each | 7 // source files which are necessary for compiling it are determined. For each |
8 // compilation unit, a file is created containing a list of all file paths of | 8 // compilation unit, a file is created containing a list of all file paths of |
9 // included files. | 9 // included files. |
10 | 10 |
11 #include <assert.h> | 11 #include <assert.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 #include <fstream> | 13 #include <fstream> |
14 #include <iostream> | 14 #include <iostream> |
15 #include <memory> | 15 #include <memory> |
16 #include <set> | 16 #include <set> |
17 #include <stack> | 17 #include <stack> |
18 #include <string> | 18 #include <string> |
19 #include <vector> | 19 #include <vector> |
20 | 20 |
| 21 #include "clang/Basic/Diagnostic.h" |
21 #include "clang/Basic/FileManager.h" | 22 #include "clang/Basic/FileManager.h" |
22 #include "clang/Basic/SourceManager.h" | 23 #include "clang/Basic/SourceManager.h" |
23 #include "clang/Frontend/CompilerInstance.h" | 24 #include "clang/Frontend/CompilerInstance.h" |
24 #include "clang/Frontend/FrontendActions.h" | 25 #include "clang/Frontend/FrontendActions.h" |
25 #include "clang/Lex/PPCallbacks.h" | 26 #include "clang/Lex/PPCallbacks.h" |
26 #include "clang/Lex/Preprocessor.h" | 27 #include "clang/Lex/Preprocessor.h" |
27 #include "clang/Tooling/CommonOptionsParser.h" | 28 #include "clang/Tooling/CommonOptionsParser.h" |
28 #include "clang/Tooling/CompilationDatabase.h" | 29 #include "clang/Tooling/CompilationDatabase.h" |
29 #include "clang/Tooling/Refactoring.h" | 30 #include "clang/Tooling/Refactoring.h" |
30 #include "clang/Tooling/Tooling.h" | 31 #include "clang/Tooling/Tooling.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 130 |
130 // If the file is a top level file ("file.cc"), we normalize to a path | 131 // If the file is a top level file ("file.cc"), we normalize to a path |
131 // relative to "./". | 132 // relative to "./". |
132 if (parent.empty() || parent == "/") | 133 if (parent.empty() || parent == "/") |
133 parent = "."; | 134 parent = "."; |
134 | 135 |
135 // Otherwise we take the literal path as we stored it for the current | 136 // Otherwise we take the literal path as we stored it for the current |
136 // file, and append the relative path. | 137 // file, and append the relative path. |
137 last_inclusion_directive_ = parent + "/" + relative_path.str(); | 138 last_inclusion_directive_ = parent + "/" + relative_path.str(); |
138 } else if (!search_path.empty()) { | 139 } else if (!search_path.empty()) { |
139 last_inclusion_directive_ = string(search_path) + "/" + relative_path.str(); | 140 // We want to be able to extract the search path relative to which the |
| 141 // include statement is defined. Therefore if search_path is an absolute |
| 142 // path (indicating it is most likely a system header) we use "//" as a |
| 143 // separator between the search path and the relative path. |
| 144 last_inclusion_directive_ = search_path.str() + |
| 145 (llvm::sys::path::is_absolute(search_path) ? "//" : "/") + |
| 146 relative_path.str(); |
140 } else { | 147 } else { |
141 last_inclusion_directive_ = file_name.str(); | 148 last_inclusion_directive_ = file_name.str(); |
142 } | 149 } |
143 AddFile(last_inclusion_directive_); | 150 AddFile(last_inclusion_directive_); |
144 } | 151 } |
145 | 152 |
146 void IncludeFinderPPCallbacks::EndOfMainFile() { | 153 void IncludeFinderPPCallbacks::EndOfMainFile() { |
147 const clang::FileEntry* main_file = | 154 const clang::FileEntry* main_file = |
148 source_manager_->getFileEntryForID(source_manager_->getMainFileID()); | 155 source_manager_->getFileEntryForID(source_manager_->getMainFileID()); |
149 assert(*main_source_file_ == main_file->getName()); | 156 assert(*main_source_file_ == main_file->getName()); |
(...skipping 27 matching lines...) Expand all Loading... |
177 | 184 |
178 Preprocess(); | 185 Preprocess(); |
179 } | 186 } |
180 | 187 |
181 void CompilationIndexerAction::Preprocess() { | 188 void CompilationIndexerAction::Preprocess() { |
182 clang::Preprocessor& preprocessor = getCompilerInstance().getPreprocessor(); | 189 clang::Preprocessor& preprocessor = getCompilerInstance().getPreprocessor(); |
183 preprocessor.addPPCallbacks(llvm::make_unique<IncludeFinderPPCallbacks>( | 190 preprocessor.addPPCallbacks(llvm::make_unique<IncludeFinderPPCallbacks>( |
184 &getCompilerInstance().getSourceManager(), | 191 &getCompilerInstance().getSourceManager(), |
185 &main_source_file_, | 192 &main_source_file_, |
186 &source_file_paths_)); | 193 &source_file_paths_)); |
187 preprocessor.IgnorePragmas(); | 194 preprocessor.getDiagnostics().setIgnoreAllWarnings(true); |
188 preprocessor.SetSuppressIncludeNotFoundError(true); | 195 preprocessor.SetSuppressIncludeNotFoundError(true); |
189 preprocessor.EnterMainSourceFile(); | 196 preprocessor.EnterMainSourceFile(); |
190 clang::Token token; | 197 clang::Token token; |
191 do { | 198 do { |
192 preprocessor.Lex(token); | 199 preprocessor.Lex(token); |
193 } while (token.isNot(clang::tok::eof)); | 200 } while (token.isNot(clang::tok::eof)); |
194 } | 201 } |
195 | 202 |
196 void CompilationIndexerAction::EndSourceFileAction() { | 203 void CompilationIndexerAction::EndSourceFileAction() { |
197 std::ofstream out(main_source_file_ + ".filepaths"); | 204 std::ofstream out(main_source_file_ + ".filepaths"); |
(...skipping 11 matching lines...) Expand all Loading... |
209 std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory = | 216 std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory = |
210 clang::tooling::newFrontendActionFactory<CompilationIndexerAction>(); | 217 clang::tooling::newFrontendActionFactory<CompilationIndexerAction>(); |
211 clang::tooling::ClangTool tool(options.getCompilations(), | 218 clang::tooling::ClangTool tool(options.getCompilations(), |
212 options.getSourcePathList()); | 219 options.getSourcePathList()); |
213 // This clang tool does not actually produce edits, but run_tool.py expects | 220 // This clang tool does not actually produce edits, but run_tool.py expects |
214 // this. So we just print an empty edit block. | 221 // this. So we just print an empty edit block. |
215 llvm::outs() << "==== BEGIN EDITS ====\n"; | 222 llvm::outs() << "==== BEGIN EDITS ====\n"; |
216 llvm::outs() << "==== END EDITS ====\n"; | 223 llvm::outs() << "==== END EDITS ====\n"; |
217 return tool.run(frontend_factory.get()); | 224 return tool.run(frontend_factory.get()); |
218 } | 225 } |
OLD | NEW |