| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- Pragma.cpp - Pragma registration and handling --------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This file implements the PragmaHandler/PragmaTable interfaces and implements | 
 | 11 | // pragma related methods of the Preprocessor class. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
 | 15 | #include "clang/Lex/Pragma.h" | 
 | 16 | #include "clang/Lex/PPCallbacks.h" | 
 | 17 | #include "clang/Lex/HeaderSearch.h" | 
 | 18 | #include "clang/Lex/Preprocessor.h" | 
 | 19 | #include "clang/Basic/Diagnostic.h" | 
 | 20 | #include "clang/Basic/FileManager.h" | 
 | 21 | #include "clang/Basic/SourceManager.h" | 
 | 22 | #include "llvm/ADT/SmallVector.h" | 
 | 23 | using namespace clang; | 
 | 24 |  | 
 | 25 | // Out-of-line destructor to provide a home for the class. | 
 | 26 | PragmaHandler::~PragmaHandler() { | 
 | 27 | } | 
 | 28 |  | 
 | 29 | //===----------------------------------------------------------------------===// | 
 | 30 | // PragmaNamespace Implementation. | 
 | 31 | //===----------------------------------------------------------------------===// | 
 | 32 |  | 
 | 33 |  | 
 | 34 | PragmaNamespace::~PragmaNamespace() { | 
 | 35 |   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) | 
 | 36 |     delete Handlers[i]; | 
 | 37 | } | 
 | 38 |  | 
 | 39 | /// FindHandler - Check to see if there is already a handler for the | 
 | 40 | /// specified name.  If not, return the handler for the null identifier if it | 
 | 41 | /// exists, otherwise return null.  If IgnoreNull is true (the default) then | 
 | 42 | /// the null handler isn't returned on failure to match. | 
 | 43 | PragmaHandler *PragmaNamespace::FindHandler(const IdentifierInfo *Name, | 
 | 44 |                                             bool IgnoreNull) const { | 
 | 45 |   PragmaHandler *NullHandler = 0; | 
 | 46 |   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { | 
 | 47 |     if (Handlers[i]->getName() == Name)  | 
 | 48 |       return Handlers[i]; | 
 | 49 |      | 
 | 50 |     if (Handlers[i]->getName() == 0) | 
 | 51 |       NullHandler = Handlers[i]; | 
 | 52 |   } | 
 | 53 |   return IgnoreNull ? 0 : NullHandler; | 
 | 54 | } | 
 | 55 |  | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 56 | void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 57 |   // Read the 'namespace' that the directive is in, e.g. STDC.  Do not macro | 
 | 58 |   // expand it, the user can have a STDC #define, that should not affect this. | 
 | 59 |   PP.LexUnexpandedToken(Tok); | 
 | 60 |    | 
 | 61 |   // Get the handler for this token.  If there is no handler, ignore the pragma. | 
 | 62 |   PragmaHandler *Handler = FindHandler(Tok.getIdentifierInfo(), false); | 
 | 63 |   if (Handler == 0) return; | 
 | 64 |    | 
 | 65 |   // Otherwise, pass it down. | 
 | 66 |   Handler->HandlePragma(PP, Tok); | 
 | 67 | } | 
 | 68 |  | 
 | 69 | //===----------------------------------------------------------------------===// | 
 | 70 | // Preprocessor Pragma Directive Handling. | 
 | 71 | //===----------------------------------------------------------------------===// | 
 | 72 |  | 
 | 73 | /// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the | 
 | 74 | /// rest of the pragma, passing it to the registered pragma handlers. | 
 | 75 | void Preprocessor::HandlePragmaDirective() { | 
 | 76 |   ++NumPragma; | 
 | 77 |    | 
 | 78 |   // Invoke the first level of pragma handlers which reads the namespace id. | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 79 |   Token Tok; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 80 |   PragmaHandlers->HandlePragma(*this, Tok); | 
 | 81 |    | 
 | 82 |   // If the pragma handler didn't read the rest of the line, consume it now. | 
 | 83 |   if (CurLexer->ParsingPreprocessorDirective) | 
 | 84 |     DiscardUntilEndOfDirective(); | 
 | 85 | } | 
 | 86 |  | 
 | 87 | /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then | 
 | 88 | /// return the first token after the directive.  The _Pragma token has just | 
 | 89 | /// been read into 'Tok'. | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 90 | void Preprocessor::Handle_Pragma(Token &Tok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 91 |   // Remember the pragma token location. | 
 | 92 |   SourceLocation PragmaLoc = Tok.getLocation(); | 
 | 93 |    | 
 | 94 |   // Read the '('. | 
 | 95 |   Lex(Tok); | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 96 |   if (Tok.isNot(tok::l_paren)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 97 |     return Diag(PragmaLoc, diag::err__Pragma_malformed); | 
 | 98 |  | 
 | 99 |   // Read the '"..."'. | 
 | 100 |   Lex(Tok); | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 101 |   if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 102 |     return Diag(PragmaLoc, diag::err__Pragma_malformed); | 
 | 103 |    | 
 | 104 |   // Remember the string. | 
 | 105 |   std::string StrVal = getSpelling(Tok); | 
 | 106 |   SourceLocation StrLoc = Tok.getLocation(); | 
 | 107 |  | 
 | 108 |   // Read the ')'. | 
 | 109 |   Lex(Tok); | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 110 |   if (Tok.isNot(tok::r_paren)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 111 |     return Diag(PragmaLoc, diag::err__Pragma_malformed); | 
 | 112 |    | 
 | 113 |   // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1. | 
 | 114 |   if (StrVal[0] == 'L')  // Remove L prefix. | 
 | 115 |     StrVal.erase(StrVal.begin()); | 
 | 116 |   assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && | 
 | 117 |          "Invalid string token!"); | 
 | 118 |    | 
 | 119 |   // Remove the front quote, replacing it with a space, so that the pragma | 
 | 120 |   // contents appear to have a space before them. | 
 | 121 |   StrVal[0] = ' '; | 
 | 122 |    | 
 | 123 |   // Replace the terminating quote with a \n\0. | 
 | 124 |   StrVal[StrVal.size()-1] = '\n'; | 
 | 125 |   StrVal += '\0'; | 
 | 126 |    | 
 | 127 |   // Remove escaped quotes and escapes. | 
 | 128 |   for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) { | 
 | 129 |     if (StrVal[i] == '\\' && | 
 | 130 |         (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) { | 
 | 131 |       // \\ -> '\' and \" -> '"'. | 
 | 132 |       StrVal.erase(StrVal.begin()+i); | 
 | 133 |       --e; | 
 | 134 |     } | 
 | 135 |   } | 
 | 136 |    | 
 | 137 |   // Plop the string (including the newline and trailing null) into a buffer | 
 | 138 |   // where we can lex it. | 
 | 139 |   SourceLocation TokLoc = CreateString(&StrVal[0], StrVal.size(), StrLoc); | 
 | 140 |   const char *StrData = SourceMgr.getCharacterData(TokLoc); | 
 | 141 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 142 |   // Make and enter a lexer object so that we lex and expand the tokens just | 
 | 143 |   // like any others. | 
| Chris Lattner | 25bdb51 | 2007-07-20 16:52:03 +0000 | [diff] [blame] | 144 |   Lexer *TL = new Lexer(TokLoc, *this, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 145 |                         StrData, StrData+StrVal.size()-1 /* no null */); | 
 | 146 |    | 
 | 147 |   // Ensure that the lexer thinks it is inside a directive, so that end \n will | 
 | 148 |   // return an EOM token. | 
 | 149 |   TL->ParsingPreprocessorDirective = true; | 
 | 150 |    | 
 | 151 |   // This lexer really is for _Pragma. | 
 | 152 |   TL->Is_PragmaLexer = true; | 
 | 153 |  | 
 | 154 |   EnterSourceFileWithLexer(TL, 0); | 
 | 155 |  | 
 | 156 |   // With everything set up, lex this as a #pragma directive. | 
 | 157 |   HandlePragmaDirective(); | 
 | 158 |    | 
 | 159 |   // Finally, return whatever came after the pragma directive. | 
 | 160 |   return Lex(Tok); | 
 | 161 | } | 
 | 162 |  | 
 | 163 |  | 
 | 164 |  | 
 | 165 | /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'. | 
 | 166 | /// | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 167 | void Preprocessor::HandlePragmaOnce(Token &OnceTok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 168 |   if (isInPrimaryFile()) { | 
 | 169 |     Diag(OnceTok, diag::pp_pragma_once_in_main_file); | 
 | 170 |     return; | 
 | 171 |   } | 
 | 172 |    | 
 | 173 |   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc. | 
| Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 174 |   SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 175 |    | 
 | 176 |   // Mark the file as a once-only file now. | 
| Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 177 |   HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForLoc(FileLoc)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 178 | } | 
 | 179 |  | 
| Chris Lattner | 2243449 | 2007-12-19 19:38:36 +0000 | [diff] [blame] | 180 | void Preprocessor::HandlePragmaMark() { | 
 | 181 |   assert(CurLexer && "No current lexer?"); | 
 | 182 |   CurLexer->ReadToEndOfLine(); | 
 | 183 | } | 
 | 184 |  | 
 | 185 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 186 | /// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'. | 
 | 187 | /// | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 188 | void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { | 
 | 189 |   Token Tok; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 190 |  | 
 | 191 |   while (1) { | 
 | 192 |     // Read the next token to poison.  While doing this, pretend that we are | 
 | 193 |     // skipping while reading the identifier to poison. | 
 | 194 |     // This avoids errors on code like: | 
 | 195 |     //   #pragma GCC poison X | 
 | 196 |     //   #pragma GCC poison X | 
 | 197 |     if (CurLexer) CurLexer->LexingRawMode = true; | 
 | 198 |     LexUnexpandedToken(Tok); | 
 | 199 |     if (CurLexer) CurLexer->LexingRawMode = false; | 
 | 200 |      | 
 | 201 |     // If we reached the end of line, we're done. | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 202 |     if (Tok.is(tok::eom)) return; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 203 |      | 
 | 204 |     // Can only poison identifiers. | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 205 |     if (Tok.isNot(tok::identifier)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 206 |       Diag(Tok, diag::err_pp_invalid_poison); | 
 | 207 |       return; | 
 | 208 |     } | 
 | 209 |      | 
 | 210 |     // Look up the identifier info for the token.  We disabled identifier lookup | 
 | 211 |     // by saying we're skipping contents, so we need to do this manually. | 
 | 212 |     IdentifierInfo *II = LookUpIdentifierInfo(Tok); | 
 | 213 |      | 
 | 214 |     // Already poisoned. | 
 | 215 |     if (II->isPoisoned()) continue; | 
 | 216 |      | 
 | 217 |     // If this is a macro identifier, emit a warning. | 
