Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Parse/ParseAST.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | c4bab56944e8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file implements the clang::ParseAST method. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #include "clang/Parse/ParseAST.h" | |
14 #include "clang/AST/ASTConsumer.h" | |
15 #include "clang/AST/ASTContext.h" | |
16 #include "clang/AST/ExternalASTSource.h" | |
17 #include "clang/AST/Stmt.h" | |
18 #include "clang/Parse/ParseDiagnostic.h" | |
19 #include "clang/Parse/Parser.h" | |
20 #include "clang/Sema/CodeCompleteConsumer.h" | |
21 #include "clang/Sema/Sema.h" | |
22 #include "clang/Sema/SemaConsumer.h" | |
23 #include "clang/Sema/TemplateInstCallback.h" | |
24 #include "llvm/Support/CrashRecoveryContext.h" | |
25 #include "llvm/Support/TimeProfiler.h" | |
26 #include <cstdio> | |
27 #include <memory> | |
28 | |
29 using namespace clang; | |
30 | |
31 namespace { | |
32 | |
33 /// Resets LLVM's pretty stack state so that stack traces are printed correctly | |
34 /// when there are nested CrashRecoveryContexts and the inner one recovers from | |
35 /// a crash. | |
36 class ResetStackCleanup | |
37 : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, | |
38 const void> { | |
39 public: | |
40 ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top) | |
41 : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>( | |
42 Context, Top) {} | |
43 void recoverResources() override { | |
44 llvm::RestorePrettyStackState(resource); | |
45 } | |
46 }; | |
47 | |
48 /// If a crash happens while the parser is active, an entry is printed for it. | |
49 class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { | |
50 const Parser &P; | |
51 public: | |
52 PrettyStackTraceParserEntry(const Parser &p) : P(p) {} | |
53 void print(raw_ostream &OS) const override; | |
54 }; | |
55 | |
56 /// If a crash happens while the parser is active, print out a line indicating | |
57 /// what the current token is. | |
58 void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { | |
59 const Token &Tok = P.getCurToken(); | |
60 if (Tok.is(tok::eof)) { | |
61 OS << "<eof> parser at end of file\n"; | |
62 return; | |
63 } | |
64 | |
65 if (Tok.getLocation().isInvalid()) { | |
66 OS << "<unknown> parser at unknown location\n"; | |
67 return; | |
68 } | |
69 | |
70 const Preprocessor &PP = P.getPreprocessor(); | |
71 Tok.getLocation().print(OS, PP.getSourceManager()); | |
72 if (Tok.isAnnotation()) { | |
73 OS << ": at annotation token\n"; | |
74 } else { | |
75 // Do the equivalent of PP.getSpelling(Tok) except for the parts that would | |
76 // allocate memory. | |
77 bool Invalid = false; | |
78 const SourceManager &SM = P.getPreprocessor().getSourceManager(); | |
79 unsigned Length = Tok.getLength(); | |
80 const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); | |
81 if (Invalid) { | |
82 OS << ": unknown current parser token\n"; | |
83 return; | |
84 } | |
85 OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; | |
86 } | |
87 } | |
88 | |
89 } // namespace | |
90 | |
91 //===----------------------------------------------------------------------===// | |
92 // Public interface to the file | |
93 //===----------------------------------------------------------------------===// | |
94 | |
95 /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as | |
96 /// the file is parsed. This inserts the parsed decls into the translation unit | |
97 /// held by Ctx. | |
98 /// | |
99 void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, | |
100 ASTContext &Ctx, bool PrintStats, | |
101 TranslationUnitKind TUKind, | |
102 CodeCompleteConsumer *CompletionConsumer, | |
103 bool SkipFunctionBodies) { | |
104 | |
105 std::unique_ptr<Sema> S( | |
106 new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); | |
107 | |
108 // Recover resources if we crash before exiting this method. | |
109 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); | |
110 | |
111 ParseAST(*S.get(), PrintStats, SkipFunctionBodies); | |
112 } | |
113 | |
114 void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { | |
115 // Collect global stats on Decls/Stmts (until we have a module streamer). | |
116 if (PrintStats) { | |
117 Decl::EnableStatistics(); | |
118 Stmt::EnableStatistics(); | |
119 } | |
120 | |
121 // Also turn on collection of stats inside of the Sema object. | |
122 bool OldCollectStats = PrintStats; | |
123 std::swap(OldCollectStats, S.CollectStats); | |
124 | |
125 // Initialize the template instantiation observer chain. | |
126 // FIXME: See note on "finalize" below. | |
127 initialize(S.TemplateInstCallbacks, S); | |
128 | |
129 ASTConsumer *Consumer = &S.getASTConsumer(); | |
130 | |
131 std::unique_ptr<Parser> ParseOP( | |
132 new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); | |
133 Parser &P = *ParseOP.get(); | |
134 | |
135 llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> | |
136 CleanupPrettyStack(llvm::SavePrettyStackState()); | |
137 PrettyStackTraceParserEntry CrashInfo(P); | |
138 | |
139 // Recover resources if we crash before exiting this method. | |
140 llvm::CrashRecoveryContextCleanupRegistrar<Parser> | |
141 CleanupParser(ParseOP.get()); | |
142 | |
143 S.getPreprocessor().EnterMainSourceFile(); | |
144 ExternalASTSource *External = S.getASTContext().getExternalSource(); | |
145 if (External) | |
146 External->StartTranslationUnit(Consumer); | |
147 | |
148 // If a PCH through header is specified that does not have an include in | |
149 // the source, or a PCH is being created with #pragma hdrstop with nothing | |
150 // after the pragma, there won't be any tokens or a Lexer. | |
151 bool HaveLexer = S.getPreprocessor().getCurrentLexer(); | |
152 | |
153 if (HaveLexer) { | |
154 llvm::TimeTraceScope TimeScope("Frontend"); | |
155 P.Initialize(); | |
156 Parser::DeclGroupPtrTy ADecl; | |
157 for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; | |
158 AtEOF = P.ParseTopLevelDecl(ADecl)) { | |
159 // If we got a null return and something *was* parsed, ignore it. This | |
160 // is due to a top-level semicolon, an action override, or a parse error | |
161 // skipping something. | |
162 if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) | |
163 return; | |
164 } | |
165 } | |
166 | |
167 // Process any TopLevelDecls generated by #pragma weak. | |
168 for (Decl *D : S.WeakTopLevelDecls()) | |
169 Consumer->HandleTopLevelDecl(DeclGroupRef(D)); | |
170 | |
171 Consumer->HandleTranslationUnit(S.getASTContext()); | |
172 | |
173 // Finalize the template instantiation observer chain. | |
174 // FIXME: This (and init.) should be done in the Sema class, but because | |
175 // Sema does not have a reliable "Finalize" function (it has a | |
176 // destructor, but it is not guaranteed to be called ("-disable-free")). | |
177 // So, do the initialization above and do the finalization here: | |
178 finalize(S.TemplateInstCallbacks, S); | |
179 | |
180 std::swap(OldCollectStats, S.CollectStats); | |
181 if (PrintStats) { | |
182 llvm::errs() << "\nSTATISTICS:\n"; | |
183 if (HaveLexer) P.getActions().PrintStats(); | |
184 S.getASTContext().PrintStats(); | |
185 Decl::PrintStats(); | |
186 Stmt::PrintStats(); | |
187 Consumer->PrintStats(); | |
188 } | |
189 } |