diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/Pragma.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 122 |
1 files changed, 99 insertions, 23 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index 8ed8328..5eb6655 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -22,6 +22,7 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -400,7 +401,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { if (II->isPoisoned()) continue; // If this is a macro identifier, emit a warning. - if (II->hasMacroDefinition()) + if (isMacroDefined(II)) Diag(Tok, diag::pp_poisoning_existing_macro); // Finally, poison it! @@ -590,8 +591,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { PragmaPushMacroInfo.find(IdentInfo); if (iter != PragmaPushMacroInfo.end()) { // Forget the MacroInfo currently associated with IdentInfo. - if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) { - MacroInfo *MI = CurrentMD->getMacroInfo(); + if (MacroInfo *MI = getMacroInfo(IdentInfo)) { if (MI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc)); @@ -600,11 +600,9 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); - if (MacroToReInstall) { + if (MacroToReInstall) // Reinstall the previously pushed macro. - appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc, - /*isImported=*/false, /*Overrides*/None); - } + appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc); // Pop PragmaPushMacroInfo stack. iter->second.pop_back(); @@ -648,7 +646,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { SourceLocation End; if (ConcatenateIncludeName(FileNameBuffer, End)) return; // Diagnostic already emitted - SourceFileName = FileNameBuffer.str(); + SourceFileName = FileNameBuffer; } else { Diag(Tok, diag::warn_pragma_include_alias_expected_filename); return; @@ -679,7 +677,7 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { SourceLocation End; if (ConcatenateIncludeName(FileNameBuffer, End)) return; // Diagnostic already emitted - ReplaceFileName = FileNameBuffer.str(); + ReplaceFileName = FileNameBuffer; } else { Diag(Tok, diag::warn_pragma_include_alias_expected_filename); return; @@ -870,12 +868,22 @@ struct PragmaDebugHandler : public PragmaHandler { LLVM_BUILTIN_TRAP; } else if (II->isStr("parser_crash")) { Token Crasher; + Crasher.startToken(); Crasher.setKind(tok::annot_pragma_parser_crash); + Crasher.setAnnotationRange(SourceRange(Tok.getLocation())); PP.EnterToken(Crasher); } else if (II->isStr("llvm_fatal_error")) { llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); } else if (II->isStr("llvm_unreachable")) { llvm_unreachable("#pragma clang __debug llvm_unreachable"); + } else if (II->isStr("macro")) { + Token MacroName; + PP.LexUnexpandedToken(MacroName); + auto *MacroII = MacroName.getIdentifierInfo(); + if (MacroII) + PP.dumpMacroInfo(MacroII); + else + PP.Diag(MacroName, diag::warn_pragma_diagnostic_invalid); } else if (II->isStr("overflow_stack")) { DebugOverflowStack(); } else if (II->isStr("handle_crash")) { @@ -1029,12 +1037,8 @@ struct PragmaWarningHandler : public PragmaHandler { PP.Lex(Tok); IdentifierInfo *II = Tok.getIdentifierInfo(); - if (!II) { - PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid); - return; - } - if (II->isStr("push")) { + if (II && II->isStr("push")) { // #pragma warning( push[ ,n ] ) int Level = -1; PP.Lex(Tok); @@ -1051,7 +1055,7 @@ struct PragmaWarningHandler : public PragmaHandler { } if (Callbacks) Callbacks->PragmaWarningPush(DiagLoc, Level); - } else if (II->isStr("pop")) { + } else if (II && II->isStr("pop")) { // #pragma warning( pop ) PP.Lex(Tok); if (Callbacks) @@ -1061,23 +1065,40 @@ struct PragmaWarningHandler : public PragmaHandler { // [; warning-specifier : warning-number-list...] ) while (true) { II = Tok.getIdentifierInfo(); - if (!II) { + if (!II && !Tok.is(tok::numeric_constant)) { PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid); return; } // Figure out which warning specifier this is. - StringRef Specifier = II->getName(); - bool SpecifierValid = - llvm::StringSwitch<bool>(Specifier) - .Cases("1", "2", "3", "4", true) - .Cases("default", "disable", "error", "once", "suppress", true) - .Default(false); + bool SpecifierValid; + StringRef Specifier; + llvm::SmallString<1> SpecifierBuf; + if (II) { + Specifier = II->getName(); + SpecifierValid = llvm::StringSwitch<bool>(Specifier) + .Cases("default", "disable", "error", "once", + "suppress", true) + .Default(false); + // If we read a correct specifier, snatch next token (that should be + // ":", checked later). + if (SpecifierValid) + PP.Lex(Tok); + } 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); + } else + SpecifierValid = false; + // Next token already snatched by parseSimpleIntegerLiteral. + } + if (!SpecifierValid) { PP.Diag(Tok, diag::warn_pragma_warning_spec_invalid); return; } - PP.Lex(Tok); if (Tok.isNot(tok::colon)) { PP.Diag(Tok, diag::warn_pragma_warning_expected) << ":"; return; @@ -1321,6 +1342,60 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { } }; +/// PragmaAssumeNonNullHandler - +/// \#pragma clang assume_nonnull begin/end +struct PragmaAssumeNonNullHandler : public PragmaHandler { + PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &NameTok) override { + SourceLocation Loc = NameTok.getLocation(); + bool IsBegin; + + Token Tok; + + // Lex the 'begin' or 'end'. + PP.LexUnexpandedToken(Tok); + const IdentifierInfo *BeginEnd = Tok.getIdentifierInfo(); + if (BeginEnd && BeginEnd->isStr("begin")) { + IsBegin = true; + } else if (BeginEnd && BeginEnd->isStr("end")) { + IsBegin = false; + } else { + PP.Diag(Tok.getLocation(), diag::err_pp_assume_nonnull_syntax); + return; + } + + // Verify that this is followed by EOD. + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // The start location of the active audit. + SourceLocation BeginLoc = PP.getPragmaAssumeNonNullLoc(); + + // The start location we want after processing this. + SourceLocation NewLoc; + + if (IsBegin) { + // Complain about attempts to re-enter an audit. + if (BeginLoc.isValid()) { + PP.Diag(Loc, diag::err_pp_double_begin_of_assume_nonnull); + PP.Diag(BeginLoc, diag::note_pragma_entered_here); + } + NewLoc = Loc; + } else { + // Complain about attempts to leave an audit that doesn't exist. + if (!BeginLoc.isValid()) { + PP.Diag(Loc, diag::err_pp_unmatched_end_of_assume_nonnull); + return; + } + NewLoc = SourceLocation(); + } + + PP.setPragmaAssumeNonNullLoc(NewLoc); + } +}; + /// \brief Handle "\#pragma region [...]" /// /// The syntax is @@ -1372,6 +1447,7 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler("clang", new PragmaDependencyHandler()); AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang")); AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler()); + AddPragmaHandler("clang", new PragmaAssumeNonNullHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); |