1f4a2713aSLionel Sambuc //===--- Pragma.cpp - Pragma registration and handling --------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the PragmaHandler/PragmaTable interfaces and implements
11f4a2713aSLionel Sambuc // pragma related methods of the Preprocessor class.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "clang/Lex/Pragma.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
18f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearch.h"
19f4a2713aSLionel Sambuc #include "clang/Lex/LexDiagnostic.h"
20f4a2713aSLionel Sambuc #include "clang/Lex/LiteralSupport.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/MacroInfo.h"
22f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
24f4a2713aSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
25f4a2713aSLionel Sambuc #include "llvm/Support/CrashRecoveryContext.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
27f4a2713aSLionel Sambuc #include <algorithm>
28f4a2713aSLionel Sambuc using namespace clang;
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
31f4a2713aSLionel Sambuc
32f4a2713aSLionel Sambuc // Out-of-line destructor to provide a home for the class.
~PragmaHandler()33f4a2713aSLionel Sambuc PragmaHandler::~PragmaHandler() {
34f4a2713aSLionel Sambuc }
35f4a2713aSLionel Sambuc
36f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
37f4a2713aSLionel Sambuc // EmptyPragmaHandler Implementation.
38f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
39f4a2713aSLionel Sambuc
EmptyPragmaHandler()40f4a2713aSLionel Sambuc EmptyPragmaHandler::EmptyPragmaHandler() {}
41f4a2713aSLionel Sambuc
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstToken)42f4a2713aSLionel Sambuc void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
43f4a2713aSLionel Sambuc PragmaIntroducerKind Introducer,
44f4a2713aSLionel Sambuc Token &FirstToken) {}
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
47f4a2713aSLionel Sambuc // PragmaNamespace Implementation.
48f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
49f4a2713aSLionel Sambuc
~PragmaNamespace()50f4a2713aSLionel Sambuc PragmaNamespace::~PragmaNamespace() {
51*0a6a1f1dSLionel Sambuc llvm::DeleteContainerSeconds(Handlers);
52f4a2713aSLionel Sambuc }
53f4a2713aSLionel Sambuc
54f4a2713aSLionel Sambuc /// FindHandler - Check to see if there is already a handler for the
55f4a2713aSLionel Sambuc /// specified name. If not, return the handler for the null identifier if it
56f4a2713aSLionel Sambuc /// exists, otherwise return null. If IgnoreNull is true (the default) then
57f4a2713aSLionel Sambuc /// the null handler isn't returned on failure to match.
FindHandler(StringRef Name,bool IgnoreNull) const58f4a2713aSLionel Sambuc PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
59f4a2713aSLionel Sambuc bool IgnoreNull) const {
60f4a2713aSLionel Sambuc if (PragmaHandler *Handler = Handlers.lookup(Name))
61f4a2713aSLionel Sambuc return Handler;
62*0a6a1f1dSLionel Sambuc return IgnoreNull ? nullptr : Handlers.lookup(StringRef());
63f4a2713aSLionel Sambuc }
64f4a2713aSLionel Sambuc
AddPragma(PragmaHandler * Handler)65f4a2713aSLionel Sambuc void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
66f4a2713aSLionel Sambuc assert(!Handlers.lookup(Handler->getName()) &&
67f4a2713aSLionel Sambuc "A handler with this name is already registered in this namespace");
68*0a6a1f1dSLionel Sambuc Handlers[Handler->getName()] = Handler;
69f4a2713aSLionel Sambuc }
70f4a2713aSLionel Sambuc
RemovePragmaHandler(PragmaHandler * Handler)71f4a2713aSLionel Sambuc void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
72f4a2713aSLionel Sambuc assert(Handlers.lookup(Handler->getName()) &&
73f4a2713aSLionel Sambuc "Handler not registered in this namespace");
74f4a2713aSLionel Sambuc Handlers.erase(Handler->getName());
75f4a2713aSLionel Sambuc }
76f4a2713aSLionel Sambuc
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)77f4a2713aSLionel Sambuc void PragmaNamespace::HandlePragma(Preprocessor &PP,
78f4a2713aSLionel Sambuc PragmaIntroducerKind Introducer,
79f4a2713aSLionel Sambuc Token &Tok) {
80f4a2713aSLionel Sambuc // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro
81f4a2713aSLionel Sambuc // expand it, the user can have a STDC #define, that should not affect this.
82f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
83f4a2713aSLionel Sambuc
84f4a2713aSLionel Sambuc // Get the handler for this token. If there is no handler, ignore the pragma.
85f4a2713aSLionel Sambuc PragmaHandler *Handler
86f4a2713aSLionel Sambuc = FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName()
87f4a2713aSLionel Sambuc : StringRef(),
88f4a2713aSLionel Sambuc /*IgnoreNull=*/false);
89*0a6a1f1dSLionel Sambuc if (!Handler) {
90f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_ignored);
91f4a2713aSLionel Sambuc return;
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc
94f4a2713aSLionel Sambuc // Otherwise, pass it down.
95f4a2713aSLionel Sambuc Handler->HandlePragma(PP, Introducer, Tok);
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc
98f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
99f4a2713aSLionel Sambuc // Preprocessor Pragma Directive Handling.
100f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
101f4a2713aSLionel Sambuc
102f4a2713aSLionel Sambuc /// HandlePragmaDirective - The "\#pragma" directive has been parsed. Lex the
103f4a2713aSLionel Sambuc /// rest of the pragma, passing it to the registered pragma handlers.
HandlePragmaDirective(SourceLocation IntroducerLoc,PragmaIntroducerKind Introducer)104f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc,
105f4a2713aSLionel Sambuc PragmaIntroducerKind Introducer) {
106f4a2713aSLionel Sambuc if (Callbacks)
107f4a2713aSLionel Sambuc Callbacks->PragmaDirective(IntroducerLoc, Introducer);
108f4a2713aSLionel Sambuc
109f4a2713aSLionel Sambuc if (!PragmasEnabled)
110f4a2713aSLionel Sambuc return;
111f4a2713aSLionel Sambuc
112f4a2713aSLionel Sambuc ++NumPragma;
113f4a2713aSLionel Sambuc
114f4a2713aSLionel Sambuc // Invoke the first level of pragma handlers which reads the namespace id.
115f4a2713aSLionel Sambuc Token Tok;
116f4a2713aSLionel Sambuc PragmaHandlers->HandlePragma(*this, Introducer, Tok);
117f4a2713aSLionel Sambuc
118f4a2713aSLionel Sambuc // If the pragma handler didn't read the rest of the line, consume it now.
119f4a2713aSLionel Sambuc if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
120f4a2713aSLionel Sambuc || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
121f4a2713aSLionel Sambuc DiscardUntilEndOfDirective();
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc
124f4a2713aSLionel Sambuc namespace {
125f4a2713aSLionel Sambuc /// \brief Helper class for \see Preprocessor::Handle_Pragma.
126f4a2713aSLionel Sambuc class LexingFor_PragmaRAII {
127f4a2713aSLionel Sambuc Preprocessor &PP;
128f4a2713aSLionel Sambuc bool InMacroArgPreExpansion;
129f4a2713aSLionel Sambuc bool Failed;
130f4a2713aSLionel Sambuc Token &OutTok;
131f4a2713aSLionel Sambuc Token PragmaTok;
132f4a2713aSLionel Sambuc
133f4a2713aSLionel Sambuc public:
LexingFor_PragmaRAII(Preprocessor & PP,bool InMacroArgPreExpansion,Token & Tok)134f4a2713aSLionel Sambuc LexingFor_PragmaRAII(Preprocessor &PP, bool InMacroArgPreExpansion,
135f4a2713aSLionel Sambuc Token &Tok)
136f4a2713aSLionel Sambuc : PP(PP), InMacroArgPreExpansion(InMacroArgPreExpansion),
137f4a2713aSLionel Sambuc Failed(false), OutTok(Tok) {
138f4a2713aSLionel Sambuc if (InMacroArgPreExpansion) {
139f4a2713aSLionel Sambuc PragmaTok = OutTok;
140f4a2713aSLionel Sambuc PP.EnableBacktrackAtThisPos();
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc }
143f4a2713aSLionel Sambuc
~LexingFor_PragmaRAII()144f4a2713aSLionel Sambuc ~LexingFor_PragmaRAII() {
145f4a2713aSLionel Sambuc if (InMacroArgPreExpansion) {
146f4a2713aSLionel Sambuc if (Failed) {
147f4a2713aSLionel Sambuc PP.CommitBacktrackedTokens();
148f4a2713aSLionel Sambuc } else {
149f4a2713aSLionel Sambuc PP.Backtrack();
150f4a2713aSLionel Sambuc OutTok = PragmaTok;
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc }
153f4a2713aSLionel Sambuc }
154f4a2713aSLionel Sambuc
failed()155f4a2713aSLionel Sambuc void failed() {
156f4a2713aSLionel Sambuc Failed = true;
157f4a2713aSLionel Sambuc }
158f4a2713aSLionel Sambuc };
159f4a2713aSLionel Sambuc }
160f4a2713aSLionel Sambuc
161f4a2713aSLionel Sambuc /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
162f4a2713aSLionel Sambuc /// return the first token after the directive. The _Pragma token has just
163f4a2713aSLionel Sambuc /// been read into 'Tok'.
Handle_Pragma(Token & Tok)164f4a2713aSLionel Sambuc void Preprocessor::Handle_Pragma(Token &Tok) {
165f4a2713aSLionel Sambuc
166f4a2713aSLionel Sambuc // This works differently if we are pre-expanding a macro argument.
167f4a2713aSLionel Sambuc // In that case we don't actually "activate" the pragma now, we only lex it
168f4a2713aSLionel Sambuc // until we are sure it is lexically correct and then we backtrack so that
169f4a2713aSLionel Sambuc // we activate the pragma whenever we encounter the tokens again in the token
170f4a2713aSLionel Sambuc // stream. This ensures that we will activate it in the correct location
171f4a2713aSLionel Sambuc // or that we will ignore it if it never enters the token stream, e.g:
172f4a2713aSLionel Sambuc //
173f4a2713aSLionel Sambuc // #define EMPTY(x)
174f4a2713aSLionel Sambuc // #define INACTIVE(x) EMPTY(x)
175f4a2713aSLionel Sambuc // INACTIVE(_Pragma("clang diagnostic ignored \"-Wconversion\""))
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc LexingFor_PragmaRAII _PragmaLexing(*this, InMacroArgPreExpansion, Tok);
178f4a2713aSLionel Sambuc
179f4a2713aSLionel Sambuc // Remember the pragma token location.
180f4a2713aSLionel Sambuc SourceLocation PragmaLoc = Tok.getLocation();
181f4a2713aSLionel Sambuc
182f4a2713aSLionel Sambuc // Read the '('.
183f4a2713aSLionel Sambuc Lex(Tok);
184f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) {
185f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err__Pragma_malformed);
186f4a2713aSLionel Sambuc return _PragmaLexing.failed();
187f4a2713aSLionel Sambuc }
188f4a2713aSLionel Sambuc
189f4a2713aSLionel Sambuc // Read the '"..."'.
190f4a2713aSLionel Sambuc Lex(Tok);
191f4a2713aSLionel Sambuc if (!tok::isStringLiteral(Tok.getKind())) {
192f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err__Pragma_malformed);
193f4a2713aSLionel Sambuc // Skip this token, and the ')', if present.
194*0a6a1f1dSLionel Sambuc if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof))
195f4a2713aSLionel Sambuc Lex(Tok);
196f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren))
197f4a2713aSLionel Sambuc Lex(Tok);
198f4a2713aSLionel Sambuc return _PragmaLexing.failed();
199f4a2713aSLionel Sambuc }
200f4a2713aSLionel Sambuc
201f4a2713aSLionel Sambuc if (Tok.hasUDSuffix()) {
202f4a2713aSLionel Sambuc Diag(Tok, diag::err_invalid_string_udl);
203f4a2713aSLionel Sambuc // Skip this token, and the ')', if present.
204f4a2713aSLionel Sambuc Lex(Tok);
205f4a2713aSLionel Sambuc if (Tok.is(tok::r_paren))
206f4a2713aSLionel Sambuc Lex(Tok);
207f4a2713aSLionel Sambuc return _PragmaLexing.failed();
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc
210f4a2713aSLionel Sambuc // Remember the string.
211f4a2713aSLionel Sambuc Token StrTok = Tok;
212f4a2713aSLionel Sambuc
213f4a2713aSLionel Sambuc // Read the ')'.
214f4a2713aSLionel Sambuc Lex(Tok);
215f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) {
216f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err__Pragma_malformed);
217f4a2713aSLionel Sambuc return _PragmaLexing.failed();
218f4a2713aSLionel Sambuc }
219f4a2713aSLionel Sambuc
220f4a2713aSLionel Sambuc if (InMacroArgPreExpansion)
221f4a2713aSLionel Sambuc return;
222f4a2713aSLionel Sambuc
223f4a2713aSLionel Sambuc SourceLocation RParenLoc = Tok.getLocation();
224f4a2713aSLionel Sambuc std::string StrVal = getSpelling(StrTok);
225f4a2713aSLionel Sambuc
226f4a2713aSLionel Sambuc // The _Pragma is lexically sound. Destringize according to C11 6.10.9.1:
227f4a2713aSLionel Sambuc // "The string literal is destringized by deleting any encoding prefix,
228f4a2713aSLionel Sambuc // deleting the leading and trailing double-quotes, replacing each escape
229f4a2713aSLionel Sambuc // sequence \" by a double-quote, and replacing each escape sequence \\ by a
230f4a2713aSLionel Sambuc // single backslash."
231f4a2713aSLionel Sambuc if (StrVal[0] == 'L' || StrVal[0] == 'U' ||
232f4a2713aSLionel Sambuc (StrVal[0] == 'u' && StrVal[1] != '8'))
233f4a2713aSLionel Sambuc StrVal.erase(StrVal.begin());
234f4a2713aSLionel Sambuc else if (StrVal[0] == 'u')
235f4a2713aSLionel Sambuc StrVal.erase(StrVal.begin(), StrVal.begin() + 2);
236f4a2713aSLionel Sambuc
237f4a2713aSLionel Sambuc if (StrVal[0] == 'R') {
238f4a2713aSLionel Sambuc // FIXME: C++11 does not specify how to handle raw-string-literals here.
239f4a2713aSLionel Sambuc // We strip off the 'R', the quotes, the d-char-sequences, and the parens.
240f4a2713aSLionel Sambuc assert(StrVal[1] == '"' && StrVal[StrVal.size() - 1] == '"' &&
241f4a2713aSLionel Sambuc "Invalid raw string token!");
242f4a2713aSLionel Sambuc
243f4a2713aSLionel Sambuc // Measure the length of the d-char-sequence.
244f4a2713aSLionel Sambuc unsigned NumDChars = 0;
245f4a2713aSLionel Sambuc while (StrVal[2 + NumDChars] != '(') {
246f4a2713aSLionel Sambuc assert(NumDChars < (StrVal.size() - 5) / 2 &&
247f4a2713aSLionel Sambuc "Invalid raw string token!");
248f4a2713aSLionel Sambuc ++NumDChars;
249f4a2713aSLionel Sambuc }
250f4a2713aSLionel Sambuc assert(StrVal[StrVal.size() - 2 - NumDChars] == ')');
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc // Remove 'R " d-char-sequence' and 'd-char-sequence "'. We'll replace the
253f4a2713aSLionel Sambuc // parens below.
254f4a2713aSLionel Sambuc StrVal.erase(0, 2 + NumDChars);
255f4a2713aSLionel Sambuc StrVal.erase(StrVal.size() - 1 - NumDChars);
256f4a2713aSLionel Sambuc } else {
257f4a2713aSLionel Sambuc assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
258f4a2713aSLionel Sambuc "Invalid string token!");
259f4a2713aSLionel Sambuc
260f4a2713aSLionel Sambuc // Remove escaped quotes and escapes.
261f4a2713aSLionel Sambuc unsigned ResultPos = 1;
262f4a2713aSLionel Sambuc for (unsigned i = 1, e = StrVal.size() - 1; i != e; ++i) {
263f4a2713aSLionel Sambuc // Skip escapes. \\ -> '\' and \" -> '"'.
264f4a2713aSLionel Sambuc if (StrVal[i] == '\\' && i + 1 < e &&
265f4a2713aSLionel Sambuc (StrVal[i + 1] == '\\' || StrVal[i + 1] == '"'))
266f4a2713aSLionel Sambuc ++i;
267f4a2713aSLionel Sambuc StrVal[ResultPos++] = StrVal[i];
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc StrVal.erase(StrVal.begin() + ResultPos, StrVal.end() - 1);
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc
272f4a2713aSLionel Sambuc // Remove the front quote, replacing it with a space, so that the pragma
273f4a2713aSLionel Sambuc // contents appear to have a space before them.
274f4a2713aSLionel Sambuc StrVal[0] = ' ';
275f4a2713aSLionel Sambuc
276f4a2713aSLionel Sambuc // Replace the terminating quote with a \n.
277f4a2713aSLionel Sambuc StrVal[StrVal.size()-1] = '\n';
278f4a2713aSLionel Sambuc
279f4a2713aSLionel Sambuc // Plop the string (including the newline and trailing null) into a buffer
280f4a2713aSLionel Sambuc // where we can lex it.
281f4a2713aSLionel Sambuc Token TmpTok;
282f4a2713aSLionel Sambuc TmpTok.startToken();
283f4a2713aSLionel Sambuc CreateString(StrVal, TmpTok);
284f4a2713aSLionel Sambuc SourceLocation TokLoc = TmpTok.getLocation();
285f4a2713aSLionel Sambuc
286f4a2713aSLionel Sambuc // Make and enter a lexer object so that we lex and expand the tokens just
287f4a2713aSLionel Sambuc // like any others.
288f4a2713aSLionel Sambuc Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
289f4a2713aSLionel Sambuc StrVal.size(), *this);
290f4a2713aSLionel Sambuc
291*0a6a1f1dSLionel Sambuc EnterSourceFileWithLexer(TL, nullptr);
292f4a2713aSLionel Sambuc
293f4a2713aSLionel Sambuc // With everything set up, lex this as a #pragma directive.
294f4a2713aSLionel Sambuc HandlePragmaDirective(PragmaLoc, PIK__Pragma);
295f4a2713aSLionel Sambuc
296f4a2713aSLionel Sambuc // Finally, return whatever came after the pragma directive.
297f4a2713aSLionel Sambuc return Lex(Tok);
298f4a2713aSLionel Sambuc }
299f4a2713aSLionel Sambuc
300f4a2713aSLionel Sambuc /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
301f4a2713aSLionel Sambuc /// is not enclosed within a string literal.
HandleMicrosoft__pragma(Token & Tok)302f4a2713aSLionel Sambuc void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
303f4a2713aSLionel Sambuc // Remember the pragma token location.
304f4a2713aSLionel Sambuc SourceLocation PragmaLoc = Tok.getLocation();
305f4a2713aSLionel Sambuc
306f4a2713aSLionel Sambuc // Read the '('.
307f4a2713aSLionel Sambuc Lex(Tok);
308f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) {
309f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err__Pragma_malformed);
310f4a2713aSLionel Sambuc return;
311f4a2713aSLionel Sambuc }
312f4a2713aSLionel Sambuc
313f4a2713aSLionel Sambuc // Get the tokens enclosed within the __pragma(), as well as the final ')'.
314f4a2713aSLionel Sambuc SmallVector<Token, 32> PragmaToks;
315f4a2713aSLionel Sambuc int NumParens = 0;
316f4a2713aSLionel Sambuc Lex(Tok);
317f4a2713aSLionel Sambuc while (Tok.isNot(tok::eof)) {
318f4a2713aSLionel Sambuc PragmaToks.push_back(Tok);
319f4a2713aSLionel Sambuc if (Tok.is(tok::l_paren))
320f4a2713aSLionel Sambuc NumParens++;
321f4a2713aSLionel Sambuc else if (Tok.is(tok::r_paren) && NumParens-- == 0)
322f4a2713aSLionel Sambuc break;
323f4a2713aSLionel Sambuc Lex(Tok);
324f4a2713aSLionel Sambuc }
325f4a2713aSLionel Sambuc
326f4a2713aSLionel Sambuc if (Tok.is(tok::eof)) {
327f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err_unterminated___pragma);
328f4a2713aSLionel Sambuc return;
329f4a2713aSLionel Sambuc }
330f4a2713aSLionel Sambuc
331f4a2713aSLionel Sambuc PragmaToks.front().setFlag(Token::LeadingSpace);
332f4a2713aSLionel Sambuc
333f4a2713aSLionel Sambuc // Replace the ')' with an EOD to mark the end of the pragma.
334f4a2713aSLionel Sambuc PragmaToks.back().setKind(tok::eod);
335f4a2713aSLionel Sambuc
336f4a2713aSLionel Sambuc Token *TokArray = new Token[PragmaToks.size()];
337f4a2713aSLionel Sambuc std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray);
338f4a2713aSLionel Sambuc
339f4a2713aSLionel Sambuc // Push the tokens onto the stack.
340f4a2713aSLionel Sambuc EnterTokenStream(TokArray, PragmaToks.size(), true, true);
341f4a2713aSLionel Sambuc
342f4a2713aSLionel Sambuc // With everything set up, lex this as a #pragma directive.
343f4a2713aSLionel Sambuc HandlePragmaDirective(PragmaLoc, PIK___pragma);
344f4a2713aSLionel Sambuc
345f4a2713aSLionel Sambuc // Finally, return whatever came after the pragma directive.
346f4a2713aSLionel Sambuc return Lex(Tok);
347f4a2713aSLionel Sambuc }
348f4a2713aSLionel Sambuc
349f4a2713aSLionel Sambuc /// HandlePragmaOnce - Handle \#pragma once. OnceTok is the 'once'.
350f4a2713aSLionel Sambuc ///
HandlePragmaOnce(Token & OnceTok)351f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
352f4a2713aSLionel Sambuc if (isInPrimaryFile()) {
353f4a2713aSLionel Sambuc Diag(OnceTok, diag::pp_pragma_once_in_main_file);
354f4a2713aSLionel Sambuc return;
355f4a2713aSLionel Sambuc }
356f4a2713aSLionel Sambuc
357f4a2713aSLionel Sambuc // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
358f4a2713aSLionel Sambuc // Mark the file as a once-only file now.
359f4a2713aSLionel Sambuc HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
360f4a2713aSLionel Sambuc }
361f4a2713aSLionel Sambuc
HandlePragmaMark()362f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaMark() {
363f4a2713aSLionel Sambuc assert(CurPPLexer && "No current lexer?");
364f4a2713aSLionel Sambuc if (CurLexer)
365f4a2713aSLionel Sambuc CurLexer->ReadToEndOfLine();
366f4a2713aSLionel Sambuc else
367f4a2713aSLionel Sambuc CurPTHLexer->DiscardToEndOfLine();
368f4a2713aSLionel Sambuc }
369f4a2713aSLionel Sambuc
370f4a2713aSLionel Sambuc
371f4a2713aSLionel Sambuc /// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
372f4a2713aSLionel Sambuc ///
HandlePragmaPoison(Token & PoisonTok)373f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
374f4a2713aSLionel Sambuc Token Tok;
375f4a2713aSLionel Sambuc
376f4a2713aSLionel Sambuc while (1) {
377f4a2713aSLionel Sambuc // Read the next token to poison. While doing this, pretend that we are
378f4a2713aSLionel Sambuc // skipping while reading the identifier to poison.
379f4a2713aSLionel Sambuc // This avoids errors on code like:
380f4a2713aSLionel Sambuc // #pragma GCC poison X
381f4a2713aSLionel Sambuc // #pragma GCC poison X
382f4a2713aSLionel Sambuc if (CurPPLexer) CurPPLexer->LexingRawMode = true;
383f4a2713aSLionel Sambuc LexUnexpandedToken(Tok);
384f4a2713aSLionel Sambuc if (CurPPLexer) CurPPLexer->LexingRawMode = false;
385f4a2713aSLionel Sambuc
386f4a2713aSLionel Sambuc // If we reached the end of line, we're done.
387f4a2713aSLionel Sambuc if (Tok.is(tok::eod)) return;
388f4a2713aSLionel Sambuc
389f4a2713aSLionel Sambuc // Can only poison identifiers.
390f4a2713aSLionel Sambuc if (Tok.isNot(tok::raw_identifier)) {
391f4a2713aSLionel Sambuc Diag(Tok, diag::err_pp_invalid_poison);
392f4a2713aSLionel Sambuc return;
393f4a2713aSLionel Sambuc }
394f4a2713aSLionel Sambuc
395f4a2713aSLionel Sambuc // Look up the identifier info for the token. We disabled identifier lookup
396f4a2713aSLionel Sambuc // by saying we're skipping contents, so we need to do this manually.
397f4a2713aSLionel Sambuc IdentifierInfo *II = LookUpIdentifierInfo(Tok);
398f4a2713aSLionel Sambuc
399f4a2713aSLionel Sambuc // Already poisoned.
400f4a2713aSLionel Sambuc if (II->isPoisoned()) continue;
401f4a2713aSLionel Sambuc
402f4a2713aSLionel Sambuc // If this is a macro identifier, emit a warning.
403f4a2713aSLionel Sambuc if (II->hasMacroDefinition())
404f4a2713aSLionel Sambuc Diag(Tok, diag::pp_poisoning_existing_macro);
405f4a2713aSLionel Sambuc
406f4a2713aSLionel Sambuc // Finally, poison it!
407f4a2713aSLionel Sambuc II->setIsPoisoned();
408f4a2713aSLionel Sambuc if (II->isFromAST())
409f4a2713aSLionel Sambuc II->setChangedSinceDeserialization();
410f4a2713aSLionel Sambuc }
411f4a2713aSLionel Sambuc }
412f4a2713aSLionel Sambuc
413f4a2713aSLionel Sambuc /// HandlePragmaSystemHeader - Implement \#pragma GCC system_header. We know
414f4a2713aSLionel Sambuc /// that the whole directive has been parsed.
HandlePragmaSystemHeader(Token & SysHeaderTok)415f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
416f4a2713aSLionel Sambuc if (isInPrimaryFile()) {
417f4a2713aSLionel Sambuc Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
418f4a2713aSLionel Sambuc return;
419f4a2713aSLionel Sambuc }
420f4a2713aSLionel Sambuc
421f4a2713aSLionel Sambuc // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
422f4a2713aSLionel Sambuc PreprocessorLexer *TheLexer = getCurrentFileLexer();
423f4a2713aSLionel Sambuc
424f4a2713aSLionel Sambuc // Mark the file as a system header.
425f4a2713aSLionel Sambuc HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
426f4a2713aSLionel Sambuc
427f4a2713aSLionel Sambuc
428f4a2713aSLionel Sambuc PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
429f4a2713aSLionel Sambuc if (PLoc.isInvalid())
430f4a2713aSLionel Sambuc return;
431f4a2713aSLionel Sambuc
432f4a2713aSLionel Sambuc unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename());
433f4a2713aSLionel Sambuc
434f4a2713aSLionel Sambuc // Notify the client, if desired, that we are in a new source file.
435f4a2713aSLionel Sambuc if (Callbacks)
436f4a2713aSLionel Sambuc Callbacks->FileChanged(SysHeaderTok.getLocation(),
437f4a2713aSLionel Sambuc PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
438f4a2713aSLionel Sambuc
439f4a2713aSLionel Sambuc // Emit a line marker. This will change any source locations from this point
440f4a2713aSLionel Sambuc // forward to realize they are in a system header.
441f4a2713aSLionel Sambuc // Create a line note with this information.
442f4a2713aSLionel Sambuc SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine()+1,
443f4a2713aSLionel Sambuc FilenameID, /*IsEntry=*/false, /*IsExit=*/false,
444f4a2713aSLionel Sambuc /*IsSystem=*/true, /*IsExternC=*/false);
445f4a2713aSLionel Sambuc }
446f4a2713aSLionel Sambuc
447f4a2713aSLionel Sambuc /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
448f4a2713aSLionel Sambuc ///
HandlePragmaDependency(Token & DependencyTok)449f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
450f4a2713aSLionel Sambuc Token FilenameTok;
451f4a2713aSLionel Sambuc CurPPLexer->LexIncludeFilename(FilenameTok);
452f4a2713aSLionel Sambuc
453f4a2713aSLionel Sambuc // If the token kind is EOD, the error has already been diagnosed.
454f4a2713aSLionel Sambuc if (FilenameTok.is(tok::eod))
455f4a2713aSLionel Sambuc return;
456f4a2713aSLionel Sambuc
457f4a2713aSLionel Sambuc // Reserve a buffer to get the spelling.
458f4a2713aSLionel Sambuc SmallString<128> FilenameBuffer;
459f4a2713aSLionel Sambuc bool Invalid = false;
460f4a2713aSLionel Sambuc StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
461f4a2713aSLionel Sambuc if (Invalid)
462f4a2713aSLionel Sambuc return;
463f4a2713aSLionel Sambuc
464f4a2713aSLionel Sambuc bool isAngled =
465f4a2713aSLionel Sambuc GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
466f4a2713aSLionel Sambuc // If GetIncludeFilenameSpelling set the start ptr to null, there was an
467f4a2713aSLionel Sambuc // error.
468f4a2713aSLionel Sambuc if (Filename.empty())
469f4a2713aSLionel Sambuc return;
470f4a2713aSLionel Sambuc
471f4a2713aSLionel Sambuc // Search include directories for this file.
472f4a2713aSLionel Sambuc const DirectoryLookup *CurDir;
473*0a6a1f1dSLionel Sambuc const FileEntry *File =
474*0a6a1f1dSLionel Sambuc LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
475*0a6a1f1dSLionel Sambuc nullptr, CurDir, nullptr, nullptr, nullptr);
476*0a6a1f1dSLionel Sambuc if (!File) {
477f4a2713aSLionel Sambuc if (!SuppressIncludeNotFoundError)
478f4a2713aSLionel Sambuc Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
479f4a2713aSLionel Sambuc return;
480f4a2713aSLionel Sambuc }
481f4a2713aSLionel Sambuc
482f4a2713aSLionel Sambuc const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
483f4a2713aSLionel Sambuc
484f4a2713aSLionel Sambuc // If this file is older than the file it depends on, emit a diagnostic.
485f4a2713aSLionel Sambuc if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
486f4a2713aSLionel Sambuc // Lex tokens at the end of the message and include them in the message.
487f4a2713aSLionel Sambuc std::string Message;
488f4a2713aSLionel Sambuc Lex(DependencyTok);
489f4a2713aSLionel Sambuc while (DependencyTok.isNot(tok::eod)) {
490f4a2713aSLionel Sambuc Message += getSpelling(DependencyTok) + " ";
491f4a2713aSLionel Sambuc Lex(DependencyTok);
492f4a2713aSLionel Sambuc }
493f4a2713aSLionel Sambuc
494f4a2713aSLionel Sambuc // Remove the trailing ' ' if present.
495f4a2713aSLionel Sambuc if (!Message.empty())
496f4a2713aSLionel Sambuc Message.erase(Message.end()-1);
497f4a2713aSLionel Sambuc Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
498f4a2713aSLionel Sambuc }
499f4a2713aSLionel Sambuc }
500f4a2713aSLionel Sambuc
501f4a2713aSLionel Sambuc /// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro.
502f4a2713aSLionel Sambuc /// Return the IdentifierInfo* associated with the macro to push or pop.
ParsePragmaPushOrPopMacro(Token & Tok)503f4a2713aSLionel Sambuc IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
504f4a2713aSLionel Sambuc // Remember the pragma token location.
505f4a2713aSLionel Sambuc Token PragmaTok = Tok;
506f4a2713aSLionel Sambuc
507f4a2713aSLionel Sambuc // Read the '('.
508f4a2713aSLionel Sambuc Lex(Tok);
509f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) {
510f4a2713aSLionel Sambuc Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
511f4a2713aSLionel Sambuc << getSpelling(PragmaTok);
512*0a6a1f1dSLionel Sambuc return nullptr;
513f4a2713aSLionel Sambuc }
514f4a2713aSLionel Sambuc
515f4a2713aSLionel Sambuc // Read the macro name string.
516f4a2713aSLionel Sambuc Lex(Tok);
517f4a2713aSLionel Sambuc if (Tok.isNot(tok::string_literal)) {
518f4a2713aSLionel Sambuc Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
519f4a2713aSLionel Sambuc << getSpelling(PragmaTok);
520*0a6a1f1dSLionel Sambuc return nullptr;
521f4a2713aSLionel Sambuc }
522f4a2713aSLionel Sambuc
523f4a2713aSLionel Sambuc if (Tok.hasUDSuffix()) {
524f4a2713aSLionel Sambuc Diag(Tok, diag::err_invalid_string_udl);
525*0a6a1f1dSLionel Sambuc return nullptr;
526f4a2713aSLionel Sambuc }
527f4a2713aSLionel Sambuc
528f4a2713aSLionel Sambuc // Remember the macro string.
529f4a2713aSLionel Sambuc std::string StrVal = getSpelling(Tok);
530f4a2713aSLionel Sambuc
531f4a2713aSLionel Sambuc // Read the ')'.
532f4a2713aSLionel Sambuc Lex(Tok);
533f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) {
534f4a2713aSLionel Sambuc Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
535f4a2713aSLionel Sambuc << getSpelling(PragmaTok);
536*0a6a1f1dSLionel Sambuc return nullptr;
537f4a2713aSLionel Sambuc }
538f4a2713aSLionel Sambuc
539f4a2713aSLionel Sambuc assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
540f4a2713aSLionel Sambuc "Invalid string token!");
541f4a2713aSLionel Sambuc
542f4a2713aSLionel Sambuc // Create a Token from the string.
543f4a2713aSLionel Sambuc Token MacroTok;
544f4a2713aSLionel Sambuc MacroTok.startToken();
545f4a2713aSLionel Sambuc MacroTok.setKind(tok::raw_identifier);
546f4a2713aSLionel Sambuc CreateString(StringRef(&StrVal[1], StrVal.size() - 2), MacroTok);
547f4a2713aSLionel Sambuc
548f4a2713aSLionel Sambuc // Get the IdentifierInfo of MacroToPushTok.
549f4a2713aSLionel Sambuc return LookUpIdentifierInfo(MacroTok);
550f4a2713aSLionel Sambuc }
551f4a2713aSLionel Sambuc
552f4a2713aSLionel Sambuc /// \brief Handle \#pragma push_macro.
553f4a2713aSLionel Sambuc ///
554f4a2713aSLionel Sambuc /// The syntax is:
555f4a2713aSLionel Sambuc /// \code
556f4a2713aSLionel Sambuc /// #pragma push_macro("macro")
557f4a2713aSLionel Sambuc /// \endcode
HandlePragmaPushMacro(Token & PushMacroTok)558f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
559f4a2713aSLionel Sambuc // Parse the pragma directive and get the macro IdentifierInfo*.
560f4a2713aSLionel Sambuc IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PushMacroTok);
561f4a2713aSLionel Sambuc if (!IdentInfo) return;
562f4a2713aSLionel Sambuc
563f4a2713aSLionel Sambuc // Get the MacroInfo associated with IdentInfo.
564f4a2713aSLionel Sambuc MacroInfo *MI = getMacroInfo(IdentInfo);
565f4a2713aSLionel Sambuc
566f4a2713aSLionel Sambuc if (MI) {
567f4a2713aSLionel Sambuc // Allow the original MacroInfo to be redefined later.
568f4a2713aSLionel Sambuc MI->setIsAllowRedefinitionsWithoutWarning(true);
569f4a2713aSLionel Sambuc }
570f4a2713aSLionel Sambuc
571f4a2713aSLionel Sambuc // Push the cloned MacroInfo so we can retrieve it later.
572f4a2713aSLionel Sambuc PragmaPushMacroInfo[IdentInfo].push_back(MI);
573f4a2713aSLionel Sambuc }
574f4a2713aSLionel Sambuc
575f4a2713aSLionel Sambuc /// \brief Handle \#pragma pop_macro.
576f4a2713aSLionel Sambuc ///
577f4a2713aSLionel Sambuc /// The syntax is:
578f4a2713aSLionel Sambuc /// \code
579f4a2713aSLionel Sambuc /// #pragma pop_macro("macro")
580f4a2713aSLionel Sambuc /// \endcode
HandlePragmaPopMacro(Token & PopMacroTok)581f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
582f4a2713aSLionel Sambuc SourceLocation MessageLoc = PopMacroTok.getLocation();
583f4a2713aSLionel Sambuc
584f4a2713aSLionel Sambuc // Parse the pragma directive and get the macro IdentifierInfo*.
585f4a2713aSLionel Sambuc IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok);
586f4a2713aSLionel Sambuc if (!IdentInfo) return;
587f4a2713aSLionel Sambuc
588f4a2713aSLionel Sambuc // Find the vector<MacroInfo*> associated with the macro.
589f4a2713aSLionel Sambuc llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter =
590f4a2713aSLionel Sambuc PragmaPushMacroInfo.find(IdentInfo);
591f4a2713aSLionel Sambuc if (iter != PragmaPushMacroInfo.end()) {
592f4a2713aSLionel Sambuc // Forget the MacroInfo currently associated with IdentInfo.
593f4a2713aSLionel Sambuc if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) {
594f4a2713aSLionel Sambuc MacroInfo *MI = CurrentMD->getMacroInfo();
595f4a2713aSLionel Sambuc if (MI->isWarnIfUnused())
596f4a2713aSLionel Sambuc WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
597f4a2713aSLionel Sambuc appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc));
598f4a2713aSLionel Sambuc }
599f4a2713aSLionel Sambuc
600f4a2713aSLionel Sambuc // Get the MacroInfo we want to reinstall.
601f4a2713aSLionel Sambuc MacroInfo *MacroToReInstall = iter->second.back();
602f4a2713aSLionel Sambuc
603f4a2713aSLionel Sambuc if (MacroToReInstall) {
604f4a2713aSLionel Sambuc // Reinstall the previously pushed macro.
605f4a2713aSLionel Sambuc appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc,
606*0a6a1f1dSLionel Sambuc /*isImported=*/false, /*Overrides*/None);
607f4a2713aSLionel Sambuc }
608f4a2713aSLionel Sambuc
609f4a2713aSLionel Sambuc // Pop PragmaPushMacroInfo stack.
610f4a2713aSLionel Sambuc iter->second.pop_back();
611f4a2713aSLionel Sambuc if (iter->second.size() == 0)
612f4a2713aSLionel Sambuc PragmaPushMacroInfo.erase(iter);
613f4a2713aSLionel Sambuc } else {
614f4a2713aSLionel Sambuc Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push)
615f4a2713aSLionel Sambuc << IdentInfo->getName();
616f4a2713aSLionel Sambuc }
617f4a2713aSLionel Sambuc }
618f4a2713aSLionel Sambuc
HandlePragmaIncludeAlias(Token & Tok)619f4a2713aSLionel Sambuc void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
620f4a2713aSLionel Sambuc // We will either get a quoted filename or a bracketed filename, and we
621f4a2713aSLionel Sambuc // have to track which we got. The first filename is the source name,
622f4a2713aSLionel Sambuc // and the second name is the mapped filename. If the first is quoted,
623f4a2713aSLionel Sambuc // the second must be as well (cannot mix and match quotes and brackets).
624f4a2713aSLionel Sambuc
625f4a2713aSLionel Sambuc // Get the open paren
626f4a2713aSLionel Sambuc Lex(Tok);
627f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) {
628f4a2713aSLionel Sambuc Diag(Tok, diag::warn_pragma_include_alias_expected) << "(";
629f4a2713aSLionel Sambuc return;
630f4a2713aSLionel Sambuc }
631f4a2713aSLionel Sambuc
632f4a2713aSLionel Sambuc // We expect either a quoted string literal, or a bracketed name
633f4a2713aSLionel Sambuc Token SourceFilenameTok;
634f4a2713aSLionel Sambuc CurPPLexer->LexIncludeFilename(SourceFilenameTok);
635f4a2713aSLionel Sambuc if (SourceFilenameTok.is(tok::eod)) {
636f4a2713aSLionel Sambuc // The diagnostic has already been handled
637f4a2713aSLionel Sambuc return;
638f4a2713aSLionel Sambuc }
639f4a2713aSLionel Sambuc
640f4a2713aSLionel Sambuc StringRef SourceFileName;
641f4a2713aSLionel Sambuc SmallString<128> FileNameBuffer;
642f4a2713aSLionel Sambuc if (SourceFilenameTok.is(tok::string_literal) ||
643f4a2713aSLionel Sambuc SourceFilenameTok.is(tok::angle_string_literal)) {
644f4a2713aSLionel Sambuc SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
645f4a2713aSLionel Sambuc } else if (SourceFilenameTok.is(tok::less)) {
646f4a2713aSLionel Sambuc // This could be a path instead of just a name
647f4a2713aSLionel Sambuc FileNameBuffer.push_back('<');
648f4a2713aSLionel Sambuc SourceLocation End;
649f4a2713aSLionel Sambuc if (ConcatenateIncludeName(FileNameBuffer, End))
650f4a2713aSLionel Sambuc return; // Diagnostic already emitted
651f4a2713aSLionel Sambuc SourceFileName = FileNameBuffer.str();
652f4a2713aSLionel Sambuc } else {
653f4a2713aSLionel Sambuc Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
654f4a2713aSLionel Sambuc return;
655f4a2713aSLionel Sambuc }
656f4a2713aSLionel Sambuc FileNameBuffer.clear();
657f4a2713aSLionel Sambuc
658f4a2713aSLionel Sambuc // Now we expect a comma, followed by another include name
659f4a2713aSLionel Sambuc Lex(Tok);
660f4a2713aSLionel Sambuc if (Tok.isNot(tok::comma)) {
661f4a2713aSLionel Sambuc Diag(Tok, diag::warn_pragma_include_alias_expected) << ",";
662f4a2713aSLionel Sambuc return;
663f4a2713aSLionel Sambuc }
664f4a2713aSLionel Sambuc
665f4a2713aSLionel Sambuc Token ReplaceFilenameTok;
666f4a2713aSLionel Sambuc CurPPLexer->LexIncludeFilename(ReplaceFilenameTok);
667f4a2713aSLionel Sambuc if (ReplaceFilenameTok.is(tok::eod)) {
668f4a2713aSLionel Sambuc // The diagnostic has already been handled
669f4a2713aSLionel Sambuc return;
670f4a2713aSLionel Sambuc }
671f4a2713aSLionel Sambuc
672f4a2713aSLionel Sambuc StringRef ReplaceFileName;
673f4a2713aSLionel Sambuc if (ReplaceFilenameTok.is(tok::string_literal) ||
674f4a2713aSLionel Sambuc ReplaceFilenameTok.is(tok::angle_string_literal)) {
675f4a2713aSLionel Sambuc ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
676f4a2713aSLionel Sambuc } else if (ReplaceFilenameTok.is(tok::less)) {
677f4a2713aSLionel Sambuc // This could be a path instead of just a name
678f4a2713aSLionel Sambuc FileNameBuffer.push_back('<');
679f4a2713aSLionel Sambuc SourceLocation End;
680f4a2713aSLionel Sambuc if (ConcatenateIncludeName(FileNameBuffer, End))
681f4a2713aSLionel Sambuc return; // Diagnostic already emitted
682f4a2713aSLionel Sambuc ReplaceFileName = FileNameBuffer.str();
683f4a2713aSLionel Sambuc } else {
684f4a2713aSLionel Sambuc Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
685f4a2713aSLionel Sambuc return;
686f4a2713aSLionel Sambuc }
687f4a2713aSLionel Sambuc
688f4a2713aSLionel Sambuc // Finally, we expect the closing paren
689f4a2713aSLionel Sambuc Lex(Tok);
690f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) {
691f4a2713aSLionel Sambuc Diag(Tok, diag::warn_pragma_include_alias_expected) << ")";
692f4a2713aSLionel Sambuc return;
693f4a2713aSLionel Sambuc }
694f4a2713aSLionel Sambuc
695f4a2713aSLionel Sambuc // Now that we have the source and target filenames, we need to make sure
696f4a2713aSLionel Sambuc // they're both of the same type (angled vs non-angled)
697f4a2713aSLionel Sambuc StringRef OriginalSource = SourceFileName;
698f4a2713aSLionel Sambuc
699f4a2713aSLionel Sambuc bool SourceIsAngled =
700f4a2713aSLionel Sambuc GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
701f4a2713aSLionel Sambuc SourceFileName);
702f4a2713aSLionel Sambuc bool ReplaceIsAngled =
703f4a2713aSLionel Sambuc GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
704f4a2713aSLionel Sambuc ReplaceFileName);
705f4a2713aSLionel Sambuc if (!SourceFileName.empty() && !ReplaceFileName.empty() &&
706f4a2713aSLionel Sambuc (SourceIsAngled != ReplaceIsAngled)) {
707f4a2713aSLionel Sambuc unsigned int DiagID;
708f4a2713aSLionel Sambuc if (SourceIsAngled)
709f4a2713aSLionel Sambuc DiagID = diag::warn_pragma_include_alias_mismatch_angle;
710f4a2713aSLionel Sambuc else
711f4a2713aSLionel Sambuc DiagID = diag::warn_pragma_include_alias_mismatch_quote;
712f4a2713aSLionel Sambuc
713f4a2713aSLionel Sambuc Diag(SourceFilenameTok.getLocation(), DiagID)
714f4a2713aSLionel Sambuc << SourceFileName
715f4a2713aSLionel Sambuc << ReplaceFileName;
716f4a2713aSLionel Sambuc
717f4a2713aSLionel Sambuc return;
718f4a2713aSLionel Sambuc }
719f4a2713aSLionel Sambuc
720f4a2713aSLionel Sambuc // Now we can let the include handler know about this mapping
721f4a2713aSLionel Sambuc getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
722f4a2713aSLionel Sambuc }
723f4a2713aSLionel Sambuc
724f4a2713aSLionel Sambuc /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
725f4a2713aSLionel Sambuc /// If 'Namespace' is non-null, then it is a token required to exist on the
726f4a2713aSLionel Sambuc /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
AddPragmaHandler(StringRef Namespace,PragmaHandler * Handler)727f4a2713aSLionel Sambuc void Preprocessor::AddPragmaHandler(StringRef Namespace,
728f4a2713aSLionel Sambuc PragmaHandler *Handler) {
729*0a6a1f1dSLionel Sambuc PragmaNamespace *InsertNS = PragmaHandlers.get();
730f4a2713aSLionel Sambuc
731f4a2713aSLionel Sambuc // If this is specified to be in a namespace, step down into it.
732f4a2713aSLionel Sambuc if (!Namespace.empty()) {
733f4a2713aSLionel Sambuc // If there is already a pragma handler with the name of this namespace,
734f4a2713aSLionel Sambuc // we either have an error (directive with the same name as a namespace) or
735f4a2713aSLionel Sambuc // we already have the namespace to insert into.
736f4a2713aSLionel Sambuc if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) {
737f4a2713aSLionel Sambuc InsertNS = Existing->getIfNamespace();
738*0a6a1f1dSLionel Sambuc assert(InsertNS != nullptr && "Cannot have a pragma namespace and pragma"
739f4a2713aSLionel Sambuc " handler with the same name!");
740f4a2713aSLionel Sambuc } else {
741f4a2713aSLionel Sambuc // Otherwise, this namespace doesn't exist yet, create and insert the
742f4a2713aSLionel Sambuc // handler for it.
743f4a2713aSLionel Sambuc InsertNS = new PragmaNamespace(Namespace);
744f4a2713aSLionel Sambuc PragmaHandlers->AddPragma(InsertNS);
745f4a2713aSLionel Sambuc }
746f4a2713aSLionel Sambuc }
747f4a2713aSLionel Sambuc
748f4a2713aSLionel Sambuc // Check to make sure we don't already have a pragma for this identifier.
749f4a2713aSLionel Sambuc assert(!InsertNS->FindHandler(Handler->getName()) &&
750f4a2713aSLionel Sambuc "Pragma handler already exists for this identifier!");
751f4a2713aSLionel Sambuc InsertNS->AddPragma(Handler);
752f4a2713aSLionel Sambuc }
753f4a2713aSLionel Sambuc
754f4a2713aSLionel Sambuc /// RemovePragmaHandler - Remove the specific pragma handler from the
755f4a2713aSLionel Sambuc /// preprocessor. If \arg Namespace is non-null, then it should be the
756f4a2713aSLionel Sambuc /// namespace that \arg Handler was added to. It is an error to remove
757f4a2713aSLionel Sambuc /// a handler that has not been registered.
RemovePragmaHandler(StringRef Namespace,PragmaHandler * Handler)758f4a2713aSLionel Sambuc void Preprocessor::RemovePragmaHandler(StringRef Namespace,
759f4a2713aSLionel Sambuc PragmaHandler *Handler) {
760*0a6a1f1dSLionel Sambuc PragmaNamespace *NS = PragmaHandlers.get();
761f4a2713aSLionel Sambuc
762f4a2713aSLionel Sambuc // If this is specified to be in a namespace, step down into it.
763f4a2713aSLionel Sambuc if (!Namespace.empty()) {
764f4a2713aSLionel Sambuc PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace);
765f4a2713aSLionel Sambuc assert(Existing && "Namespace containing handler does not exist!");
766f4a2713aSLionel Sambuc
767f4a2713aSLionel Sambuc NS = Existing->getIfNamespace();
768f4a2713aSLionel Sambuc assert(NS && "Invalid namespace, registered as a regular pragma handler!");
769f4a2713aSLionel Sambuc }
770f4a2713aSLionel Sambuc
771f4a2713aSLionel Sambuc NS->RemovePragmaHandler(Handler);
772f4a2713aSLionel Sambuc
773*0a6a1f1dSLionel Sambuc // If this is a non-default namespace and it is now empty, remove it.
774*0a6a1f1dSLionel Sambuc if (NS != PragmaHandlers.get() && NS->IsEmpty()) {
775f4a2713aSLionel Sambuc PragmaHandlers->RemovePragmaHandler(NS);
776f4a2713aSLionel Sambuc delete NS;
777f4a2713aSLionel Sambuc }
778f4a2713aSLionel Sambuc }
779f4a2713aSLionel Sambuc
LexOnOffSwitch(tok::OnOffSwitch & Result)780f4a2713aSLionel Sambuc bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) {
781f4a2713aSLionel Sambuc Token Tok;
782f4a2713aSLionel Sambuc LexUnexpandedToken(Tok);
783f4a2713aSLionel Sambuc
784f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) {
785f4a2713aSLionel Sambuc Diag(Tok, diag::ext_on_off_switch_syntax);
786f4a2713aSLionel Sambuc return true;
787f4a2713aSLionel Sambuc }
788f4a2713aSLionel Sambuc IdentifierInfo *II = Tok.getIdentifierInfo();
789f4a2713aSLionel Sambuc if (II->isStr("ON"))
790f4a2713aSLionel Sambuc Result = tok::OOS_ON;
791f4a2713aSLionel Sambuc else if (II->isStr("OFF"))
792f4a2713aSLionel Sambuc Result = tok::OOS_OFF;
793f4a2713aSLionel Sambuc else if (II->isStr("DEFAULT"))
794f4a2713aSLionel Sambuc Result = tok::OOS_DEFAULT;
795f4a2713aSLionel Sambuc else {
796f4a2713aSLionel Sambuc Diag(Tok, diag::ext_on_off_switch_syntax);
797f4a2713aSLionel Sambuc return true;
798f4a2713aSLionel Sambuc }
799f4a2713aSLionel Sambuc
800f4a2713aSLionel Sambuc // Verify that this is followed by EOD.
801f4a2713aSLionel Sambuc LexUnexpandedToken(Tok);
802f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod))
803f4a2713aSLionel Sambuc Diag(Tok, diag::ext_pragma_syntax_eod);
804f4a2713aSLionel Sambuc return false;
805f4a2713aSLionel Sambuc }
806f4a2713aSLionel Sambuc
807f4a2713aSLionel Sambuc namespace {
808f4a2713aSLionel Sambuc /// PragmaOnceHandler - "\#pragma once" marks the file as atomically included.
809f4a2713aSLionel Sambuc struct PragmaOnceHandler : public PragmaHandler {
PragmaOnceHandler__anon8441e45d0211::PragmaOnceHandler810f4a2713aSLionel Sambuc PragmaOnceHandler() : PragmaHandler("once") {}
HandlePragma__anon8441e45d0211::PragmaOnceHandler811*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
812*0a6a1f1dSLionel Sambuc Token &OnceTok) override {
813f4a2713aSLionel Sambuc PP.CheckEndOfDirective("pragma once");
814f4a2713aSLionel Sambuc PP.HandlePragmaOnce(OnceTok);
815f4a2713aSLionel Sambuc }
816f4a2713aSLionel Sambuc };
817f4a2713aSLionel Sambuc
818f4a2713aSLionel Sambuc /// PragmaMarkHandler - "\#pragma mark ..." is ignored by the compiler, and the
819f4a2713aSLionel Sambuc /// rest of the line is not lexed.
820f4a2713aSLionel Sambuc struct PragmaMarkHandler : public PragmaHandler {
PragmaMarkHandler__anon8441e45d0211::PragmaMarkHandler821f4a2713aSLionel Sambuc PragmaMarkHandler() : PragmaHandler("mark") {}
HandlePragma__anon8441e45d0211::PragmaMarkHandler822*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
823*0a6a1f1dSLionel Sambuc Token &MarkTok) override {
824f4a2713aSLionel Sambuc PP.HandlePragmaMark();
825f4a2713aSLionel Sambuc }
826f4a2713aSLionel Sambuc };
827f4a2713aSLionel Sambuc
828f4a2713aSLionel Sambuc /// PragmaPoisonHandler - "\#pragma poison x" marks x as not usable.
829f4a2713aSLionel Sambuc struct PragmaPoisonHandler : public PragmaHandler {
PragmaPoisonHandler__anon8441e45d0211::PragmaPoisonHandler830f4a2713aSLionel Sambuc PragmaPoisonHandler() : PragmaHandler("poison") {}
HandlePragma__anon8441e45d0211::PragmaPoisonHandler831*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
832*0a6a1f1dSLionel Sambuc Token &PoisonTok) override {
833f4a2713aSLionel Sambuc PP.HandlePragmaPoison(PoisonTok);
834f4a2713aSLionel Sambuc }
835f4a2713aSLionel Sambuc };
836f4a2713aSLionel Sambuc
837f4a2713aSLionel Sambuc /// PragmaSystemHeaderHandler - "\#pragma system_header" marks the current file
838f4a2713aSLionel Sambuc /// as a system header, which silences warnings in it.
839f4a2713aSLionel Sambuc struct PragmaSystemHeaderHandler : public PragmaHandler {
PragmaSystemHeaderHandler__anon8441e45d0211::PragmaSystemHeaderHandler840f4a2713aSLionel Sambuc PragmaSystemHeaderHandler() : PragmaHandler("system_header") {}
HandlePragma__anon8441e45d0211::PragmaSystemHeaderHandler841*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
842*0a6a1f1dSLionel Sambuc Token &SHToken) override {
843f4a2713aSLionel Sambuc PP.HandlePragmaSystemHeader(SHToken);
844f4a2713aSLionel Sambuc PP.CheckEndOfDirective("pragma");
845f4a2713aSLionel Sambuc }
846f4a2713aSLionel Sambuc };
847f4a2713aSLionel Sambuc struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler__anon8441e45d0211::PragmaDependencyHandler848f4a2713aSLionel Sambuc PragmaDependencyHandler() : PragmaHandler("dependency") {}
HandlePragma__anon8441e45d0211::PragmaDependencyHandler849*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
850*0a6a1f1dSLionel Sambuc Token &DepToken) override {
851f4a2713aSLionel Sambuc PP.HandlePragmaDependency(DepToken);
852f4a2713aSLionel Sambuc }
853f4a2713aSLionel Sambuc };
854f4a2713aSLionel Sambuc
855f4a2713aSLionel Sambuc struct PragmaDebugHandler : public PragmaHandler {
PragmaDebugHandler__anon8441e45d0211::PragmaDebugHandler856f4a2713aSLionel Sambuc PragmaDebugHandler() : PragmaHandler("__debug") {}
HandlePragma__anon8441e45d0211::PragmaDebugHandler857*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
858*0a6a1f1dSLionel Sambuc Token &DepToken) override {
859f4a2713aSLionel Sambuc Token Tok;
860f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
861f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) {
862f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
863f4a2713aSLionel Sambuc return;
864f4a2713aSLionel Sambuc }
865f4a2713aSLionel Sambuc IdentifierInfo *II = Tok.getIdentifierInfo();
866f4a2713aSLionel Sambuc
867f4a2713aSLionel Sambuc if (II->isStr("assert")) {
868f4a2713aSLionel Sambuc llvm_unreachable("This is an assertion!");
869f4a2713aSLionel Sambuc } else if (II->isStr("crash")) {
870f4a2713aSLionel Sambuc LLVM_BUILTIN_TRAP;
871f4a2713aSLionel Sambuc } else if (II->isStr("parser_crash")) {
872f4a2713aSLionel Sambuc Token Crasher;
873f4a2713aSLionel Sambuc Crasher.setKind(tok::annot_pragma_parser_crash);
874f4a2713aSLionel Sambuc PP.EnterToken(Crasher);
875f4a2713aSLionel Sambuc } else if (II->isStr("llvm_fatal_error")) {
876f4a2713aSLionel Sambuc llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
877f4a2713aSLionel Sambuc } else if (II->isStr("llvm_unreachable")) {
878f4a2713aSLionel Sambuc llvm_unreachable("#pragma clang __debug llvm_unreachable");
879f4a2713aSLionel Sambuc } else if (II->isStr("overflow_stack")) {
880f4a2713aSLionel Sambuc DebugOverflowStack();
881f4a2713aSLionel Sambuc } else if (II->isStr("handle_crash")) {
882f4a2713aSLionel Sambuc llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent();
883f4a2713aSLionel Sambuc if (CRC)
884f4a2713aSLionel Sambuc CRC->HandleCrash();
885f4a2713aSLionel Sambuc } else if (II->isStr("captured")) {
886f4a2713aSLionel Sambuc HandleCaptured(PP);
887f4a2713aSLionel Sambuc } else {
888f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
889f4a2713aSLionel Sambuc << II->getName();
890f4a2713aSLionel Sambuc }
891f4a2713aSLionel Sambuc
892f4a2713aSLionel Sambuc PPCallbacks *Callbacks = PP.getPPCallbacks();
893f4a2713aSLionel Sambuc if (Callbacks)
894f4a2713aSLionel Sambuc Callbacks->PragmaDebug(Tok.getLocation(), II->getName());
895f4a2713aSLionel Sambuc }
896f4a2713aSLionel Sambuc
HandleCaptured__anon8441e45d0211::PragmaDebugHandler897f4a2713aSLionel Sambuc void HandleCaptured(Preprocessor &PP) {
898f4a2713aSLionel Sambuc // Skip if emitting preprocessed output.
899f4a2713aSLionel Sambuc if (PP.isPreprocessedOutput())
900f4a2713aSLionel Sambuc return;
901f4a2713aSLionel Sambuc
902f4a2713aSLionel Sambuc Token Tok;
903f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
904f4a2713aSLionel Sambuc
905f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod)) {
906f4a2713aSLionel Sambuc PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol)
907f4a2713aSLionel Sambuc << "pragma clang __debug captured";
908f4a2713aSLionel Sambuc return;
909f4a2713aSLionel Sambuc }
910f4a2713aSLionel Sambuc
911f4a2713aSLionel Sambuc SourceLocation NameLoc = Tok.getLocation();
912f4a2713aSLionel Sambuc Token *Toks = PP.getPreprocessorAllocator().Allocate<Token>(1);
913f4a2713aSLionel Sambuc Toks->startToken();
914f4a2713aSLionel Sambuc Toks->setKind(tok::annot_pragma_captured);
915f4a2713aSLionel Sambuc Toks->setLocation(NameLoc);
916f4a2713aSLionel Sambuc
917f4a2713aSLionel Sambuc PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
918f4a2713aSLionel Sambuc /*OwnsTokens=*/false);
919f4a2713aSLionel Sambuc }
920f4a2713aSLionel Sambuc
921f4a2713aSLionel Sambuc // Disable MSVC warning about runtime stack overflow.
922f4a2713aSLionel Sambuc #ifdef _MSC_VER
923f4a2713aSLionel Sambuc #pragma warning(disable : 4717)
924f4a2713aSLionel Sambuc #endif
DebugOverflowStack__anon8441e45d0211::PragmaDebugHandler925*0a6a1f1dSLionel Sambuc static void DebugOverflowStack() {
926*0a6a1f1dSLionel Sambuc void (*volatile Self)() = DebugOverflowStack;
927*0a6a1f1dSLionel Sambuc Self();
928f4a2713aSLionel Sambuc }
929f4a2713aSLionel Sambuc #ifdef _MSC_VER
930f4a2713aSLionel Sambuc #pragma warning(default : 4717)
931f4a2713aSLionel Sambuc #endif
932f4a2713aSLionel Sambuc
933f4a2713aSLionel Sambuc };
934f4a2713aSLionel Sambuc
935f4a2713aSLionel Sambuc /// PragmaDiagnosticHandler - e.g. '\#pragma GCC diagnostic ignored "-Wformat"'
936f4a2713aSLionel Sambuc struct PragmaDiagnosticHandler : public PragmaHandler {
937f4a2713aSLionel Sambuc private:
938f4a2713aSLionel Sambuc const char *Namespace;
939f4a2713aSLionel Sambuc public:
PragmaDiagnosticHandler__anon8441e45d0211::PragmaDiagnosticHandler940f4a2713aSLionel Sambuc explicit PragmaDiagnosticHandler(const char *NS) :
941f4a2713aSLionel Sambuc PragmaHandler("diagnostic"), Namespace(NS) {}
HandlePragma__anon8441e45d0211::PragmaDiagnosticHandler942*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
943*0a6a1f1dSLionel Sambuc Token &DiagToken) override {
944f4a2713aSLionel Sambuc SourceLocation DiagLoc = DiagToken.getLocation();
945f4a2713aSLionel Sambuc Token Tok;
946f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
947f4a2713aSLionel Sambuc if (Tok.isNot(tok::identifier)) {
948f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
949f4a2713aSLionel Sambuc return;
950f4a2713aSLionel Sambuc }
951f4a2713aSLionel Sambuc IdentifierInfo *II = Tok.getIdentifierInfo();
952f4a2713aSLionel Sambuc PPCallbacks *Callbacks = PP.getPPCallbacks();
953f4a2713aSLionel Sambuc
954*0a6a1f1dSLionel Sambuc if (II->isStr("pop")) {
955f4a2713aSLionel Sambuc if (!PP.getDiagnostics().popMappings(DiagLoc))
956f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
957f4a2713aSLionel Sambuc else if (Callbacks)
958f4a2713aSLionel Sambuc Callbacks->PragmaDiagnosticPop(DiagLoc, Namespace);
959f4a2713aSLionel Sambuc return;
960f4a2713aSLionel Sambuc } else if (II->isStr("push")) {
961f4a2713aSLionel Sambuc PP.getDiagnostics().pushMappings(DiagLoc);
962f4a2713aSLionel Sambuc if (Callbacks)
963f4a2713aSLionel Sambuc Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace);
964f4a2713aSLionel Sambuc return;
965*0a6a1f1dSLionel Sambuc }
966*0a6a1f1dSLionel Sambuc
967*0a6a1f1dSLionel Sambuc diag::Severity SV = llvm::StringSwitch<diag::Severity>(II->getName())
968*0a6a1f1dSLionel Sambuc .Case("ignored", diag::Severity::Ignored)
969*0a6a1f1dSLionel Sambuc .Case("warning", diag::Severity::Warning)
970*0a6a1f1dSLionel Sambuc .Case("error", diag::Severity::Error)
971*0a6a1f1dSLionel Sambuc .Case("fatal", diag::Severity::Fatal)
972*0a6a1f1dSLionel Sambuc .Default(diag::Severity());
973*0a6a1f1dSLionel Sambuc
974*0a6a1f1dSLionel Sambuc if (SV == diag::Severity()) {
975f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
976f4a2713aSLionel Sambuc return;
977f4a2713aSLionel Sambuc }
978f4a2713aSLionel Sambuc
979f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
980f4a2713aSLionel Sambuc SourceLocation StringLoc = Tok.getLocation();
981f4a2713aSLionel Sambuc
982f4a2713aSLionel Sambuc std::string WarningName;
983f4a2713aSLionel Sambuc if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic",
984f4a2713aSLionel Sambuc /*MacroExpansion=*/false))
985f4a2713aSLionel Sambuc return;
986f4a2713aSLionel Sambuc
987f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod)) {
988f4a2713aSLionel Sambuc PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
989f4a2713aSLionel Sambuc return;
990f4a2713aSLionel Sambuc }
991f4a2713aSLionel Sambuc
992f4a2713aSLionel Sambuc if (WarningName.size() < 3 || WarningName[0] != '-' ||
993*0a6a1f1dSLionel Sambuc (WarningName[1] != 'W' && WarningName[1] != 'R')) {
994f4a2713aSLionel Sambuc PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option);
995f4a2713aSLionel Sambuc return;
996f4a2713aSLionel Sambuc }
997f4a2713aSLionel Sambuc
998*0a6a1f1dSLionel Sambuc if (PP.getDiagnostics().setSeverityForGroup(
999*0a6a1f1dSLionel Sambuc WarningName[1] == 'W' ? diag::Flavor::WarningOrError
1000*0a6a1f1dSLionel Sambuc : diag::Flavor::Remark,
1001*0a6a1f1dSLionel Sambuc WarningName.substr(2), SV, DiagLoc))
1002f4a2713aSLionel Sambuc PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning)
1003f4a2713aSLionel Sambuc << WarningName;
1004f4a2713aSLionel Sambuc else if (Callbacks)
1005*0a6a1f1dSLionel Sambuc Callbacks->PragmaDiagnostic(DiagLoc, Namespace, SV, WarningName);
1006f4a2713aSLionel Sambuc }
1007f4a2713aSLionel Sambuc };
1008f4a2713aSLionel Sambuc
1009f4a2713aSLionel Sambuc /// "\#pragma warning(...)". MSVC's diagnostics do not map cleanly to clang's
1010f4a2713aSLionel Sambuc /// diagnostics, so we don't really implement this pragma. We parse it and
1011f4a2713aSLionel Sambuc /// ignore it to avoid -Wunknown-pragma warnings.
1012f4a2713aSLionel Sambuc struct PragmaWarningHandler : public PragmaHandler {
PragmaWarningHandler__anon8441e45d0211::PragmaWarningHandler1013f4a2713aSLionel Sambuc PragmaWarningHandler() : PragmaHandler("warning") {}
1014f4a2713aSLionel Sambuc
HandlePragma__anon8441e45d0211::PragmaWarningHandler1015*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1016*0a6a1f1dSLionel Sambuc Token &Tok) override {
1017f4a2713aSLionel Sambuc // Parse things like:
1018f4a2713aSLionel Sambuc // warning(push, 1)
1019f4a2713aSLionel Sambuc // warning(pop)
1020f4a2713aSLionel Sambuc // warning(disable : 1 2 3 ; error : 4 5 6 ; suppress : 7 8 9)
1021f4a2713aSLionel Sambuc SourceLocation DiagLoc = Tok.getLocation();
1022f4a2713aSLionel Sambuc PPCallbacks *Callbacks = PP.getPPCallbacks();
1023f4a2713aSLionel Sambuc
1024f4a2713aSLionel Sambuc PP.Lex(Tok);
1025f4a2713aSLionel Sambuc if (Tok.isNot(tok::l_paren)) {
1026f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_expected) << "(";
1027f4a2713aSLionel Sambuc return;
1028f4a2713aSLionel Sambuc }
1029f4a2713aSLionel Sambuc
1030f4a2713aSLionel Sambuc PP.Lex(Tok);
1031f4a2713aSLionel Sambuc IdentifierInfo *II = Tok.getIdentifierInfo();
1032f4a2713aSLionel Sambuc if (!II) {
1033f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
1034f4a2713aSLionel Sambuc return;
1035f4a2713aSLionel Sambuc }
1036f4a2713aSLionel Sambuc
1037f4a2713aSLionel Sambuc if (II->isStr("push")) {
1038f4a2713aSLionel Sambuc // #pragma warning( push[ ,n ] )
1039f4a2713aSLionel Sambuc int Level = -1;
1040f4a2713aSLionel Sambuc PP.Lex(Tok);
1041f4a2713aSLionel Sambuc if (Tok.is(tok::comma)) {
1042f4a2713aSLionel Sambuc PP.Lex(Tok);
1043*0a6a1f1dSLionel Sambuc uint64_t Value;
1044*0a6a1f1dSLionel Sambuc if (Tok.is(tok::numeric_constant) &&
1045*0a6a1f1dSLionel Sambuc PP.parseSimpleIntegerLiteral(Tok, Value))
1046*0a6a1f1dSLionel Sambuc Level = int(Value);
1047f4a2713aSLionel Sambuc if (Level < 0 || Level > 4) {
1048f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_push_level);
1049f4a2713aSLionel Sambuc return;
1050f4a2713aSLionel Sambuc }
1051f4a2713aSLionel Sambuc }
1052f4a2713aSLionel Sambuc if (Callbacks)
1053f4a2713aSLionel Sambuc Callbacks->PragmaWarningPush(DiagLoc, Level);
1054f4a2713aSLionel Sambuc } else if (II->isStr("pop")) {
1055f4a2713aSLionel Sambuc // #pragma warning( pop )
1056f4a2713aSLionel Sambuc PP.Lex(Tok);
1057f4a2713aSLionel Sambuc if (Callbacks)
1058f4a2713aSLionel Sambuc Callbacks->PragmaWarningPop(DiagLoc);
1059f4a2713aSLionel Sambuc } else {
1060f4a2713aSLionel Sambuc // #pragma warning( warning-specifier : warning-number-list
1061f4a2713aSLionel Sambuc // [; warning-specifier : warning-number-list...] )
1062f4a2713aSLionel Sambuc while (true) {
1063f4a2713aSLionel Sambuc II = Tok.getIdentifierInfo();
1064f4a2713aSLionel Sambuc if (!II) {
1065f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
1066f4a2713aSLionel Sambuc return;
1067f4a2713aSLionel Sambuc }
1068f4a2713aSLionel Sambuc
1069f4a2713aSLionel Sambuc // Figure out which warning specifier this is.
1070f4a2713aSLionel Sambuc StringRef Specifier = II->getName();
1071f4a2713aSLionel Sambuc bool SpecifierValid =
1072f4a2713aSLionel Sambuc llvm::StringSwitch<bool>(Specifier)
1073f4a2713aSLionel Sambuc .Cases("1", "2", "3", "4", true)
1074f4a2713aSLionel Sambuc .Cases("default", "disable", "error", "once", "suppress", true)
1075f4a2713aSLionel Sambuc .Default(false);
1076f4a2713aSLionel Sambuc if (!SpecifierValid) {
1077f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
1078f4a2713aSLionel Sambuc return;
1079f4a2713aSLionel Sambuc }
1080f4a2713aSLionel Sambuc PP.Lex(Tok);
1081f4a2713aSLionel Sambuc if (Tok.isNot(tok::colon)) {
1082f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":";
1083f4a2713aSLionel Sambuc return;
1084f4a2713aSLionel Sambuc }
1085f4a2713aSLionel Sambuc
1086f4a2713aSLionel Sambuc // Collect the warning ids.
1087f4a2713aSLionel Sambuc SmallVector<int, 4> Ids;
1088f4a2713aSLionel Sambuc PP.Lex(Tok);
1089f4a2713aSLionel Sambuc while (Tok.is(tok::numeric_constant)) {
1090*0a6a1f1dSLionel Sambuc uint64_t Value;
1091*0a6a1f1dSLionel Sambuc if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 ||
1092*0a6a1f1dSLionel Sambuc Value > INT_MAX) {
1093f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_expected_number);
1094f4a2713aSLionel Sambuc return;
1095f4a2713aSLionel Sambuc }
1096*0a6a1f1dSLionel Sambuc Ids.push_back(int(Value));
1097f4a2713aSLionel Sambuc }
1098f4a2713aSLionel Sambuc if (Callbacks)
1099f4a2713aSLionel Sambuc Callbacks->PragmaWarning(DiagLoc, Specifier, Ids);
1100f4a2713aSLionel Sambuc
1101f4a2713aSLionel Sambuc // Parse the next specifier if there is a semicolon.
1102f4a2713aSLionel Sambuc if (Tok.isNot(tok::semi))
1103f4a2713aSLionel Sambuc break;
1104f4a2713aSLionel Sambuc PP.Lex(Tok);
1105f4a2713aSLionel Sambuc }
1106f4a2713aSLionel Sambuc }
1107f4a2713aSLionel Sambuc
1108f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) {
1109f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_pragma_warning_expected) << ")";
1110f4a2713aSLionel Sambuc return;
1111f4a2713aSLionel Sambuc }
1112f4a2713aSLionel Sambuc
1113f4a2713aSLionel Sambuc PP.Lex(Tok);
1114f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod))
1115f4a2713aSLionel Sambuc PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma warning";
1116f4a2713aSLionel Sambuc }
1117f4a2713aSLionel Sambuc };
1118f4a2713aSLionel Sambuc
1119f4a2713aSLionel Sambuc /// PragmaIncludeAliasHandler - "\#pragma include_alias("...")".
1120f4a2713aSLionel Sambuc struct PragmaIncludeAliasHandler : public PragmaHandler {
PragmaIncludeAliasHandler__anon8441e45d0211::PragmaIncludeAliasHandler1121f4a2713aSLionel Sambuc PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
HandlePragma__anon8441e45d0211::PragmaIncludeAliasHandler1122*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1123*0a6a1f1dSLionel Sambuc Token &IncludeAliasTok) override {
1124f4a2713aSLionel Sambuc PP.HandlePragmaIncludeAlias(IncludeAliasTok);
1125f4a2713aSLionel Sambuc }
1126f4a2713aSLionel Sambuc };
1127f4a2713aSLionel Sambuc
1128f4a2713aSLionel Sambuc /// PragmaMessageHandler - Handle the microsoft and gcc \#pragma message
1129f4a2713aSLionel Sambuc /// extension. The syntax is:
1130f4a2713aSLionel Sambuc /// \code
1131f4a2713aSLionel Sambuc /// #pragma message(string)
1132f4a2713aSLionel Sambuc /// \endcode
1133f4a2713aSLionel Sambuc /// OR, in GCC mode:
1134f4a2713aSLionel Sambuc /// \code
1135f4a2713aSLionel Sambuc /// #pragma message string
1136f4a2713aSLionel Sambuc /// \endcode
1137f4a2713aSLionel Sambuc /// string is a string, which is fully macro expanded, and permits string
1138f4a2713aSLionel Sambuc /// concatenation, embedded escape characters, etc... See MSDN for more details.
1139f4a2713aSLionel Sambuc /// Also handles \#pragma GCC warning and \#pragma GCC error which take the same
1140f4a2713aSLionel Sambuc /// form as \#pragma message.
1141f4a2713aSLionel Sambuc struct PragmaMessageHandler : public PragmaHandler {
1142f4a2713aSLionel Sambuc private:
1143f4a2713aSLionel Sambuc const PPCallbacks::PragmaMessageKind Kind;
1144f4a2713aSLionel Sambuc const StringRef Namespace;
1145f4a2713aSLionel Sambuc
PragmaKind__anon8441e45d0211::PragmaMessageHandler1146f4a2713aSLionel Sambuc static const char* PragmaKind(PPCallbacks::PragmaMessageKind Kind,
1147f4a2713aSLionel Sambuc bool PragmaNameOnly = false) {
1148f4a2713aSLionel Sambuc switch (Kind) {
1149f4a2713aSLionel Sambuc case PPCallbacks::PMK_Message:
1150f4a2713aSLionel Sambuc return PragmaNameOnly ? "message" : "pragma message";
1151f4a2713aSLionel Sambuc case PPCallbacks::PMK_Warning:
1152f4a2713aSLionel Sambuc return PragmaNameOnly ? "warning" : "pragma warning";
1153f4a2713aSLionel Sambuc case PPCallbacks::PMK_Error:
1154f4a2713aSLionel Sambuc return PragmaNameOnly ? "error" : "pragma error";
1155f4a2713aSLionel Sambuc }
1156f4a2713aSLionel Sambuc llvm_unreachable("Unknown PragmaMessageKind!");
1157f4a2713aSLionel Sambuc }
1158f4a2713aSLionel Sambuc
1159f4a2713aSLionel Sambuc public:
PragmaMessageHandler__anon8441e45d0211::PragmaMessageHandler1160f4a2713aSLionel Sambuc PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind,
1161f4a2713aSLionel Sambuc StringRef Namespace = StringRef())
1162f4a2713aSLionel Sambuc : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), Namespace(Namespace) {}
1163f4a2713aSLionel Sambuc
HandlePragma__anon8441e45d0211::PragmaMessageHandler1164*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1165*0a6a1f1dSLionel Sambuc Token &Tok) override {
1166f4a2713aSLionel Sambuc SourceLocation MessageLoc = Tok.getLocation();
1167f4a2713aSLionel Sambuc PP.Lex(Tok);
1168f4a2713aSLionel Sambuc bool ExpectClosingParen = false;
1169f4a2713aSLionel Sambuc switch (Tok.getKind()) {
1170f4a2713aSLionel Sambuc case tok::l_paren:
1171f4a2713aSLionel Sambuc // We have a MSVC style pragma message.
1172f4a2713aSLionel Sambuc ExpectClosingParen = true;
1173f4a2713aSLionel Sambuc // Read the string.
1174f4a2713aSLionel Sambuc PP.Lex(Tok);
1175f4a2713aSLionel Sambuc break;
1176f4a2713aSLionel Sambuc case tok::string_literal:
1177f4a2713aSLionel Sambuc // We have a GCC style pragma message, and we just read the string.
1178f4a2713aSLionel Sambuc break;
1179f4a2713aSLionel Sambuc default:
1180f4a2713aSLionel Sambuc PP.Diag(MessageLoc, diag::err_pragma_message_malformed) << Kind;
1181f4a2713aSLionel Sambuc return;
1182f4a2713aSLionel Sambuc }
1183f4a2713aSLionel Sambuc
1184f4a2713aSLionel Sambuc std::string MessageString;
1185f4a2713aSLionel Sambuc if (!PP.FinishLexStringLiteral(Tok, MessageString, PragmaKind(Kind),
1186f4a2713aSLionel Sambuc /*MacroExpansion=*/true))
1187f4a2713aSLionel Sambuc return;
1188f4a2713aSLionel Sambuc
1189f4a2713aSLionel Sambuc if (ExpectClosingParen) {
1190f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren)) {
1191f4a2713aSLionel Sambuc PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind;
1192f4a2713aSLionel Sambuc return;
1193f4a2713aSLionel Sambuc }
1194f4a2713aSLionel Sambuc PP.Lex(Tok); // eat the r_paren.
1195f4a2713aSLionel Sambuc }
1196f4a2713aSLionel Sambuc
1197f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod)) {
1198f4a2713aSLionel Sambuc PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind;
1199f4a2713aSLionel Sambuc return;
1200f4a2713aSLionel Sambuc }
1201f4a2713aSLionel Sambuc
1202f4a2713aSLionel Sambuc // Output the message.
1203f4a2713aSLionel Sambuc PP.Diag(MessageLoc, (Kind == PPCallbacks::PMK_Error)
1204f4a2713aSLionel Sambuc ? diag::err_pragma_message
1205f4a2713aSLionel Sambuc : diag::warn_pragma_message) << MessageString;
1206f4a2713aSLionel Sambuc
1207f4a2713aSLionel Sambuc // If the pragma is lexically sound, notify any interested PPCallbacks.
1208f4a2713aSLionel Sambuc if (PPCallbacks *Callbacks = PP.getPPCallbacks())
1209f4a2713aSLionel Sambuc Callbacks->PragmaMessage(MessageLoc, Namespace, Kind, MessageString);
1210f4a2713aSLionel Sambuc }
1211f4a2713aSLionel Sambuc };
1212f4a2713aSLionel Sambuc
1213f4a2713aSLionel Sambuc /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the
1214f4a2713aSLionel Sambuc /// macro on the top of the stack.
1215f4a2713aSLionel Sambuc struct PragmaPushMacroHandler : public PragmaHandler {
PragmaPushMacroHandler__anon8441e45d0211::PragmaPushMacroHandler1216f4a2713aSLionel Sambuc PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
HandlePragma__anon8441e45d0211::PragmaPushMacroHandler1217*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1218*0a6a1f1dSLionel Sambuc Token &PushMacroTok) override {
1219f4a2713aSLionel Sambuc PP.HandlePragmaPushMacro(PushMacroTok);
1220f4a2713aSLionel Sambuc }
1221f4a2713aSLionel Sambuc };
1222f4a2713aSLionel Sambuc
1223f4a2713aSLionel Sambuc
1224f4a2713aSLionel Sambuc /// PragmaPopMacroHandler - "\#pragma pop_macro" sets the value of the
1225f4a2713aSLionel Sambuc /// macro to the value on the top of the stack.
1226f4a2713aSLionel Sambuc struct PragmaPopMacroHandler : public PragmaHandler {
PragmaPopMacroHandler__anon8441e45d0211::PragmaPopMacroHandler1227f4a2713aSLionel Sambuc PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
HandlePragma__anon8441e45d0211::PragmaPopMacroHandler1228*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1229*0a6a1f1dSLionel Sambuc Token &PopMacroTok) override {
1230f4a2713aSLionel Sambuc PP.HandlePragmaPopMacro(PopMacroTok);
1231f4a2713aSLionel Sambuc }
1232f4a2713aSLionel Sambuc };
1233f4a2713aSLionel Sambuc
1234f4a2713aSLionel Sambuc // Pragma STDC implementations.
1235f4a2713aSLionel Sambuc
1236f4a2713aSLionel Sambuc /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
1237f4a2713aSLionel Sambuc struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler__anon8441e45d0211::PragmaSTDC_FENV_ACCESSHandler1238f4a2713aSLionel Sambuc PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
HandlePragma__anon8441e45d0211::PragmaSTDC_FENV_ACCESSHandler1239*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1240*0a6a1f1dSLionel Sambuc Token &Tok) override {
1241f4a2713aSLionel Sambuc tok::OnOffSwitch OOS;
1242f4a2713aSLionel Sambuc if (PP.LexOnOffSwitch(OOS))
1243f4a2713aSLionel Sambuc return;
1244f4a2713aSLionel Sambuc if (OOS == tok::OOS_ON)
1245f4a2713aSLionel Sambuc PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
1246f4a2713aSLionel Sambuc }
1247f4a2713aSLionel Sambuc };
1248f4a2713aSLionel Sambuc
1249f4a2713aSLionel Sambuc /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
1250f4a2713aSLionel Sambuc struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler__anon8441e45d0211::PragmaSTDC_CX_LIMITED_RANGEHandler1251f4a2713aSLionel Sambuc PragmaSTDC_CX_LIMITED_RANGEHandler()
1252f4a2713aSLionel Sambuc : PragmaHandler("CX_LIMITED_RANGE") {}
HandlePragma__anon8441e45d0211::PragmaSTDC_CX_LIMITED_RANGEHandler1253*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1254*0a6a1f1dSLionel Sambuc Token &Tok) override {
1255f4a2713aSLionel Sambuc tok::OnOffSwitch OOS;
1256f4a2713aSLionel Sambuc PP.LexOnOffSwitch(OOS);
1257f4a2713aSLionel Sambuc }
1258f4a2713aSLionel Sambuc };
1259f4a2713aSLionel Sambuc
1260f4a2713aSLionel Sambuc /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
1261f4a2713aSLionel Sambuc struct PragmaSTDC_UnknownHandler : public PragmaHandler {
PragmaSTDC_UnknownHandler__anon8441e45d0211::PragmaSTDC_UnknownHandler1262f4a2713aSLionel Sambuc PragmaSTDC_UnknownHandler() {}
HandlePragma__anon8441e45d0211::PragmaSTDC_UnknownHandler1263*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1264*0a6a1f1dSLionel Sambuc Token &UnknownTok) override {
1265f4a2713aSLionel Sambuc // C99 6.10.6p2, unknown forms are not allowed.
1266f4a2713aSLionel Sambuc PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
1267f4a2713aSLionel Sambuc }
1268f4a2713aSLionel Sambuc };
1269f4a2713aSLionel Sambuc
1270f4a2713aSLionel Sambuc /// PragmaARCCFCodeAuditedHandler -
1271f4a2713aSLionel Sambuc /// \#pragma clang arc_cf_code_audited begin/end
1272f4a2713aSLionel Sambuc struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
PragmaARCCFCodeAuditedHandler__anon8441e45d0211::PragmaARCCFCodeAuditedHandler1273f4a2713aSLionel Sambuc PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {}
HandlePragma__anon8441e45d0211::PragmaARCCFCodeAuditedHandler1274*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1275*0a6a1f1dSLionel Sambuc Token &NameTok) override {
1276f4a2713aSLionel Sambuc SourceLocation Loc = NameTok.getLocation();
1277f4a2713aSLionel Sambuc bool IsBegin;
1278f4a2713aSLionel Sambuc
1279f4a2713aSLionel Sambuc Token Tok;
1280f4a2713aSLionel Sambuc
1281f4a2713aSLionel Sambuc // Lex the 'begin' or 'end'.
1282f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
1283f4a2713aSLionel Sambuc const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo();
1284f4a2713aSLionel Sambuc if (BeginEnd && BeginEnd->isStr("begin")) {
1285f4a2713aSLionel Sambuc IsBegin = true;
1286f4a2713aSLionel Sambuc } else if (BeginEnd && BeginEnd->isStr("end")) {
1287f4a2713aSLionel Sambuc IsBegin = false;
1288f4a2713aSLionel Sambuc } else {
1289f4a2713aSLionel Sambuc PP.Diag(Tok.getLocation(), diag::err_pp_arc_cf_code_audited_syntax);
1290f4a2713aSLionel Sambuc return;
1291f4a2713aSLionel Sambuc }
1292f4a2713aSLionel Sambuc
1293f4a2713aSLionel Sambuc // Verify that this is followed by EOD.
1294f4a2713aSLionel Sambuc PP.LexUnexpandedToken(Tok);
1295f4a2713aSLionel Sambuc if (Tok.isNot(tok::eod))
1296f4a2713aSLionel Sambuc PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
1297f4a2713aSLionel Sambuc
1298f4a2713aSLionel Sambuc // The start location of the active audit.
1299f4a2713aSLionel Sambuc SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedLoc();
1300f4a2713aSLionel Sambuc
1301f4a2713aSLionel Sambuc // The start location we want after processing this.
1302f4a2713aSLionel Sambuc SourceLocation NewLoc;
1303f4a2713aSLionel Sambuc
1304f4a2713aSLionel Sambuc if (IsBegin) {
1305f4a2713aSLionel Sambuc // Complain about attempts to re-enter an audit.
1306f4a2713aSLionel Sambuc if (BeginLoc.isValid()) {
1307f4a2713aSLionel Sambuc PP.Diag(Loc, diag::err_pp_double_begin_of_arc_cf_code_audited);
1308f4a2713aSLionel Sambuc PP.Diag(BeginLoc, diag::note_pragma_entered_here);
1309f4a2713aSLionel Sambuc }
1310f4a2713aSLionel Sambuc NewLoc = Loc;
1311f4a2713aSLionel Sambuc } else {
1312f4a2713aSLionel Sambuc // Complain about attempts to leave an audit that doesn't exist.
1313f4a2713aSLionel Sambuc if (!BeginLoc.isValid()) {
1314f4a2713aSLionel Sambuc PP.Diag(Loc, diag::err_pp_unmatched_end_of_arc_cf_code_audited);
1315f4a2713aSLionel Sambuc return;
1316f4a2713aSLionel Sambuc }
1317f4a2713aSLionel Sambuc NewLoc = SourceLocation();
1318f4a2713aSLionel Sambuc }
1319f4a2713aSLionel Sambuc
1320f4a2713aSLionel Sambuc PP.setPragmaARCCFCodeAuditedLoc(NewLoc);
1321f4a2713aSLionel Sambuc }
1322f4a2713aSLionel Sambuc };
1323f4a2713aSLionel Sambuc
1324f4a2713aSLionel Sambuc /// \brief Handle "\#pragma region [...]"
1325f4a2713aSLionel Sambuc ///
1326f4a2713aSLionel Sambuc /// The syntax is
1327f4a2713aSLionel Sambuc /// \code
1328f4a2713aSLionel Sambuc /// #pragma region [optional name]
1329f4a2713aSLionel Sambuc /// #pragma endregion [optional comment]
1330f4a2713aSLionel Sambuc /// \endcode
1331f4a2713aSLionel Sambuc ///
1332f4a2713aSLionel Sambuc /// \note This is
1333f4a2713aSLionel Sambuc /// <a href="http://msdn.microsoft.com/en-us/library/b6xkz944(v=vs.80).aspx">editor-only</a>
1334f4a2713aSLionel Sambuc /// pragma, just skipped by compiler.
1335f4a2713aSLionel Sambuc struct PragmaRegionHandler : public PragmaHandler {
PragmaRegionHandler__anon8441e45d0211::PragmaRegionHandler1336f4a2713aSLionel Sambuc PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) { }
1337f4a2713aSLionel Sambuc
HandlePragma__anon8441e45d0211::PragmaRegionHandler1338*0a6a1f1dSLionel Sambuc void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
1339*0a6a1f1dSLionel Sambuc Token &NameTok) override {
1340f4a2713aSLionel Sambuc // #pragma region: endregion matches can be verified
1341f4a2713aSLionel Sambuc // __pragma(region): no sense, but ignored by msvc
1342f4a2713aSLionel Sambuc // _Pragma is not valid for MSVC, but there isn't any point
1343f4a2713aSLionel Sambuc // to handle a _Pragma differently.
1344f4a2713aSLionel Sambuc }
1345f4a2713aSLionel Sambuc };
1346f4a2713aSLionel Sambuc
1347f4a2713aSLionel Sambuc } // end anonymous namespace
1348f4a2713aSLionel Sambuc
1349f4a2713aSLionel Sambuc
1350f4a2713aSLionel Sambuc /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
1351f4a2713aSLionel Sambuc /// \#pragma GCC poison/system_header/dependency and \#pragma once.
RegisterBuiltinPragmas()1352f4a2713aSLionel Sambuc void Preprocessor::RegisterBuiltinPragmas() {
1353f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaOnceHandler());
1354f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaMarkHandler());
1355f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaPushMacroHandler());
1356f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaPopMacroHandler());
1357f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaMessageHandler(PPCallbacks::PMK_Message));
1358f4a2713aSLionel Sambuc
1359f4a2713aSLionel Sambuc // #pragma GCC ...
1360f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaPoisonHandler());
1361f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaSystemHeaderHandler());
1362f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaDependencyHandler());
1363f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaDiagnosticHandler("GCC"));
1364f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Warning,
1365f4a2713aSLionel Sambuc "GCC"));
1366f4a2713aSLionel Sambuc AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Error,
1367f4a2713aSLionel Sambuc "GCC"));
1368f4a2713aSLionel Sambuc // #pragma clang ...
1369f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaPoisonHandler());
1370f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
1371f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaDebugHandler());
1372f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaDependencyHandler());
1373f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
1374f4a2713aSLionel Sambuc AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
1375f4a2713aSLionel Sambuc
1376f4a2713aSLionel Sambuc AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
1377f4a2713aSLionel Sambuc AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
1378f4a2713aSLionel Sambuc AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
1379f4a2713aSLionel Sambuc
1380f4a2713aSLionel Sambuc // MS extensions.
1381f4a2713aSLionel Sambuc if (LangOpts.MicrosoftExt) {
1382f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaWarningHandler());
1383f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaIncludeAliasHandler());
1384f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaRegionHandler("region"));
1385f4a2713aSLionel Sambuc AddPragmaHandler(new PragmaRegionHandler("endregion"));
1386f4a2713aSLionel Sambuc }
1387f4a2713aSLionel Sambuc }
1388*0a6a1f1dSLionel Sambuc
1389*0a6a1f1dSLionel Sambuc /// Ignore all pragmas, useful for modes such as -Eonly which would otherwise
1390*0a6a1f1dSLionel Sambuc /// warn about those pragmas being unknown.
IgnorePragmas()1391*0a6a1f1dSLionel Sambuc void Preprocessor::IgnorePragmas() {
1392*0a6a1f1dSLionel Sambuc AddPragmaHandler(new EmptyPragmaHandler());
1393*0a6a1f1dSLionel Sambuc // Also ignore all pragmas in all namespaces created
1394*0a6a1f1dSLionel Sambuc // in Preprocessor::RegisterBuiltinPragmas().
1395*0a6a1f1dSLionel Sambuc AddPragmaHandler("GCC", new EmptyPragmaHandler());
1396*0a6a1f1dSLionel Sambuc AddPragmaHandler("clang", new EmptyPragmaHandler());
1397*0a6a1f1dSLionel Sambuc if (PragmaHandler *NS = PragmaHandlers->FindHandler("STDC")) {
1398*0a6a1f1dSLionel Sambuc // Preprocessor::RegisterBuiltinPragmas() already registers
1399*0a6a1f1dSLionel Sambuc // PragmaSTDC_UnknownHandler as the empty handler, so remove it first,
1400*0a6a1f1dSLionel Sambuc // otherwise there will be an assert about a duplicate handler.
1401*0a6a1f1dSLionel Sambuc PragmaNamespace *STDCNamespace = NS->getIfNamespace();
1402*0a6a1f1dSLionel Sambuc assert(STDCNamespace &&
1403*0a6a1f1dSLionel Sambuc "Invalid namespace, registered as a regular pragma handler!");
1404*0a6a1f1dSLionel Sambuc if (PragmaHandler *Existing = STDCNamespace->FindHandler("", false)) {
1405*0a6a1f1dSLionel Sambuc RemovePragmaHandler("STDC", Existing);
1406*0a6a1f1dSLionel Sambuc delete Existing;
1407*0a6a1f1dSLionel Sambuc }
1408*0a6a1f1dSLionel Sambuc }
1409*0a6a1f1dSLionel Sambuc AddPragmaHandler("STDC", new EmptyPragmaHandler());
1410*0a6a1f1dSLionel Sambuc }
1411