10b57cec5SDimitry Andric //===- Pragma.cpp - Pragma registration and handling ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the PragmaHandler/PragmaTable interfaces and implements
100b57cec5SDimitry Andric // pragma related methods of the Preprocessor class.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "clang/Lex/Pragma.h"
15349cc55cSDimitry Andric #include "clang/Basic/CLWarnings.h"
160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
170b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
180b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
190b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
200b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
210b57cec5SDimitry Andric #include "clang/Basic/Module.h"
220b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
230b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
240b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
250b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h"
260b57cec5SDimitry Andric #include "clang/Lex/LexDiagnostic.h"
270b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
280b57cec5SDimitry Andric #include "clang/Lex/LiteralSupport.h"
290b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h"
300b57cec5SDimitry Andric #include "clang/Lex/ModuleLoader.h"
310b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h"
320b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
330b57cec5SDimitry Andric #include "clang/Lex/PreprocessorLexer.h"
3413138422SDimitry Andric #include "clang/Lex/PreprocessorOptions.h"
350b57cec5SDimitry Andric #include "clang/Lex/Token.h"
360b57cec5SDimitry Andric #include "clang/Lex/TokenLexer.h"
370b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
380b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
390b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
400b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
410b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
420b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
430b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
440b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
45cd675bb6SDimitry Andric #include "llvm/Support/Timer.h"
460b57cec5SDimitry Andric #include <algorithm>
470b57cec5SDimitry Andric #include <cassert>
480b57cec5SDimitry Andric #include <cstddef>
490b57cec5SDimitry Andric #include <cstdint>
500b57cec5SDimitry Andric #include <limits>
51bdd1243dSDimitry Andric #include <optional>
520b57cec5SDimitry Andric #include <string>
530b57cec5SDimitry Andric #include <utility>
540b57cec5SDimitry Andric #include <vector>
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric using namespace clang;
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric // Out-of-line destructor to provide a home for the class.
590b57cec5SDimitry Andric PragmaHandler::~PragmaHandler() = default;
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
620b57cec5SDimitry Andric // EmptyPragmaHandler Implementation.
630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
640b57cec5SDimitry Andric
EmptyPragmaHandler(StringRef Name)650b57cec5SDimitry Andric EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {}
660b57cec5SDimitry Andric
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)670b57cec5SDimitry Andric void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
680b57cec5SDimitry Andric PragmaIntroducer Introducer,
690b57cec5SDimitry Andric Token &FirstToken) {}
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
720b57cec5SDimitry Andric // PragmaNamespace Implementation.
730b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric /// FindHandler - Check to see if there is already a handler for the
760b57cec5SDimitry Andric /// specified name. If not, return the handler for the null identifier if it
770b57cec5SDimitry Andric /// exists, otherwise return null. If IgnoreNull is true (the default) then
780b57cec5SDimitry Andric /// the null handler isn't returned on failure to match.
FindHandler(StringRef Name,bool IgnoreNull) const790b57cec5SDimitry Andric PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
800b57cec5SDimitry Andric bool IgnoreNull) const {
815ffd83dbSDimitry Andric auto I = Handlers.find(Name);
825ffd83dbSDimitry Andric if (I != Handlers.end())
835ffd83dbSDimitry Andric return I->getValue().get();
845ffd83dbSDimitry Andric if (IgnoreNull)
855ffd83dbSDimitry Andric return nullptr;
865ffd83dbSDimitry Andric I = Handlers.find(StringRef());
875ffd83dbSDimitry Andric if (I != Handlers.end())
885ffd83dbSDimitry Andric return I->getValue().get();
895ffd83dbSDimitry Andric return nullptr;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
AddPragma(PragmaHandler * Handler)920b57cec5SDimitry Andric void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
935ffd83dbSDimitry Andric assert(!Handlers.count(Handler->getName()) &&
940b57cec5SDimitry Andric "A handler with this name is already registered in this namespace");
955ffd83dbSDimitry Andric Handlers[Handler->getName()].reset(Handler);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
RemovePragmaHandler(PragmaHandler * Handler)980b57cec5SDimitry Andric void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
995ffd83dbSDimitry Andric auto I = Handlers.find(Handler->getName());
1005ffd83dbSDimitry Andric assert(I != Handlers.end() &&
1010b57cec5SDimitry Andric "Handler not registered in this namespace");
1025ffd83dbSDimitry Andric // Release ownership back to the caller.
1035ffd83dbSDimitry Andric I->getValue().release();
1045ffd83dbSDimitry Andric Handlers.erase(I);
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)1070b57cec5SDimitry Andric void PragmaNamespace::HandlePragma(Preprocessor &PP,
1080b57cec5SDimitry Andric PragmaIntroducer Introducer, Token &Tok) {
1090b57cec5SDimitry Andric // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro
1100b57cec5SDimitry Andric // expand it, the user can have a STDC #define, that should not affect this.
1110b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric // Get the handler for this token. If there is no handler, ignore the pragma.
1140b57cec5SDimitry Andric PragmaHandler *Handler
1150b57cec5SDimitry Andric = FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName()
1160b57cec5SDimitry Andric : StringRef(),
1170b57cec5SDimitry Andric /*IgnoreNull=*/false);
1180b57cec5SDimitry Andric if (!Handler) {
1190b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_ignored);
1200b57cec5SDimitry Andric return;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // Otherwise, pass it down.
1240b57cec5SDimitry Andric Handler->HandlePragma(PP, Introducer, Tok);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1280b57cec5SDimitry Andric // Preprocessor Pragma Directive Handling.
1290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1300b57cec5SDimitry Andric
131a7dea167SDimitry Andric namespace {
132a7dea167SDimitry Andric // TokenCollector provides the option to collect tokens that were "read"
133a7dea167SDimitry Andric // and return them to the stream to be read later.
134a7dea167SDimitry Andric // Currently used when reading _Pragma/__pragma directives.
135a7dea167SDimitry Andric struct TokenCollector {
136a7dea167SDimitry Andric Preprocessor &Self;
137a7dea167SDimitry Andric bool Collect;
138a7dea167SDimitry Andric SmallVector<Token, 3> Tokens;
139a7dea167SDimitry Andric Token &Tok;
140a7dea167SDimitry Andric
lex__anon851a8f8a0111::TokenCollector141a7dea167SDimitry Andric void lex() {
142a7dea167SDimitry Andric if (Collect)
143a7dea167SDimitry Andric Tokens.push_back(Tok);
144a7dea167SDimitry Andric Self.Lex(Tok);
145a7dea167SDimitry Andric }
146a7dea167SDimitry Andric
revert__anon851a8f8a0111::TokenCollector147a7dea167SDimitry Andric void revert() {
148a7dea167SDimitry Andric assert(Collect && "did not collect tokens");
149a7dea167SDimitry Andric assert(!Tokens.empty() && "collected unexpected number of tokens");
150a7dea167SDimitry Andric
151a7dea167SDimitry Andric // Push the ( "string" ) tokens into the token stream.
152a7dea167SDimitry Andric auto Toks = std::make_unique<Token[]>(Tokens.size());
153a7dea167SDimitry Andric std::copy(Tokens.begin() + 1, Tokens.end(), Toks.get());
154a7dea167SDimitry Andric Toks[Tokens.size() - 1] = Tok;
155a7dea167SDimitry Andric Self.EnterTokenStream(std::move(Toks), Tokens.size(),
156a7dea167SDimitry Andric /*DisableMacroExpansion*/ true,
157a7dea167SDimitry Andric /*IsReinject*/ true);
158a7dea167SDimitry Andric
159a7dea167SDimitry Andric // ... and return the pragma token unchanged.
160a7dea167SDimitry Andric Tok = *Tokens.begin();
161a7dea167SDimitry Andric }
162a7dea167SDimitry Andric };
163a7dea167SDimitry Andric } // namespace
164a7dea167SDimitry Andric
1650b57cec5SDimitry Andric /// HandlePragmaDirective - The "\#pragma" directive has been parsed. Lex the
1660b57cec5SDimitry Andric /// rest of the pragma, passing it to the registered pragma handlers.
HandlePragmaDirective(PragmaIntroducer Introducer)1670b57cec5SDimitry Andric void Preprocessor::HandlePragmaDirective(PragmaIntroducer Introducer) {
1680b57cec5SDimitry Andric if (Callbacks)
1690b57cec5SDimitry Andric Callbacks->PragmaDirective(Introducer.Loc, Introducer.Kind);
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric if (!PragmasEnabled)
1720b57cec5SDimitry Andric return;
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric ++NumPragma;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric // Invoke the first level of pragma handlers which reads the namespace id.
1770b57cec5SDimitry Andric Token Tok;
1780b57cec5SDimitry Andric PragmaHandlers->HandlePragma(*this, Introducer, Tok);
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric // If the pragma handler didn't read the rest of the line, consume it now.
1810b57cec5SDimitry Andric if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
1820b57cec5SDimitry Andric || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
1830b57cec5SDimitry Andric DiscardUntilEndOfDirective();
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
1870b57cec5SDimitry Andric /// return the first token after the directive. The _Pragma token has just
1880b57cec5SDimitry Andric /// been read into 'Tok'.
Handle_Pragma(Token & Tok)1890b57cec5SDimitry Andric void Preprocessor::Handle_Pragma(Token &Tok) {
1900b57cec5SDimitry Andric // C11 6.10.3.4/3:
1910b57cec5SDimitry Andric // all pragma unary operator expressions within [a completely
1920b57cec5SDimitry Andric // macro-replaced preprocessing token sequence] are [...] processed [after
1930b57cec5SDimitry Andric // rescanning is complete]
1940b57cec5SDimitry Andric //
1950b57cec5SDimitry Andric // This means that we execute _Pragma operators in two cases:
1960b57cec5SDimitry Andric //
1970b57cec5SDimitry Andric // 1) on token sequences that would otherwise be produced as the output of
1980b57cec5SDimitry Andric // phase 4 of preprocessing, and
1990b57cec5SDimitry Andric // 2) on token sequences formed as the macro-replaced token sequence of a
2000b57cec5SDimitry Andric // macro argument
2010b57cec5SDimitry Andric //
2020b57cec5SDimitry Andric // Case #2 appears to be a wording bug: only _Pragmas that would survive to
2030b57cec5SDimitry Andric // the end of phase 4 should actually be executed. Discussion on the WG14
2040b57cec5SDimitry Andric // mailing list suggests that a _Pragma operator is notionally checked early,
2050b57cec5SDimitry Andric // but only pragmas that survive to the end of phase 4 should be executed.
2060b57cec5SDimitry Andric //
2070b57cec5SDimitry Andric // In Case #2, we check the syntax now, but then put the tokens back into the
2080b57cec5SDimitry Andric // token stream for later consumption.
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok};
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric // Remember the pragma token location.
2130b57cec5SDimitry Andric SourceLocation PragmaLoc = Tok.getLocation();
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric // Read the '('.
2160b57cec5SDimitry Andric Toks.lex();
2170b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
2180b57cec5SDimitry Andric Diag(PragmaLoc, diag::err__Pragma_malformed);
2190b57cec5SDimitry Andric return;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric // Read the '"..."'.
2230b57cec5SDimitry Andric Toks.lex();
2240b57cec5SDimitry Andric if (!tok::isStringLiteral(Tok.getKind())) {
2250b57cec5SDimitry Andric Diag(PragmaLoc, diag::err__Pragma_malformed);
2260b57cec5SDimitry Andric // Skip bad tokens, and the ')', if present.
2270b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof))
2280b57cec5SDimitry Andric Lex(Tok);
2290b57cec5SDimitry Andric while (Tok.isNot(tok::r_paren) &&
2300b57cec5SDimitry Andric !Tok.isAtStartOfLine() &&
2310b57cec5SDimitry Andric Tok.isNot(tok::eof))
2320b57cec5SDimitry Andric Lex(Tok);
2330b57cec5SDimitry Andric if (Tok.is(tok::r_paren))
2340b57cec5SDimitry Andric Lex(Tok);
2350b57cec5SDimitry Andric return;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric if (Tok.hasUDSuffix()) {
2390b57cec5SDimitry Andric Diag(Tok, diag::err_invalid_string_udl);
2400b57cec5SDimitry Andric // Skip this token, and the ')', if present.
2410b57cec5SDimitry Andric Lex(Tok);
2420b57cec5SDimitry Andric if (Tok.is(tok::r_paren))
2430b57cec5SDimitry Andric Lex(Tok);
2440b57cec5SDimitry Andric return;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric // Remember the string.
2480b57cec5SDimitry Andric Token StrTok = Tok;
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric // Read the ')'.
2510b57cec5SDimitry Andric Toks.lex();
2520b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
2530b57cec5SDimitry Andric Diag(PragmaLoc, diag::err__Pragma_malformed);
2540b57cec5SDimitry Andric return;
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric // If we're expanding a macro argument, put the tokens back.
2580b57cec5SDimitry Andric if (InMacroArgPreExpansion) {
2590b57cec5SDimitry Andric Toks.revert();
2600b57cec5SDimitry Andric return;
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric SourceLocation RParenLoc = Tok.getLocation();
26481ad6265SDimitry Andric bool Invalid = false;
26506c3fb27SDimitry Andric SmallString<64> StrVal;
26606c3fb27SDimitry Andric StrVal.resize(StrTok.getLength());
26706c3fb27SDimitry Andric StringRef StrValRef = getSpelling(StrTok, StrVal, &Invalid);
26881ad6265SDimitry Andric if (Invalid) {
26981ad6265SDimitry Andric Diag(PragmaLoc, diag::err__Pragma_malformed);
27081ad6265SDimitry Andric return;
27181ad6265SDimitry Andric }
2720b57cec5SDimitry Andric
27306c3fb27SDimitry Andric assert(StrValRef.size() <= StrVal.size());
27406c3fb27SDimitry Andric
27506c3fb27SDimitry Andric // If the token was spelled somewhere else, copy it.
27606c3fb27SDimitry Andric if (StrValRef.begin() != StrVal.begin())
27706c3fb27SDimitry Andric StrVal.assign(StrValRef);
27806c3fb27SDimitry Andric // Truncate if necessary.
27906c3fb27SDimitry Andric else if (StrValRef.size() != StrVal.size())
28006c3fb27SDimitry Andric StrVal.resize(StrValRef.size());
28106c3fb27SDimitry Andric
28206c3fb27SDimitry Andric // The _Pragma is lexically sound. Destringize according to C11 6.10.9.1.
28306c3fb27SDimitry Andric prepare_PragmaString(StrVal);
28406c3fb27SDimitry Andric
28506c3fb27SDimitry Andric // Plop the string (including the newline and trailing null) into a buffer
28606c3fb27SDimitry Andric // where we can lex it.
28706c3fb27SDimitry Andric Token TmpTok;
28806c3fb27SDimitry Andric TmpTok.startToken();
28906c3fb27SDimitry Andric CreateString(StrVal, TmpTok);
29006c3fb27SDimitry Andric SourceLocation TokLoc = TmpTok.getLocation();
29106c3fb27SDimitry Andric
29206c3fb27SDimitry Andric // Make and enter a lexer object so that we lex and expand the tokens just
29306c3fb27SDimitry Andric // like any others.
29406c3fb27SDimitry Andric Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
29506c3fb27SDimitry Andric StrVal.size(), *this);
29606c3fb27SDimitry Andric
29706c3fb27SDimitry Andric EnterSourceFileWithLexer(TL, nullptr);
29806c3fb27SDimitry Andric
29906c3fb27SDimitry Andric // With everything set up, lex this as a #pragma directive.
30006c3fb27SDimitry Andric HandlePragmaDirective({PIK__Pragma, PragmaLoc});
30106c3fb27SDimitry Andric
30206c3fb27SDimitry Andric // Finally, return whatever came after the pragma directive.
30306c3fb27SDimitry Andric return Lex(Tok);
30406c3fb27SDimitry Andric }
30506c3fb27SDimitry Andric
prepare_PragmaString(SmallVectorImpl<char> & StrVal)30606c3fb27SDimitry Andric void clang::prepare_PragmaString(SmallVectorImpl<char> &StrVal) {
3070b57cec5SDimitry Andric if (StrVal[0] == 'L' || StrVal[0] == 'U' ||
3080b57cec5SDimitry Andric (StrVal[0] == 'u' && StrVal[1] != '8'))
3090b57cec5SDimitry Andric StrVal.erase(StrVal.begin());
3100b57cec5SDimitry Andric else if (StrVal[0] == 'u')
3110b57cec5SDimitry Andric StrVal.erase(StrVal.begin(), StrVal.begin() + 2);
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric if (StrVal[0] == 'R') {
3140b57cec5SDimitry Andric // FIXME: C++11 does not specify how to handle raw-string-literals here.
3150b57cec5SDimitry Andric // We strip off the 'R', the quotes, the d-char-sequences, and the parens.
3160b57cec5SDimitry Andric assert(StrVal[1] == '"' && StrVal[StrVal.size() - 1] == '"' &&
3170b57cec5SDimitry Andric "Invalid raw string token!");
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric // Measure the length of the d-char-sequence.
3200b57cec5SDimitry Andric unsigned NumDChars = 0;
3210b57cec5SDimitry Andric while (StrVal[2 + NumDChars] != '(') {
3220b57cec5SDimitry Andric assert(NumDChars < (StrVal.size() - 5) / 2 &&
3230b57cec5SDimitry Andric "Invalid raw string token!");
3240b57cec5SDimitry Andric ++NumDChars;
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric assert(StrVal[StrVal.size() - 2 - NumDChars] == ')');
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric // Remove 'R " d-char-sequence' and 'd-char-sequence "'. We'll replace the
3290b57cec5SDimitry Andric // parens below.
33006c3fb27SDimitry Andric StrVal.erase(StrVal.begin(), StrVal.begin() + 2 + NumDChars);
33106c3fb27SDimitry Andric StrVal.erase(StrVal.end() - 1 - NumDChars, StrVal.end());
3320b57cec5SDimitry Andric } else {
3330b57cec5SDimitry Andric assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
3340b57cec5SDimitry Andric "Invalid string token!");
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric // Remove escaped quotes and escapes.
3370b57cec5SDimitry Andric unsigned ResultPos = 1;
3380b57cec5SDimitry Andric for (size_t i = 1, e = StrVal.size() - 1; i != e; ++i) {
3390b57cec5SDimitry Andric // Skip escapes. \\ -> '\' and \" -> '"'.
3400b57cec5SDimitry Andric if (StrVal[i] == '\\' && i + 1 < e &&
3410b57cec5SDimitry Andric (StrVal[i + 1] == '\\' || StrVal[i + 1] == '"'))
3420b57cec5SDimitry Andric ++i;
3430b57cec5SDimitry Andric StrVal[ResultPos++] = StrVal[i];
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric StrVal.erase(StrVal.begin() + ResultPos, StrVal.end() - 1);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric // Remove the front quote, replacing it with a space, so that the pragma
3490b57cec5SDimitry Andric // contents appear to have a space before them.
3500b57cec5SDimitry Andric StrVal[0] = ' ';
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric // Replace the terminating quote with a \n.
3530b57cec5SDimitry Andric StrVal[StrVal.size() - 1] = '\n';
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
3570b57cec5SDimitry Andric /// is not enclosed within a string literal.
HandleMicrosoft__pragma(Token & Tok)3580b57cec5SDimitry Andric void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
359a7dea167SDimitry Andric // During macro pre-expansion, check the syntax now but put the tokens back
360a7dea167SDimitry Andric // into the token stream for later consumption. Same as Handle_Pragma.
361a7dea167SDimitry Andric TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok};
362a7dea167SDimitry Andric
3630b57cec5SDimitry Andric // Remember the pragma token location.
3640b57cec5SDimitry Andric SourceLocation PragmaLoc = Tok.getLocation();
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric // Read the '('.
367a7dea167SDimitry Andric Toks.lex();
3680b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
3690b57cec5SDimitry Andric Diag(PragmaLoc, diag::err__Pragma_malformed);
3700b57cec5SDimitry Andric return;
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric // Get the tokens enclosed within the __pragma(), as well as the final ')'.
3740b57cec5SDimitry Andric SmallVector<Token, 32> PragmaToks;
3750b57cec5SDimitry Andric int NumParens = 0;
376a7dea167SDimitry Andric Toks.lex();
3770b57cec5SDimitry Andric while (Tok.isNot(tok::eof)) {
3780b57cec5SDimitry Andric PragmaToks.push_back(Tok);
3790b57cec5SDimitry Andric if (Tok.is(tok::l_paren))
3800b57cec5SDimitry Andric NumParens++;
3810b57cec5SDimitry Andric else if (Tok.is(tok::r_paren) && NumParens-- == 0)
3820b57cec5SDimitry Andric break;
383a7dea167SDimitry Andric Toks.lex();
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric if (Tok.is(tok::eof)) {
3870b57cec5SDimitry Andric Diag(PragmaLoc, diag::err_unterminated___pragma);
3880b57cec5SDimitry Andric return;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
391a7dea167SDimitry Andric // If we're expanding a macro argument, put the tokens back.
392a7dea167SDimitry Andric if (InMacroArgPreExpansion) {
393a7dea167SDimitry Andric Toks.revert();
394a7dea167SDimitry Andric return;
395a7dea167SDimitry Andric }
396a7dea167SDimitry Andric
3970b57cec5SDimitry Andric PragmaToks.front().setFlag(Token::LeadingSpace);
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric // Replace the ')' with an EOD to mark the end of the pragma.
4000b57cec5SDimitry Andric PragmaToks.back().setKind(tok::eod);
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric Token *TokArray = new Token[PragmaToks.size()];
4030b57cec5SDimitry Andric std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray);
4040b57cec5SDimitry Andric
4050b57cec5SDimitry Andric // Push the tokens onto the stack.
4060b57cec5SDimitry Andric EnterTokenStream(TokArray, PragmaToks.size(), true, true,
4070b57cec5SDimitry Andric /*IsReinject*/ false);
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric // With everything set up, lex this as a #pragma directive.
4100b57cec5SDimitry Andric HandlePragmaDirective({PIK___pragma, PragmaLoc});
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric // Finally, return whatever came after the pragma directive.
4130b57cec5SDimitry Andric return Lex(Tok);
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric /// HandlePragmaOnce - Handle \#pragma once. OnceTok is the 'once'.
HandlePragmaOnce(Token & OnceTok)4170b57cec5SDimitry Andric void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
4180b57cec5SDimitry Andric // Don't honor the 'once' when handling the primary source file, unless
4190b57cec5SDimitry Andric // this is a prefix to a TU, which indicates we're generating a PCH file, or
4200b57cec5SDimitry Andric // when the main file is a header (e.g. when -xc-header is provided on the
4210b57cec5SDimitry Andric // commandline).
4220b57cec5SDimitry Andric if (isInPrimaryFile() && TUKind != TU_Prefix && !getLangOpts().IsHeaderFile) {
4230b57cec5SDimitry Andric Diag(OnceTok, diag::pp_pragma_once_in_main_file);
4240b57cec5SDimitry Andric return;
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
4280b57cec5SDimitry Andric // Mark the file as a once-only file now.
4295f757f3fSDimitry Andric HeaderInfo.MarkFileIncludeOnce(*getCurrentFileLexer()->getFileEntry());
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric
HandlePragmaMark(Token & MarkTok)432fe6060f1SDimitry Andric void Preprocessor::HandlePragmaMark(Token &MarkTok) {
4330b57cec5SDimitry Andric assert(CurPPLexer && "No current lexer?");
434fe6060f1SDimitry Andric
435fe6060f1SDimitry Andric SmallString<64> Buffer;
436fe6060f1SDimitry Andric CurLexer->ReadToEndOfLine(&Buffer);
437fe6060f1SDimitry Andric if (Callbacks)
438fe6060f1SDimitry Andric Callbacks->PragmaMark(MarkTok.getLocation(), Buffer);
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric /// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
HandlePragmaPoison()4420b57cec5SDimitry Andric void Preprocessor::HandlePragmaPoison() {
4430b57cec5SDimitry Andric Token Tok;
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric while (true) {
4460b57cec5SDimitry Andric // Read the next token to poison. While doing this, pretend that we are
4470b57cec5SDimitry Andric // skipping while reading the identifier to poison.
4480b57cec5SDimitry Andric // This avoids errors on code like:
4490b57cec5SDimitry Andric // #pragma GCC poison X
4500b57cec5SDimitry Andric // #pragma GCC poison X
4510b57cec5SDimitry Andric if (CurPPLexer) CurPPLexer->LexingRawMode = true;
4520b57cec5SDimitry Andric LexUnexpandedToken(Tok);
4530b57cec5SDimitry Andric if (CurPPLexer) CurPPLexer->LexingRawMode = false;
4540b57cec5SDimitry Andric
4550b57cec5SDimitry Andric // If we reached the end of line, we're done.
4560b57cec5SDimitry Andric if (Tok.is(tok::eod)) return;
4570b57cec5SDimitry Andric
4580b57cec5SDimitry Andric // Can only poison identifiers.
4590b57cec5SDimitry Andric if (Tok.isNot(tok::raw_identifier)) {
4600b57cec5SDimitry Andric Diag(Tok, diag::err_pp_invalid_poison);
4610b57cec5SDimitry Andric return;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric // Look up the identifier info for the token. We disabled identifier lookup
4650b57cec5SDimitry Andric // by saying we're skipping contents, so we need to do this manually.
4660b57cec5SDimitry Andric IdentifierInfo *II = LookUpIdentifierInfo(Tok);
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric // Already poisoned.
4690b57cec5SDimitry Andric if (II->isPoisoned()) continue;
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // If this is a macro identifier, emit a warning.
4720b57cec5SDimitry Andric if (isMacroDefined(II))
4730b57cec5SDimitry Andric Diag(Tok, diag::pp_poisoning_existing_macro);
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric // Finally, poison it!
4760b57cec5SDimitry Andric II->setIsPoisoned();
4770b57cec5SDimitry Andric if (II->isFromAST())
4780b57cec5SDimitry Andric II->setChangedSinceDeserialization();
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric
4820b57cec5SDimitry Andric /// HandlePragmaSystemHeader - Implement \#pragma GCC system_header. We know
4830b57cec5SDimitry Andric /// that the whole directive has been parsed.
HandlePragmaSystemHeader(Token & SysHeaderTok)4840b57cec5SDimitry Andric void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
4850b57cec5SDimitry Andric if (isInPrimaryFile()) {
4860b57cec5SDimitry Andric Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
4870b57cec5SDimitry Andric return;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric
4900b57cec5SDimitry Andric // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
4910b57cec5SDimitry Andric PreprocessorLexer *TheLexer = getCurrentFileLexer();
4920b57cec5SDimitry Andric
4930b57cec5SDimitry Andric // Mark the file as a system header.
4945f757f3fSDimitry Andric HeaderInfo.MarkFileSystemHeader(*TheLexer->getFileEntry());
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andric PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
4970b57cec5SDimitry Andric if (PLoc.isInvalid())
4980b57cec5SDimitry Andric return;
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename());
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric // Notify the client, if desired, that we are in a new source file.
5030b57cec5SDimitry Andric if (Callbacks)
5040b57cec5SDimitry Andric Callbacks->FileChanged(SysHeaderTok.getLocation(),
5050b57cec5SDimitry Andric PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andric // Emit a line marker. This will change any source locations from this point
5080b57cec5SDimitry Andric // forward to realize they are in a system header.
5090b57cec5SDimitry Andric // Create a line note with this information.
5100b57cec5SDimitry Andric SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine() + 1,
5110b57cec5SDimitry Andric FilenameID, /*IsEntry=*/false, /*IsExit=*/false,
5120b57cec5SDimitry Andric SrcMgr::C_System);
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric
51581ad6265SDimitry Andric /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
HandlePragmaDependency(Token & DependencyTok)51681ad6265SDimitry Andric void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
5170b57cec5SDimitry Andric Token FilenameTok;
51881ad6265SDimitry Andric if (LexHeaderName(FilenameTok, /*AllowConcatenation*/false))
51981ad6265SDimitry Andric return;
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric // If the next token wasn't a header-name, diagnose the error.
5220b57cec5SDimitry Andric if (FilenameTok.isNot(tok::header_name)) {
52381ad6265SDimitry Andric Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
52481ad6265SDimitry Andric return;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
5270b57cec5SDimitry Andric // Reserve a buffer to get the spelling.
5280b57cec5SDimitry Andric SmallString<128> FilenameBuffer;
5290b57cec5SDimitry Andric bool Invalid = false;
53081ad6265SDimitry Andric StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
5310b57cec5SDimitry Andric if (Invalid)
53281ad6265SDimitry Andric return;
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric bool isAngled =
53581ad6265SDimitry Andric GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
5360b57cec5SDimitry Andric // If GetIncludeFilenameSpelling set the start ptr to null, there was an
5370b57cec5SDimitry Andric // error.
5380b57cec5SDimitry Andric if (Filename.empty())
53981ad6265SDimitry Andric return;
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andric // Search include directories for this file.
542bdd1243dSDimitry Andric OptionalFileEntryRef File =
54381ad6265SDimitry Andric LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
54481ad6265SDimitry Andric nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
5450b57cec5SDimitry Andric if (!File) {
5460b57cec5SDimitry Andric if (!SuppressIncludeNotFoundError)
54781ad6265SDimitry Andric Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
5480b57cec5SDimitry Andric return;
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric
5515f757f3fSDimitry Andric OptionalFileEntryRef CurFile = getCurrentFileLexer()->getFileEntry();
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric // If this file is older than the file it depends on, emit a diagnostic.
5540b57cec5SDimitry Andric if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
5550b57cec5SDimitry Andric // Lex tokens at the end of the message and include them in the message.
5560b57cec5SDimitry Andric std::string Message;
5570b57cec5SDimitry Andric Lex(DependencyTok);
5580b57cec5SDimitry Andric while (DependencyTok.isNot(tok::eod)) {
5590b57cec5SDimitry Andric Message += getSpelling(DependencyTok) + " ";
5600b57cec5SDimitry Andric Lex(DependencyTok);
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // Remove the trailing ' ' if present.
5640b57cec5SDimitry Andric if (!Message.empty())
5650b57cec5SDimitry Andric Message.erase(Message.end()-1);
56681ad6265SDimitry Andric Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andric /// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro.
5710b57cec5SDimitry Andric /// Return the IdentifierInfo* associated with the macro to push or pop.
ParsePragmaPushOrPopMacro(Token & Tok)5720b57cec5SDimitry Andric IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
5730b57cec5SDimitry Andric // Remember the pragma token location.
5740b57cec5SDimitry Andric Token PragmaTok = Tok;
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric // Read the '('.
5770b57cec5SDimitry Andric Lex(Tok);
5780b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
5790b57cec5SDimitry Andric Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
5800b57cec5SDimitry Andric << getSpelling(PragmaTok);
5810b57cec5SDimitry Andric return nullptr;
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric // Read the macro name string.
5850b57cec5SDimitry Andric Lex(Tok);
5860b57cec5SDimitry Andric if (Tok.isNot(tok::string_literal)) {
5870b57cec5SDimitry Andric Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
5880b57cec5SDimitry Andric << getSpelling(PragmaTok);
5890b57cec5SDimitry Andric return nullptr;
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric if (Tok.hasUDSuffix()) {
5930b57cec5SDimitry Andric Diag(Tok, diag::err_invalid_string_udl);
5940b57cec5SDimitry Andric return nullptr;
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric
5970b57cec5SDimitry Andric // Remember the macro string.
5980b57cec5SDimitry Andric std::string StrVal = getSpelling(Tok);
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric // Read the ')'.
6010b57cec5SDimitry Andric Lex(Tok);
6020b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
6030b57cec5SDimitry Andric Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
6040b57cec5SDimitry Andric << getSpelling(PragmaTok);
6050b57cec5SDimitry Andric return nullptr;
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andric assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
6090b57cec5SDimitry Andric "Invalid string token!");
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric // Create a Token from the string.
6120b57cec5SDimitry Andric Token MacroTok;
6130b57cec5SDimitry Andric MacroTok.startToken();
6140b57cec5SDimitry Andric MacroTok.setKind(tok::raw_identifier);
6150b57cec5SDimitry Andric CreateString(StringRef(&StrVal[1], StrVal.size() - 2), MacroTok);
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andric // Get the IdentifierInfo of MacroToPushTok.
6180b57cec5SDimitry Andric return LookUpIdentifierInfo(MacroTok);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric /// Handle \#pragma push_macro.
6220b57cec5SDimitry Andric ///
6230b57cec5SDimitry Andric /// The syntax is:
6240b57cec5SDimitry Andric /// \code
6250b57cec5SDimitry Andric /// #pragma push_macro("macro")
6260b57cec5SDimitry Andric /// \endcode
HandlePragmaPushMacro(Token & PushMacroTok)6270b57cec5SDimitry Andric void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
6280b57cec5SDimitry Andric // Parse the pragma directive and get the macro IdentifierInfo*.
6290b57cec5SDimitry Andric IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PushMacroTok);
6300b57cec5SDimitry Andric if (!IdentInfo) return;
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric // Get the MacroInfo associated with IdentInfo.
6330b57cec5SDimitry Andric MacroInfo *MI = getMacroInfo(IdentInfo);
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric if (MI) {
6360b57cec5SDimitry Andric // Allow the original MacroInfo to be redefined later.
6370b57cec5SDimitry Andric MI->setIsAllowRedefinitionsWithoutWarning(true);
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andric // Push the cloned MacroInfo so we can retrieve it later.
6410b57cec5SDimitry Andric PragmaPushMacroInfo[IdentInfo].push_back(MI);
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric
6440b57cec5SDimitry Andric /// Handle \#pragma pop_macro.
6450b57cec5SDimitry Andric ///
6460b57cec5SDimitry Andric /// The syntax is:
6470b57cec5SDimitry Andric /// \code
6480b57cec5SDimitry Andric /// #pragma pop_macro("macro")
6490b57cec5SDimitry Andric /// \endcode
HandlePragmaPopMacro(Token & PopMacroTok)6500b57cec5SDimitry Andric void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
6510b57cec5SDimitry Andric SourceLocation MessageLoc = PopMacroTok.getLocation();
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric // Parse the pragma directive and get the macro IdentifierInfo*.
6540b57cec5SDimitry Andric IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok);
6550b57cec5SDimitry Andric if (!IdentInfo) return;
6560b57cec5SDimitry Andric
6570b57cec5SDimitry Andric // Find the vector<MacroInfo*> associated with the macro.
6580b57cec5SDimitry Andric llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>>::iterator iter =
6590b57cec5SDimitry Andric PragmaPushMacroInfo.find(IdentInfo);
6600b57cec5SDimitry Andric if (iter != PragmaPushMacroInfo.end()) {
6610b57cec5SDimitry Andric // Forget the MacroInfo currently associated with IdentInfo.
6620b57cec5SDimitry Andric if (MacroInfo *MI = getMacroInfo(IdentInfo)) {
6630b57cec5SDimitry Andric if (MI->isWarnIfUnused())
6640b57cec5SDimitry Andric WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
6650b57cec5SDimitry Andric appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc));
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric
6680b57cec5SDimitry Andric // Get the MacroInfo we want to reinstall.
6690b57cec5SDimitry Andric MacroInfo *MacroToReInstall = iter->second.back();
6700b57cec5SDimitry Andric
6710b57cec5SDimitry Andric if (MacroToReInstall)
6720b57cec5SDimitry Andric // Reinstall the previously pushed macro.
6730b57cec5SDimitry Andric appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc);
6740b57cec5SDimitry Andric
6750b57cec5SDimitry Andric // Pop PragmaPushMacroInfo stack.
6760b57cec5SDimitry Andric iter->second.pop_back();
6770b57cec5SDimitry Andric if (iter->second.empty())
6780b57cec5SDimitry Andric PragmaPushMacroInfo.erase(iter);
6790b57cec5SDimitry Andric } else {
6800b57cec5SDimitry Andric Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push)
6810b57cec5SDimitry Andric << IdentInfo->getName();
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric
HandlePragmaIncludeAlias(Token & Tok)6850b57cec5SDimitry Andric void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) {
6860b57cec5SDimitry Andric // We will either get a quoted filename or a bracketed filename, and we
6870b57cec5SDimitry Andric // have to track which we got. The first filename is the source name,
6880b57cec5SDimitry Andric // and the second name is the mapped filename. If the first is quoted,
6890b57cec5SDimitry Andric // the second must be as well (cannot mix and match quotes and brackets).
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric // Get the open paren
6920b57cec5SDimitry Andric Lex(Tok);
6930b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
6940b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_include_alias_expected) << "(";
6950b57cec5SDimitry Andric return;
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric
6980b57cec5SDimitry Andric // We expect either a quoted string literal, or a bracketed name
6990b57cec5SDimitry Andric Token SourceFilenameTok;
7000b57cec5SDimitry Andric if (LexHeaderName(SourceFilenameTok))
7010b57cec5SDimitry Andric return;
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric StringRef SourceFileName;
7040b57cec5SDimitry Andric SmallString<128> FileNameBuffer;
7050b57cec5SDimitry Andric if (SourceFilenameTok.is(tok::header_name)) {
7060b57cec5SDimitry Andric SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer);
7070b57cec5SDimitry Andric } else {
7080b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
7090b57cec5SDimitry Andric return;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric FileNameBuffer.clear();
7120b57cec5SDimitry Andric
7130b57cec5SDimitry Andric // Now we expect a comma, followed by another include name
7140b57cec5SDimitry Andric Lex(Tok);
7150b57cec5SDimitry Andric if (Tok.isNot(tok::comma)) {
7160b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_include_alias_expected) << ",";
7170b57cec5SDimitry Andric return;
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric
7200b57cec5SDimitry Andric Token ReplaceFilenameTok;
7210b57cec5SDimitry Andric if (LexHeaderName(ReplaceFilenameTok))
7220b57cec5SDimitry Andric return;
7230b57cec5SDimitry Andric
7240b57cec5SDimitry Andric StringRef ReplaceFileName;
7250b57cec5SDimitry Andric if (ReplaceFilenameTok.is(tok::header_name)) {
7260b57cec5SDimitry Andric ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer);
7270b57cec5SDimitry Andric } else {
7280b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_include_alias_expected_filename);
7290b57cec5SDimitry Andric return;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric
7320b57cec5SDimitry Andric // Finally, we expect the closing paren
7330b57cec5SDimitry Andric Lex(Tok);
7340b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
7350b57cec5SDimitry Andric Diag(Tok, diag::warn_pragma_include_alias_expected) << ")";
7360b57cec5SDimitry Andric return;
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric
7390b57cec5SDimitry Andric // Now that we have the source and target filenames, we need to make sure
7400b57cec5SDimitry Andric // they're both of the same type (angled vs non-angled)
7410b57cec5SDimitry Andric StringRef OriginalSource = SourceFileName;
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric bool SourceIsAngled =
7440b57cec5SDimitry Andric GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(),
7450b57cec5SDimitry Andric SourceFileName);
7460b57cec5SDimitry Andric bool ReplaceIsAngled =
7470b57cec5SDimitry Andric GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(),
7480b57cec5SDimitry Andric ReplaceFileName);
7490b57cec5SDimitry Andric if (!SourceFileName.empty() && !ReplaceFileName.empty() &&
7500b57cec5SDimitry Andric (SourceIsAngled != ReplaceIsAngled)) {
7510b57cec5SDimitry Andric unsigned int DiagID;
7520b57cec5SDimitry Andric if (SourceIsAngled)
7530b57cec5SDimitry Andric DiagID = diag::warn_pragma_include_alias_mismatch_angle;
7540b57cec5SDimitry Andric else
7550b57cec5SDimitry Andric DiagID = diag::warn_pragma_include_alias_mismatch_quote;
7560b57cec5SDimitry Andric
7570b57cec5SDimitry Andric Diag(SourceFilenameTok.getLocation(), DiagID)
7580b57cec5SDimitry Andric << SourceFileName
7590b57cec5SDimitry Andric << ReplaceFileName;
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric return;
7620b57cec5SDimitry Andric }
7630b57cec5SDimitry Andric
7640b57cec5SDimitry Andric // Now we can let the include handler know about this mapping
7650b57cec5SDimitry Andric getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName);
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric // Lex a component of a module name: either an identifier or a string literal;
7690b57cec5SDimitry Andric // for components that can be expressed both ways, the two forms are equivalent.
LexModuleNameComponent(Preprocessor & PP,Token & Tok,std::pair<IdentifierInfo *,SourceLocation> & ModuleNameComponent,bool First)7700b57cec5SDimitry Andric static bool LexModuleNameComponent(
7710b57cec5SDimitry Andric Preprocessor &PP, Token &Tok,
7720b57cec5SDimitry Andric std::pair<IdentifierInfo *, SourceLocation> &ModuleNameComponent,
7730b57cec5SDimitry Andric bool First) {
7740b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
7750b57cec5SDimitry Andric if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) {
7760b57cec5SDimitry Andric StringLiteralParser Literal(Tok, PP);
7770b57cec5SDimitry Andric if (Literal.hadError)
7780b57cec5SDimitry Andric return true;
7790b57cec5SDimitry Andric ModuleNameComponent = std::make_pair(
7800b57cec5SDimitry Andric PP.getIdentifierInfo(Literal.GetString()), Tok.getLocation());
7810b57cec5SDimitry Andric } else if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) {
7820b57cec5SDimitry Andric ModuleNameComponent =
7830b57cec5SDimitry Andric std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation());
7840b57cec5SDimitry Andric } else {
7850b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << First;
7860b57cec5SDimitry Andric return true;
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric return false;
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric
LexModuleName(Preprocessor & PP,Token & Tok,llvm::SmallVectorImpl<std::pair<IdentifierInfo *,SourceLocation>> & ModuleName)7910b57cec5SDimitry Andric static bool LexModuleName(
7920b57cec5SDimitry Andric Preprocessor &PP, Token &Tok,
7930b57cec5SDimitry Andric llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>>
7940b57cec5SDimitry Andric &ModuleName) {
7950b57cec5SDimitry Andric while (true) {
7960b57cec5SDimitry Andric std::pair<IdentifierInfo*, SourceLocation> NameComponent;
7970b57cec5SDimitry Andric if (LexModuleNameComponent(PP, Tok, NameComponent, ModuleName.empty()))
7980b57cec5SDimitry Andric return true;
7990b57cec5SDimitry Andric ModuleName.push_back(NameComponent);
8000b57cec5SDimitry Andric
8010b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
8020b57cec5SDimitry Andric if (Tok.isNot(tok::period))
8030b57cec5SDimitry Andric return false;
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric }
8060b57cec5SDimitry Andric
HandlePragmaModuleBuild(Token & Tok)8070b57cec5SDimitry Andric void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
8080b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
8110b57cec5SDimitry Andric if (LexModuleNameComponent(*this, Tok, ModuleNameLoc, true))
8120b57cec5SDimitry Andric return;
8130b57cec5SDimitry Andric IdentifierInfo *ModuleName = ModuleNameLoc.first;
8140b57cec5SDimitry Andric
8150b57cec5SDimitry Andric LexUnexpandedToken(Tok);
8160b57cec5SDimitry Andric if (Tok.isNot(tok::eod)) {
8170b57cec5SDimitry Andric Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
8180b57cec5SDimitry Andric DiscardUntilEndOfDirective();
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric CurLexer->LexingRawMode = true;
8220b57cec5SDimitry Andric
8230b57cec5SDimitry Andric auto TryConsumeIdentifier = [&](StringRef Ident) -> bool {
8240b57cec5SDimitry Andric if (Tok.getKind() != tok::raw_identifier ||
8250b57cec5SDimitry Andric Tok.getRawIdentifier() != Ident)
8260b57cec5SDimitry Andric return false;
8270b57cec5SDimitry Andric CurLexer->Lex(Tok);
8280b57cec5SDimitry Andric return true;
8290b57cec5SDimitry Andric };
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric // Scan forward looking for the end of the module.
8320b57cec5SDimitry Andric const char *Start = CurLexer->getBufferLocation();
8330b57cec5SDimitry Andric const char *End = nullptr;
8340b57cec5SDimitry Andric unsigned NestingLevel = 1;
8350b57cec5SDimitry Andric while (true) {
8360b57cec5SDimitry Andric End = CurLexer->getBufferLocation();
8370b57cec5SDimitry Andric CurLexer->Lex(Tok);
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric if (Tok.is(tok::eof)) {
8400b57cec5SDimitry Andric Diag(Loc, diag::err_pp_module_build_missing_end);
8410b57cec5SDimitry Andric break;
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric
8440b57cec5SDimitry Andric if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) {
8450b57cec5SDimitry Andric // Token was part of module; keep going.
8460b57cec5SDimitry Andric continue;
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric // We hit something directive-shaped; check to see if this is the end
8500b57cec5SDimitry Andric // of the module build.
8510b57cec5SDimitry Andric CurLexer->ParsingPreprocessorDirective = true;
8520b57cec5SDimitry Andric CurLexer->Lex(Tok);
8530b57cec5SDimitry Andric if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") &&
8540b57cec5SDimitry Andric TryConsumeIdentifier("module")) {
8550b57cec5SDimitry Andric if (TryConsumeIdentifier("build"))
8560b57cec5SDimitry Andric // #pragma clang module build -> entering a nested module build.
8570b57cec5SDimitry Andric ++NestingLevel;
8580b57cec5SDimitry Andric else if (TryConsumeIdentifier("endbuild")) {
8590b57cec5SDimitry Andric // #pragma clang module endbuild -> leaving a module build.
8600b57cec5SDimitry Andric if (--NestingLevel == 0)
8610b57cec5SDimitry Andric break;
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric // We should either be looking at the EOD or more of the current directive
8640b57cec5SDimitry Andric // preceding the EOD. Either way we can ignore this token and keep going.
8650b57cec5SDimitry Andric assert(Tok.getKind() != tok::eof && "missing EOD before EOF");
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric
8690b57cec5SDimitry Andric CurLexer->LexingRawMode = false;
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric // Load the extracted text as a preprocessed module.
8720b57cec5SDimitry Andric assert(CurLexer->getBuffer().begin() <= Start &&
8730b57cec5SDimitry Andric Start <= CurLexer->getBuffer().end() &&
8740b57cec5SDimitry Andric CurLexer->getBuffer().begin() <= End &&
8750b57cec5SDimitry Andric End <= CurLexer->getBuffer().end() &&
8760b57cec5SDimitry Andric "module source range not contained within same file buffer");
877480093f4SDimitry Andric TheModuleLoader.createModuleFromSource(Loc, ModuleName->getName(),
8780b57cec5SDimitry Andric StringRef(Start, End - Start));
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric
HandlePragmaHdrstop(Token & Tok)8810b57cec5SDimitry Andric void Preprocessor::HandlePragmaHdrstop(Token &Tok) {
8820b57cec5SDimitry Andric Lex(Tok);
8830b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) {
8840b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::warn_pp_hdrstop_filename_ignored);
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric std::string FileName;
8870b57cec5SDimitry Andric if (!LexStringLiteral(Tok, FileName, "pragma hdrstop", false))
8880b57cec5SDimitry Andric return;
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
8910b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::r_paren;
8920b57cec5SDimitry Andric return;
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric Lex(Tok);
8950b57cec5SDimitry Andric }
8960b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
8970b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::ext_pp_extra_tokens_at_eol)
8980b57cec5SDimitry Andric << "pragma hdrstop";
8990b57cec5SDimitry Andric
9000b57cec5SDimitry Andric if (creatingPCHWithPragmaHdrStop() &&
9010b57cec5SDimitry Andric SourceMgr.isInMainFile(Tok.getLocation())) {
9020b57cec5SDimitry Andric assert(CurLexer && "no lexer for #pragma hdrstop processing");
9030b57cec5SDimitry Andric Token &Result = Tok;
9040b57cec5SDimitry Andric Result.startToken();
9050b57cec5SDimitry Andric CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
9060b57cec5SDimitry Andric CurLexer->cutOffLexing();
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric if (usingPCHWithPragmaHdrStop())
9090b57cec5SDimitry Andric SkippingUntilPragmaHdrStop = false;
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andric /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
9130b57cec5SDimitry Andric /// If 'Namespace' is non-null, then it is a token required to exist on the
9140b57cec5SDimitry Andric /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
AddPragmaHandler(StringRef Namespace,PragmaHandler * Handler)9150b57cec5SDimitry Andric void Preprocessor::AddPragmaHandler(StringRef Namespace,
9160b57cec5SDimitry Andric PragmaHandler *Handler) {
9170b57cec5SDimitry Andric PragmaNamespace *InsertNS = PragmaHandlers.get();
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric // If this is specified to be in a namespace, step down into it.
9200b57cec5SDimitry Andric if (!Namespace.empty()) {
9210b57cec5SDimitry Andric // If there is already a pragma handler with the name of this namespace,
9220b57cec5SDimitry Andric // we either have an error (directive with the same name as a namespace) or
9230b57cec5SDimitry Andric // we already have the namespace to insert into.
9240b57cec5SDimitry Andric if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) {
9250b57cec5SDimitry Andric InsertNS = Existing->getIfNamespace();
9260b57cec5SDimitry Andric assert(InsertNS != nullptr && "Cannot have a pragma namespace and pragma"
9270b57cec5SDimitry Andric " handler with the same name!");
9280b57cec5SDimitry Andric } else {
9290b57cec5SDimitry Andric // Otherwise, this namespace doesn't exist yet, create and insert the
9300b57cec5SDimitry Andric // handler for it.
9310b57cec5SDimitry Andric InsertNS = new PragmaNamespace(Namespace);
9320b57cec5SDimitry Andric PragmaHandlers->AddPragma(InsertNS);
9330b57cec5SDimitry Andric }
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric
9360b57cec5SDimitry Andric // Check to make sure we don't already have a pragma for this identifier.
9370b57cec5SDimitry Andric assert(!InsertNS->FindHandler(Handler->getName()) &&
9380b57cec5SDimitry Andric "Pragma handler already exists for this identifier!");
9390b57cec5SDimitry Andric InsertNS->AddPragma(Handler);
9400b57cec5SDimitry Andric }
9410b57cec5SDimitry Andric
9420b57cec5SDimitry Andric /// RemovePragmaHandler - Remove the specific pragma handler from the
9430b57cec5SDimitry Andric /// preprocessor. If \arg Namespace is non-null, then it should be the
9440b57cec5SDimitry Andric /// namespace that \arg Handler was added to. It is an error to remove
9450b57cec5SDimitry Andric /// a handler that has not been registered.
RemovePragmaHandler(StringRef Namespace,PragmaHandler * Handler)9460b57cec5SDimitry Andric void Preprocessor::RemovePragmaHandler(StringRef Namespace,
9470b57cec5SDimitry Andric PragmaHandler *Handler) {
9480b57cec5SDimitry Andric PragmaNamespace *NS = PragmaHandlers.get();
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric // If this is specified to be in a namespace, step down into it.
9510b57cec5SDimitry Andric if (!Namespace.empty()) {
9520b57cec5SDimitry Andric PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace);
9530b57cec5SDimitry Andric assert(Existing && "Namespace containing handler does not exist!");
9540b57cec5SDimitry Andric
9550b57cec5SDimitry Andric NS = Existing->getIfNamespace();
9560b57cec5SDimitry Andric assert(NS && "Invalid namespace, registered as a regular pragma handler!");
9570b57cec5SDimitry Andric }
9580b57cec5SDimitry Andric
9590b57cec5SDimitry Andric NS->RemovePragmaHandler(Handler);
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric // If this is a non-default namespace and it is now empty, remove it.
9620b57cec5SDimitry Andric if (NS != PragmaHandlers.get() && NS->IsEmpty()) {
9630b57cec5SDimitry Andric PragmaHandlers->RemovePragmaHandler(NS);
9640b57cec5SDimitry Andric delete NS;
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric }
9670b57cec5SDimitry Andric
LexOnOffSwitch(tok::OnOffSwitch & Result)9680b57cec5SDimitry Andric bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) {
9690b57cec5SDimitry Andric Token Tok;
9700b57cec5SDimitry Andric LexUnexpandedToken(Tok);
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
9730b57cec5SDimitry Andric Diag(Tok, diag::ext_on_off_switch_syntax);
9740b57cec5SDimitry Andric return true;
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
9770b57cec5SDimitry Andric if (II->isStr("ON"))
9780b57cec5SDimitry Andric Result = tok::OOS_ON;
9790b57cec5SDimitry Andric else if (II->isStr("OFF"))
9800b57cec5SDimitry Andric Result = tok::OOS_OFF;
9810b57cec5SDimitry Andric else if (II->isStr("DEFAULT"))
9820b57cec5SDimitry Andric Result = tok::OOS_DEFAULT;
9830b57cec5SDimitry Andric else {
9840b57cec5SDimitry Andric Diag(Tok, diag::ext_on_off_switch_syntax);
9850b57cec5SDimitry Andric return true;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric
9880b57cec5SDimitry Andric // Verify that this is followed by EOD.
9890b57cec5SDimitry Andric LexUnexpandedToken(Tok);
9900b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
9910b57cec5SDimitry Andric Diag(Tok, diag::ext_pragma_syntax_eod);
9920b57cec5SDimitry Andric return false;
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andric namespace {
9960b57cec5SDimitry Andric
9970b57cec5SDimitry Andric /// PragmaOnceHandler - "\#pragma once" marks the file as atomically included.
9980b57cec5SDimitry Andric struct PragmaOnceHandler : public PragmaHandler {
PragmaOnceHandler__anon851a8f8a0311::PragmaOnceHandler9990b57cec5SDimitry Andric PragmaOnceHandler() : PragmaHandler("once") {}
10000b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaOnceHandler10010b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10020b57cec5SDimitry Andric Token &OnceTok) override {
10030b57cec5SDimitry Andric PP.CheckEndOfDirective("pragma once");
10040b57cec5SDimitry Andric PP.HandlePragmaOnce(OnceTok);
10050b57cec5SDimitry Andric }
10060b57cec5SDimitry Andric };
10070b57cec5SDimitry Andric
10080b57cec5SDimitry Andric /// PragmaMarkHandler - "\#pragma mark ..." is ignored by the compiler, and the
10090b57cec5SDimitry Andric /// rest of the line is not lexed.
10100b57cec5SDimitry Andric struct PragmaMarkHandler : public PragmaHandler {
PragmaMarkHandler__anon851a8f8a0311::PragmaMarkHandler10110b57cec5SDimitry Andric PragmaMarkHandler() : PragmaHandler("mark") {}
10120b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaMarkHandler10130b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10140b57cec5SDimitry Andric Token &MarkTok) override {
1015fe6060f1SDimitry Andric PP.HandlePragmaMark(MarkTok);
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric };
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric /// PragmaPoisonHandler - "\#pragma poison x" marks x as not usable.
10200b57cec5SDimitry Andric struct PragmaPoisonHandler : public PragmaHandler {
PragmaPoisonHandler__anon851a8f8a0311::PragmaPoisonHandler10210b57cec5SDimitry Andric PragmaPoisonHandler() : PragmaHandler("poison") {}
10220b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaPoisonHandler10230b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10240b57cec5SDimitry Andric Token &PoisonTok) override {
10250b57cec5SDimitry Andric PP.HandlePragmaPoison();
10260b57cec5SDimitry Andric }
10270b57cec5SDimitry Andric };
10280b57cec5SDimitry Andric
10290b57cec5SDimitry Andric /// PragmaSystemHeaderHandler - "\#pragma system_header" marks the current file
10300b57cec5SDimitry Andric /// as a system header, which silences warnings in it.
10310b57cec5SDimitry Andric struct PragmaSystemHeaderHandler : public PragmaHandler {
PragmaSystemHeaderHandler__anon851a8f8a0311::PragmaSystemHeaderHandler10320b57cec5SDimitry Andric PragmaSystemHeaderHandler() : PragmaHandler("system_header") {}
10330b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaSystemHeaderHandler10340b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10350b57cec5SDimitry Andric Token &SHToken) override {
10360b57cec5SDimitry Andric PP.HandlePragmaSystemHeader(SHToken);
10370b57cec5SDimitry Andric PP.CheckEndOfDirective("pragma");
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric };
10400b57cec5SDimitry Andric
10410b57cec5SDimitry Andric struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler__anon851a8f8a0311::PragmaDependencyHandler10420b57cec5SDimitry Andric PragmaDependencyHandler() : PragmaHandler("dependency") {}
10430b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaDependencyHandler10440b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10450b57cec5SDimitry Andric Token &DepToken) override {
10460b57cec5SDimitry Andric PP.HandlePragmaDependency(DepToken);
10470b57cec5SDimitry Andric }
10480b57cec5SDimitry Andric };
10490b57cec5SDimitry Andric
10500b57cec5SDimitry Andric struct PragmaDebugHandler : public PragmaHandler {
PragmaDebugHandler__anon851a8f8a0311::PragmaDebugHandler10510b57cec5SDimitry Andric PragmaDebugHandler() : PragmaHandler("__debug") {}
10520b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaDebugHandler10530b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
10540b57cec5SDimitry Andric Token &DebugToken) override {
10550b57cec5SDimitry Andric Token Tok;
10560b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
10570b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
1058bdd1243dSDimitry Andric PP.Diag(Tok, diag::warn_pragma_debug_missing_command);
10590b57cec5SDimitry Andric return;
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric if (II->isStr("assert")) {
106413138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
10650b57cec5SDimitry Andric llvm_unreachable("This is an assertion!");
10660b57cec5SDimitry Andric } else if (II->isStr("crash")) {
1067cd675bb6SDimitry Andric llvm::Timer T("crash", "pragma crash");
1068cd675bb6SDimitry Andric llvm::TimeRegion R(&T);
106913138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
10700b57cec5SDimitry Andric LLVM_BUILTIN_TRAP;
10710b57cec5SDimitry Andric } else if (II->isStr("parser_crash")) {
107213138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) {
10730b57cec5SDimitry Andric Token Crasher;
10740b57cec5SDimitry Andric Crasher.startToken();
10750b57cec5SDimitry Andric Crasher.setKind(tok::annot_pragma_parser_crash);
10760b57cec5SDimitry Andric Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
10770b57cec5SDimitry Andric PP.EnterToken(Crasher, /*IsReinject*/ false);
107813138422SDimitry Andric }
10790b57cec5SDimitry Andric } else if (II->isStr("dump")) {
10800b57cec5SDimitry Andric Token DumpAnnot;
10810b57cec5SDimitry Andric DumpAnnot.startToken();
10820b57cec5SDimitry Andric DumpAnnot.setKind(tok::annot_pragma_dump);
108306c3fb27SDimitry Andric DumpAnnot.setAnnotationRange(SourceRange(Tok.getLocation()));
10840b57cec5SDimitry Andric PP.EnterToken(DumpAnnot, /*IsReinject*/false);
10850b57cec5SDimitry Andric } else if (II->isStr("diag_mapping")) {
10860b57cec5SDimitry Andric Token DiagName;
10870b57cec5SDimitry Andric PP.LexUnexpandedToken(DiagName);
10880b57cec5SDimitry Andric if (DiagName.is(tok::eod))
10890b57cec5SDimitry Andric PP.getDiagnostics().dump();
10900b57cec5SDimitry Andric else if (DiagName.is(tok::string_literal) && !DiagName.hasUDSuffix()) {
109106c3fb27SDimitry Andric StringLiteralParser Literal(DiagName, PP,
109206c3fb27SDimitry Andric StringLiteralEvalMethod::Unevaluated);
10930b57cec5SDimitry Andric if (Literal.hadError)
10940b57cec5SDimitry Andric return;
10950b57cec5SDimitry Andric PP.getDiagnostics().dump(Literal.GetString());
10960b57cec5SDimitry Andric } else {
10970b57cec5SDimitry Andric PP.Diag(DiagName, diag::warn_pragma_debug_missing_argument)
10980b57cec5SDimitry Andric << II->getName();
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric } else if (II->isStr("llvm_fatal_error")) {
110113138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
11020b57cec5SDimitry Andric llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
11030b57cec5SDimitry Andric } else if (II->isStr("llvm_unreachable")) {
110413138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
11050b57cec5SDimitry Andric llvm_unreachable("#pragma clang __debug llvm_unreachable");
11060b57cec5SDimitry Andric } else if (II->isStr("macro")) {
11070b57cec5SDimitry Andric Token MacroName;
11080b57cec5SDimitry Andric PP.LexUnexpandedToken(MacroName);
11090b57cec5SDimitry Andric auto *MacroII = MacroName.getIdentifierInfo();
11100b57cec5SDimitry Andric if (MacroII)
11110b57cec5SDimitry Andric PP.dumpMacroInfo(MacroII);
11120b57cec5SDimitry Andric else
11130b57cec5SDimitry Andric PP.Diag(MacroName, diag::warn_pragma_debug_missing_argument)
11140b57cec5SDimitry Andric << II->getName();
11150b57cec5SDimitry Andric } else if (II->isStr("module_map")) {
11160b57cec5SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8>
11170b57cec5SDimitry Andric ModuleName;
11180b57cec5SDimitry Andric if (LexModuleName(PP, Tok, ModuleName))
11190b57cec5SDimitry Andric return;
11200b57cec5SDimitry Andric ModuleMap &MM = PP.getHeaderSearchInfo().getModuleMap();
11210b57cec5SDimitry Andric Module *M = nullptr;
11220b57cec5SDimitry Andric for (auto IIAndLoc : ModuleName) {
11230b57cec5SDimitry Andric M = MM.lookupModuleQualified(IIAndLoc.first->getName(), M);
11240b57cec5SDimitry Andric if (!M) {
11250b57cec5SDimitry Andric PP.Diag(IIAndLoc.second, diag::warn_pragma_debug_unknown_module)
11260b57cec5SDimitry Andric << IIAndLoc.first;
11270b57cec5SDimitry Andric return;
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric M->dump();
11310b57cec5SDimitry Andric } else if (II->isStr("overflow_stack")) {
113213138422SDimitry Andric if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
11330b57cec5SDimitry Andric DebugOverflowStack();
11340b57cec5SDimitry Andric } else if (II->isStr("captured")) {
11350b57cec5SDimitry Andric HandleCaptured(PP);
1136fe6060f1SDimitry Andric } else if (II->isStr("modules")) {
1137fe6060f1SDimitry Andric struct ModuleVisitor {
1138fe6060f1SDimitry Andric Preprocessor &PP;
1139fe6060f1SDimitry Andric void visit(Module *M, bool VisibleOnly) {
1140fe6060f1SDimitry Andric SourceLocation ImportLoc = PP.getModuleImportLoc(M);
1141fe6060f1SDimitry Andric if (!VisibleOnly || ImportLoc.isValid()) {
1142fe6060f1SDimitry Andric llvm::errs() << M->getFullModuleName() << " ";
1143fe6060f1SDimitry Andric if (ImportLoc.isValid()) {
1144fe6060f1SDimitry Andric llvm::errs() << M << " visible ";
1145fe6060f1SDimitry Andric ImportLoc.print(llvm::errs(), PP.getSourceManager());
1146fe6060f1SDimitry Andric }
1147fe6060f1SDimitry Andric llvm::errs() << "\n";
1148fe6060f1SDimitry Andric }
1149fe6060f1SDimitry Andric for (Module *Sub : M->submodules()) {
1150fe6060f1SDimitry Andric if (!VisibleOnly || ImportLoc.isInvalid() || Sub->IsExplicit)
1151fe6060f1SDimitry Andric visit(Sub, VisibleOnly);
1152fe6060f1SDimitry Andric }
1153fe6060f1SDimitry Andric }
1154fe6060f1SDimitry Andric void visitAll(bool VisibleOnly) {
1155fe6060f1SDimitry Andric for (auto &NameAndMod :
1156fe6060f1SDimitry Andric PP.getHeaderSearchInfo().getModuleMap().modules())
1157fe6060f1SDimitry Andric visit(NameAndMod.second, VisibleOnly);
1158fe6060f1SDimitry Andric }
1159fe6060f1SDimitry Andric } Visitor{PP};
1160fe6060f1SDimitry Andric
1161fe6060f1SDimitry Andric Token Kind;
1162fe6060f1SDimitry Andric PP.LexUnexpandedToken(Kind);
1163fe6060f1SDimitry Andric auto *DumpII = Kind.getIdentifierInfo();
1164fe6060f1SDimitry Andric if (!DumpII) {
1165fe6060f1SDimitry Andric PP.Diag(Kind, diag::warn_pragma_debug_missing_argument)
1166fe6060f1SDimitry Andric << II->getName();
1167fe6060f1SDimitry Andric } else if (DumpII->isStr("all")) {
1168fe6060f1SDimitry Andric Visitor.visitAll(false);
1169fe6060f1SDimitry Andric } else if (DumpII->isStr("visible")) {
1170fe6060f1SDimitry Andric Visitor.visitAll(true);
1171fe6060f1SDimitry Andric } else if (DumpII->isStr("building")) {
1172fe6060f1SDimitry Andric for (auto &Building : PP.getBuildingSubmodules()) {
1173fe6060f1SDimitry Andric llvm::errs() << "in " << Building.M->getFullModuleName();
1174fe6060f1SDimitry Andric if (Building.ImportLoc.isValid()) {
1175fe6060f1SDimitry Andric llvm::errs() << " imported ";
1176fe6060f1SDimitry Andric if (Building.IsPragma)
1177fe6060f1SDimitry Andric llvm::errs() << "via pragma ";
1178fe6060f1SDimitry Andric llvm::errs() << "at ";
1179fe6060f1SDimitry Andric Building.ImportLoc.print(llvm::errs(), PP.getSourceManager());
1180fe6060f1SDimitry Andric llvm::errs() << "\n";
1181fe6060f1SDimitry Andric }
1182fe6060f1SDimitry Andric }
1183fe6060f1SDimitry Andric } else {
1184fe6060f1SDimitry Andric PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
1185fe6060f1SDimitry Andric << DumpII->getName();
1186fe6060f1SDimitry Andric }
1187bdd1243dSDimitry Andric } else if (II->isStr("sloc_usage")) {
1188bdd1243dSDimitry Andric // An optional integer literal argument specifies the number of files to
1189bdd1243dSDimitry Andric // specifically report information about.
1190bdd1243dSDimitry Andric std::optional<unsigned> MaxNotes;
1191bdd1243dSDimitry Andric Token ArgToken;
1192bdd1243dSDimitry Andric PP.Lex(ArgToken);
1193bdd1243dSDimitry Andric uint64_t Value;
1194bdd1243dSDimitry Andric if (ArgToken.is(tok::numeric_constant) &&
1195bdd1243dSDimitry Andric PP.parseSimpleIntegerLiteral(ArgToken, Value)) {
1196bdd1243dSDimitry Andric MaxNotes = Value;
1197bdd1243dSDimitry Andric } else if (ArgToken.isNot(tok::eod)) {
1198bdd1243dSDimitry Andric PP.Diag(ArgToken, diag::warn_pragma_debug_unexpected_argument);
1199bdd1243dSDimitry Andric }
1200bdd1243dSDimitry Andric
1201bdd1243dSDimitry Andric PP.Diag(Tok, diag::remark_sloc_usage);
1202bdd1243dSDimitry Andric PP.getSourceManager().noteSLocAddressSpaceUsage(PP.getDiagnostics(),
1203bdd1243dSDimitry Andric MaxNotes);
12040b57cec5SDimitry Andric } else {
12050b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
12060b57cec5SDimitry Andric << II->getName();
12070b57cec5SDimitry Andric }
12080b57cec5SDimitry Andric
12090b57cec5SDimitry Andric PPCallbacks *Callbacks = PP.getPPCallbacks();
12100b57cec5SDimitry Andric if (Callbacks)
12110b57cec5SDimitry Andric Callbacks->PragmaDebug(Tok.getLocation(), II->getName());
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric
HandleCaptured__anon851a8f8a0311::PragmaDebugHandler12140b57cec5SDimitry Andric void HandleCaptured(Preprocessor &PP) {
12150b57cec5SDimitry Andric Token Tok;
12160b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
12170b57cec5SDimitry Andric
12180b57cec5SDimitry Andric if (Tok.isNot(tok::eod)) {
12190b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol)
12200b57cec5SDimitry Andric << "pragma clang __debug captured";
12210b57cec5SDimitry Andric return;
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric
12240b57cec5SDimitry Andric SourceLocation NameLoc = Tok.getLocation();
12250b57cec5SDimitry Andric MutableArrayRef<Token> Toks(
12260b57cec5SDimitry Andric PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
12270b57cec5SDimitry Andric Toks[0].startToken();
12280b57cec5SDimitry Andric Toks[0].setKind(tok::annot_pragma_captured);
12290b57cec5SDimitry Andric Toks[0].setLocation(NameLoc);
12300b57cec5SDimitry Andric
12310b57cec5SDimitry Andric PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
12320b57cec5SDimitry Andric /*IsReinject=*/false);
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andric // Disable MSVC warning about runtime stack overflow.
12360b57cec5SDimitry Andric #ifdef _MSC_VER
12370b57cec5SDimitry Andric #pragma warning(disable : 4717)
12380b57cec5SDimitry Andric #endif
DebugOverflowStack__anon851a8f8a0311::PragmaDebugHandler12390b57cec5SDimitry Andric static void DebugOverflowStack(void (*P)() = nullptr) {
12400b57cec5SDimitry Andric void (*volatile Self)(void(*P)()) = DebugOverflowStack;
12410b57cec5SDimitry Andric Self(reinterpret_cast<void(*)()>(Self));
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric #ifdef _MSC_VER
12440b57cec5SDimitry Andric #pragma warning(default : 4717)
12450b57cec5SDimitry Andric #endif
12460b57cec5SDimitry Andric };
12470b57cec5SDimitry Andric
124806c3fb27SDimitry Andric struct PragmaUnsafeBufferUsageHandler : public PragmaHandler {
PragmaUnsafeBufferUsageHandler__anon851a8f8a0311::PragmaUnsafeBufferUsageHandler124906c3fb27SDimitry Andric PragmaUnsafeBufferUsageHandler() : PragmaHandler("unsafe_buffer_usage") {}
HandlePragma__anon851a8f8a0311::PragmaUnsafeBufferUsageHandler125006c3fb27SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
125106c3fb27SDimitry Andric Token &FirstToken) override {
125206c3fb27SDimitry Andric Token Tok;
125306c3fb27SDimitry Andric
125406c3fb27SDimitry Andric PP.LexUnexpandedToken(Tok);
125506c3fb27SDimitry Andric if (Tok.isNot(tok::identifier)) {
125606c3fb27SDimitry Andric PP.Diag(Tok, diag::err_pp_pragma_unsafe_buffer_usage_syntax);
125706c3fb27SDimitry Andric return;
125806c3fb27SDimitry Andric }
125906c3fb27SDimitry Andric
126006c3fb27SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
126106c3fb27SDimitry Andric SourceLocation Loc = Tok.getLocation();
126206c3fb27SDimitry Andric
126306c3fb27SDimitry Andric if (II->isStr("begin")) {
126406c3fb27SDimitry Andric if (PP.enterOrExitSafeBufferOptOutRegion(true, Loc))
126506c3fb27SDimitry Andric PP.Diag(Loc, diag::err_pp_double_begin_pragma_unsafe_buffer_usage);
126606c3fb27SDimitry Andric } else if (II->isStr("end")) {
126706c3fb27SDimitry Andric if (PP.enterOrExitSafeBufferOptOutRegion(false, Loc))
126806c3fb27SDimitry Andric PP.Diag(Loc, diag::err_pp_unmatched_end_begin_pragma_unsafe_buffer_usage);
126906c3fb27SDimitry Andric } else
127006c3fb27SDimitry Andric PP.Diag(Tok, diag::err_pp_pragma_unsafe_buffer_usage_syntax);
127106c3fb27SDimitry Andric }
127206c3fb27SDimitry Andric };
127306c3fb27SDimitry Andric
12740b57cec5SDimitry Andric /// PragmaDiagnosticHandler - e.g. '\#pragma GCC diagnostic ignored "-Wformat"'
12750b57cec5SDimitry Andric struct PragmaDiagnosticHandler : public PragmaHandler {
12760b57cec5SDimitry Andric private:
12770b57cec5SDimitry Andric const char *Namespace;
12780b57cec5SDimitry Andric
12790b57cec5SDimitry Andric public:
PragmaDiagnosticHandler__anon851a8f8a0311::PragmaDiagnosticHandler12800b57cec5SDimitry Andric explicit PragmaDiagnosticHandler(const char *NS)
12810b57cec5SDimitry Andric : PragmaHandler("diagnostic"), Namespace(NS) {}
12820b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaDiagnosticHandler12830b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
12840b57cec5SDimitry Andric Token &DiagToken) override {
12850b57cec5SDimitry Andric SourceLocation DiagLoc = DiagToken.getLocation();
12860b57cec5SDimitry Andric Token Tok;
12870b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
12880b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
12890b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
12900b57cec5SDimitry Andric return;
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
12930b57cec5SDimitry Andric PPCallbacks *Callbacks = PP.getPPCallbacks();
12940b57cec5SDimitry Andric
129506c3fb27SDimitry Andric // Get the next token, which is either an EOD or a string literal. We lex
129606c3fb27SDimitry Andric // it now so that we can early return if the previous token was push or pop.
129706c3fb27SDimitry Andric PP.LexUnexpandedToken(Tok);
129806c3fb27SDimitry Andric
12990b57cec5SDimitry Andric if (II->isStr("pop")) {
13000b57cec5SDimitry Andric if (!PP.getDiagnostics().popMappings(DiagLoc))
13010b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
13020b57cec5SDimitry Andric else if (Callbacks)
13030b57cec5SDimitry Andric Callbacks->PragmaDiagnosticPop(DiagLoc, Namespace);
130406c3fb27SDimitry Andric
130506c3fb27SDimitry Andric if (Tok.isNot(tok::eod))
130606c3fb27SDimitry Andric PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
13070b57cec5SDimitry Andric return;
13080b57cec5SDimitry Andric } else if (II->isStr("push")) {
13090b57cec5SDimitry Andric PP.getDiagnostics().pushMappings(DiagLoc);
13100b57cec5SDimitry Andric if (Callbacks)
13110b57cec5SDimitry Andric Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace);
131206c3fb27SDimitry Andric
131306c3fb27SDimitry Andric if (Tok.isNot(tok::eod))
131406c3fb27SDimitry Andric PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
13150b57cec5SDimitry Andric return;
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric
13180b57cec5SDimitry Andric diag::Severity SV = llvm::StringSwitch<diag::Severity>(II->getName())
13190b57cec5SDimitry Andric .Case("ignored", diag::Severity::Ignored)
13200b57cec5SDimitry Andric .Case("warning", diag::Severity::Warning)
13210b57cec5SDimitry Andric .Case("error", diag::Severity::Error)
13220b57cec5SDimitry Andric .Case("fatal", diag::Severity::Fatal)
13230b57cec5SDimitry Andric .Default(diag::Severity());
13240b57cec5SDimitry Andric
13250b57cec5SDimitry Andric if (SV == diag::Severity()) {
13260b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
13270b57cec5SDimitry Andric return;
13280b57cec5SDimitry Andric }
13290b57cec5SDimitry Andric
133006c3fb27SDimitry Andric // At this point, we expect a string literal.
13310b57cec5SDimitry Andric SourceLocation StringLoc = Tok.getLocation();
13320b57cec5SDimitry Andric std::string WarningName;
13330b57cec5SDimitry Andric if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic",
13340b57cec5SDimitry Andric /*AllowMacroExpansion=*/false))
13350b57cec5SDimitry Andric return;
13360b57cec5SDimitry Andric
13370b57cec5SDimitry Andric if (Tok.isNot(tok::eod)) {
13380b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
13390b57cec5SDimitry Andric return;
13400b57cec5SDimitry Andric }
13410b57cec5SDimitry Andric
13420b57cec5SDimitry Andric if (WarningName.size() < 3 || WarningName[0] != '-' ||
13430b57cec5SDimitry Andric (WarningName[1] != 'W' && WarningName[1] != 'R')) {
13440b57cec5SDimitry Andric PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option);
13450b57cec5SDimitry Andric return;
13460b57cec5SDimitry Andric }
13470b57cec5SDimitry Andric
13480b57cec5SDimitry Andric diag::Flavor Flavor = WarningName[1] == 'W' ? diag::Flavor::WarningOrError
13490b57cec5SDimitry Andric : diag::Flavor::Remark;
13500b57cec5SDimitry Andric StringRef Group = StringRef(WarningName).substr(2);
13510b57cec5SDimitry Andric bool unknownDiag = false;
13520b57cec5SDimitry Andric if (Group == "everything") {
13530b57cec5SDimitry Andric // Special handling for pragma clang diagnostic ... "-Weverything".
13540b57cec5SDimitry Andric // There is no formal group named "everything", so there has to be a
13550b57cec5SDimitry Andric // special case for it.
13560b57cec5SDimitry Andric PP.getDiagnostics().setSeverityForAll(Flavor, SV, DiagLoc);
13570b57cec5SDimitry Andric } else
13580b57cec5SDimitry Andric unknownDiag = PP.getDiagnostics().setSeverityForGroup(Flavor, Group, SV,
13590b57cec5SDimitry Andric DiagLoc);
13600b57cec5SDimitry Andric if (unknownDiag)
13610b57cec5SDimitry Andric PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning)
13620b57cec5SDimitry Andric << WarningName;
13630b57cec5SDimitry Andric else if (Callbacks)
13640b57cec5SDimitry Andric Callbacks->PragmaDiagnostic(DiagLoc, Namespace, SV, WarningName);
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric };
13670b57cec5SDimitry Andric
13680b57cec5SDimitry Andric /// "\#pragma hdrstop [<header-name-string>]"
13690b57cec5SDimitry Andric struct PragmaHdrstopHandler : public PragmaHandler {
PragmaHdrstopHandler__anon851a8f8a0311::PragmaHdrstopHandler13700b57cec5SDimitry Andric PragmaHdrstopHandler() : PragmaHandler("hdrstop") {}
HandlePragma__anon851a8f8a0311::PragmaHdrstopHandler13710b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
13720b57cec5SDimitry Andric Token &DepToken) override {
13730b57cec5SDimitry Andric PP.HandlePragmaHdrstop(DepToken);
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric };
13760b57cec5SDimitry Andric
13770b57cec5SDimitry Andric /// "\#pragma warning(...)". MSVC's diagnostics do not map cleanly to clang's
13780b57cec5SDimitry Andric /// diagnostics, so we don't really implement this pragma. We parse it and
13790b57cec5SDimitry Andric /// ignore it to avoid -Wunknown-pragma warnings.
13800b57cec5SDimitry Andric struct PragmaWarningHandler : public PragmaHandler {
PragmaWarningHandler__anon851a8f8a0311::PragmaWarningHandler13810b57cec5SDimitry Andric PragmaWarningHandler() : PragmaHandler("warning") {}
13820b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaWarningHandler13830b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
13840b57cec5SDimitry Andric Token &Tok) override {
13850b57cec5SDimitry Andric // Parse things like:
13860b57cec5SDimitry Andric // warning(push, 1)
13870b57cec5SDimitry Andric // warning(pop)
13880b57cec5SDimitry Andric // warning(disable : 1 2 3 ; error : 4 5 6 ; suppress : 7 8 9)
13890b57cec5SDimitry Andric SourceLocation DiagLoc = Tok.getLocation();
13900b57cec5SDimitry Andric PPCallbacks *Callbacks = PP.getPPCallbacks();
13910b57cec5SDimitry Andric
13920b57cec5SDimitry Andric PP.Lex(Tok);
13930b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
13940b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_expected) << "(";
13950b57cec5SDimitry Andric return;
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric
13980b57cec5SDimitry Andric PP.Lex(Tok);
13990b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
14000b57cec5SDimitry Andric
14010b57cec5SDimitry Andric if (II && II->isStr("push")) {
14020b57cec5SDimitry Andric // #pragma warning( push[ ,n ] )
14030b57cec5SDimitry Andric int Level = -1;
14040b57cec5SDimitry Andric PP.Lex(Tok);
14050b57cec5SDimitry Andric if (Tok.is(tok::comma)) {
14060b57cec5SDimitry Andric PP.Lex(Tok);
14070b57cec5SDimitry Andric uint64_t Value;
14080b57cec5SDimitry Andric if (Tok.is(tok::numeric_constant) &&
14090b57cec5SDimitry Andric PP.parseSimpleIntegerLiteral(Tok, Value))
14100b57cec5SDimitry Andric Level = int(Value);
14110b57cec5SDimitry Andric if (Level < 0 || Level > 4) {
14120b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_push_level);
14130b57cec5SDimitry Andric return;
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric }
1416349cc55cSDimitry Andric PP.getDiagnostics().pushMappings(DiagLoc);
14170b57cec5SDimitry Andric if (Callbacks)
14180b57cec5SDimitry Andric Callbacks->PragmaWarningPush(DiagLoc, Level);
14190b57cec5SDimitry Andric } else if (II && II->isStr("pop")) {
14200b57cec5SDimitry Andric // #pragma warning( pop )
14210b57cec5SDimitry Andric PP.Lex(Tok);
1422349cc55cSDimitry Andric if (!PP.getDiagnostics().popMappings(DiagLoc))
1423349cc55cSDimitry Andric PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
1424349cc55cSDimitry Andric else if (Callbacks)
14250b57cec5SDimitry Andric Callbacks->PragmaWarningPop(DiagLoc);
14260b57cec5SDimitry Andric } else {
14270b57cec5SDimitry Andric // #pragma warning( warning-specifier : warning-number-list
14280b57cec5SDimitry Andric // [; warning-specifier : warning-number-list...] )
14290b57cec5SDimitry Andric while (true) {
14300b57cec5SDimitry Andric II = Tok.getIdentifierInfo();
14310b57cec5SDimitry Andric if (!II && !Tok.is(tok::numeric_constant)) {
14320b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
14330b57cec5SDimitry Andric return;
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric
14360b57cec5SDimitry Andric // Figure out which warning specifier this is.
14370b57cec5SDimitry Andric bool SpecifierValid;
1438349cc55cSDimitry Andric PPCallbacks::PragmaWarningSpecifier Specifier;
14390b57cec5SDimitry Andric if (II) {
1440349cc55cSDimitry Andric int SpecifierInt = llvm::StringSwitch<int>(II->getName())
1441349cc55cSDimitry Andric .Case("default", PPCallbacks::PWS_Default)
1442349cc55cSDimitry Andric .Case("disable", PPCallbacks::PWS_Disable)
1443349cc55cSDimitry Andric .Case("error", PPCallbacks::PWS_Error)
1444349cc55cSDimitry Andric .Case("once", PPCallbacks::PWS_Once)
1445349cc55cSDimitry Andric .Case("suppress", PPCallbacks::PWS_Suppress)
1446349cc55cSDimitry Andric .Default(-1);
1447*0fca6ea1SDimitry Andric SpecifierValid = SpecifierInt != -1;
1448*0fca6ea1SDimitry Andric if (SpecifierValid)
1449349cc55cSDimitry Andric Specifier =
1450349cc55cSDimitry Andric static_cast<PPCallbacks::PragmaWarningSpecifier>(SpecifierInt);
1451349cc55cSDimitry Andric
14520b57cec5SDimitry Andric // If we read a correct specifier, snatch next token (that should be
14530b57cec5SDimitry Andric // ":", checked later).
14540b57cec5SDimitry Andric if (SpecifierValid)
14550b57cec5SDimitry Andric PP.Lex(Tok);
14560b57cec5SDimitry Andric } else {
14570b57cec5SDimitry Andric // Token is a numeric constant. It should be either 1, 2, 3 or 4.
14580b57cec5SDimitry Andric uint64_t Value;
14590b57cec5SDimitry Andric if (PP.parseSimpleIntegerLiteral(Tok, Value)) {
1460349cc55cSDimitry Andric if ((SpecifierValid = (Value >= 1) && (Value <= 4)))
1461349cc55cSDimitry Andric Specifier = static_cast<PPCallbacks::PragmaWarningSpecifier>(
1462349cc55cSDimitry Andric PPCallbacks::PWS_Level1 + Value - 1);
14630b57cec5SDimitry Andric } else
14640b57cec5SDimitry Andric SpecifierValid = false;
14650b57cec5SDimitry Andric // Next token already snatched by parseSimpleIntegerLiteral.
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric if (!SpecifierValid) {
14690b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid);
14700b57cec5SDimitry Andric return;
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric if (Tok.isNot(tok::colon)) {
14730b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":";
14740b57cec5SDimitry Andric return;
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric
14770b57cec5SDimitry Andric // Collect the warning ids.
14780b57cec5SDimitry Andric SmallVector<int, 4> Ids;
14790b57cec5SDimitry Andric PP.Lex(Tok);
14800b57cec5SDimitry Andric while (Tok.is(tok::numeric_constant)) {
14810b57cec5SDimitry Andric uint64_t Value;
14820b57cec5SDimitry Andric if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 ||
1483e8d8bef9SDimitry Andric Value > INT_MAX) {
14840b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_expected_number);
14850b57cec5SDimitry Andric return;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric Ids.push_back(int(Value));
14880b57cec5SDimitry Andric }
1489349cc55cSDimitry Andric
1490349cc55cSDimitry Andric // Only act on disable for now.
1491349cc55cSDimitry Andric diag::Severity SV = diag::Severity();
1492349cc55cSDimitry Andric if (Specifier == PPCallbacks::PWS_Disable)
1493349cc55cSDimitry Andric SV = diag::Severity::Ignored;
1494349cc55cSDimitry Andric if (SV != diag::Severity())
1495349cc55cSDimitry Andric for (int Id : Ids) {
1496349cc55cSDimitry Andric if (auto Group = diagGroupFromCLWarningID(Id)) {
1497349cc55cSDimitry Andric bool unknownDiag = PP.getDiagnostics().setSeverityForGroup(
1498349cc55cSDimitry Andric diag::Flavor::WarningOrError, *Group, SV, DiagLoc);
1499349cc55cSDimitry Andric assert(!unknownDiag &&
1500349cc55cSDimitry Andric "wd table should only contain known diags");
1501349cc55cSDimitry Andric (void)unknownDiag;
1502349cc55cSDimitry Andric }
1503349cc55cSDimitry Andric }
1504349cc55cSDimitry Andric
15050b57cec5SDimitry Andric if (Callbacks)
15060b57cec5SDimitry Andric Callbacks->PragmaWarning(DiagLoc, Specifier, Ids);
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric // Parse the next specifier if there is a semicolon.
15090b57cec5SDimitry Andric if (Tok.isNot(tok::semi))
15100b57cec5SDimitry Andric break;
15110b57cec5SDimitry Andric PP.Lex(Tok);
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric
15150b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
15160b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_warning_expected) << ")";
15170b57cec5SDimitry Andric return;
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric
15200b57cec5SDimitry Andric PP.Lex(Tok);
15210b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
15220b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma warning";
15230b57cec5SDimitry Andric }
15240b57cec5SDimitry Andric };
15250b57cec5SDimitry Andric
15260b57cec5SDimitry Andric /// "\#pragma execution_character_set(...)". MSVC supports this pragma only
15270b57cec5SDimitry Andric /// for "UTF-8". We parse it and ignore it if UTF-8 is provided and warn
15280b57cec5SDimitry Andric /// otherwise to avoid -Wunknown-pragma warnings.
15290b57cec5SDimitry Andric struct PragmaExecCharsetHandler : public PragmaHandler {
PragmaExecCharsetHandler__anon851a8f8a0311::PragmaExecCharsetHandler15300b57cec5SDimitry Andric PragmaExecCharsetHandler() : PragmaHandler("execution_character_set") {}
15310b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaExecCharsetHandler15320b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
15330b57cec5SDimitry Andric Token &Tok) override {
15340b57cec5SDimitry Andric // Parse things like:
15350b57cec5SDimitry Andric // execution_character_set(push, "UTF-8")
15360b57cec5SDimitry Andric // execution_character_set(pop)
15370b57cec5SDimitry Andric SourceLocation DiagLoc = Tok.getLocation();
15380b57cec5SDimitry Andric PPCallbacks *Callbacks = PP.getPPCallbacks();
15390b57cec5SDimitry Andric
15400b57cec5SDimitry Andric PP.Lex(Tok);
15410b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
15420b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << "(";
15430b57cec5SDimitry Andric return;
15440b57cec5SDimitry Andric }
15450b57cec5SDimitry Andric
15460b57cec5SDimitry Andric PP.Lex(Tok);
15470b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
15480b57cec5SDimitry Andric
15490b57cec5SDimitry Andric if (II && II->isStr("push")) {
15500b57cec5SDimitry Andric // #pragma execution_character_set( push[ , string ] )
15510b57cec5SDimitry Andric PP.Lex(Tok);
15520b57cec5SDimitry Andric if (Tok.is(tok::comma)) {
15530b57cec5SDimitry Andric PP.Lex(Tok);
15540b57cec5SDimitry Andric
15550b57cec5SDimitry Andric std::string ExecCharset;
15560b57cec5SDimitry Andric if (!PP.FinishLexStringLiteral(Tok, ExecCharset,
15570b57cec5SDimitry Andric "pragma execution_character_set",
15580b57cec5SDimitry Andric /*AllowMacroExpansion=*/false))
15590b57cec5SDimitry Andric return;
15600b57cec5SDimitry Andric
15610b57cec5SDimitry Andric // MSVC supports either of these, but nothing else.
15620b57cec5SDimitry Andric if (ExecCharset != "UTF-8" && ExecCharset != "utf-8") {
15630b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_exec_charset_push_invalid) << ExecCharset;
15640b57cec5SDimitry Andric return;
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric }
15670b57cec5SDimitry Andric if (Callbacks)
15680b57cec5SDimitry Andric Callbacks->PragmaExecCharsetPush(DiagLoc, "UTF-8");
15690b57cec5SDimitry Andric } else if (II && II->isStr("pop")) {
15700b57cec5SDimitry Andric // #pragma execution_character_set( pop )
15710b57cec5SDimitry Andric PP.Lex(Tok);
15720b57cec5SDimitry Andric if (Callbacks)
15730b57cec5SDimitry Andric Callbacks->PragmaExecCharsetPop(DiagLoc);
15740b57cec5SDimitry Andric } else {
15750b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_exec_charset_spec_invalid);
15760b57cec5SDimitry Andric return;
15770b57cec5SDimitry Andric }
15780b57cec5SDimitry Andric
15790b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
15800b57cec5SDimitry Andric PP.Diag(Tok, diag::warn_pragma_exec_charset_expected) << ")";
15810b57cec5SDimitry Andric return;
15820b57cec5SDimitry Andric }
15830b57cec5SDimitry Andric
15840b57cec5SDimitry Andric PP.Lex(Tok);
15850b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
15860b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma execution_character_set";
15870b57cec5SDimitry Andric }
15880b57cec5SDimitry Andric };
15890b57cec5SDimitry Andric
15900b57cec5SDimitry Andric /// PragmaIncludeAliasHandler - "\#pragma include_alias("...")".
15910b57cec5SDimitry Andric struct PragmaIncludeAliasHandler : public PragmaHandler {
PragmaIncludeAliasHandler__anon851a8f8a0311::PragmaIncludeAliasHandler15920b57cec5SDimitry Andric PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
15930b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaIncludeAliasHandler15940b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
15950b57cec5SDimitry Andric Token &IncludeAliasTok) override {
15960b57cec5SDimitry Andric PP.HandlePragmaIncludeAlias(IncludeAliasTok);
15970b57cec5SDimitry Andric }
15980b57cec5SDimitry Andric };
15990b57cec5SDimitry Andric
16000b57cec5SDimitry Andric /// PragmaMessageHandler - Handle the microsoft and gcc \#pragma message
16010b57cec5SDimitry Andric /// extension. The syntax is:
16020b57cec5SDimitry Andric /// \code
16030b57cec5SDimitry Andric /// #pragma message(string)
16040b57cec5SDimitry Andric /// \endcode
16050b57cec5SDimitry Andric /// OR, in GCC mode:
16060b57cec5SDimitry Andric /// \code
16070b57cec5SDimitry Andric /// #pragma message string
16080b57cec5SDimitry Andric /// \endcode
16090b57cec5SDimitry Andric /// string is a string, which is fully macro expanded, and permits string
16100b57cec5SDimitry Andric /// concatenation, embedded escape characters, etc... See MSDN for more details.
16110b57cec5SDimitry Andric /// Also handles \#pragma GCC warning and \#pragma GCC error which take the same
16120b57cec5SDimitry Andric /// form as \#pragma message.
16130b57cec5SDimitry Andric struct PragmaMessageHandler : public PragmaHandler {
16140b57cec5SDimitry Andric private:
16150b57cec5SDimitry Andric const PPCallbacks::PragmaMessageKind Kind;
16160b57cec5SDimitry Andric const StringRef Namespace;
16170b57cec5SDimitry Andric
PragmaKind__anon851a8f8a0311::PragmaMessageHandler16180b57cec5SDimitry Andric static const char* PragmaKind(PPCallbacks::PragmaMessageKind Kind,
16190b57cec5SDimitry Andric bool PragmaNameOnly = false) {
16200b57cec5SDimitry Andric switch (Kind) {
16210b57cec5SDimitry Andric case PPCallbacks::PMK_Message:
16220b57cec5SDimitry Andric return PragmaNameOnly ? "message" : "pragma message";
16230b57cec5SDimitry Andric case PPCallbacks::PMK_Warning:
16240b57cec5SDimitry Andric return PragmaNameOnly ? "warning" : "pragma warning";
16250b57cec5SDimitry Andric case PPCallbacks::PMK_Error:
16260b57cec5SDimitry Andric return PragmaNameOnly ? "error" : "pragma error";
16270b57cec5SDimitry Andric }
16280b57cec5SDimitry Andric llvm_unreachable("Unknown PragmaMessageKind!");
16290b57cec5SDimitry Andric }
16300b57cec5SDimitry Andric
16310b57cec5SDimitry Andric public:
PragmaMessageHandler__anon851a8f8a0311::PragmaMessageHandler16320b57cec5SDimitry Andric PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind,
16330b57cec5SDimitry Andric StringRef Namespace = StringRef())
16340b57cec5SDimitry Andric : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind),
16350b57cec5SDimitry Andric Namespace(Namespace) {}
16360b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaMessageHandler16370b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
16380b57cec5SDimitry Andric Token &Tok) override {
16390b57cec5SDimitry Andric SourceLocation MessageLoc = Tok.getLocation();
16400b57cec5SDimitry Andric PP.Lex(Tok);
16410b57cec5SDimitry Andric bool ExpectClosingParen = false;
16420b57cec5SDimitry Andric switch (Tok.getKind()) {
16430b57cec5SDimitry Andric case tok::l_paren:
16440b57cec5SDimitry Andric // We have a MSVC style pragma message.
16450b57cec5SDimitry Andric ExpectClosingParen = true;
16460b57cec5SDimitry Andric // Read the string.
16470b57cec5SDimitry Andric PP.Lex(Tok);
16480b57cec5SDimitry Andric break;
16490b57cec5SDimitry Andric case tok::string_literal:
16500b57cec5SDimitry Andric // We have a GCC style pragma message, and we just read the string.
16510b57cec5SDimitry Andric break;
16520b57cec5SDimitry Andric default:
16530b57cec5SDimitry Andric PP.Diag(MessageLoc, diag::err_pragma_message_malformed) << Kind;
16540b57cec5SDimitry Andric return;
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric
16570b57cec5SDimitry Andric std::string MessageString;
16580b57cec5SDimitry Andric if (!PP.FinishLexStringLiteral(Tok, MessageString, PragmaKind(Kind),
16590b57cec5SDimitry Andric /*AllowMacroExpansion=*/true))
16600b57cec5SDimitry Andric return;
16610b57cec5SDimitry Andric
16620b57cec5SDimitry Andric if (ExpectClosingParen) {
16630b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren)) {
16640b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind;
16650b57cec5SDimitry Andric return;
16660b57cec5SDimitry Andric }
16670b57cec5SDimitry Andric PP.Lex(Tok); // eat the r_paren.
16680b57cec5SDimitry Andric }
16690b57cec5SDimitry Andric
16700b57cec5SDimitry Andric if (Tok.isNot(tok::eod)) {
16710b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind;
16720b57cec5SDimitry Andric return;
16730b57cec5SDimitry Andric }
16740b57cec5SDimitry Andric
16750b57cec5SDimitry Andric // Output the message.
16760b57cec5SDimitry Andric PP.Diag(MessageLoc, (Kind == PPCallbacks::PMK_Error)
16770b57cec5SDimitry Andric ? diag::err_pragma_message
16780b57cec5SDimitry Andric : diag::warn_pragma_message) << MessageString;
16790b57cec5SDimitry Andric
16800b57cec5SDimitry Andric // If the pragma is lexically sound, notify any interested PPCallbacks.
16810b57cec5SDimitry Andric if (PPCallbacks *Callbacks = PP.getPPCallbacks())
16820b57cec5SDimitry Andric Callbacks->PragmaMessage(MessageLoc, Namespace, Kind, MessageString);
16830b57cec5SDimitry Andric }
16840b57cec5SDimitry Andric };
16850b57cec5SDimitry Andric
16860b57cec5SDimitry Andric /// Handle the clang \#pragma module import extension. The syntax is:
16870b57cec5SDimitry Andric /// \code
16880b57cec5SDimitry Andric /// #pragma clang module import some.module.name
16890b57cec5SDimitry Andric /// \endcode
16900b57cec5SDimitry Andric struct PragmaModuleImportHandler : public PragmaHandler {
PragmaModuleImportHandler__anon851a8f8a0311::PragmaModuleImportHandler16910b57cec5SDimitry Andric PragmaModuleImportHandler() : PragmaHandler("import") {}
16920b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaModuleImportHandler16930b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
16940b57cec5SDimitry Andric Token &Tok) override {
16950b57cec5SDimitry Andric SourceLocation ImportLoc = Tok.getLocation();
16960b57cec5SDimitry Andric
16970b57cec5SDimitry Andric // Read the module name.
16980b57cec5SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8>
16990b57cec5SDimitry Andric ModuleName;
17000b57cec5SDimitry Andric if (LexModuleName(PP, Tok, ModuleName))
17010b57cec5SDimitry Andric return;
17020b57cec5SDimitry Andric
17030b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
17040b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
17050b57cec5SDimitry Andric
17060b57cec5SDimitry Andric // If we have a non-empty module path, load the named module.
17070b57cec5SDimitry Andric Module *Imported =
17080b57cec5SDimitry Andric PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden,
17090b57cec5SDimitry Andric /*IsInclusionDirective=*/false);
17100b57cec5SDimitry Andric if (!Imported)
17110b57cec5SDimitry Andric return;
17120b57cec5SDimitry Andric
17130b57cec5SDimitry Andric PP.makeModuleVisible(Imported, ImportLoc);
17140b57cec5SDimitry Andric PP.EnterAnnotationToken(SourceRange(ImportLoc, ModuleName.back().second),
17150b57cec5SDimitry Andric tok::annot_module_include, Imported);
17160b57cec5SDimitry Andric if (auto *CB = PP.getPPCallbacks())
17170b57cec5SDimitry Andric CB->moduleImport(ImportLoc, ModuleName, Imported);
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric };
17200b57cec5SDimitry Andric
17210b57cec5SDimitry Andric /// Handle the clang \#pragma module begin extension. The syntax is:
17220b57cec5SDimitry Andric /// \code
17230b57cec5SDimitry Andric /// #pragma clang module begin some.module.name
17240b57cec5SDimitry Andric /// ...
17250b57cec5SDimitry Andric /// #pragma clang module end
17260b57cec5SDimitry Andric /// \endcode
17270b57cec5SDimitry Andric struct PragmaModuleBeginHandler : public PragmaHandler {
PragmaModuleBeginHandler__anon851a8f8a0311::PragmaModuleBeginHandler17280b57cec5SDimitry Andric PragmaModuleBeginHandler() : PragmaHandler("begin") {}
17290b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaModuleBeginHandler17300b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
17310b57cec5SDimitry Andric Token &Tok) override {
17320b57cec5SDimitry Andric SourceLocation BeginLoc = Tok.getLocation();
17330b57cec5SDimitry Andric
17340b57cec5SDimitry Andric // Read the module name.
17350b57cec5SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8>
17360b57cec5SDimitry Andric ModuleName;
17370b57cec5SDimitry Andric if (LexModuleName(PP, Tok, ModuleName))
17380b57cec5SDimitry Andric return;
17390b57cec5SDimitry Andric
17400b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
17410b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
17420b57cec5SDimitry Andric
17430b57cec5SDimitry Andric // We can only enter submodules of the current module.
17440b57cec5SDimitry Andric StringRef Current = PP.getLangOpts().CurrentModule;
17450b57cec5SDimitry Andric if (ModuleName.front().first->getName() != Current) {
17460b57cec5SDimitry Andric PP.Diag(ModuleName.front().second, diag::err_pp_module_begin_wrong_module)
17470b57cec5SDimitry Andric << ModuleName.front().first << (ModuleName.size() > 1)
17480b57cec5SDimitry Andric << Current.empty() << Current;
17490b57cec5SDimitry Andric return;
17500b57cec5SDimitry Andric }
17510b57cec5SDimitry Andric
17520b57cec5SDimitry Andric // Find the module we're entering. We require that a module map for it
17530b57cec5SDimitry Andric // be loaded or implicitly loadable.
17540b57cec5SDimitry Andric auto &HSI = PP.getHeaderSearchInfo();
1755349cc55cSDimitry Andric Module *M = HSI.lookupModule(Current, ModuleName.front().second);
17560b57cec5SDimitry Andric if (!M) {
17570b57cec5SDimitry Andric PP.Diag(ModuleName.front().second,
17580b57cec5SDimitry Andric diag::err_pp_module_begin_no_module_map) << Current;
17590b57cec5SDimitry Andric return;
17600b57cec5SDimitry Andric }
17610b57cec5SDimitry Andric for (unsigned I = 1; I != ModuleName.size(); ++I) {
17620b57cec5SDimitry Andric auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName());
17630b57cec5SDimitry Andric if (!NewM) {
17640b57cec5SDimitry Andric PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule)
17650b57cec5SDimitry Andric << M->getFullModuleName() << ModuleName[I].first;
17660b57cec5SDimitry Andric return;
17670b57cec5SDimitry Andric }
17680b57cec5SDimitry Andric M = NewM;
17690b57cec5SDimitry Andric }
17700b57cec5SDimitry Andric
17710b57cec5SDimitry Andric // If the module isn't available, it doesn't make sense to enter it.
17720b57cec5SDimitry Andric if (Preprocessor::checkModuleIsAvailable(
17735f757f3fSDimitry Andric PP.getLangOpts(), PP.getTargetInfo(), *M, PP.getDiagnostics())) {
17740b57cec5SDimitry Andric PP.Diag(BeginLoc, diag::note_pp_module_begin_here)
17750b57cec5SDimitry Andric << M->getTopLevelModuleName();
17760b57cec5SDimitry Andric return;
17770b57cec5SDimitry Andric }
17780b57cec5SDimitry Andric
17790b57cec5SDimitry Andric // Enter the scope of the submodule.
17800b57cec5SDimitry Andric PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true);
17810b57cec5SDimitry Andric PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second),
17820b57cec5SDimitry Andric tok::annot_module_begin, M);
17830b57cec5SDimitry Andric }
17840b57cec5SDimitry Andric };
17850b57cec5SDimitry Andric
17860b57cec5SDimitry Andric /// Handle the clang \#pragma module end extension.
17870b57cec5SDimitry Andric struct PragmaModuleEndHandler : public PragmaHandler {
PragmaModuleEndHandler__anon851a8f8a0311::PragmaModuleEndHandler17880b57cec5SDimitry Andric PragmaModuleEndHandler() : PragmaHandler("end") {}
17890b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaModuleEndHandler17900b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
17910b57cec5SDimitry Andric Token &Tok) override {
17920b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
17930b57cec5SDimitry Andric
17940b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
17950b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
17960b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
17970b57cec5SDimitry Andric
17980b57cec5SDimitry Andric Module *M = PP.LeaveSubmodule(/*ForPragma*/true);
17990b57cec5SDimitry Andric if (M)
18000b57cec5SDimitry Andric PP.EnterAnnotationToken(SourceRange(Loc), tok::annot_module_end, M);
18010b57cec5SDimitry Andric else
18020b57cec5SDimitry Andric PP.Diag(Loc, diag::err_pp_module_end_without_module_begin);
18030b57cec5SDimitry Andric }
18040b57cec5SDimitry Andric };
18050b57cec5SDimitry Andric
18060b57cec5SDimitry Andric /// Handle the clang \#pragma module build extension.
18070b57cec5SDimitry Andric struct PragmaModuleBuildHandler : public PragmaHandler {
PragmaModuleBuildHandler__anon851a8f8a0311::PragmaModuleBuildHandler18080b57cec5SDimitry Andric PragmaModuleBuildHandler() : PragmaHandler("build") {}
18090b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaModuleBuildHandler18100b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
18110b57cec5SDimitry Andric Token &Tok) override {
18120b57cec5SDimitry Andric PP.HandlePragmaModuleBuild(Tok);
18130b57cec5SDimitry Andric }
18140b57cec5SDimitry Andric };
18150b57cec5SDimitry Andric
18160b57cec5SDimitry Andric /// Handle the clang \#pragma module load extension.
18170b57cec5SDimitry Andric struct PragmaModuleLoadHandler : public PragmaHandler {
PragmaModuleLoadHandler__anon851a8f8a0311::PragmaModuleLoadHandler18180b57cec5SDimitry Andric PragmaModuleLoadHandler() : PragmaHandler("load") {}
18190b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaModuleLoadHandler18200b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
18210b57cec5SDimitry Andric Token &Tok) override {
18220b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
18230b57cec5SDimitry Andric
18240b57cec5SDimitry Andric // Read the module name.
18250b57cec5SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8>
18260b57cec5SDimitry Andric ModuleName;
18270b57cec5SDimitry Andric if (LexModuleName(PP, Tok, ModuleName))
18280b57cec5SDimitry Andric return;
18290b57cec5SDimitry Andric
18300b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
18310b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
18320b57cec5SDimitry Andric
18330b57cec5SDimitry Andric // Load the module, don't make it visible.
18340b57cec5SDimitry Andric PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden,
18350b57cec5SDimitry Andric /*IsInclusionDirective=*/false);
18360b57cec5SDimitry Andric }
18370b57cec5SDimitry Andric };
18380b57cec5SDimitry Andric
18390b57cec5SDimitry Andric /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the
18400b57cec5SDimitry Andric /// macro on the top of the stack.
18410b57cec5SDimitry Andric struct PragmaPushMacroHandler : public PragmaHandler {
PragmaPushMacroHandler__anon851a8f8a0311::PragmaPushMacroHandler18420b57cec5SDimitry Andric PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
18430b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaPushMacroHandler18440b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
18450b57cec5SDimitry Andric Token &PushMacroTok) override {
18460b57cec5SDimitry Andric PP.HandlePragmaPushMacro(PushMacroTok);
18470b57cec5SDimitry Andric }
18480b57cec5SDimitry Andric };
18490b57cec5SDimitry Andric
18500b57cec5SDimitry Andric /// PragmaPopMacroHandler - "\#pragma pop_macro" sets the value of the
18510b57cec5SDimitry Andric /// macro to the value on the top of the stack.
18520b57cec5SDimitry Andric struct PragmaPopMacroHandler : public PragmaHandler {
PragmaPopMacroHandler__anon851a8f8a0311::PragmaPopMacroHandler18530b57cec5SDimitry Andric PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
18540b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaPopMacroHandler18550b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
18560b57cec5SDimitry Andric Token &PopMacroTok) override {
18570b57cec5SDimitry Andric PP.HandlePragmaPopMacro(PopMacroTok);
18580b57cec5SDimitry Andric }
18590b57cec5SDimitry Andric };
18600b57cec5SDimitry Andric
18610b57cec5SDimitry Andric /// PragmaARCCFCodeAuditedHandler -
18620b57cec5SDimitry Andric /// \#pragma clang arc_cf_code_audited begin/end
18630b57cec5SDimitry Andric struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
PragmaARCCFCodeAuditedHandler__anon851a8f8a0311::PragmaARCCFCodeAuditedHandler18640b57cec5SDimitry Andric PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {}
18650b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaARCCFCodeAuditedHandler18660b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
18670b57cec5SDimitry Andric Token &NameTok) override {
18680b57cec5SDimitry Andric SourceLocation Loc = NameTok.getLocation();
18690b57cec5SDimitry Andric bool IsBegin;
18700b57cec5SDimitry Andric
18710b57cec5SDimitry Andric Token Tok;
18720b57cec5SDimitry Andric
18730b57cec5SDimitry Andric // Lex the 'begin' or 'end'.
18740b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
18750b57cec5SDimitry Andric const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo();
18760b57cec5SDimitry Andric if (BeginEnd && BeginEnd->isStr("begin")) {
18770b57cec5SDimitry Andric IsBegin = true;
18780b57cec5SDimitry Andric } else if (BeginEnd && BeginEnd->isStr("end")) {
18790b57cec5SDimitry Andric IsBegin = false;
18800b57cec5SDimitry Andric } else {
18810b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pp_arc_cf_code_audited_syntax);
18820b57cec5SDimitry Andric return;
18830b57cec5SDimitry Andric }
18840b57cec5SDimitry Andric
18850b57cec5SDimitry Andric // Verify that this is followed by EOD.
18860b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
18870b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
18880b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
18890b57cec5SDimitry Andric
18900b57cec5SDimitry Andric // The start location of the active audit.
1891a7dea167SDimitry Andric SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedInfo().second;
18920b57cec5SDimitry Andric
18930b57cec5SDimitry Andric // The start location we want after processing this.
18940b57cec5SDimitry Andric SourceLocation NewLoc;
18950b57cec5SDimitry Andric
18960b57cec5SDimitry Andric if (IsBegin) {
18970b57cec5SDimitry Andric // Complain about attempts to re-enter an audit.
18980b57cec5SDimitry Andric if (BeginLoc.isValid()) {
18990b57cec5SDimitry Andric PP.Diag(Loc, diag::err_pp_double_begin_of_arc_cf_code_audited);
19000b57cec5SDimitry Andric PP.Diag(BeginLoc, diag::note_pragma_entered_here);
19010b57cec5SDimitry Andric }
19020b57cec5SDimitry Andric NewLoc = Loc;
19030b57cec5SDimitry Andric } else {
19040b57cec5SDimitry Andric // Complain about attempts to leave an audit that doesn't exist.
19050b57cec5SDimitry Andric if (!BeginLoc.isValid()) {
19060b57cec5SDimitry Andric PP.Diag(Loc, diag::err_pp_unmatched_end_of_arc_cf_code_audited);
19070b57cec5SDimitry Andric return;
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric NewLoc = SourceLocation();
19100b57cec5SDimitry Andric }
19110b57cec5SDimitry Andric
1912a7dea167SDimitry Andric PP.setPragmaARCCFCodeAuditedInfo(NameTok.getIdentifierInfo(), NewLoc);
19130b57cec5SDimitry Andric }
19140b57cec5SDimitry Andric };
19150b57cec5SDimitry Andric
19160b57cec5SDimitry Andric /// PragmaAssumeNonNullHandler -
19170b57cec5SDimitry Andric /// \#pragma clang assume_nonnull begin/end
19180b57cec5SDimitry Andric struct PragmaAssumeNonNullHandler : public PragmaHandler {
PragmaAssumeNonNullHandler__anon851a8f8a0311::PragmaAssumeNonNullHandler19190b57cec5SDimitry Andric PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {}
19200b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaAssumeNonNullHandler19210b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
19220b57cec5SDimitry Andric Token &NameTok) override {
19230b57cec5SDimitry Andric SourceLocation Loc = NameTok.getLocation();
19240b57cec5SDimitry Andric bool IsBegin;
19250b57cec5SDimitry Andric
19260b57cec5SDimitry Andric Token Tok;
19270b57cec5SDimitry Andric
19280b57cec5SDimitry Andric // Lex the 'begin' or 'end'.
19290b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
19300b57cec5SDimitry Andric const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo();
19310b57cec5SDimitry Andric if (BeginEnd && BeginEnd->isStr("begin")) {
19320b57cec5SDimitry Andric IsBegin = true;
19330b57cec5SDimitry Andric } else if (BeginEnd && BeginEnd->isStr("end")) {
19340b57cec5SDimitry Andric IsBegin = false;
19350b57cec5SDimitry Andric } else {
19360b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pp_assume_nonnull_syntax);
19370b57cec5SDimitry Andric return;
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric
19400b57cec5SDimitry Andric // Verify that this is followed by EOD.
19410b57cec5SDimitry Andric PP.LexUnexpandedToken(Tok);
19420b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
19430b57cec5SDimitry Andric PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma";
19440b57cec5SDimitry Andric
19450b57cec5SDimitry Andric // The start location of the active audit.
19460b57cec5SDimitry Andric SourceLocation BeginLoc = PP.getPragmaAssumeNonNullLoc();
19470b57cec5SDimitry Andric
19480b57cec5SDimitry Andric // The start location we want after processing this.
19490b57cec5SDimitry Andric SourceLocation NewLoc;
19500b57cec5SDimitry Andric PPCallbacks *Callbacks = PP.getPPCallbacks();
19510b57cec5SDimitry Andric
19520b57cec5SDimitry Andric if (IsBegin) {
19530b57cec5SDimitry Andric // Complain about attempts to re-enter an audit.
19540b57cec5SDimitry Andric if (BeginLoc.isValid()) {
19550b57cec5SDimitry Andric PP.Diag(Loc, diag::err_pp_double_begin_of_assume_nonnull);
19560b57cec5SDimitry Andric PP.Diag(BeginLoc, diag::note_pragma_entered_here);
19570b57cec5SDimitry Andric }
19580b57cec5SDimitry Andric NewLoc = Loc;
19590b57cec5SDimitry Andric if (Callbacks)
19600b57cec5SDimitry Andric Callbacks->PragmaAssumeNonNullBegin(NewLoc);
19610b57cec5SDimitry Andric } else {
19620b57cec5SDimitry Andric // Complain about attempts to leave an audit that doesn't exist.
19630b57cec5SDimitry Andric if (!BeginLoc.isValid()) {
19640b57cec5SDimitry Andric PP.Diag(Loc, diag::err_pp_unmatched_end_of_assume_nonnull);
19650b57cec5SDimitry Andric return;
19660b57cec5SDimitry Andric }
19670b57cec5SDimitry Andric NewLoc = SourceLocation();
19680b57cec5SDimitry Andric if (Callbacks)
19690b57cec5SDimitry Andric Callbacks->PragmaAssumeNonNullEnd(NewLoc);
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric
19720b57cec5SDimitry Andric PP.setPragmaAssumeNonNullLoc(NewLoc);
19730b57cec5SDimitry Andric }
19740b57cec5SDimitry Andric };
19750b57cec5SDimitry Andric
19760b57cec5SDimitry Andric /// Handle "\#pragma region [...]"
19770b57cec5SDimitry Andric ///
19780b57cec5SDimitry Andric /// The syntax is
19790b57cec5SDimitry Andric /// \code
19800b57cec5SDimitry Andric /// #pragma region [optional name]
19810b57cec5SDimitry Andric /// #pragma endregion [optional comment]
19820b57cec5SDimitry Andric /// \endcode
19830b57cec5SDimitry Andric ///
19840b57cec5SDimitry Andric /// \note This is
19850b57cec5SDimitry Andric /// <a href="http://msdn.microsoft.com/en-us/library/b6xkz944(v=vs.80).aspx">editor-only</a>
19860b57cec5SDimitry Andric /// pragma, just skipped by compiler.
19870b57cec5SDimitry Andric struct PragmaRegionHandler : public PragmaHandler {
PragmaRegionHandler__anon851a8f8a0311::PragmaRegionHandler19880b57cec5SDimitry Andric PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) {}
19890b57cec5SDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaRegionHandler19900b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
19910b57cec5SDimitry Andric Token &NameTok) override {
19920b57cec5SDimitry Andric // #pragma region: endregion matches can be verified
19930b57cec5SDimitry Andric // __pragma(region): no sense, but ignored by msvc
19940b57cec5SDimitry Andric // _Pragma is not valid for MSVC, but there isn't any point
19950b57cec5SDimitry Andric // to handle a _Pragma differently.
19960b57cec5SDimitry Andric }
19970b57cec5SDimitry Andric };
19980b57cec5SDimitry Andric
1999bdd1243dSDimitry Andric /// "\#pragma managed"
2000bdd1243dSDimitry Andric /// "\#pragma managed(...)"
2001bdd1243dSDimitry Andric /// "\#pragma unmanaged"
2002bdd1243dSDimitry Andric /// MSVC ignores this pragma when not compiling using /clr, which clang doesn't
2003bdd1243dSDimitry Andric /// support. We parse it and ignore it to avoid -Wunknown-pragma warnings.
2004bdd1243dSDimitry Andric struct PragmaManagedHandler : public EmptyPragmaHandler {
PragmaManagedHandler__anon851a8f8a0311::PragmaManagedHandler2005bdd1243dSDimitry Andric PragmaManagedHandler(const char *pragma) : EmptyPragmaHandler(pragma) {}
2006bdd1243dSDimitry Andric };
2007bdd1243dSDimitry Andric
2008349cc55cSDimitry Andric /// This handles parsing pragmas that take a macro name and optional message
HandleMacroAnnotationPragma(Preprocessor & PP,Token & Tok,const char * Pragma,std::string & MessageString)2009349cc55cSDimitry Andric static IdentifierInfo *HandleMacroAnnotationPragma(Preprocessor &PP, Token &Tok,
2010349cc55cSDimitry Andric const char *Pragma,
2011349cc55cSDimitry Andric std::string &MessageString) {
2012349cc55cSDimitry Andric PP.Lex(Tok);
2013349cc55cSDimitry Andric if (Tok.isNot(tok::l_paren)) {
2014349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << "(";
2015349cc55cSDimitry Andric return nullptr;
2016349cc55cSDimitry Andric }
2017349cc55cSDimitry Andric
2018349cc55cSDimitry Andric PP.LexUnexpandedToken(Tok);
2019349cc55cSDimitry Andric if (!Tok.is(tok::identifier)) {
2020349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << tok::identifier;
2021349cc55cSDimitry Andric return nullptr;
2022349cc55cSDimitry Andric }
2023349cc55cSDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
2024349cc55cSDimitry Andric
2025349cc55cSDimitry Andric if (!II->hasMacroDefinition()) {
2026349cc55cSDimitry Andric PP.Diag(Tok, diag::err_pp_visibility_non_macro) << II;
2027349cc55cSDimitry Andric return nullptr;
2028349cc55cSDimitry Andric }
2029349cc55cSDimitry Andric
2030349cc55cSDimitry Andric PP.Lex(Tok);
2031349cc55cSDimitry Andric if (Tok.is(tok::comma)) {
2032349cc55cSDimitry Andric PP.Lex(Tok);
2033349cc55cSDimitry Andric if (!PP.FinishLexStringLiteral(Tok, MessageString, Pragma,
2034349cc55cSDimitry Andric /*AllowMacroExpansion=*/true))
2035349cc55cSDimitry Andric return nullptr;
2036349cc55cSDimitry Andric }
2037349cc55cSDimitry Andric
2038349cc55cSDimitry Andric if (Tok.isNot(tok::r_paren)) {
2039349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << ")";
2040349cc55cSDimitry Andric return nullptr;
2041349cc55cSDimitry Andric }
2042349cc55cSDimitry Andric return II;
2043349cc55cSDimitry Andric }
2044349cc55cSDimitry Andric
2045349cc55cSDimitry Andric /// "\#pragma clang deprecated(...)"
2046349cc55cSDimitry Andric ///
2047349cc55cSDimitry Andric /// The syntax is
2048349cc55cSDimitry Andric /// \code
2049349cc55cSDimitry Andric /// #pragma clang deprecate(MACRO_NAME [, Message])
2050349cc55cSDimitry Andric /// \endcode
2051349cc55cSDimitry Andric struct PragmaDeprecatedHandler : public PragmaHandler {
PragmaDeprecatedHandler__anon851a8f8a0311::PragmaDeprecatedHandler2052349cc55cSDimitry Andric PragmaDeprecatedHandler() : PragmaHandler("deprecated") {}
2053349cc55cSDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaDeprecatedHandler2054349cc55cSDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2055349cc55cSDimitry Andric Token &Tok) override {
2056349cc55cSDimitry Andric std::string MessageString;
2057349cc55cSDimitry Andric
2058349cc55cSDimitry Andric if (IdentifierInfo *II = HandleMacroAnnotationPragma(
2059349cc55cSDimitry Andric PP, Tok, "#pragma clang deprecated", MessageString)) {
2060349cc55cSDimitry Andric II->setIsDeprecatedMacro(true);
2061349cc55cSDimitry Andric PP.addMacroDeprecationMsg(II, std::move(MessageString),
2062349cc55cSDimitry Andric Tok.getLocation());
2063349cc55cSDimitry Andric }
2064349cc55cSDimitry Andric }
2065349cc55cSDimitry Andric };
2066349cc55cSDimitry Andric
2067349cc55cSDimitry Andric /// "\#pragma clang restrict_expansion(...)"
2068349cc55cSDimitry Andric ///
2069349cc55cSDimitry Andric /// The syntax is
2070349cc55cSDimitry Andric /// \code
2071349cc55cSDimitry Andric /// #pragma clang restrict_expansion(MACRO_NAME [, Message])
2072349cc55cSDimitry Andric /// \endcode
2073349cc55cSDimitry Andric struct PragmaRestrictExpansionHandler : public PragmaHandler {
PragmaRestrictExpansionHandler__anon851a8f8a0311::PragmaRestrictExpansionHandler2074349cc55cSDimitry Andric PragmaRestrictExpansionHandler() : PragmaHandler("restrict_expansion") {}
2075349cc55cSDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaRestrictExpansionHandler2076349cc55cSDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2077349cc55cSDimitry Andric Token &Tok) override {
2078349cc55cSDimitry Andric std::string MessageString;
2079349cc55cSDimitry Andric
2080349cc55cSDimitry Andric if (IdentifierInfo *II = HandleMacroAnnotationPragma(
2081349cc55cSDimitry Andric PP, Tok, "#pragma clang restrict_expansion", MessageString)) {
2082349cc55cSDimitry Andric II->setIsRestrictExpansion(true);
2083349cc55cSDimitry Andric PP.addRestrictExpansionMsg(II, std::move(MessageString),
2084349cc55cSDimitry Andric Tok.getLocation());
2085349cc55cSDimitry Andric }
2086349cc55cSDimitry Andric }
2087349cc55cSDimitry Andric };
2088349cc55cSDimitry Andric
2089349cc55cSDimitry Andric /// "\#pragma clang final(...)"
2090349cc55cSDimitry Andric ///
2091349cc55cSDimitry Andric /// The syntax is
2092349cc55cSDimitry Andric /// \code
2093349cc55cSDimitry Andric /// #pragma clang final(MACRO_NAME)
2094349cc55cSDimitry Andric /// \endcode
2095349cc55cSDimitry Andric struct PragmaFinalHandler : public PragmaHandler {
PragmaFinalHandler__anon851a8f8a0311::PragmaFinalHandler2096349cc55cSDimitry Andric PragmaFinalHandler() : PragmaHandler("final") {}
2097349cc55cSDimitry Andric
HandlePragma__anon851a8f8a0311::PragmaFinalHandler2098349cc55cSDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
2099349cc55cSDimitry Andric Token &Tok) override {
2100349cc55cSDimitry Andric PP.Lex(Tok);
2101349cc55cSDimitry Andric if (Tok.isNot(tok::l_paren)) {
2102349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << "(";
2103349cc55cSDimitry Andric return;
2104349cc55cSDimitry Andric }
2105349cc55cSDimitry Andric
2106349cc55cSDimitry Andric PP.LexUnexpandedToken(Tok);
2107349cc55cSDimitry Andric if (!Tok.is(tok::identifier)) {
2108349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << tok::identifier;
2109349cc55cSDimitry Andric return;
2110349cc55cSDimitry Andric }
2111349cc55cSDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
2112349cc55cSDimitry Andric
2113349cc55cSDimitry Andric if (!II->hasMacroDefinition()) {
2114349cc55cSDimitry Andric PP.Diag(Tok, diag::err_pp_visibility_non_macro) << II;
2115349cc55cSDimitry Andric return;
2116349cc55cSDimitry Andric }
2117349cc55cSDimitry Andric
2118349cc55cSDimitry Andric PP.Lex(Tok);
2119349cc55cSDimitry Andric if (Tok.isNot(tok::r_paren)) {
2120349cc55cSDimitry Andric PP.Diag(Tok, diag::err_expected) << ")";
2121349cc55cSDimitry Andric return;
2122349cc55cSDimitry Andric }
2123349cc55cSDimitry Andric II->setIsFinal(true);
2124349cc55cSDimitry Andric PP.addFinalLoc(II, Tok.getLocation());
2125349cc55cSDimitry Andric }
2126349cc55cSDimitry Andric };
2127349cc55cSDimitry Andric
21280b57cec5SDimitry Andric } // namespace
21290b57cec5SDimitry Andric
21300b57cec5SDimitry Andric /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
21310b57cec5SDimitry Andric /// \#pragma GCC poison/system_header/dependency and \#pragma once.
RegisterBuiltinPragmas()21320b57cec5SDimitry Andric void Preprocessor::RegisterBuiltinPragmas() {
21330b57cec5SDimitry Andric AddPragmaHandler(new PragmaOnceHandler());
21340b57cec5SDimitry Andric AddPragmaHandler(new PragmaMarkHandler());
21350b57cec5SDimitry Andric AddPragmaHandler(new PragmaPushMacroHandler());
21360b57cec5SDimitry Andric AddPragmaHandler(new PragmaPopMacroHandler());
21370b57cec5SDimitry Andric AddPragmaHandler(new PragmaMessageHandler(PPCallbacks::PMK_Message));
21380b57cec5SDimitry Andric
21390b57cec5SDimitry Andric // #pragma GCC ...
21400b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaPoisonHandler());
21410b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaSystemHeaderHandler());
21420b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaDependencyHandler());
21430b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaDiagnosticHandler("GCC"));
21440b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Warning,
21450b57cec5SDimitry Andric "GCC"));
21460b57cec5SDimitry Andric AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Error,
21470b57cec5SDimitry Andric "GCC"));
21480b57cec5SDimitry Andric // #pragma clang ...
21490b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaPoisonHandler());
21500b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
21510b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaDebugHandler());
21520b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaDependencyHandler());
21530b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
21540b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
21550b57cec5SDimitry Andric AddPragmaHandler("clang", new PragmaAssumeNonNullHandler());
2156349cc55cSDimitry Andric AddPragmaHandler("clang", new PragmaDeprecatedHandler());
2157349cc55cSDimitry Andric AddPragmaHandler("clang", new PragmaRestrictExpansionHandler());
2158349cc55cSDimitry Andric AddPragmaHandler("clang", new PragmaFinalHandler());
21590b57cec5SDimitry Andric
21600b57cec5SDimitry Andric // #pragma clang module ...
21610b57cec5SDimitry Andric auto *ModuleHandler = new PragmaNamespace("module");
21620b57cec5SDimitry Andric AddPragmaHandler("clang", ModuleHandler);
21630b57cec5SDimitry Andric ModuleHandler->AddPragma(new PragmaModuleImportHandler());
21640b57cec5SDimitry Andric ModuleHandler->AddPragma(new PragmaModuleBeginHandler());
21650b57cec5SDimitry Andric ModuleHandler->AddPragma(new PragmaModuleEndHandler());
21660b57cec5SDimitry Andric ModuleHandler->AddPragma(new PragmaModuleBuildHandler());
21670b57cec5SDimitry Andric ModuleHandler->AddPragma(new PragmaModuleLoadHandler());
21680b57cec5SDimitry Andric
216906c3fb27SDimitry Andric // Safe Buffers pragmas
217006c3fb27SDimitry Andric AddPragmaHandler("clang", new PragmaUnsafeBufferUsageHandler);
217106c3fb27SDimitry Andric
21720b57cec5SDimitry Andric // Add region pragmas.
21730b57cec5SDimitry Andric AddPragmaHandler(new PragmaRegionHandler("region"));
21740b57cec5SDimitry Andric AddPragmaHandler(new PragmaRegionHandler("endregion"));
21750b57cec5SDimitry Andric
21760b57cec5SDimitry Andric // MS extensions.
21770b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) {
21780b57cec5SDimitry Andric AddPragmaHandler(new PragmaWarningHandler());
21790b57cec5SDimitry Andric AddPragmaHandler(new PragmaExecCharsetHandler());
21800b57cec5SDimitry Andric AddPragmaHandler(new PragmaIncludeAliasHandler());
21810b57cec5SDimitry Andric AddPragmaHandler(new PragmaHdrstopHandler());
2182fe6060f1SDimitry Andric AddPragmaHandler(new PragmaSystemHeaderHandler());
2183bdd1243dSDimitry Andric AddPragmaHandler(new PragmaManagedHandler("managed"));
2184bdd1243dSDimitry Andric AddPragmaHandler(new PragmaManagedHandler("unmanaged"));
21850b57cec5SDimitry Andric }
21860b57cec5SDimitry Andric
21870b57cec5SDimitry Andric // Pragmas added by plugins
21885ffd83dbSDimitry Andric for (const PragmaHandlerRegistry::entry &handler :
21895ffd83dbSDimitry Andric PragmaHandlerRegistry::entries()) {
21905ffd83dbSDimitry Andric AddPragmaHandler(handler.instantiate().release());
21910b57cec5SDimitry Andric }
21920b57cec5SDimitry Andric }
21930b57cec5SDimitry Andric
21940b57cec5SDimitry Andric /// Ignore all pragmas, useful for modes such as -Eonly which would otherwise
21950b57cec5SDimitry Andric /// warn about those pragmas being unknown.
IgnorePragmas()21960b57cec5SDimitry Andric void Preprocessor::IgnorePragmas() {
21970b57cec5SDimitry Andric AddPragmaHandler(new EmptyPragmaHandler());
21980b57cec5SDimitry Andric // Also ignore all pragmas in all namespaces created
21990b57cec5SDimitry Andric // in Preprocessor::RegisterBuiltinPragmas().
22000b57cec5SDimitry Andric AddPragmaHandler("GCC", new EmptyPragmaHandler());
22010b57cec5SDimitry Andric AddPragmaHandler("clang", new EmptyPragmaHandler());
22020b57cec5SDimitry Andric }
2203