| Chris Lattner | 0edde55 | 2007-10-07 08:04:56 +0000 | [diff] [blame] | 218 |     if (II->hasMacroDefinition()) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 219 |       Diag(Tok, diag::pp_poisoning_existing_macro); | 
 | 220 |      | 
 | 221 |     // Finally, poison it! | 
 | 222 |     II->setIsPoisoned(); | 
 | 223 |   } | 
 | 224 | } | 
 | 225 |  | 
 | 226 | /// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know | 
 | 227 | /// that the whole directive has been parsed. | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 228 | void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 229 |   if (isInPrimaryFile()) { | 
 | 230 |     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file); | 
 | 231 |     return; | 
 | 232 |   } | 
 | 233 |    | 
 | 234 |   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc. | 
 | 235 |   Lexer *TheLexer = getCurrentFileLexer(); | 
 | 236 |    | 
 | 237 |   // Mark the file as a system header. | 
| Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 238 |   const FileEntry *File = SourceMgr.getFileEntryForLoc(TheLexer->getFileLoc()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 239 |   HeaderInfo.MarkFileSystemHeader(File); | 
 | 240 |    | 
 | 241 |   // Notify the client, if desired, that we are in a new source file. | 
 | 242 |   if (Callbacks) | 
 | 243 |     Callbacks->FileChanged(TheLexer->getSourceLocation(TheLexer->BufferPtr), | 
 | 244 |                            PPCallbacks::SystemHeaderPragma, | 
 | 245 |                            DirectoryLookup::SystemHeaderDir); | 
 | 246 | } | 
 | 247 |  | 
 | 248 | /// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah. | 
 | 249 | /// | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 250 | void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { | 
 | 251 |   Token FilenameTok; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 252 |   CurLexer->LexIncludeFilename(FilenameTok); | 
 | 253 |  | 
 | 254 |   // If the token kind is EOM, the error has already been diagnosed. | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 255 |   if (FilenameTok.is(tok::eom)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 256 |     return; | 
 | 257 |    | 
 | 258 |   // Reserve a buffer to get the spelling. | 
 | 259 |   llvm::SmallVector<char, 128> FilenameBuffer; | 
 | 260 |   FilenameBuffer.resize(FilenameTok.getLength()); | 
 | 261 |    | 
