//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the language specific #pragma handlers. // //===----------------------------------------------------------------------===// #include "ParsePragma.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Action.h" #include "clang/Parse/Parser.h" using namespace clang; // #pragma pack(...) comes in the following delicious flavors: // pack '(' [integer] ')' // pack '(' 'show' ')' // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation PackLoc = PackTok.getLocation(); Token Tok; PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; return; } Action::PragmaPackKind Kind = Action::PPK_Default; IdentifierInfo *Name = 0; Action::OwningExprResult Alignment(Actions); SourceLocation LParenLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { Alignment = Actions.ActOnNumericConstant(Tok); if (Alignment.isInvalid()) return; PP.Lex(Tok); } else if (Tok.is(tok::identifier)) { const IdentifierInfo *II = Tok.getIdentifierInfo(); if (II->isStr("show")) { Kind = Action::PPK_Show; PP.Lex(Tok); } else { if (II->isStr("push")) { Kind = Action::PPK_Push; } else if (II->isStr("pop")) { Kind = Action::PPK_Pop; } else { PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action); return; } PP.Lex(Tok); if (Tok.is(tok::comma)) { PP.Lex(Tok); if (Tok.is(tok::numeric_constant)) { Alignment = Actions.ActOnNumericConstant(Tok); if (Alignment.isInvalid()) return; PP.Lex(Tok); } else if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); PP.Lex(Tok); if (Tok.is(tok::comma)) { PP.Lex(Tok); if (Tok.isNot(tok::numeric_constant)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); return; } Alignment = Actions.ActOnNumericConstant(Tok); if (Alignment.isInvalid()) return; PP.Lex(Tok); } } else { PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); return; } } } } if (Tok.isNot(tok::r_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; return; } SourceLocation RParenLoc = Tok.getLocation(); Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc, LParenLoc, RParenLoc); } // #pragma unused(identifier) void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation UnusedLoc = UnusedTok.getLocation(); // Lex the left '('. Token Tok; PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; return; } SourceLocation LParenLoc = Tok.getLocation(); // Lex the declaration reference(s). llvm::SmallVector Ex; SourceLocation RParenLoc; bool LexID = true; while (true) { PP.Lex(Tok); if (LexID) { if (Tok.is(tok::identifier)) { Action::OwningExprResult Name = Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(), *Tok.getIdentifierInfo(), false); if (Name.isInvalid()) { if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); return; } Ex.push_back(Name.release()); LexID = false; continue; } // Illegal token! Release the parsed expressions (if any) and emit // a warning. if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); return; } // We are execting a ')' or a ','. if (Tok.is(tok::comma)) { LexID = true; continue; } if (Tok.is(tok::r_paren)) { RParenLoc = Tok.getLocation(); break; } // Illegal token! Release the parsed expressions (if any) and emit // a warning. if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); return; } // Verify that we have a location for the right parenthesis. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); assert(!Ex.empty() && "Valid '#pragma unused' must have arguments"); // Perform the action to handle the pragma. Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc); }