aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Lex/Pragma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Lex/Pragma.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Lex/Pragma.cpp441
1 files changed, 301 insertions, 140 deletions
diff --git a/contrib/llvm-project/clang/lib/Lex/Pragma.cpp b/contrib/llvm-project/clang/lib/Lex/Pragma.cpp
index 27765af34fed..499813f8ab7d 100644
--- a/contrib/llvm-project/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm-project/clang/lib/Lex/Pragma.cpp
@@ -12,8 +12,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/Pragma.h"
+#include "clang/Basic/CLWarnings.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
@@ -36,12 +36,10 @@
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Timer.h"
@@ -50,6 +48,7 @@
#include <cstddef>
#include <cstdint>
#include <limits>
+#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -262,13 +261,49 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
}
SourceLocation RParenLoc = Tok.getLocation();
- std::string StrVal = getSpelling(StrTok);
+ bool Invalid = false;
+ SmallString<64> StrVal;
+ StrVal.resize(StrTok.getLength());
+ StringRef StrValRef = getSpelling(StrTok, StrVal, &Invalid);
+ if (Invalid) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ assert(StrValRef.size() <= StrVal.size());
+
+ // If the token was spelled somewhere else, copy it.
+ if (StrValRef.begin() != StrVal.begin())
+ StrVal.assign(StrValRef);
+ // Truncate if necessary.
+ else if (StrValRef.size() != StrVal.size())
+ StrVal.resize(StrValRef.size());
+
+ // The _Pragma is lexically sound. Destringize according to C11 6.10.9.1.
+ prepare_PragmaString(StrVal);
+
+ // Plop the string (including the newline and trailing null) into a buffer
+ // where we can lex it.
+ Token TmpTok;
+ TmpTok.startToken();
+ CreateString(StrVal, TmpTok);
+ SourceLocation TokLoc = TmpTok.getLocation();
+
+ // Make and enter a lexer object so that we lex and expand the tokens just
+ // like any others.
+ Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
+ StrVal.size(), *this);
+
+ EnterSourceFileWithLexer(TL, nullptr);
+
+ // With everything set up, lex this as a #pragma directive.
+ HandlePragmaDirective({PIK__Pragma, PragmaLoc});
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
- // The _Pragma is lexically sound. Destringize according to C11 6.10.9.1:
- // "The string literal is destringized by deleting any encoding prefix,
- // deleting the leading and trailing double-quotes, replacing each escape
- // sequence \" by a double-quote, and replacing each escape sequence \\ by a
- // single backslash."
+void clang::prepare_PragmaString(SmallVectorImpl<char> &StrVal) {
if (StrVal[0] == 'L' || StrVal[0] == 'U' ||
(StrVal[0] == 'u' && StrVal[1] != '8'))
StrVal.erase(StrVal.begin());
@@ -292,8 +327,8 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
// Remove 'R " d-char-sequence' and 'd-char-sequence "'. We'll replace the
// parens below.
- StrVal.erase(0, 2 + NumDChars);
- StrVal.erase(StrVal.size() - 1 - NumDChars);
+ StrVal.erase(StrVal.begin(), StrVal.begin() + 2 + NumDChars);
+ StrVal.erase(StrVal.end() - 1 - NumDChars, StrVal.end());
} else {
assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
"Invalid string token!");
@@ -315,27 +350,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
StrVal[0] = ' ';
// Replace the terminating quote with a \n.
- StrVal[StrVal.size()-1] = '\n';
-
- // Plop the string (including the newline and trailing null) into a buffer
- // where we can lex it.
- Token TmpTok;
- TmpTok.startToken();
- CreateString(StrVal, TmpTok);
- SourceLocation TokLoc = TmpTok.getLocation();
-
- // Make and enter a lexer object so that we lex and expand the tokens just
- // like any others.
- Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
- StrVal.size(), *this);
-
- EnterSourceFileWithLexer(TL, nullptr);
-
- // With everything set up, lex this as a #pragma directive.
- HandlePragmaDirective({PIK__Pragma, PragmaLoc});
-
- // Finally, return whatever came after the pragma directive.
- return Lex(Tok);
+ StrVal[StrVal.size() - 1] = '\n';
}
/// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
@@ -411,7 +426,7 @@ void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
// Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
// Mark the file as a once-only file now.
- HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
+ HeaderInfo.MarkFileIncludeOnce(*getCurrentFileLexer()->getFileEntry());
}
void Preprocessor::HandlePragmaMark(Token &MarkTok) {
@@ -476,7 +491,7 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
PreprocessorLexer *TheLexer = getCurrentFileLexer();
// Mark the file as a system header.
- HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
+ HeaderInfo.MarkFileSystemHeader(*TheLexer->getFileEntry());
PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
if (PLoc.isInvalid())
@@ -497,89 +512,43 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
SrcMgr::C_System);
}
-static llvm::Optional<Token> LexHeader(Preprocessor &PP,
- Optional<FileEntryRef> &File,
- bool SuppressIncludeNotFoundError) {
+/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
+void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
Token FilenameTok;
- if (PP.LexHeaderName(FilenameTok, /*AllowConcatenation*/ false))
- return llvm::None;
+ if (LexHeaderName(FilenameTok, /*AllowConcatenation*/false))
+ return;
// If the next token wasn't a header-name, diagnose the error.
if (FilenameTok.isNot(tok::header_name)) {
- PP.Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
- return llvm::None;
+ Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+ return;
}
// Reserve a buffer to get the spelling.
SmallString<128> FilenameBuffer;
bool Invalid = false;
- StringRef Filename = PP.getSpelling(FilenameTok, FilenameBuffer, &Invalid);
+ StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
if (Invalid)
- return llvm::None;
+ return;
bool isAngled =
- PP.GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
+ GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
if (Filename.empty())
- return llvm::None;
+ return;
// Search include directories for this file.
- const DirectoryLookup *CurDir;
- File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
- nullptr, CurDir, nullptr, nullptr, nullptr, nullptr,
- nullptr);
+ OptionalFileEntryRef File =
+ LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!File) {
if (!SuppressIncludeNotFoundError)
- PP.Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
- return llvm::None;
- }
-
- return FilenameTok;
-}
-
-/// HandlePragmaIncludeInstead - Handle \#pragma clang include_instead(header).
-void Preprocessor::HandlePragmaIncludeInstead(Token &Tok) {
- // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
- PreprocessorLexer *TheLexer = getCurrentFileLexer();
-
- if (!SourceMgr.isInSystemHeader(Tok.getLocation())) {
- Diag(Tok, diag::err_pragma_include_instead_not_sysheader);
+ Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
}
- Lex(Tok);
- if (Tok.isNot(tok::l_paren)) {
- Diag(Tok, diag::err_expected) << "(";
- return;
- }
-
- Optional<FileEntryRef> File;
- llvm::Optional<Token> FilenameTok =
- LexHeader(*this, File, SuppressIncludeNotFoundError);
- if (!FilenameTok)
- return;
-
- Lex(Tok);
- if (Tok.isNot(tok::r_paren)) {
- Diag(Tok, diag::err_expected) << ")";
- return;
- }
-
- SmallString<128> FilenameBuffer;
- StringRef Filename = getSpelling(*FilenameTok, FilenameBuffer);
- HeaderInfo.AddFileAlias(TheLexer->getFileEntry(), Filename);
-}
-
-/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
-void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
- Optional<FileEntryRef> File;
- llvm::Optional<Token> FilenameTok =
- LexHeader(*this, File, SuppressIncludeNotFoundError);
- if (!FilenameTok)
- return;
-
- const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
+ OptionalFileEntryRef CurFile = getCurrentFileLexer()->getFileEntry();
// If this file is older than the file it depends on, emit a diagnostic.
if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
@@ -594,7 +563,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
// Remove the trailing ' ' if present.
if (!Message.empty())
Message.erase(Message.end()-1);
- Diag(*FilenameTok, diag::pp_out_of_date_dependency) << Message;
+ Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
}
}
@@ -1069,18 +1038,6 @@ struct PragmaSystemHeaderHandler : public PragmaHandler {
}
};
-/// PragmaIncludeInsteadHandler - "\#pragma clang include_instead(header)" marks
-/// the current file as non-includable if the including header is not a system
-/// header.
-struct PragmaIncludeInsteadHandler : public PragmaHandler {
- PragmaIncludeInsteadHandler() : PragmaHandler("include_instead") {}
-
- void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
- Token &IIToken) override {
- PP.HandlePragmaIncludeInstead(IIToken);
- }
-};
-
struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler() : PragmaHandler("dependency") {}
@@ -1098,7 +1055,7 @@ struct PragmaDebugHandler : public PragmaHandler {
Token Tok;
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ PP.Diag(Tok, diag::warn_pragma_debug_missing_command);
return;
}
IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -1120,28 +1077,19 @@ struct PragmaDebugHandler : public PragmaHandler {
PP.EnterToken(Crasher, /*IsReinject*/ false);
}
} else if (II->isStr("dump")) {
- Token Identifier;
- PP.LexUnexpandedToken(Identifier);
- if (auto *DumpII = Identifier.getIdentifierInfo()) {
- Token DumpAnnot;
- DumpAnnot.startToken();
- DumpAnnot.setKind(tok::annot_pragma_dump);
- DumpAnnot.setAnnotationRange(
- SourceRange(Tok.getLocation(), Identifier.getLocation()));
- DumpAnnot.setAnnotationValue(DumpII);
- PP.DiscardUntilEndOfDirective();
- PP.EnterToken(DumpAnnot, /*IsReinject*/false);
- } else {
- PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument)
- << II->getName();
- }
+ Token DumpAnnot;
+ DumpAnnot.startToken();
+ DumpAnnot.setKind(tok::annot_pragma_dump);
+ DumpAnnot.setAnnotationRange(SourceRange(Tok.getLocation()));
+ PP.EnterToken(DumpAnnot, /*IsReinject*/false);
} else if (II->isStr("diag_mapping")) {
Token DiagName;
PP.LexUnexpandedToken(DiagName);
if (DiagName.is(tok::eod))
PP.getDiagnostics().dump();
else if (DiagName.is(tok::string_literal) && !DiagName.hasUDSuffix()) {
- StringLiteralParser Literal(DiagName, PP);
+ StringLiteralParser Literal(DiagName, PP,
+ StringLiteralEvalMethod::Unevaluated);
if (Literal.hadError)
return;
PP.getDiagnostics().dump(Literal.GetString());
@@ -1236,6 +1184,23 @@ struct PragmaDebugHandler : public PragmaHandler {
PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
<< DumpII->getName();
}
+ } else if (II->isStr("sloc_usage")) {
+ // An optional integer literal argument specifies the number of files to
+ // specifically report information about.
+ std::optional<unsigned> MaxNotes;
+ Token ArgToken;
+ PP.Lex(ArgToken);
+ uint64_t Value;
+ if (ArgToken.is(tok::numeric_constant) &&
+ PP.parseSimpleIntegerLiteral(ArgToken, Value)) {
+ MaxNotes = Value;
+ } else if (ArgToken.isNot(tok::eod)) {
+ PP.Diag(ArgToken, diag::warn_pragma_debug_unexpected_argument);
+ }
+
+ PP.Diag(Tok, diag::remark_sloc_usage);
+ PP.getSourceManager().noteSLocAddressSpaceUsage(PP.getDiagnostics(),
+ MaxNotes);
} else {
PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
<< II->getName();
@@ -1280,6 +1245,32 @@ struct PragmaDebugHandler : public PragmaHandler {
#endif
};
+struct PragmaUnsafeBufferUsageHandler : public PragmaHandler {
+ PragmaUnsafeBufferUsageHandler() : PragmaHandler("unsafe_buffer_usage") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override {
+ Token Tok;
+
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok, diag::err_pp_pragma_unsafe_buffer_usage_syntax);
+ return;
+ }
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ SourceLocation Loc = Tok.getLocation();
+
+ if (II->isStr("begin")) {
+ if (PP.enterOrExitSafeBufferOptOutRegion(true, Loc))
+ PP.Diag(Loc, diag::err_pp_double_begin_pragma_unsafe_buffer_usage);
+ } else if (II->isStr("end")) {
+ if (PP.enterOrExitSafeBufferOptOutRegion(false, Loc))
+ PP.Diag(Loc, diag::err_pp_unmatched_end_begin_pragma_unsafe_buffer_usage);
+ } else
+ PP.Diag(Tok, diag::err_pp_pragma_unsafe_buffer_usage_syntax);
+ }
+};
+
/// PragmaDiagnosticHandler - e.g. '\#pragma GCC diagnostic ignored "-Wformat"'
struct PragmaDiagnosticHandler : public PragmaHandler {
private:
@@ -1301,16 +1292,26 @@ public:
IdentifierInfo *II = Tok.getIdentifierInfo();
PPCallbacks *Callbacks = PP.getPPCallbacks();
+ // Get the next token, which is either an EOD or a string literal. We lex
+ // it now so that we can early return if the previous token was push or pop.
+ PP.LexUnexpandedToken(Tok);
+
if (II->isStr("pop")) {
if (!PP.getDiagnostics().popMappings(DiagLoc))
PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
else if (Callbacks)
Callbacks->PragmaDiagnosticPop(DiagLoc, Namespace);
+
+ if (Tok.isNot(tok::eod))
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
return;
} else if (II->isStr("push")) {
PP.getDiagnostics().pushMappings(DiagLoc);
if (Callbacks)
Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace);
+
+ if (Tok.isNot(tok::eod))
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
return;
}
@@ -1326,9 +1327,8 @@ public:
return;
}
- PP.LexUnexpandedToken(Tok);
+ // At this point, we expect a string literal.
SourceLocation StringLoc = Tok.getLocation();
-
std::string WarningName;
if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic",
/*AllowMacroExpansion=*/false))
@@ -1413,12 +1413,15 @@ struct PragmaWarningHandler : public PragmaHandler {
return;
}
}
+ PP.getDiagnostics().pushMappings(DiagLoc);
if (Callbacks)
Callbacks->PragmaWarningPush(DiagLoc, Level);
} else if (II && II->isStr("pop")) {
// #pragma warning( pop )
PP.Lex(Tok);
- if (Callbacks)
+ if (!PP.getDiagnostics().popMappings(DiagLoc))
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
+ else if (Callbacks)
Callbacks->PragmaWarningPop(DiagLoc);
} else {
// #pragma warning( warning-specifier : warning-number-list
@@ -1432,14 +1435,19 @@ struct PragmaWarningHandler : public PragmaHandler {
// Figure out which warning specifier this is.
bool SpecifierValid;
- StringRef Specifier;
- llvm::SmallString<1> SpecifierBuf;
+ PPCallbacks::PragmaWarningSpecifier Specifier;
if (II) {
- Specifier = II->getName();
- SpecifierValid = llvm::StringSwitch<bool>(Specifier)
- .Cases("default", "disable", "error", "once",
- "suppress", true)
- .Default(false);
+ int SpecifierInt = llvm::StringSwitch<int>(II->getName())
+ .Case("default", PPCallbacks::PWS_Default)
+ .Case("disable", PPCallbacks::PWS_Disable)
+ .Case("error", PPCallbacks::PWS_Error)
+ .Case("once", PPCallbacks::PWS_Once)
+ .Case("suppress", PPCallbacks::PWS_Suppress)
+ .Default(-1);
+ if ((SpecifierValid = SpecifierInt != -1))
+ Specifier =
+ static_cast<PPCallbacks::PragmaWarningSpecifier>(SpecifierInt);
+
// If we read a correct specifier, snatch next token (that should be
// ":", checked later).
if (SpecifierValid)
@@ -1447,9 +1455,10 @@ struct PragmaWarningHandler : public PragmaHandler {
} else {
// Token is a numeric constant. It should be either 1, 2, 3 or 4.
uint64_t Value;
- Specifier = PP.getSpelling(Tok, SpecifierBuf);
if (PP.parseSimpleIntegerLiteral(Tok, Value)) {
- SpecifierValid = (Value >= 1) && (Value <= 4);
+ if ((SpecifierValid = (Value >= 1) && (Value <= 4)))
+ Specifier = static_cast<PPCallbacks::PragmaWarningSpecifier>(
+ PPCallbacks::PWS_Level1 + Value - 1);
} else
SpecifierValid = false;
// Next token already snatched by parseSimpleIntegerLiteral.
@@ -1476,6 +1485,22 @@ struct PragmaWarningHandler : public PragmaHandler {
}
Ids.push_back(int(Value));
}
+
+ // Only act on disable for now.
+ diag::Severity SV = diag::Severity();
+ if (Specifier == PPCallbacks::PWS_Disable)
+ SV = diag::Severity::Ignored;
+ if (SV != diag::Severity())
+ for (int Id : Ids) {
+ if (auto Group = diagGroupFromCLWarningID(Id)) {
+ bool unknownDiag = PP.getDiagnostics().setSeverityForGroup(
+ diag::Flavor::WarningOrError, *Group, SV, DiagLoc);
+ assert(!unknownDiag &&
+ "wd table should only contain known diags");
+ (void)unknownDiag;
+ }
+ }
+
if (Callbacks)
Callbacks->PragmaWarning(DiagLoc, Specifier, Ids);
@@ -1726,7 +1751,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// Find the module we're entering. We require that a module map for it
// be loaded or implicitly loadable.
auto &HSI = PP.getHeaderSearchInfo();
- Module *M = HSI.lookupModule(Current);
+ Module *M = HSI.lookupModule(Current, ModuleName.front().second);
if (!M) {
PP.Diag(ModuleName.front().second,
diag::err_pp_module_begin_no_module_map) << Current;
@@ -1744,7 +1769,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// If the module isn't available, it doesn't make sense to enter it.
if (Preprocessor::checkModuleIsAvailable(
- PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) {
+ PP.getLangOpts(), PP.getTargetInfo(), *M, PP.getDiagnostics())) {
PP.Diag(BeginLoc, diag::note_pp_module_begin_here)
<< M->getTopLevelModuleName();
return;
@@ -1970,6 +1995,135 @@ struct PragmaRegionHandler : public PragmaHandler {
}
};
+/// "\#pragma managed"
+/// "\#pragma managed(...)"
+/// "\#pragma unmanaged"
+/// MSVC ignores this pragma when not compiling using /clr, which clang doesn't
+/// support. We parse it and ignore it to avoid -Wunknown-pragma warnings.
+struct PragmaManagedHandler : public EmptyPragmaHandler {
+ PragmaManagedHandler(const char *pragma) : EmptyPragmaHandler(pragma) {}
+};
+
+/// This handles parsing pragmas that take a macro name and optional message
+static IdentifierInfo *HandleMacroAnnotationPragma(Preprocessor &PP, Token &Tok,
+ const char *Pragma,
+ std::string &MessageString) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok, diag::err_expected) << "(";
+ return nullptr;
+ }
+
+ PP.LexUnexpandedToken(Tok);
+ if (!Tok.is(tok::identifier)) {
+ PP.Diag(Tok, diag::err_expected) << tok::identifier;
+ return nullptr;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (!II->hasMacroDefinition()) {
+ PP.Diag(Tok, diag::err_pp_visibility_non_macro) << II;
+ return nullptr;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+ if (!PP.FinishLexStringLiteral(Tok, MessageString, Pragma,
+ /*AllowMacroExpansion=*/true))
+ return nullptr;
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok, diag::err_expected) << ")";
+ return nullptr;
+ }
+ return II;
+}
+
+/// "\#pragma clang deprecated(...)"
+///
+/// The syntax is
+/// \code
+/// #pragma clang deprecate(MACRO_NAME [, Message])
+/// \endcode
+struct PragmaDeprecatedHandler : public PragmaHandler {
+ PragmaDeprecatedHandler() : PragmaHandler("deprecated") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &Tok) override {
+ std::string MessageString;
+
+ if (IdentifierInfo *II = HandleMacroAnnotationPragma(
+ PP, Tok, "#pragma clang deprecated", MessageString)) {
+ II->setIsDeprecatedMacro(true);
+ PP.addMacroDeprecationMsg(II, std::move(MessageString),
+ Tok.getLocation());
+ }
+ }
+};
+
+/// "\#pragma clang restrict_expansion(...)"
+///
+/// The syntax is
+/// \code
+/// #pragma clang restrict_expansion(MACRO_NAME [, Message])
+/// \endcode
+struct PragmaRestrictExpansionHandler : public PragmaHandler {
+ PragmaRestrictExpansionHandler() : PragmaHandler("restrict_expansion") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &Tok) override {
+ std::string MessageString;
+
+ if (IdentifierInfo *II = HandleMacroAnnotationPragma(
+ PP, Tok, "#pragma clang restrict_expansion", MessageString)) {
+ II->setIsRestrictExpansion(true);
+ PP.addRestrictExpansionMsg(II, std::move(MessageString),
+ Tok.getLocation());
+ }
+ }
+};
+
+/// "\#pragma clang final(...)"
+///
+/// The syntax is
+/// \code
+/// #pragma clang final(MACRO_NAME)
+/// \endcode
+struct PragmaFinalHandler : public PragmaHandler {
+ PragmaFinalHandler() : PragmaHandler("final") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &Tok) override {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok, diag::err_expected) << "(";
+ return;
+ }
+
+ PP.LexUnexpandedToken(Tok);
+ if (!Tok.is(tok::identifier)) {
+ PP.Diag(Tok, diag::err_expected) << tok::identifier;
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (!II->hasMacroDefinition()) {
+ PP.Diag(Tok, diag::err_pp_visibility_non_macro) << II;
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok, diag::err_expected) << ")";
+ return;
+ }
+ II->setIsFinal(true);
+ PP.addFinalLoc(II, Tok.getLocation());
+ }
+};
+
} // namespace
/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
@@ -1993,12 +2147,14 @@ void Preprocessor::RegisterBuiltinPragmas() {
// #pragma clang ...
AddPragmaHandler("clang", new PragmaPoisonHandler());
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
- AddPragmaHandler("clang", new PragmaIncludeInsteadHandler());
AddPragmaHandler("clang", new PragmaDebugHandler());
AddPragmaHandler("clang", new PragmaDependencyHandler());
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler());
AddPragmaHandler("clang", new PragmaAssumeNonNullHandler());
+ AddPragmaHandler("clang", new PragmaDeprecatedHandler());
+ AddPragmaHandler("clang", new PragmaRestrictExpansionHandler());
+ AddPragmaHandler("clang", new PragmaFinalHandler());
// #pragma clang module ...
auto *ModuleHandler = new PragmaNamespace("module");
@@ -2009,6 +2165,9 @@ void Preprocessor::RegisterBuiltinPragmas() {
ModuleHandler->AddPragma(new PragmaModuleBuildHandler());
ModuleHandler->AddPragma(new PragmaModuleLoadHandler());
+ // Safe Buffers pragmas
+ AddPragmaHandler("clang", new PragmaUnsafeBufferUsageHandler);
+
// Add region pragmas.
AddPragmaHandler(new PragmaRegionHandler("region"));
AddPragmaHandler(new PragmaRegionHandler("endregion"));
@@ -2020,6 +2179,8 @@ void Preprocessor::RegisterBuiltinPragmas() {
AddPragmaHandler(new PragmaIncludeAliasHandler());
AddPragmaHandler(new PragmaHdrstopHandler());
AddPragmaHandler(new PragmaSystemHeaderHandler());
+ AddPragmaHandler(new PragmaManagedHandler("managed"));
+ AddPragmaHandler(new PragmaManagedHandler("unmanaged"));
}
// Pragmas added by plugins