 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
72.1% |
49 / 68 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
94.1% |
64 / 68 |
| |
|
Line Coverage: |
89.4% |
93 / 104 |
| |
 |
|
 |
1 : //===--- FrontendAction.cpp -----------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "clang/Frontend/FrontendAction.h"
11 : #include "clang/AST/ASTContext.h"
12 : #include "clang/Lex/HeaderSearch.h"
13 : #include "clang/Lex/Preprocessor.h"
14 : #include "clang/Frontend/ASTUnit.h"
15 : #include "clang/Frontend/CompilerInstance.h"
16 : #include "clang/Frontend/FrontendDiagnostic.h"
17 : #include "clang/Sema/ParseAST.h"
18 : #include "llvm/Support/MemoryBuffer.h"
19 : #include "llvm/Support/Timer.h"
20 : #include "llvm/Support/ErrorHandling.h"
21 : #include "llvm/Support/raw_ostream.h"
22 : using namespace clang;
23 :
24 2523: FrontendAction::FrontendAction() : Instance(0) {}
25 :
0: branch 2 not taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 12 not taken
2523: branch 13 taken
26 2523: FrontendAction::~FrontendAction() {}
27 :
28 5047: void FrontendAction::setCurrentFile(llvm::StringRef Value, ASTUnit *AST) {
29 5047: CurrentFile = Value;
30 5047: CurrentASTUnit.reset(AST);
31 5047: }
32 :
33 : bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
34 : llvm::StringRef Filename,
35 2522: bool IsAST) {
0: branch 0 not taken
2522: branch 1 taken
36 2522: assert(!Instance && "Already processing a source file!");
2522: branch 1 taken
0: branch 2 not taken
37 2522: assert(!Filename.empty() && "Unexpected empty filename!");
38 2522: setCurrentFile(Filename);
39 2522: setCompilerInstance(&CI);
40 :
41 : // AST files follow a very different path, since they share objects via the
42 : // AST unit.
2: branch 0 taken
2520: branch 1 taken
43 2522: if (IsAST) {
44 : assert(!usesPreprocessorOnly() &&
2: branch 1 taken
0: branch 2 not taken
45 2: "Attempt to pass AST file to preprocessor only action!");
2: branch 1 taken
0: branch 2 not taken
46 2: assert(hasASTSupport() && "This action does not have AST support!");
47 :
48 2: std::string Error;
49 2: ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, CI.getDiagnostics());
0: branch 0 not taken
2: branch 1 taken
50 2: if (!AST)
51 0: goto failure;
52 :
53 2: setCurrentFile(Filename, AST);
54 :
55 : // Set the shared objects, these are reset when we finish processing the
56 : // file, otherwise the CompilerInstance will happily destroy them.
57 2: CI.setFileManager(&AST->getFileManager());
58 2: CI.setSourceManager(&AST->getSourceManager());
59 2: CI.setPreprocessor(&AST->getPreprocessor());
60 2: CI.setASTContext(&AST->getASTContext());
61 :
62 : // Initialize the action.
0: branch 1 not taken
2: branch 2 taken
63 2: if (!BeginSourceFileAction(CI, Filename))
64 : goto failure;
65 :
66 : /// Create the AST consumer.
67 2: CI.setASTConsumer(CreateASTConsumer(CI, Filename));
0: branch 1 not taken
2: branch 2 taken
68 2: if (!CI.hasASTConsumer())
69 : goto failure;
70 :
0: branch 1 not taken
2: branch 2 taken
71 4: return true;
72 : }
73 :
74 : // Inform the diagnostic client we are processing a source file.
75 : CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
76 2520: &CI.getPreprocessor());
77 :
78 : // Initialize the action.
2520: branch 1 taken
0: branch 2 not taken
79 2520: if (!BeginSourceFileAction(CI, Filename))
80 0: goto failure;
81 :
82 : /// Create the AST context and consumer unless this is a preprocessor only
83 : /// action.
2237: branch 1 taken
283: branch 2 taken
84 2520: if (!usesPreprocessorOnly()) {
85 2237: CI.createASTContext();
86 2237: CI.setASTConsumer(CreateASTConsumer(CI, Filename));
1: branch 1 taken
2236: branch 2 taken
87 2237: if (!CI.hasASTConsumer())
88 1: goto failure;
89 :
90 : /// Use PCH?
35: branch 2 taken
2201: branch 3 taken
91 2236: if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
35: branch 1 taken
0: branch 2 not taken
92 35: assert(hasPCHSupport() && "This action does not have PCH support!");
93 : CI.createPCHExternalASTSource(
94 35: CI.getPreprocessorOpts().ImplicitPCHInclude);
2: branch 2 taken
33: branch 3 taken
95 35: if (!CI.getASTContext().getExternalSource())
96 2: goto failure;
97 : }
98 : }
99 :
100 : // Initialize builtin info as long as we aren't using an external AST
101 : // source.
2234: branch 1 taken
283: branch 2 taken
2201: branch 5 taken
33: branch 6 taken
2484: branch 7 taken
33: branch 8 taken
102 2517: if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
103 2484: Preprocessor &PP = CI.getPreprocessor();
104 : PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
105 2484: PP.getLangOptions().NoBuiltin);
106 : }
107 :
108 2517: return true;
109 :
110 : // If we failed, reset state since the client will not end up calling the
111 : // matching EndSourceFile().
112 3: failure:
0: branch 1 not taken
3: branch 2 taken
113 3: if (isCurrentFileAST()) {
114 0: CI.takeASTContext();
115 0: CI.takePreprocessor();
116 0: CI.takeSourceManager();
117 0: CI.takeFileManager();
118 : }
119 :
120 3: CI.getDiagnosticClient().EndSourceFile();
121 3: setCurrentFile("");
122 3: setCompilerInstance(0);
123 3: return false;
124 : }
125 :
126 2519: void FrontendAction::Execute() {
127 2519: CompilerInstance &CI = getCompilerInstance();
128 :
129 : // Initialize the main file entry. This needs to be delayed until after PCH
130 : // has loaded.
2: branch 1 taken
2517: branch 2 taken
131 2519: if (isCurrentFileAST()) {
132 : // Set the main file ID to an empty file.
133 : //
134 : // FIXME: We probably shouldn't need this, but for now this is the
135 : // simplest way to reuse the logic in ParseAST.
136 2: const char *EmptyStr = "";
137 : llvm::MemoryBuffer *SB =
138 2: llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
139 2: CI.getSourceManager().createMainFileIDForMemBuffer(SB);
140 : } else {
0: branch 3 not taken
2517: branch 4 taken
141 2517: if (!CI.InitializeSourceManager(getCurrentFile()))
142 0: return;
143 : }
144 :
0: branch 1 not taken
2519: branch 2 taken
145 2519: if (CI.hasFrontendTimer()) {
146 0: llvm::TimeRegion Timer(CI.getFrontendTimer());
147 0: ExecuteAction();
148 : }
149 2519: else ExecuteAction();
150 : }
151 :
152 2519: void FrontendAction::EndSourceFile() {
153 2519: CompilerInstance &CI = getCompilerInstance();
154 :
155 : // Finalize the action.
156 2519: EndSourceFileAction();
157 :
158 : // Release the consumer and the AST, in that order since the consumer may
159 : // perform actions in its destructor which require the context.
160 : //
161 : // FIXME: There is more per-file stuff we could just drop here?
152: branch 1 taken
2367: branch 2 taken
162 2519: if (CI.getFrontendOpts().DisableFree) {
163 152: CI.takeASTConsumer();
150: branch 1 taken
2: branch 2 taken
164 152: if (!isCurrentFileAST())
165 150: CI.takeASTContext();
166 : } else {
167 2367: CI.setASTConsumer(0);
2367: branch 1 taken
0: branch 2 not taken
168 2367: if (!isCurrentFileAST())
169 2367: CI.setASTContext(0);
170 : }
171 :
2: branch 1 taken
2517: branch 2 taken
172 2519: if (CI.getFrontendOpts().ShowStats) {
173 2: llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
174 2: CI.getPreprocessor().PrintStats();
175 2: CI.getPreprocessor().getIdentifierTable().PrintStats();
176 2: CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
177 2: CI.getSourceManager().PrintStats();
178 2: llvm::errs() << "\n";
179 : }
180 :
181 : // Cleanup the output streams, and erase the output files if we encountered
182 : // an error.
183 2519: CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors());
184 :
185 : // Inform the diagnostic client we are done with this source file.
186 2519: CI.getDiagnosticClient().EndSourceFile();
187 :
2: branch 1 taken
2517: branch 2 taken
188 2519: if (isCurrentFileAST()) {
189 2: CI.takeASTContext();
190 2: CI.takePreprocessor();
191 2: CI.takeSourceManager();
192 2: CI.takeFileManager();
193 : }
194 :
195 2519: setCompilerInstance(0);
196 2519: setCurrentFile("");
197 2519: }
198 :
199 : //===----------------------------------------------------------------------===//
200 : // Utility Actions
201 : //===----------------------------------------------------------------------===//
202 :
203 2236: void ASTFrontendAction::ExecuteAction() {
204 2236: CompilerInstance &CI = getCompilerInstance();
205 :
206 : // FIXME: Move the truncation aspect of this into Sema, we delayed this till
207 : // here so the source manager would be initialized.
1278: branch 1 taken
958: branch 2 taken
87: branch 5 taken
1191: branch 6 taken
87: branch 7 taken
2149: branch 8 taken
208 2236: if (hasCodeCompletionSupport() &&
209 : !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
210 87: CI.createCodeCompletionConsumer();
211 :
212 : // Use a code completion consumer?
213 2236: CodeCompleteConsumer *CompletionConsumer = 0;
87: branch 1 taken
2149: branch 2 taken
214 2236: if (CI.hasCodeCompletionConsumer())
215 87: CompletionConsumer = &CI.getCodeCompletionConsumer();
216 :
217 : ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(),
218 : CI.getFrontendOpts().ShowStats,
219 2236: usesCompleteTranslationUnit(), CompletionConsumer);
220 2236: }
221 :
222 : ASTConsumer *
223 : PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
224 0: llvm::StringRef InFile) {
225 0: llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
226 : }
Generated: 2010-02-10 01:31 by zcov