| Chris Lattner | f1c99ac | 2007-07-23 04:15:27 +0000 | [diff] [blame] | 262 |   const char *FilenameStart = &FilenameBuffer[0]; | 
 | 263 |   unsigned Len = getSpelling(FilenameTok, FilenameStart); | 
 | 264 |   const char *FilenameEnd = FilenameStart+Len; | 
 | 265 |   bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(), | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 266 |                                              FilenameStart, FilenameEnd); | 
 | 267 |   // If GetIncludeFilenameSpelling set the start ptr to null, there was an | 
 | 268 |   // error. | 
 | 269 |   if (FilenameStart == 0) | 
 | 270 |     return; | 
 | 271 |    | 
 | 272 |   // Search include directories for this file. | 
 | 273 |   const DirectoryLookup *CurDir; | 
 | 274 |   const FileEntry *File = LookupFile(FilenameStart, FilenameEnd, | 
 | 275 |                                      isAngled, 0, CurDir); | 
 | 276 |   if (File == 0) | 
 | 277 |     return Diag(FilenameTok, diag::err_pp_file_not_found, | 
 | 278 |                 std::string(FilenameStart, FilenameEnd)); | 
 | 279 |    | 
| Chris Lattner | 9dc1f53 | 2007-07-20 16:37:10 +0000 | [diff] [blame] | 280 |   SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc(); | 
 | 281 |   const FileEntry *CurFile = SourceMgr.getFileEntryForLoc(FileLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 282 |  | 
 | 283 |   // If this file is older than the file it depends on, emit a diagnostic. | 
 | 284 |   if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) { | 
 | 285 |     // Lex tokens at the end of the message and include them in the message. | 
 | 286 |     std::string Message; | 
 | 287 |     Lex(DependencyTok); | 
| Chris Lattner | 22f6bbc | 2007-10-09 18:02:16 +0000 | [diff] [blame] | 288 |     while (DependencyTok.isNot(tok::eom)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 289 |       Message += getSpelling(DependencyTok) + " "; | 
 | 290 |       Lex(DependencyTok); | 
 | 291 |     } | 
 | 292 |      | 
 | 293 |     Message.erase(Message.end()-1); | 
 | 294 |     Diag(FilenameTok, diag::pp_out_of_date_dependency, Message); | 
 | 295 |   } | 
 | 296 | } | 
 | 297 |  | 
 | 298 |  | 
 | 299 | /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. | 
 | 300 | /// If 'Namespace' is non-null, then it is a token required to exist on the | 
 | 301 | /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". | 
 | 302 | void Preprocessor::AddPragmaHandler(const char *Namespace,  | 
 | 303 |                                     PragmaHandler *Handler) { | 
 | 304 |   PragmaNamespace *InsertNS = PragmaHandlers; | 
 | 305 |    | 
 | 306 |   // If this is specified to be in a namespace, step down into it. | 
 | 307 |   if (Namespace) { | 
 | 308 |     IdentifierInfo *NSID = getIdentifierInfo(Namespace); | 
 | 309 |      | 
 | 310 |     // If there is already a pragma handler with the name of this namespace, | 
 | 311 |     // we either have an error (directive with the same name as a namespace) or | 
 | 312 |     // we already have the namespace to insert into. | 
 | 313 |     if (PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID)) { | 
 | 314 |       InsertNS = Existing->getIfNamespace(); | 
 | 315 |       assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma" | 
 | 316 |              " handler with the same name!"); | 
 | 317 |     } else { | 
 | 318 |       // Otherwise, this namespace doesn't exist yet, create and insert the | 
 | 319 |       // handler for it. | 
 | 320 |       InsertNS = new PragmaNamespace(NSID); | 
 | 321 |       PragmaHandlers->AddPragma(InsertNS); | 
 | 322 |     } | 
 | 323 |   } | 
 | 324 |    | 
 | 325 |   // Check to make sure we don't already have a pragma for this identifier. | 
 | 326 |   assert(!InsertNS->FindHandler(Handler->getName()) && | 
 | 327 |          "Pragma handler already exists for this identifier!"); | 
 | 328 |   InsertNS->AddPragma(Handler); | 
 | 329 | } | 
 | 330 |  | 
 | 331 | namespace { | 
| Chris Lattner | 2243449 | 2007-12-19 19:38:36 +0000 | [diff] [blame] | 332 | /// PragmaOnceHandler - "#pragma once" marks the file as atomically included. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 333 | struct PragmaOnceHandler : public PragmaHandler { | 
 | 334 |   PragmaOnceHandler(const IdentifierInfo *OnceID) : PragmaHandler(OnceID) {} | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 335 |   virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 336 |     PP.CheckEndOfDirective("#pragma once"); | 
 | 337 |     PP.HandlePragmaOnce(OnceTok); | 
 | 338 |   } | 
 | 339 | }; | 
 | 340 |  | 
