diff options
Diffstat (limited to 'lib/Lex/Pragma.cpp')
-rw-r--r-- | lib/Lex/Pragma.cpp | 208 |
1 files changed, 116 insertions, 92 deletions
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index a7b289e..f0475bc 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -35,7 +35,9 @@ PragmaHandler::~PragmaHandler() { EmptyPragmaHandler::EmptyPragmaHandler() {} -void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, Token &FirstToken) {} +void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) {} //===----------------------------------------------------------------------===// // PragmaNamespace Implementation. @@ -73,7 +75,9 @@ void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) { Handlers.erase(Handler->getName()); } -void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { +void PragmaNamespace::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro // expand it, the user can have a STDC #define, that should not affect this. PP.LexUnexpandedToken(Tok); @@ -89,7 +93,7 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { } // Otherwise, pass it down. - Handler->HandlePragma(PP, Tok); + Handler->HandlePragma(PP, Introducer, Tok); } //===----------------------------------------------------------------------===// @@ -98,12 +102,12 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { /// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the /// rest of the pragma, passing it to the registered pragma handlers. -void Preprocessor::HandlePragmaDirective() { +void Preprocessor::HandlePragmaDirective(unsigned Introducer) { ++NumPragma; // Invoke the first level of pragma handlers which reads the namespace id. Token Tok; - PragmaHandlers->HandlePragma(*this, Tok); + PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok); // If the pragma handler didn't read the rest of the line, consume it now. if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective) @@ -170,7 +174,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { } } - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); @@ -216,13 +220,14 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { SourceLocation RParenLoc = Tok.getLocation(); - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); } -void Preprocessor::Handle_Pragma(const std::string &StrVal, +void Preprocessor::Handle_Pragma(unsigned Introducer, + const std::string &StrVal, SourceLocation PragmaLoc, SourceLocation RParenLoc) { @@ -241,7 +246,7 @@ void Preprocessor::Handle_Pragma(const std::string &StrVal, EnterSourceFileWithLexer(TL, 0); // With everything set up, lex this as a #pragma directive. - HandlePragmaDirective(); + HandlePragmaDirective(Introducer); } @@ -287,7 +292,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { if (Tok.is(tok::eom)) return; // Can only poison identifiers. - if (Tok.isNot(tok::identifier)) { + if (Tok.isNot(tok::raw_identifier)) { Diag(Tok, diag::err_pp_invalid_poison); return; } @@ -324,6 +329,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation()); + if (PLoc.isInvalid()) + return; + unsigned FilenameLen = strlen(PLoc.getFilename()); unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(), FilenameLen); @@ -478,23 +486,32 @@ void Preprocessor::HandlePragmaComment(Token &Tok) { Callbacks->PragmaComment(CommentLoc, II, ArgumentString); } -/// HandlePragmaMessage - Handle the microsoft #pragma message extension. The -/// syntax is: -/// #pragma message(messagestring) -/// messagestring is a string, which is fully macro expanded, and permits string -/// concatenation, embedded escape characters etc. See MSDN for more details. +/// HandlePragmaMessage - Handle the microsoft and gcc #pragma message +/// extension. The syntax is: +/// #pragma message(string) +/// OR, in GCC mode: +/// #pragma message string +/// string is a string, which is fully macro expanded, and permits string +/// concatenation, embedded escape characters, etc... See MSDN for more details. void Preprocessor::HandlePragmaMessage(Token &Tok) { SourceLocation MessageLoc = Tok.getLocation(); Lex(Tok); - if (Tok.isNot(tok::l_paren)) { + bool ExpectClosingParen = false; + switch (Tok.getKind()) { + case tok::l_paren: + // We have a MSVC style pragma message. + ExpectClosingParen = true; + // Read the string. + Lex(Tok); + break; + case tok::string_literal: + // We have a GCC style pragma message, and we just read the string. + break; + default: Diag(MessageLoc, diag::err_pragma_message_malformed); return; } - // Read the string. - Lex(Tok); - - // We need at least one string. if (Tok.isNot(tok::string_literal)) { Diag(Tok.getLocation(), diag::err_pragma_message_malformed); @@ -522,11 +539,13 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) { llvm::StringRef MessageString(Literal.GetString(), Literal.GetStringLength()); - if (Tok.isNot(tok::r_paren)) { - Diag(Tok.getLocation(), diag::err_pragma_message_malformed); - return; + if (ExpectClosingParen) { + if (Tok.isNot(tok::r_paren)) { + Diag(Tok.getLocation(), diag::err_pragma_message_malformed); + return; + } + Lex(Tok); // eat the r_paren. } - Lex(Tok); // eat the r_paren. if (Tok.isNot(tok::eom)) { Diag(Tok.getLocation(), diag::err_pragma_message_malformed); @@ -580,7 +599,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { // Create a Token from the string. Token MacroTok; MacroTok.startToken(); - MacroTok.setKind(tok::identifier); + MacroTok.setKind(tok::raw_identifier); CreateString(&StrVal[1], StrVal.size() - 2, MacroTok); // Get the IdentifierInfo of MacroToPushTok. @@ -611,7 +630,7 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { PragmaPushMacroInfo[IdentInfo].push_back(MacroCopyToPush); } -/// HandlePragmaPopMacro - Handle #pragma push_macro. +/// HandlePragmaPopMacro - Handle #pragma pop_macro. /// The syntax is: /// #pragma pop_macro("macro") void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { @@ -627,7 +646,11 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (iter != PragmaPushMacroInfo.end()) { // Release the MacroInfo currently associated with IdentInfo. MacroInfo *CurrentMI = getMacroInfo(IdentInfo); - if (CurrentMI) ReleaseMacroInfo(CurrentMI); + if (CurrentMI) { + if (CurrentMI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); + ReleaseMacroInfo(CurrentMI); + } // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); @@ -700,11 +723,39 @@ void Preprocessor::RemovePragmaHandler(llvm::StringRef Namespace, PragmaHandlers->RemovePragmaHandler(NS); } +bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) { + Token Tok; + LexUnexpandedToken(Tok); + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::ext_on_off_switch_syntax); + return true; + } + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("ON")) + Result = tok::OOS_ON; + else if (II->isStr("OFF")) + Result = tok::OOS_OFF; + else if (II->isStr("DEFAULT")) + Result = tok::OOS_DEFAULT; + else { + Diag(Tok, diag::ext_on_off_switch_syntax); + return true; + } + + // Verify that this is followed by EOM. + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eom)) + Diag(Tok, diag::ext_pragma_syntax_eom); + return false; +} + namespace { /// PragmaOnceHandler - "#pragma once" marks the file as atomically included. struct PragmaOnceHandler : public PragmaHandler { PragmaOnceHandler() : PragmaHandler("once") {} - virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &OnceTok) { PP.CheckEndOfDirective("pragma once"); PP.HandlePragmaOnce(OnceTok); } @@ -714,7 +765,8 @@ struct PragmaOnceHandler : public PragmaHandler { /// rest of the line is not lexed. struct PragmaMarkHandler : public PragmaHandler { PragmaMarkHandler() : PragmaHandler("mark") {} - virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &MarkTok) { PP.HandlePragmaMark(); } }; @@ -722,7 +774,8 @@ struct PragmaMarkHandler : public PragmaHandler { /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable. struct PragmaPoisonHandler : public PragmaHandler { PragmaPoisonHandler() : PragmaHandler("poison") {} - virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PoisonTok) { PP.HandlePragmaPoison(PoisonTok); } }; @@ -731,21 +784,24 @@ struct PragmaPoisonHandler : public PragmaHandler { /// as a system header, which silences warnings in it. struct PragmaSystemHeaderHandler : public PragmaHandler { PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} - virtual void HandlePragma(Preprocessor &PP, Token &SHToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &SHToken) { PP.HandlePragmaSystemHeader(SHToken); PP.CheckEndOfDirective("pragma"); } }; struct PragmaDependencyHandler : public PragmaHandler { PragmaDependencyHandler() : PragmaHandler("dependency") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { PP.HandlePragmaDependency(DepToken); } }; struct PragmaDebugHandler : public PragmaHandler { PragmaDebugHandler() : PragmaHandler("__debug") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -783,7 +839,9 @@ struct PragmaDebugHandler : public PragmaHandler { struct PragmaDiagnosticHandler : public PragmaHandler { public: explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {} - virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DiagToken) { + SourceLocation DiagLoc = DiagToken.getLocation(); Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -802,12 +860,12 @@ public: else if (II->isStr("fatal")) Map = diag::MAP_FATAL; else if (II->isStr("pop")) { - if (!PP.getDiagnostics().popMappings()) + if (!PP.getDiagnostics().popMappings(DiagLoc)) PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); return; } else if (II->isStr("push")) { - PP.getDiagnostics().pushMappings(); + PP.getDiagnostics().pushMappings(DiagLoc); return; } else { PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); @@ -857,7 +915,7 @@ public: } if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2, - Map)) + Map, DiagLoc)) PP.Diag(StrToks[0].getLocation(), diag::warn_pragma_diagnostic_unknown_warning) << WarningName; } @@ -866,7 +924,8 @@ public: /// PragmaCommentHandler - "#pragma comment ...". struct PragmaCommentHandler : public PragmaHandler { PragmaCommentHandler() : PragmaHandler("comment") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaComment(CommentTok); } }; @@ -874,7 +933,8 @@ struct PragmaCommentHandler : public PragmaHandler { /// PragmaMessageHandler - "#pragma message("...")". struct PragmaMessageHandler : public PragmaHandler { PragmaMessageHandler() : PragmaHandler("message") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaMessage(CommentTok); } }; @@ -883,7 +943,8 @@ struct PragmaMessageHandler : public PragmaHandler { /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { PragmaPushMacroHandler() : PragmaHandler("push_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PushMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PushMacroTok) { PP.HandlePragmaPushMacro(PushMacroTok); } }; @@ -893,62 +954,23 @@ struct PragmaPushMacroHandler : public PragmaHandler { /// macro to the value on the top of the stack. struct PragmaPopMacroHandler : public PragmaHandler { PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PopMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PopMacroTok) { PP.HandlePragmaPopMacro(PopMacroTok); } }; // Pragma STDC implementations. -enum STDCSetting { - STDC_ON, STDC_OFF, STDC_DEFAULT, STDC_INVALID -}; - -static STDCSetting LexOnOffSwitch(Preprocessor &PP) { - Token Tok; - PP.LexUnexpandedToken(Tok); - - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok, diag::ext_stdc_pragma_syntax); - return STDC_INVALID; - } - IdentifierInfo *II = Tok.getIdentifierInfo(); - STDCSetting Result; - if (II->isStr("ON")) - Result = STDC_ON; - else if (II->isStr("OFF")) - Result = STDC_OFF; - else if (II->isStr("DEFAULT")) - Result = STDC_DEFAULT; - else { - PP.Diag(Tok, diag::ext_stdc_pragma_syntax); - return STDC_INVALID; - } - - // Verify that this is followed by EOM. - PP.LexUnexpandedToken(Tok); - if (Tok.isNot(tok::eom)) - PP.Diag(Tok, diag::ext_stdc_pragma_syntax_eom); - return Result; -} - -/// PragmaSTDC_FP_CONTRACTHandler - "#pragma STDC FP_CONTRACT ...". -struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler { - PragmaSTDC_FP_CONTRACTHandler() : PragmaHandler("FP_CONTRACT") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - // We just ignore the setting of FP_CONTRACT. Since we don't do contractions - // at all, our default is OFF and setting it to ON is an optimization hint - // we can safely ignore. When we support -ffma or something, we would need - // to diagnose that we are ignoring FMA. - LexOnOffSwitch(PP); - } -}; - /// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...". struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - if (LexOnOffSwitch(PP) == STDC_ON) + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { + tok::OnOffSwitch OOS; + if (PP.LexOnOffSwitch(OOS)) + return; + if (OOS == tok::OOS_ON) PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); } }; @@ -957,15 +979,18 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - LexOnOffSwitch(PP); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { + tok::OnOffSwitch OOS; + PP.LexOnOffSwitch(OOS); } }; /// PragmaSTDC_UnknownHandler - "#pragma STDC ...". struct PragmaSTDC_UnknownHandler : public PragmaHandler { PragmaSTDC_UnknownHandler() {} - virtual void HandlePragma(Preprocessor &PP, Token &UnknownTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) { // C99 6.10.6p2, unknown forms are not allowed. PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); } @@ -981,6 +1006,7 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler(new PragmaMarkHandler()); AddPragmaHandler(new PragmaPushMacroHandler()); AddPragmaHandler(new PragmaPopMacroHandler()); + AddPragmaHandler(new PragmaMessageHandler()); // #pragma GCC ... AddPragmaHandler("GCC", new PragmaPoisonHandler()); @@ -994,7 +1020,6 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler("clang", new PragmaDependencyHandler()); AddPragmaHandler("clang", new PragmaDiagnosticHandler()); - AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); @@ -1002,6 +1027,5 @@ void Preprocessor::RegisterBuiltinPragmas() { // MS extensions. if (Features.Microsoft) { AddPragmaHandler(new PragmaCommentHandler()); - AddPragmaHandler(new PragmaMessageHandler()); } } |