ParsePragma.cpp revision 208954
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 SourceLocation PackLoc = PackTok.getLocation(); 27 28 Token Tok; 29 PP.Lex(Tok); 30 if (Tok.isNot(tok::l_paren)) { 31 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 32 return; 33 } 34 35 Action::PragmaPackKind Kind = Action::PPK_Default; 36 IdentifierInfo *Name = 0; 37 Action::OwningExprResult Alignment(Actions); 38 SourceLocation LParenLoc = Tok.getLocation(); 39 PP.Lex(Tok); 40 if (Tok.is(tok::numeric_constant)) { 41 Alignment = Actions.ActOnNumericConstant(Tok); 42 if (Alignment.isInvalid()) 43 return; 44 45 PP.Lex(Tok); 46 } else if (Tok.is(tok::identifier)) { 47 const IdentifierInfo *II = Tok.getIdentifierInfo(); 48 if (II->isStr("show")) { 49 Kind = Action::PPK_Show; 50 PP.Lex(Tok); 51 } else { 52 if (II->isStr("push")) { 53 Kind = Action::PPK_Push; 54 } else if (II->isStr("pop")) { 55 Kind = Action::PPK_Pop; 56 } else { 57 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action); 58 return; 59 } 60 PP.Lex(Tok); 61 62 if (Tok.is(tok::comma)) { 63 PP.Lex(Tok); 64 65 if (Tok.is(tok::numeric_constant)) { 66 Alignment = Actions.ActOnNumericConstant(Tok); 67 if (Alignment.isInvalid()) 68 return; 69 70 PP.Lex(Tok); 71 } else if (Tok.is(tok::identifier)) { 72 Name = Tok.getIdentifierInfo(); 73 PP.Lex(Tok); 74 75 if (Tok.is(tok::comma)) { 76 PP.Lex(Tok); 77 78 if (Tok.isNot(tok::numeric_constant)) { 79 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 80 return; 81 } 82 83 Alignment = Actions.ActOnNumericConstant(Tok); 84 if (Alignment.isInvalid()) 85 return; 86 87 PP.Lex(Tok); 88 } 89 } else { 90 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 91 return; 92 } 93 } 94 } 95 } 96 97 if (Tok.isNot(tok::r_paren)) { 98 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 99 return; 100 } 101 102 SourceLocation RParenLoc = Tok.getLocation(); 103 PP.Lex(Tok); 104 if (Tok.isNot(tok::eom)) { 105 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 106 return; 107 } 108 109 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc, 110 LParenLoc, RParenLoc); 111} 112 113// #pragma 'options' 'align' '=' {'natural', 'mac68k', 'power', 'reset'} 114void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) { 115 SourceLocation OptionsLoc = OptionsTok.getLocation(); 116 117 Token Tok; 118 PP.Lex(Tok); 119 if (Tok.isNot(tok::identifier) || !Tok.getIdentifierInfo()->isStr("align")) { 120 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 121 return; 122 } 123 124 PP.Lex(Tok); 125 if (Tok.isNot(tok::equal)) { 126 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_equal); 127 return; 128 } 129 130 PP.Lex(Tok); 131 if (Tok.isNot(tok::identifier)) { 132 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 133 << "options"; 134 return; 135 } 136 137 Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural; 138 const IdentifierInfo *II = Tok.getIdentifierInfo(); 139 if (II->isStr("natural")) 140 Kind = Action::POAK_Natural; 141 else if (II->isStr("power")) 142 Kind = Action::POAK_Power; 143 else if (II->isStr("mac68k")) 144 Kind = Action::POAK_Mac68k; 145 else if (II->isStr("reset")) 146 Kind = Action::POAK_Reset; 147 else { 148 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option); 149 return; 150 } 151 152 SourceLocation KindLoc = Tok.getLocation(); 153 PP.Lex(Tok); 154 if (Tok.isNot(tok::eom)) { 155 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 156 << "options"; 157 return; 158 } 159 160 Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc); 161} 162 163// #pragma unused(identifier) 164void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { 165 // FIXME: Should we be expanding macros here? My guess is no. 166 SourceLocation UnusedLoc = UnusedTok.getLocation(); 167 168 // Lex the left '('. 169 Token Tok; 170 PP.Lex(Tok); 171 if (Tok.isNot(tok::l_paren)) { 172 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 173 return; 174 } 175 SourceLocation LParenLoc = Tok.getLocation(); 176 177 // Lex the declaration reference(s). 178 llvm::SmallVector<Token, 5> Identifiers; 179 SourceLocation RParenLoc; 180 bool LexID = true; 181 182 while (true) { 183 PP.Lex(Tok); 184 185 if (LexID) { 186 if (Tok.is(tok::identifier)) { 187 Identifiers.push_back(Tok); 188 LexID = false; 189 continue; 190 } 191 192 // Illegal token! 193 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 194 return; 195 } 196 197 // We are execting a ')' or a ','. 198 if (Tok.is(tok::comma)) { 199 LexID = true; 200 continue; 201 } 202 203 if (Tok.is(tok::r_paren)) { 204 RParenLoc = Tok.getLocation(); 205 break; 206 } 207 208 // Illegal token! 209 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); 210 return; 211 } 212 213 PP.Lex(Tok); 214 if (Tok.isNot(tok::eom)) { 215 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 216 "unused"; 217 return; 218 } 219 220 // Verify that we have a location for the right parenthesis. 221 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 222 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 223 224 // Perform the action to handle the pragma. 225 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(), 226 parser.CurScope, UnusedLoc, LParenLoc, RParenLoc); 227} 228 229// #pragma weak identifier 230// #pragma weak identifier '=' identifier 231void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) { 232 // FIXME: Should we be expanding macros here? My guess is no. 233 SourceLocation WeakLoc = WeakTok.getLocation(); 234 235 Token Tok; 236 PP.Lex(Tok); 237 if (Tok.isNot(tok::identifier)) { 238 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 239 return; 240 } 241 242 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0; 243 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc; 244 245 PP.Lex(Tok); 246 if (Tok.is(tok::equal)) { 247 PP.Lex(Tok); 248 if (Tok.isNot(tok::identifier)) { 249 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 250 << "weak"; 251 return; 252 } 253 AliasName = Tok.getIdentifierInfo(); 254 AliasNameLoc = Tok.getLocation(); 255 PP.Lex(Tok); 256 } 257 258 if (Tok.isNot(tok::eom)) { 259 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 260 return; 261 } 262 263 if (AliasName) { 264 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc, 265 AliasNameLoc); 266 } else { 267 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc); 268 } 269} 270