ParsePragma.cpp revision 193326
1//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the language specific #pragma handlers. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ParsePragma.h" 15#include "clang/Parse/ParseDiagnostic.h" 16#include "clang/Lex/Preprocessor.h" 17#include "clang/Parse/Action.h" 18#include "clang/Parse/Parser.h" 19using namespace clang; 20 21// #pragma pack(...) comes in the following delicious flavors: 22// pack '(' [integer] ')' 23// pack '(' 'show' ')' 24// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' 25void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) { 26 // FIXME: Should we be expanding macros here? My guess is no. 27 SourceLocation PackLoc = PackTok.getLocation(); 28 29 Token Tok; 30 PP.Lex(Tok); 31 if (Tok.isNot(tok::l_paren)) { 32 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 33 return; 34 } 35 36 Action::PragmaPackKind Kind = Action::PPK_Default; 37 IdentifierInfo *Name = 0; 38 Action::OwningExprResult Alignment(Actions); 39 SourceLocation LParenLoc = Tok.getLocation(); 40 PP.Lex(Tok); 41 if (Tok.is(tok::numeric_constant)) { 42 Alignment = Actions.ActOnNumericConstant(Tok); 43 if (Alignment.isInvalid()) 44 return; 45 46 PP.Lex(Tok); 47 } else if (Tok.is(tok::identifier)) { 48 const IdentifierInfo *II = Tok.getIdentifierInfo(); 49 if (II->isStr("show")) { 50 Kind = Action::PPK_Show; 51 PP.Lex(Tok); 52 } else { 53 if (II->isStr("push")) { 54 Kind = Action::PPK_Push; 55 } else if (II->isStr("pop")) { 56 Kind = Action::PPK_Pop; 57 } else { 58 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action); 59 return; 60 } 61 PP.Lex(Tok); 62 63 if (Tok.is(tok::comma)) { 64 PP.Lex(Tok); 65 66 if (Tok.is(tok::numeric_constant)) { 67 Alignment = Actions.ActOnNumericConstant(Tok); 68 if (Alignment.isInvalid()) 69 return; 70 71 PP.Lex(Tok); 72 } else if (Tok.is(tok::identifier)) { 73 Name = Tok.getIdentifierInfo(); 74 PP.Lex(Tok); 75 76 if (Tok.is(tok::comma)) { 77 PP.Lex(Tok); 78 79 if (Tok.isNot(tok::numeric_constant)) { 80 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 81 return; 82 } 83 84 Alignment = Actions.ActOnNumericConstant(Tok); 85 if (Alignment.isInvalid()) 86 return; 87 88 PP.Lex(Tok); 89 } 90 } else { 91 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 92 return; 93 } 94 } 95 } 96 } 97 98 if (Tok.isNot(tok::r_paren)) { 99 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 100 return; 101 } 102 103 SourceLocation RParenLoc = Tok.getLocation(); 104 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc, 105 LParenLoc, RParenLoc); 106} 107 108// #pragma unused(identifier) 109void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { 110 // FIXME: Should we be expanding macros here? My guess is no. 111 SourceLocation UnusedLoc = UnusedTok.getLocation(); 112 113 // Lex the left '('. 114 Token Tok; 115 PP.Lex(Tok); 116 if (Tok.isNot(tok::l_paren)) { 117 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 118 return; 119 } 120 SourceLocation LParenLoc = Tok.getLocation(); 121 122 // Lex the declaration reference(s). 123 llvm::SmallVector<Action::ExprTy*, 5> Ex; 124 SourceLocation RParenLoc; 125 bool LexID = true; 126 127 while (true) { 128 PP.Lex(Tok); 129 130 if (LexID) { 131 if (Tok.is(tok::identifier)) { 132 Action::OwningExprResult Name = 133 Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(), 134 *Tok.getIdentifierInfo(), false); 135 136 if (Name.isInvalid()) { 137 if (!Ex.empty()) 138 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); 139 return; 140 } 141 142 Ex.push_back(Name.release()); 143 LexID = false; 144 continue; 145 } 146 147 // Illegal token! Release the parsed expressions (if any) and emit 148 // a warning. 149 if (!Ex.empty()) 150 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); 151 152 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 153 return; 154 } 155 156 // We are execting a ')' or a ','. 157 if (Tok.is(tok::comma)) { 158 LexID = true; 159 continue; 160 } 161 162 if (Tok.is(tok::r_paren)) { 163 RParenLoc = Tok.getLocation(); 164 break; 165 } 166 167 // Illegal token! Release the parsed expressions (if any) and emit 168 // a warning. 169 if (!Ex.empty()) 170 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); 171 172 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); 173 return; 174 } 175 176 // Verify that we have a location for the right parenthesis. 177 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 178 assert(!Ex.empty() && "Valid '#pragma unused' must have arguments"); 179 180 // Perform the action to handle the pragma. 181 Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc); 182} 183