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 650b57cec5SDimitry Andric EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {} 660b57cec5SDimitry Andric 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. 790b57cec5SDimitry 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 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 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 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 141a7dea167SDimitry Andric void lex() { 142a7dea167SDimitry Andric if (Collect) 143a7dea167SDimitry Andric Tokens.push_back(Tok); 144a7dea167SDimitry Andric Self.Lex(Tok); 145a7dea167SDimitry Andric } 146a7dea167SDimitry Andric 147a7dea167SDimitry 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. 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'. 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 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. 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'. 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 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'. 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. 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. 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. 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 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 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 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. 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 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 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 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". 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. 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 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 { 9990b57cec5SDimitry Andric PragmaOnceHandler() : PragmaHandler("once") {} 10000b57cec5SDimitry Andric 10010b57cec5SDimitry 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 { 10110b57cec5SDimitry Andric PragmaMarkHandler() : PragmaHandler("mark") {} 10120b57cec5SDimitry Andric 10130b57cec5SDimitry 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 { 10210b57cec5SDimitry Andric PragmaPoisonHandler() : PragmaHandler("poison") {} 10220b57cec5SDimitry Andric 10230b57cec5SDimitry 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 { 10320b57cec5SDimitry Andric PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} 10330b57cec5SDimitry Andric 10340b57cec5SDimitry 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 { 10420b57cec5SDimitry Andric PragmaDependencyHandler() : PragmaHandler("dependency") {} 10430b57cec5SDimitry Andric 10440b57cec5SDimitry 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 { 10510b57cec5SDimitry Andric PragmaDebugHandler() : PragmaHandler("__debug") {} 10520b57cec5SDimitry Andric 10530b57cec5SDimitry 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 12140b57cec5SDimitry 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 12390b57cec5SDimitry 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 { 124906c3fb27SDimitry Andric PragmaUnsafeBufferUsageHandler() : PragmaHandler("unsafe_buffer_usage") {} 125006c3fb27SDimitry 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: 12800b57cec5SDimitry Andric explicit PragmaDiagnosticHandler(const char *NS) 12810b57cec5SDimitry Andric : PragmaHandler("diagnostic"), Namespace(NS) {} 12820b57cec5SDimitry Andric 12830b57cec5SDimitry 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 { 13700b57cec5SDimitry Andric PragmaHdrstopHandler() : PragmaHandler("hdrstop") {} 13710b57cec5SDimitry 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 { 13810b57cec5SDimitry Andric PragmaWarningHandler() : PragmaHandler("warning") {} 13820b57cec5SDimitry Andric 13830b57cec5SDimitry 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 { 15300b57cec5SDimitry Andric PragmaExecCharsetHandler() : PragmaHandler("execution_character_set") {} 15310b57cec5SDimitry Andric 15320b57cec5SDimitry 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 { 15920b57cec5SDimitry Andric PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {} 15930b57cec5SDimitry Andric 15940b57cec5SDimitry 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 16180b57cec5SDimitry 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: 16320b57cec5SDimitry Andric PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind, 16330b57cec5SDimitry Andric StringRef Namespace = StringRef()) 16340b57cec5SDimitry Andric : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), 16350b57cec5SDimitry Andric Namespace(Namespace) {} 16360b57cec5SDimitry Andric 16370b57cec5SDimitry 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 { 16910b57cec5SDimitry Andric PragmaModuleImportHandler() : PragmaHandler("import") {} 16920b57cec5SDimitry Andric 16930b57cec5SDimitry 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 { 17280b57cec5SDimitry Andric PragmaModuleBeginHandler() : PragmaHandler("begin") {} 17290b57cec5SDimitry Andric 17300b57cec5SDimitry 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 { 17880b57cec5SDimitry Andric PragmaModuleEndHandler() : PragmaHandler("end") {} 17890b57cec5SDimitry Andric 17900b57cec5SDimitry 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 { 18080b57cec5SDimitry Andric PragmaModuleBuildHandler() : PragmaHandler("build") {} 18090b57cec5SDimitry Andric 18100b57cec5SDimitry 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 { 18180b57cec5SDimitry Andric PragmaModuleLoadHandler() : PragmaHandler("load") {} 18190b57cec5SDimitry Andric 18200b57cec5SDimitry 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 { 18420b57cec5SDimitry Andric PragmaPushMacroHandler() : PragmaHandler("push_macro") {} 18430b57cec5SDimitry Andric 18440b57cec5SDimitry 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 { 18530b57cec5SDimitry Andric PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} 18540b57cec5SDimitry Andric 18550b57cec5SDimitry 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 { 18640b57cec5SDimitry Andric PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {} 18650b57cec5SDimitry Andric 18660b57cec5SDimitry 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 { 19190b57cec5SDimitry Andric PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {} 19200b57cec5SDimitry Andric 19210b57cec5SDimitry 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 { 19880b57cec5SDimitry Andric PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) {} 19890b57cec5SDimitry Andric 19900b57cec5SDimitry 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 { 2005bdd1243dSDimitry 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 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 { 2052349cc55cSDimitry Andric PragmaDeprecatedHandler() : PragmaHandler("deprecated") {} 2053349cc55cSDimitry Andric 2054349cc55cSDimitry 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 { 2074349cc55cSDimitry Andric PragmaRestrictExpansionHandler() : PragmaHandler("restrict_expansion") {} 2075349cc55cSDimitry Andric 2076349cc55cSDimitry 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 { 2096349cc55cSDimitry Andric PragmaFinalHandler() : PragmaHandler("final") {} 2097349cc55cSDimitry Andric 2098349cc55cSDimitry 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. 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. 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