From 7adf79a620cb7fbde0608e21727425930676b7db Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 6 May 2013 21:02:12 +0000 Subject: Move PragmaCommentHandler to lib/Parse in preparation for calling Sema Summary: No functionality change. The existing tests for this pragma only verify that we can preprocess it. Reviewers: rsmith CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D751 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181246 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticLexKinds.td | 3 -- include/clang/Basic/DiagnosticParseKinds.td | 4 ++ include/clang/Lex/Preprocessor.h | 1 - include/clang/Parse/Parser.h | 1 + lib/Lex/Pragma.cpp | 75 +---------------------------- lib/Parse/ParsePragma.cpp | 66 +++++++++++++++++++++++++ lib/Parse/ParsePragma.h | 8 +++ lib/Parse/Parser.cpp | 10 ++++ 8 files changed, 90 insertions(+), 78 deletions(-) diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 548823f1f0..2c16000d33 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -408,8 +408,6 @@ def warn_pragma_include_alias_expected_filename : def err__Pragma_malformed : Error< "_Pragma takes a parenthesized string literal">; -def err_pragma_comment_malformed : Error< - "pragma comment requires parenthesized identifier and optional string">; def err_pragma_message_malformed : Error< "pragma %select{message|warning|error}0 requires parenthesized string">; def err_pragma_push_pop_macro_malformed : Error< @@ -452,7 +450,6 @@ def warn_pragma_diagnostic_unknown_warning : def warn_pragma_debug_unexpected_command : Warning< "unexpected debug command '%0'">; -def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_paste_at_start : Error< "'##' cannot appear at start of macro expansion">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index f50dceca57..e001bd46a2 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -785,6 +785,10 @@ def warn_pragma_unused_expected_punc : Warning< def err_pragma_fp_contract_scope : Error< "'#pragma fp_contract' should only appear at file scope or at the start of a " "compound expression">; +// - #pragma comment +def err_pragma_comment_malformed : Error< + "pragma comment requires parenthesized identifier and optional string">; +def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; // OpenCL Section 6.8.g diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index aa84b23fe8..c5981777cd 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1452,7 +1452,6 @@ public: void HandlePragmaPoison(Token &PoisonTok); void HandlePragmaSystemHeader(Token &SysHeaderTok); void HandlePragmaDependency(Token &DependencyTok); - void HandlePragmaComment(Token &CommentTok); void HandlePragmaPushMacro(Token &Tok); void HandlePragmaPopMacro(Token &Tok); void HandlePragmaIncludeAlias(Token &Tok); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index a33d01d27b..1029a90c55 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -149,6 +149,7 @@ class Parser : public CodeCompletionHandler { OwningPtr OpenCLExtensionHandler; OwningPtr CommentSemaHandler; OwningPtr OpenMPHandler; + OwningPtr MSCommentHandler; /// Whether the '>' token acts as an operator or not. This will be /// true except when we are parsing an expression within a C++ diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index d674ad34b4..b2ae4c9c44 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -493,70 +493,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { } } -/// \brief Handle the microsoft \#pragma comment extension. -/// -/// The syntax is: -/// \code -/// #pragma comment(linker, "foo") -/// \endcode -/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. -/// "foo" is a string, which is fully macro expanded, and permits string -/// concatenation, embedded escape characters etc. See MSDN for more details. -void Preprocessor::HandlePragmaComment(Token &Tok) { - SourceLocation CommentLoc = Tok.getLocation(); - Lex(Tok); - if (Tok.isNot(tok::l_paren)) { - Diag(CommentLoc, diag::err_pragma_comment_malformed); - return; - } - - // Read the identifier. - Lex(Tok); - if (Tok.isNot(tok::identifier)) { - Diag(CommentLoc, diag::err_pragma_comment_malformed); - return; - } - - // Verify that this is one of the 5 whitelisted options. - // FIXME: warn that 'exestr' is deprecated. - const IdentifierInfo *II = Tok.getIdentifierInfo(); - if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") && - !II->isStr("linker") && !II->isStr("user")) { - Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); - return; - } - - // Read the optional string if present. - Lex(Tok); - std::string ArgumentString; - if (Tok.is(tok::comma) && !LexStringLiteral(Tok, ArgumentString, - "pragma comment", - /*MacroExpansion=*/true)) - return; - - // FIXME: If the kind is "compiler" warn if the string is present (it is - // ignored). - // FIXME: 'lib' requires a comment string. - // FIXME: 'linker' requires a comment string, and has a specific list of - // things that are allowable. - - if (Tok.isNot(tok::r_paren)) { - Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); - return; - } - Lex(Tok); // eat the r_paren. - - if (Tok.isNot(tok::eod)) { - Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); - return; - } - - // If the pragma is lexically sound, notify any interested PPCallbacks. - if (Callbacks) - Callbacks->PragmaComment(CommentLoc, II, ArgumentString); -} - -/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. +/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. /// Return the IdentifierInfo* associated with the macro to push or pop. IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { // Remember the pragma token location. @@ -1062,15 +999,6 @@ public: } }; -/// PragmaCommentHandler - "\#pragma comment ...". -struct PragmaCommentHandler : public PragmaHandler { - PragmaCommentHandler() : PragmaHandler("comment") {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &CommentTok) { - PP.HandlePragmaComment(CommentTok); - } -}; - /// PragmaIncludeAliasHandler - "\#pragma include_alias("...")". struct PragmaIncludeAliasHandler : public PragmaHandler { PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {} @@ -1334,7 +1262,6 @@ void Preprocessor::RegisterBuiltinPragmas() { // MS extensions. if (LangOpts.MicrosoftExt) { - AddPragmaHandler(new PragmaCommentHandler()); AddPragmaHandler(new PragmaIncludeAliasHandler()); AddPragmaHandler(new PragmaRegionHandler("region")); AddPragmaHandler(new PragmaRegionHandler("endregion")); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index ef43c5b4b7..3d1249aa68 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -16,6 +16,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Scope.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; /// \brief Handle the annotation token produced for #pragma unused(...) @@ -792,3 +793,68 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, PP.EnterTokenStream(Toks, Pragma.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); } + +/// \brief Handle the microsoft \#pragma comment extension. +/// +/// The syntax is: +/// \code +/// #pragma comment(linker, "foo") +/// \endcode +/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. +/// "foo" is a string, which is fully macro expanded, and permits string +/// concatenation, embedded escape characters etc. See MSDN for more details. +void PragmaCommentHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation CommentLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); + return; + } + + // Read the identifier. + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); + return; + } + + // Verify that this is one of the 5 whitelisted options. + // FIXME: warn that 'exestr' is deprecated. + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") && + !II->isStr("linker") && !II->isStr("user")) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); + return; + } + + // Read the optional string if present. + PP.Lex(Tok); + std::string ArgumentString; + if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, + "pragma comment", + /*MacroExpansion=*/true)) + return; + + // FIXME: If the kind is "compiler" warn if the string is present (it is + // ignored). + // FIXME: 'lib' requires a comment string. + // FIXME: 'linker' requires a comment string, and has a specific list of + // things that are allowable. + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); + return; + } + PP.Lex(Tok); // eat the r_paren. + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); + return; + } + + // If the pragma is lexically sound, notify any interested PPCallbacks. + if (PP.getPPCallbacks()) + PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); +} diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index 841a60be7b..d9560f3181 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -113,6 +113,14 @@ public: Token &FirstToken); }; +/// PragmaCommentHandler - "\#pragma comment ...". +class PragmaCommentHandler : public PragmaHandler { +public: + PragmaCommentHandler() : PragmaHandler("comment") {} + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; + } // end namespace clang #endif diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d819644cb8..455139b881 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -102,6 +102,11 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); + if (getLangOpts().MicrosoftExt) { + MSCommentHandler.reset(new PragmaCommentHandler()); + PP.AddPragmaHandler(MSCommentHandler.get()); + } + CommentSemaHandler.reset(new ActionCommentHandler(actions)); PP.addCommentHandler(CommentSemaHandler.get()); @@ -436,6 +441,11 @@ Parser::~Parser() { PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); + if (getLangOpts().MicrosoftExt) { + PP.RemovePragmaHandler(MSCommentHandler.get()); + MSCommentHandler.reset(); + } + PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); -- cgit v1.2.3-18-g5258