| Chris Lattner | 2243449 | 2007-12-19 19:38:36 +0000 | [diff] [blame] | 341 | /// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the | 
 | 342 | /// rest of the line is not lexed. | 
 | 343 | struct PragmaMarkHandler : public PragmaHandler { | 
 | 344 |   PragmaMarkHandler(const IdentifierInfo *MarkID) : PragmaHandler(MarkID) {} | 
 | 345 |   virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) { | 
 | 346 |     PP.HandlePragmaMark(); | 
 | 347 |   } | 
 | 348 | }; | 
 | 349 |  | 
 | 350 | /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 351 | struct PragmaPoisonHandler : public PragmaHandler { | 
 | 352 |   PragmaPoisonHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {} | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 353 |   virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 354 |     PP.HandlePragmaPoison(PoisonTok); | 
 | 355 |   } | 
 | 356 | }; | 
 | 357 |  | 
| Chris Lattner | 2243449 | 2007-12-19 19:38:36 +0000 | [diff] [blame] | 358 | /// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file | 
 | 359 | /// as a system header, which silences warnings in it. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 360 | struct PragmaSystemHeaderHandler : public PragmaHandler { | 
 | 361 |   PragmaSystemHeaderHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {} | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 362 |   virtual void HandlePragma(Preprocessor &PP, Token &SHToken) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 363 |     PP.HandlePragmaSystemHeader(SHToken); | 
 | 364 |     PP.CheckEndOfDirective("#pragma"); | 
 | 365 |   } | 
 | 366 | }; | 
 | 367 | struct PragmaDependencyHandler : public PragmaHandler { | 
 | 368 |   PragmaDependencyHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {} | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 369 |   virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 370 |     PP.HandlePragmaDependency(DepToken); | 
 | 371 |   } | 
 | 372 | }; | 
 | 373 | }  // end anonymous namespace | 
 | 374 |  | 
 | 375 |  | 
 | 376 | /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas: | 
 | 377 | /// #pragma GCC poison/system_header/dependency and #pragma once. | 
 | 378 | void Preprocessor::RegisterBuiltinPragmas() { | 
 | 379 |   AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once"))); | 
| Chris Lattner | 2243449 | 2007-12-19 19:38:36 +0000 | [diff] [blame] | 380 |   AddPragmaHandler(0, new PragmaMarkHandler(getIdentifierInfo("mark"))); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 381 |   AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison"))); | 
 | 382 |   AddPragmaHandler("GCC", new PragmaSystemHeaderHandler( | 
 | 383 |                                           getIdentifierInfo("system_header"))); | 
 | 384 |   AddPragmaHandler("GCC", new PragmaDependencyHandler( | 
 | 385 |                                           getIdentifierInfo("dependency"))); | 
 | 386 | } |