Chris Lattner | 8082d87 | 2008-02-06 00:23:21 +0000 | [diff] [blame] | 1 | //===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame^] | 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 |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
Chris Lattner | 8082d87 | 2008-02-06 00:23:21 +0000 | [diff] [blame] | 9 | // This file implements the clang::ParseAST method. |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
John McCall | 8b0666c | 2010-08-20 18:27:03 +0000 | [diff] [blame] | 13 | #include "clang/Parse/ParseAST.h" |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 14 | #include "clang/AST/ASTConsumer.h" |
Benjamin Kramer | 1ea8e09 | 2012-07-04 17:04:04 +0000 | [diff] [blame] | 15 | #include "clang/AST/ASTContext.h" |
Douglas Gregor | 1a0d0b9 | 2009-04-14 00:24:19 +0000 | [diff] [blame] | 16 | #include "clang/AST/ExternalASTSource.h" |
Daniel Dunbar | 221fa94 | 2008-08-11 04:54:23 +0000 | [diff] [blame] | 17 | #include "clang/AST/Stmt.h" |
Chandler Carruth | 3a02247 | 2012-12-04 09:13:33 +0000 | [diff] [blame] | 18 | #include "clang/Parse/ParseDiagnostic.h" |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 19 | #include "clang/Parse/Parser.h" |
Chandler Carruth | 3a02247 | 2012-12-04 09:13:33 +0000 | [diff] [blame] | 20 | #include "clang/Sema/CodeCompleteConsumer.h" |
Chandler Carruth | 3a02247 | 2012-12-04 09:13:33 +0000 | [diff] [blame] | 21 | #include "clang/Sema/Sema.h" |
| 22 | #include "clang/Sema/SemaConsumer.h" |
Gabor Horvath | 207e7b1 | 2018-02-10 14:04:45 +0000 | [diff] [blame] | 23 | #include "clang/Sema/TemplateInstCallback.h" |
Ted Kremenek | 750028b | 2011-03-18 02:06:53 +0000 | [diff] [blame] | 24 | #include "llvm/Support/CrashRecoveryContext.h" |
Torok Edwin | db71492 | 2009-08-24 13:25:12 +0000 | [diff] [blame] | 25 | #include <cstdio> |
Ahmed Charles | dfca6f9 | 2014-03-09 11:36:40 +0000 | [diff] [blame] | 26 | #include <memory> |
Torok Edwin | db71492 | 2009-08-24 13:25:12 +0000 | [diff] [blame] | 27 | |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 28 | using namespace clang; |
| 29 | |
Nico Weber | d0b91de | 2012-11-27 21:57:34 +0000 | [diff] [blame] | 30 | namespace { |
| 31 | |
Nico Weber | 6362745 | 2015-08-07 17:48:57 +0000 | [diff] [blame] | 32 | /// Resets LLVM's pretty stack state so that stack traces are printed correctly |
| 33 | /// when there are nested CrashRecoveryContexts and the inner one recovers from |
| 34 | /// a crash. |
| 35 | class ResetStackCleanup |
| 36 | : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, |
| 37 | const void> { |
| 38 | public: |
| 39 | ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top) |
| 40 | : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>( |
| 41 | Context, Top) {} |
| 42 | void recoverResources() override { |
| 43 | llvm::RestorePrettyStackState(resource); |
| 44 | } |
| 45 | }; |
| 46 | |
Nico Weber | d0b91de | 2012-11-27 21:57:34 +0000 | [diff] [blame] | 47 | /// If a crash happens while the parser is active, an entry is printed for it. |
| 48 | class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { |
| 49 | const Parser &P; |
| 50 | public: |
| 51 | PrettyStackTraceParserEntry(const Parser &p) : P(p) {} |
Craig Topper | 2b07f02 | 2014-03-12 05:09:18 +0000 | [diff] [blame] | 52 | void print(raw_ostream &OS) const override; |
Nico Weber | d0b91de | 2012-11-27 21:57:34 +0000 | [diff] [blame] | 53 | }; |
| 54 | |
| 55 | /// If a crash happens while the parser is active, print out a line indicating |
| 56 | /// what the current token is. |
| 57 | void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { |
| 58 | const Token &Tok = P.getCurToken(); |
| 59 | if (Tok.is(tok::eof)) { |
| 60 | OS << "<eof> parser at end of file\n"; |
| 61 | return; |
| 62 | } |
| 63 | |
| 64 | if (Tok.getLocation().isInvalid()) { |
| 65 | OS << "<unknown> parser at unknown location\n"; |
| 66 | return; |
| 67 | } |
| 68 | |
| 69 | const Preprocessor &PP = P.getPreprocessor(); |
| 70 | Tok.getLocation().print(OS, PP.getSourceManager()); |
Nick Lewycky | 966b199 | 2013-03-25 21:24:30 +0000 | [diff] [blame] | 71 | if (Tok.isAnnotation()) { |
| 72 | OS << ": at annotation token\n"; |
| 73 | } else { |
| 74 | // Do the equivalent of PP.getSpelling(Tok) except for the parts that would |
| 75 | // allocate memory. |
| 76 | bool Invalid = false; |
| 77 | const SourceManager &SM = P.getPreprocessor().getSourceManager(); |
| 78 | unsigned Length = Tok.getLength(); |
| 79 | const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); |
| 80 | if (Invalid) { |
| 81 | OS << ": unknown current parser token\n"; |
| 82 | return; |
| 83 | } |
| 84 | OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; |
| 85 | } |
Nico Weber | d0b91de | 2012-11-27 21:57:34 +0000 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | } // namespace |
| 89 | |
Chris Lattner | 73709ed | 2006-08-17 06:28:25 +0000 | [diff] [blame] | 90 | //===----------------------------------------------------------------------===// |
| 91 | // Public interface to the file |
| 92 | //===----------------------------------------------------------------------===// |
| 93 | |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 94 | /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as |
Chris Lattner | 66918ee | 2009-03-28 04:13:34 +0000 | [diff] [blame] | 95 | /// the file is parsed. This inserts the parsed decls into the translation unit |
| 96 | /// held by Ctx. |
Daniel Dunbar | 33d29b3 | 2008-10-16 16:54:18 +0000 | [diff] [blame] | 97 | /// |
Ted Kremenek | 062115a | 2009-01-28 04:29:29 +0000 | [diff] [blame] | 98 | void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, |
Douglas Gregor | 54feb84 | 2009-04-14 16:27:31 +0000 | [diff] [blame] | 99 | ASTContext &Ctx, bool PrintStats, |
Douglas Gregor | 69f74f8 | 2011-08-25 22:30:56 +0000 | [diff] [blame] | 100 | TranslationUnitKind TUKind, |
Erik Verbruggen | 6e92251 | 2012-04-12 10:11:59 +0000 | [diff] [blame] | 101 | CodeCompleteConsumer *CompletionConsumer, |
| 102 | bool SkipFunctionBodies) { |
Ted Kremenek | c93cf2e | 2011-03-18 03:44:21 +0000 | [diff] [blame] | 103 | |
Ahmed Charles | b898432 | 2014-03-07 20:03:18 +0000 | [diff] [blame] | 104 | std::unique_ptr<Sema> S( |
| 105 | new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); |
Ted Kremenek | 750028b | 2011-03-18 02:06:53 +0000 | [diff] [blame] | 106 | |
| 107 | // Recover resources if we crash before exiting this method. |
Erik Verbruggen | 6e92251 | 2012-04-12 10:11:59 +0000 | [diff] [blame] | 108 | llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); |
Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 109 | |
Erik Verbruggen | 6e92251 | 2012-04-12 10:11:59 +0000 | [diff] [blame] | 110 | ParseAST(*S.get(), PrintStats, SkipFunctionBodies); |
Douglas Gregor | 5c6f10b | 2010-08-12 22:51:45 +0000 | [diff] [blame] | 111 | } |
| 112 | |
Erik Verbruggen | 6e92251 | 2012-04-12 10:11:59 +0000 | [diff] [blame] | 113 | void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 114 | // Collect global stats on Decls/Stmts (until we have a module streamer). |
| 115 | if (PrintStats) { |
Daniel Dunbar | 6290557 | 2012-03-05 21:42:49 +0000 | [diff] [blame] | 116 | Decl::EnableStatistics(); |
| 117 | Stmt::EnableStatistics(); |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 118 | } |
Ted Kremenek | 062115a | 2009-01-28 04:29:29 +0000 | [diff] [blame] | 119 | |
Chandler Carruth | b4836ea | 2011-07-06 16:21:37 +0000 | [diff] [blame] | 120 | // Also turn on collection of stats inside of the Sema object. |
| 121 | bool OldCollectStats = PrintStats; |
| 122 | std::swap(OldCollectStats, S.CollectStats); |
| 123 | |
Gabor Horvath | 207e7b1 | 2018-02-10 14:04:45 +0000 | [diff] [blame] | 124 | // Initialize the template instantiation observer chain. |
| 125 | // FIXME: See note on "finalize" below. |
| 126 | initialize(S.TemplateInstCallbacks, S); |
| 127 | |
Douglas Gregor | 5c6f10b | 2010-08-12 22:51:45 +0000 | [diff] [blame] | 128 | ASTConsumer *Consumer = &S.getASTConsumer(); |
John McCall | 0af2b7c | 2010-08-12 21:23:27 +0000 | [diff] [blame] | 129 | |
Ahmed Charles | b898432 | 2014-03-07 20:03:18 +0000 | [diff] [blame] | 130 | std::unique_ptr<Parser> ParseOP( |
| 131 | new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); |
Ted Kremenek | 4c9d46b | 2011-03-22 01:15:17 +0000 | [diff] [blame] | 132 | Parser &P = *ParseOP.get(); |
| 133 | |
Nico Weber | 6362745 | 2015-08-07 17:48:57 +0000 | [diff] [blame] | 134 | llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> |
| 135 | CleanupPrettyStack(llvm::SavePrettyStackState()); |
Ted Kremenek | 4c9d46b | 2011-03-22 01:15:17 +0000 | [diff] [blame] | 136 | PrettyStackTraceParserEntry CrashInfo(P); |
| 137 | |
| 138 | // Recover resources if we crash before exiting this method. |
| 139 | llvm::CrashRecoveryContextCleanupRegistrar<Parser> |
Erik Verbruggen | 6e92251 | 2012-04-12 10:11:59 +0000 | [diff] [blame] | 140 | CleanupParser(ParseOP.get()); |
Ted Kremenek | 4c9d46b | 2011-03-22 01:15:17 +0000 | [diff] [blame] | 141 | |
Douglas Gregor | 5c6f10b | 2010-08-12 22:51:45 +0000 | [diff] [blame] | 142 | S.getPreprocessor().EnterMainSourceFile(); |
Meador Inge | cdc0057 | 2012-06-19 18:17:30 +0000 | [diff] [blame] | 143 | ExternalASTSource *External = S.getASTContext().getExternalSource(); |
| 144 | if (External) |
| 145 | External->StartTranslationUnit(Consumer); |
Argyrios Kyrtzidis | 841dd88 | 2011-11-18 00:26:59 +0000 | [diff] [blame] | 146 | |
Mike Rice | 58df1af | 2018-09-11 17:10:44 +0000 | [diff] [blame] | 147 | // If a PCH through header is specified that does not have an include in |
| 148 | // the source, or a PCH is being created with #pragma hdrstop with nothing |
| 149 | // after the pragma, there won't be any tokens or a Lexer. |
| 150 | bool HaveLexer = S.getPreprocessor().getCurrentLexer(); |
| 151 | |
| 152 | if (HaveLexer) { |
| 153 | P.Initialize(); |
| 154 | Parser::DeclGroupPtrTy ADecl; |
| 155 | for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; |
| 156 | AtEOF = P.ParseTopLevelDecl(ADecl)) { |
| 157 | // If we got a null return and something *was* parsed, ignore it. This |
| 158 | // is due to a top-level semicolon, an action override, or a parse error |
| 159 | // skipping something. |
| 160 | if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) |
| 161 | return; |
| 162 | } |
Jordan Rose | ccf43ca | 2012-06-06 17:25:21 +0000 | [diff] [blame] | 163 | } |
Meador Inge | cdc0057 | 2012-06-19 18:17:30 +0000 | [diff] [blame] | 164 | |
Daniel Dunbar | ec5f8ae | 2009-12-01 21:57:20 +0000 | [diff] [blame] | 165 | // Process any TopLevelDecls generated by #pragma weak. |
Yaron Keren | c6328f1 | 2014-12-17 16:56:54 +0000 | [diff] [blame] | 166 | for (Decl *D : S.WeakTopLevelDecls()) |
| 167 | Consumer->HandleTopLevelDecl(DeclGroupRef(D)); |
Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 168 | |
Douglas Gregor | 5c6f10b | 2010-08-12 22:51:45 +0000 | [diff] [blame] | 169 | Consumer->HandleTranslationUnit(S.getASTContext()); |
Chandler Carruth | b4836ea | 2011-07-06 16:21:37 +0000 | [diff] [blame] | 170 | |
Gabor Horvath | 207e7b1 | 2018-02-10 14:04:45 +0000 | [diff] [blame] | 171 | // Finalize the template instantiation observer chain. |
| 172 | // FIXME: This (and init.) should be done in the Sema class, but because |
| 173 | // Sema does not have a reliable "Finalize" function (it has a |
| 174 | // destructor, but it is not guaranteed to be called ("-disable-free")). |
| 175 | // So, do the initialization above and do the finalization here: |
| 176 | finalize(S.TemplateInstCallbacks, S); |
| 177 | |
Chandler Carruth | b4836ea | 2011-07-06 16:21:37 +0000 | [diff] [blame] | 178 | std::swap(OldCollectStats, S.CollectStats); |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 179 | if (PrintStats) { |
Chandler Carruth | 3c147a7 | 2011-07-04 05:32:14 +0000 | [diff] [blame] | 180 | llvm::errs() << "\nSTATISTICS:\n"; |
Mike Rice | 58df1af | 2018-09-11 17:10:44 +0000 | [diff] [blame] | 181 | if (HaveLexer) P.getActions().PrintStats(); |
Douglas Gregor | 5c6f10b | 2010-08-12 22:51:45 +0000 | [diff] [blame] | 182 | S.getASTContext().PrintStats(); |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 183 | Decl::PrintStats(); |
| 184 | Stmt::PrintStats(); |
Chris Lattner | 376cdaf | 2007-11-03 06:24:16 +0000 | [diff] [blame] | 185 | Consumer->PrintStats(); |
Chris Lattner | 75e0c8c | 2007-09-15 22:56:56 +0000 | [diff] [blame] | 186 | } |
| 187 | } |