zcov: / lib/Lex/Pragma.cpp


Files: 1 Branches Taken: 57.7% 158 / 274
Generated: 2010-02-10 01:31 Branches Executed: 78.1% 214 / 274
Line Coverage: 85.4% 287 / 336


Programs: 2 Runs 3018


       1                 : //===--- Pragma.cpp - Pragma registration and handling --------------------===//
       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 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/HeaderSearch.h"
      17                 : #include "clang/Lex/LiteralSupport.h"
      18                 : #include "clang/Lex/Preprocessor.h"
      19                 : #include "clang/Lex/LexDiagnostic.h"
      20                 : #include "clang/Basic/FileManager.h"
      21                 : #include "clang/Basic/SourceManager.h"
      22                 : #include <algorithm>
      23                 : using namespace clang;
      24                 : 
      25                 : // Out-of-line destructor to provide a home for the class.
      26            52715: PragmaHandler::~PragmaHandler() {
                    52715: branch 0 taken
                    52715: branch 1 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 6 not taken
                    52715: branch 7 taken
      27            52715: }
      28                 : 
      29                 : //===----------------------------------------------------------------------===//
      30                 : // PragmaNamespace Implementation.
      31                 : //===----------------------------------------------------------------------===//
      32                 : 
      33                 : 
      34            10120: PragmaNamespace::~PragmaNamespace() {
                    43432: branch 1 taken
                    10120: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
      35            53552:   for (unsigned i = 0, e = Handlers.size(); i != e; ++i)
                    43432: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
      36            43432:     delete Handlers[i];
                    10120: branch 2 taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
      37            10120: }
      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            73501:                                             bool IgnoreNull) const {
      45            73501:   PragmaHandler *NullHandler = 0;
                   206562: branch 1 taken
                    50247: branch 2 taken
      46           256809:   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
                    23254: branch 2 taken
                   183308: branch 3 taken
      47           206562:     if (Handlers[i]->getName() == Name)
      48            23254:       return Handlers[i];
      49                 : 
                        8: branch 2 taken
                   183300: branch 3 taken
      50           183308:     if (Handlers[i]->getName() == 0)
      51                8:       NullHandler = Handlers[i];
      52                 :   }
                    50236: branch 0 taken
                       11: branch 1 taken
      53            50247:   return IgnoreNull ? 0 : NullHandler;
      54                 : }
      55                 : 
      56             6753: void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
                    42829: branch 1 taken
                        0: branch 2 not taken
      57            42829:   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
                     6753: branch 1 taken
                    36076: branch 2 taken
      58            42829:     if (Handlers[i] == Handler) {
      59             6753:       Handlers[i] = Handlers.back();
      60             6753:       Handlers.pop_back();
      61                 :       return;
      62                 :     }
      63                 :   }
      64                0:   assert(0 && "Handler not registered in this namespace");
      65                 : }
      66                 : 
      67              268: void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) {
      68                 :   // Read the 'namespace' that the directive is in, e.g. STDC.  Do not macro
      69                 :   // expand it, the user can have a STDC #define, that should not affect this.
      70              268:   PP.LexUnexpandedToken(Tok);
      71                 : 
      72                 :   // Get the handler for this token.  If there is no handler, ignore the pragma.
      73              268:   PragmaHandler *Handler = FindHandler(Tok.getIdentifierInfo(), false);
                        3: branch 0 taken
                      265: branch 1 taken
      74              268:   if (Handler == 0) {
      75                3:     PP.Diag(Tok, diag::warn_pragma_ignored);
      76                3:     return;
      77                 :   }
      78                 : 
      79                 :   // Otherwise, pass it down.
      80              265:   Handler->HandlePragma(PP, Tok);
      81                 : }
      82                 : 
      83                 : //===----------------------------------------------------------------------===//
      84                 : // Preprocessor Pragma Directive Handling.
      85                 : //===----------------------------------------------------------------------===//
      86                 : 
      87                 : /// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the
      88                 : /// rest of the pragma, passing it to the registered pragma handlers.
      89              205: void Preprocessor::HandlePragmaDirective() {
      90              205:   ++NumPragma;
      91                 : 
      92                 :   // Invoke the first level of pragma handlers which reads the namespace id.
      93              205:   Token Tok;
      94              205:   PragmaHandlers->HandlePragma(*this, Tok);
      95                 : 
      96                 :   // If the pragma handler didn't read the rest of the line, consume it now.
                      205: branch 0 taken
                        0: branch 1 not taken
                       44: branch 2 taken
                      161: branch 3 taken
      97              205:   if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
      98               44:     DiscardUntilEndOfDirective();
      99              205: }
     100                 : 
     101                 : /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
     102                 : /// return the first token after the directive.  The _Pragma token has just
     103                 : /// been read into 'Tok'.
     104               16: void Preprocessor::Handle_Pragma(Token &Tok) {
     105                 :   // Remember the pragma token location.
     106               16:   SourceLocation PragmaLoc = Tok.getLocation();
     107                 : 
     108                 :   // Read the '('.
     109               16:   Lex(Tok);
                        0: branch 1 not taken
                       16: branch 2 taken
     110               16:   if (Tok.isNot(tok::l_paren)) {
     111                0:     Diag(PragmaLoc, diag::err__Pragma_malformed);
     112                0:     return;
     113                 :   }
     114                 : 
     115                 :   // Read the '"..."'.
     116               16:   Lex(Tok);
                        0: branch 1 not taken
                       16: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                       16: branch 7 taken
     117               16:   if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
     118                0:     Diag(PragmaLoc, diag::err__Pragma_malformed);
     119                0:     return;
     120                 :   }
     121                 : 
     122                 :   // Remember the string.
     123               16:   std::string StrVal = getSpelling(Tok);
     124                 : 
     125                 :   // Read the ')'.
     126               16:   Lex(Tok);
                        0: branch 1 not taken
                       16: branch 2 taken
     127               16:   if (Tok.isNot(tok::r_paren)) {
     128                0:     Diag(PragmaLoc, diag::err__Pragma_malformed);
     129                 :     return;
     130                 :   }
     131                 : 
     132               16:   SourceLocation RParenLoc = Tok.getLocation();
     133                 : 
     134                 :   // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1:
     135                 :   // "The string literal is destringized by deleting the L prefix, if present,
     136                 :   // deleting the leading and trailing double-quotes, replacing each escape
     137                 :   // sequence \" by a double-quote, and replacing each escape sequence \\ by a
     138                 :   // single backslash."
                        0: branch 1 not taken
                       16: branch 2 taken
     139               16:   if (StrVal[0] == 'L')  // Remove L prefix.
     140                0:     StrVal.erase(StrVal.begin());
     141                 :   assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
                       16: branch 1 taken
                        0: branch 2 not taken
                       16: branch 5 taken
                        0: branch 6 not taken
     142               16:          "Invalid string token!");
     143                 : 
     144                 :   // Remove the front quote, replacing it with a space, so that the pragma
     145                 :   // contents appear to have a space before them.
     146               16:   StrVal[0] = ' ';
     147                 : 
     148                 :   // Replace the terminating quote with a \n.
     149               16:   StrVal[StrVal.size()-1] = '\n';
     150                 : 
     151                 :   // Remove escaped quotes and escapes.
                      218: branch 1 taken
                       16: branch 2 taken
     152              234:   for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
                        6: branch 1 taken
                      212: branch 2 taken
                        6: branch 4 taken
                        0: branch 5 not taken
                        6: branch 7 taken
                        0: branch 8 not taken
                        6: branch 9 taken
                      212: branch 10 taken
     153              218:     if (StrVal[i] == '\\' &&
     154                 :         (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
     155                 :       // \\ -> '\' and \" -> '"'.
     156                6:       StrVal.erase(StrVal.begin()+i);
     157                6:       --e;
     158                 :     }
     159                 :   }
     160                 : 
     161                 :   // Plop the string (including the newline and trailing null) into a buffer
     162                 :   // where we can lex it.
     163               16:   Token TmpTok;
     164               16:   TmpTok.startToken();
     165               16:   CreateString(&StrVal[0], StrVal.size(), TmpTok);
     166               16:   SourceLocation TokLoc = TmpTok.getLocation();
     167                 : 
     168                 :   // Make and enter a lexer object so that we lex and expand the tokens just
     169                 :   // like any others.
     170                 :   Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
     171               16:                                         StrVal.size(), *this);
     172                 : 
     173               16:   EnterSourceFileWithLexer(TL, 0);
     174                 : 
     175                 :   // With everything set up, lex this as a #pragma directive.
     176               16:   HandlePragmaDirective();
     177                 : 
     178                 :   // Finally, return whatever came after the pragma directive.
     179               16:   return Lex(Tok);
     180                 : }
     181                 : 
     182                 : 
     183                 : 
     184                 : /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
     185                 : ///
     186                0: void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     187                0:   if (isInPrimaryFile()) {
     188                0:     Diag(OnceTok, diag::pp_pragma_once_in_main_file);
     189                0:     return;
     190                 :   }
     191                 : 
     192                 :   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
     193                 :   // Mark the file as a once-only file now.
     194                0:   HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
     195                 : }
     196                 : 
     197                5: void Preprocessor::HandlePragmaMark() {
                        0: branch 0 not taken
                        5: branch 1 taken
     198                5:   assert(CurPPLexer && "No current lexer?");
                        5: branch 1 taken
                        0: branch 2 not taken
     199                5:   if (CurLexer)
     200                5:     CurLexer->ReadToEndOfLine();
     201                 :   else
     202                0:     CurPTHLexer->DiscardToEndOfLine();
     203                5: }
     204                 : 
     205                 : 
     206                 : /// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
     207                 : ///
     208                5: void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
     209                5:   Token Tok;
     210                 : 
     211                5:   while (1) {
     212                 :     // Read the next token to poison.  While doing this, pretend that we are
     213                 :     // skipping while reading the identifier to poison.
     214                 :     // This avoids errors on code like:
     215                 :     //   #pragma GCC poison X
     216                 :     //   #pragma GCC poison X
                       10: branch 0 taken
                        0: branch 1 not taken
     217               10:     if (CurPPLexer) CurPPLexer->LexingRawMode = true;
     218               10:     LexUnexpandedToken(Tok);
                       10: branch 0 taken
                        0: branch 1 not taken
     219               10:     if (CurPPLexer) CurPPLexer->LexingRawMode = false;
     220                 : 
     221                 :     // If we reached the end of line, we're done.
                        5: branch 1 taken
                        5: branch 2 taken
     222               10:     if (Tok.is(tok::eom)) return;
     223                 : 
     224                 :     // Can only poison identifiers.
                        0: branch 1 not taken
                        5: branch 2 taken
     225                5:     if (Tok.isNot(tok::identifier)) {
     226                0:       Diag(Tok, diag::err_pp_invalid_poison);
     227                0:       return;
     228                 :     }
     229                 : 
     230                 :     // Look up the identifier info for the token.  We disabled identifier lookup
     231                 :     // by saying we're skipping contents, so we need to do this manually.
     232                5:     IdentifierInfo *II = LookUpIdentifierInfo(Tok);
     233                 : 
     234                 :     // Already poisoned.
                        4: branch 1 taken
                        1: branch 2 taken
     235                5:     if (II->isPoisoned()) continue;
     236                 : 
     237                 :     // If this is a macro identifier, emit a warning.
                        0: branch 1 not taken
                        4: branch 2 taken
     238                4:     if (II->hasMacroDefinition())
     239                0:       Diag(Tok, diag::pp_poisoning_existing_macro);
     240                 : 
     241                 :     // Finally, poison it!
     242                4:     II->setIsPoisoned();
     243                 :   }
     244                 : }
     245                 : 
     246                 : /// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
     247                 : /// that the whole directive has been parsed.
     248                2: void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
                        1: branch 1 taken
                        1: branch 2 taken
     249                2:   if (isInPrimaryFile()) {
     250                1:     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
     251                1:     return;
     252                 :   }
     253                 : 
     254                 :   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
     255                1:   PreprocessorLexer *TheLexer = getCurrentFileLexer();
     256                 : 
     257                 :   // Mark the file as a system header.
     258                1:   HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
     259                 : 
     260                 : 
     261                1:   PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
     262                1:   unsigned FilenameLen = strlen(PLoc.getFilename());
     263                 :   unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(),
     264                1:                                                          FilenameLen);
     265                 : 
     266                 :   // Emit a line marker.  This will change any source locations from this point
     267                 :   // forward to realize they are in a system header.
     268                 :   // Create a line note with this information.
     269                 :   SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID,
     270                1:                         false, false, true, false);
     271                 : 
     272                 :   // Notify the client, if desired, that we are in a new source file.
                        0: branch 0 not taken
                        1: branch 1 taken
     273                1:   if (Callbacks)
     274                 :     Callbacks->FileChanged(SysHeaderTok.getLocation(),
     275                0:                            PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
     276                 : }
     277                 : 
     278                 : /// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
     279                 : ///
     280                3: void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
     281                3:   Token FilenameTok;
     282                3:   CurPPLexer->LexIncludeFilename(FilenameTok);
     283                 : 
     284                 :   // If the token kind is EOM, the error has already been diagnosed.
                        0: branch 1 not taken
                        3: branch 2 taken
     285                3:   if (FilenameTok.is(tok::eom))
     286                0:     return;
     287                 : 
     288                 :   // Reserve a buffer to get the spelling.
     289                3:   llvm::SmallString<128> FilenameBuffer;
     290                3:   FilenameBuffer.resize(FilenameTok.getLength());
     291                 : 
     292                3:   const char *FilenameStart = &FilenameBuffer[0];
     293                3:   unsigned Len = getSpelling(FilenameTok, FilenameStart);
     294                3:   llvm::StringRef Filename(FilenameStart, Len);
     295                 :   bool isAngled =
     296                3:     GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
     297                 :   // If GetIncludeFilenameSpelling set the start ptr to null, there was an
     298                 :   // error.
                        0: branch 1 not taken
                        3: branch 2 taken
     299                3:   if (Filename.empty())
     300                3:     return;
     301                 : 
     302                 :   // Search include directories for this file.
     303                 :   const DirectoryLookup *CurDir;
     304                3:   const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
                        3: branch 0 taken
                        0: branch 1 not taken
     305                3:   if (File == 0) {
     306                3:     Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
     307                 :     return;
     308                 :   }
     309                 : 
     310                0:   const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
     311                 : 
     312                 :   // If this file is older than the file it depends on, emit a diagnostic.
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     313                0:   if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
     314                 :     // Lex tokens at the end of the message and include them in the message.
     315                0:     std::string Message;
     316                0:     Lex(DependencyTok);
                        0: branch 1 not taken
                        0: branch 2 not taken
     317                0:     while (DependencyTok.isNot(tok::eom)) {
     318                0:       Message += getSpelling(DependencyTok) + " ";
     319                0:       Lex(DependencyTok);
     320                 :     }
     321                 : 
     322                0:     Message.erase(Message.end()-1);
     323                0:     Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
                        0: branch 1 not taken
                        3: branch 2 taken
     324                3:   }
     325                 : }
     326                 : 
     327                 : /// HandlePragmaComment - Handle the microsoft #pragma comment extension.  The
     328                 : /// syntax is:
     329                 : ///   #pragma comment(linker, "foo")
     330                 : /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
     331                 : /// "foo" is a string, which is fully macro expanded, and permits string
     332                 : /// concatenation, embedded escape characters etc.  See MSDN for more details.
     333                8: void Preprocessor::HandlePragmaComment(Token &Tok) {
     334                8:   SourceLocation CommentLoc = Tok.getLocation();
     335                8:   Lex(Tok);
                        0: branch 1 not taken
                        8: branch 2 taken
     336                8:   if (Tok.isNot(tok::l_paren)) {
     337                0:     Diag(CommentLoc, diag::err_pragma_comment_malformed);
     338                0:     return;
     339                 :   }
     340                 : 
     341                 :   // Read the identifier.
     342                8:   Lex(Tok);
                        0: branch 1 not taken
                        8: branch 2 taken
     343                8:   if (Tok.isNot(tok::identifier)) {
     344                0:     Diag(CommentLoc, diag::err_pragma_comment_malformed);
     345                0:     return;
     346                 :   }
     347                 : 
     348                 :   // Verify that this is one of the 5 whitelisted options.
     349                 :   // FIXME: warn that 'exestr' is deprecated.
     350                8:   const IdentifierInfo *II = Tok.getIdentifierInfo();
                        5: branch 1 taken
                        3: branch 2 taken
                        5: branch 4 taken
                        0: branch 5 not taken
                        5: branch 7 taken
                        0: branch 8 not taken
                        3: branch 10 taken
                        2: branch 11 taken
                        1: branch 13 taken
                        2: branch 14 taken
                        1: branch 15 taken
                        7: branch 16 taken
     351                8:   if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") &&
     352                 :       !II->isStr("linker") && !II->isStr("user")) {
     353                1:     Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
     354                1:     return;
     355                 :   }
     356                 : 
     357                 :   // Read the optional string if present.
     358                7:   Lex(Tok);
     359                7:   std::string ArgumentString;
                        5: branch 1 taken
                        2: branch 2 taken
     360                7:   if (Tok.is(tok::comma)) {
     361                5:     Lex(Tok); // eat the comma.
     362                 : 
     363                 :     // We need at least one string.
                        1: branch 1 taken
                        4: branch 2 taken
     364                5:     if (Tok.isNot(tok::string_literal)) {
     365                1:       Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
     366                3:       return;
     367                 :     }
     368                 : 
     369                 :     // String concatenation allows multiple strings, which can even come from
     370                 :     // macro expansion.
     371                 :     // "foo " "bar" "Baz"
     372                4:     llvm::SmallVector<Token, 4> StrToks;
                        8: branch 1 taken
                        4: branch 2 taken
     373               16:     while (Tok.is(tok::string_literal)) {
     374                8:       StrToks.push_back(Tok);
     375                8:       Lex(Tok);
     376                 :     }
     377                 : 
     378                 :     // Concatenate and parse the strings.
     379                4:     StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
                        0: branch 0 not taken
                        4: branch 1 taken
     380                4:     assert(!Literal.AnyWide && "Didn't allow wide strings in");
                        0: branch 0 not taken
                        4: branch 1 taken
     381                4:     if (Literal.hadError)
     382                 :       return;
                        0: branch 0 not taken
                        4: branch 1 taken
     383                4:     if (Literal.Pascal) {
     384                0:       Diag(StrToks[0].getLocation(), diag::err_pragma_comment_malformed);
     385                 :       return;
     386                 :     }
     387                 : 
     388                 :     ArgumentString = std::string(Literal.GetString(),
                        4: branch 9 taken
                        0: branch 10 not taken
                        4: branch 12 taken
                        0: branch 13 not taken
     389                4:                                  Literal.GetString()+Literal.GetStringLength());
     390                 :   }
     391                 : 
     392                 :   // FIXME: If the kind is "compiler" warn if the string is present (it is
     393                 :   // ignored).
     394                 :   // FIXME: 'lib' requires a comment string.
     395                 :   // FIXME: 'linker' requires a comment string, and has a specific list of
     396                 :   // things that are allowable.
     397                 : 
                        1: branch 1 taken
                        5: branch 2 taken
     398                6:   if (Tok.isNot(tok::r_paren)) {
     399                1:     Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
     400                 :     return;
     401                 :   }
     402                5:   Lex(Tok);  // eat the r_paren.
     403                 : 
                        1: branch 1 taken
                        4: branch 2 taken
     404                5:   if (Tok.isNot(tok::eom)) {
     405                1:     Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
     406                 :     return;
     407                 :   }
     408                 : 
     409                 :   // If the pragma is lexically sound, notify any interested PPCallbacks.
                        0: branch 0 not taken
                        4: branch 1 taken
     410                4:   if (Callbacks)
                        4: branch 2 taken
                        3: branch 3 taken
     411                0:     Callbacks->PragmaComment(CommentLoc, II, ArgumentString);
     412                 : }
     413                 : 
     414                 : 
     415                 : 
     416                 : 
     417                 : /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
     418                 : /// If 'Namespace' is non-null, then it is a token required to exist on the
     419                 : /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
     420                 : void Preprocessor::AddPragmaHandler(const char *Namespace,
     421            42637:                                     PragmaHandler *Handler) {
     422            42637:   PragmaNamespace *InsertNS = PragmaHandlers;
     423                 : 
     424                 :   // If this is specified to be in a namespace, step down into it.
                    30596: branch 0 taken
                    12041: branch 1 taken
     425            42637:   if (Namespace) {
     426            30596:     IdentifierInfo *NSID = getIdentifierInfo(Namespace);
     427                 : 
     428                 :     // If there is already a pragma handler with the name of this namespace,
     429                 :     // we either have an error (directive with the same name as a namespace) or
     430                 :     // we already have the namespace to insert into.
                    22997: branch 1 taken
                     7599: branch 2 taken
     431            30596:     if (PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID)) {
     432            22997:       InsertNS = Existing->getIfNamespace();
     433                 :       assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
                        0: branch 0 not taken
                    22997: branch 1 taken
     434            22997:              " handler with the same name!");
     435                 :     } else {
     436                 :       // Otherwise, this namespace doesn't exist yet, create and insert the
     437                 :       // handler for it.
     438             7599:       InsertNS = new PragmaNamespace(NSID);
     439             7599:       PragmaHandlers->AddPragma(InsertNS);
     440                 :     }
     441                 :   }
     442                 : 
     443                 :   // Check to make sure we don't already have a pragma for this identifier.
     444                 :   assert(!InsertNS->FindHandler(Handler->getName()) &&
                    42637: branch 2 taken
                        0: branch 3 not taken
     445            42637:          "Pragma handler already exists for this identifier!");
     446            42637:   InsertNS->AddPragma(Handler);
     447            42637: }
     448                 : 
     449                 : /// RemovePragmaHandler - Remove the specific pragma handler from the
     450                 : /// preprocessor. If \arg Namespace is non-null, then it should be the
     451                 : /// namespace that \arg Handler was added to. It is an error to remove
     452                 : /// a handler that has not been registered.
     453                 : void Preprocessor::RemovePragmaHandler(const char *Namespace,
     454             6753:                                        PragmaHandler *Handler) {
     455             6753:   PragmaNamespace *NS = PragmaHandlers;
     456                 : 
     457                 :   // If this is specified to be in a namespace, step down into it.
                        0: branch 0 not taken
                     6753: branch 1 taken
     458             6753:   if (Namespace) {
     459                0:     IdentifierInfo *NSID = getIdentifierInfo(Namespace);
     460                0:     PragmaHandler *Existing = PragmaHandlers->FindHandler(NSID);
                        0: branch 0 not taken
                        0: branch 1 not taken
     461                0:     assert(Existing && "Namespace containing handler does not exist!");
     462                 : 
     463                0:     NS = Existing->getIfNamespace();
                        0: branch 0 not taken
                        0: branch 1 not taken
     464                0:     assert(NS && "Invalid namespace, registered as a regular pragma handler!");
     465                 :   }
     466                 : 
     467             6753:   NS->RemovePragmaHandler(Handler);
     468                 : 
     469                 :   // If this is a non-default namespace and it is now empty, remove
     470                 :   // it.
                        0: branch 0 not taken
                     6753: branch 1 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                     6753: branch 6 taken
     471             6753:   if (NS != PragmaHandlers && NS->IsEmpty())
     472                0:     PragmaHandlers->RemovePragmaHandler(NS);
     473             6753: }
     474                 : 
     475                 : namespace {
     476                 : /// PragmaOnceHandler - "#pragma once" marks the file as atomically included.
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     477             2530: struct PragmaOnceHandler : public PragmaHandler {
     478             2533:   PragmaOnceHandler(const IdentifierInfo *OnceID) : PragmaHandler(OnceID) {}
     479                0:   virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) {
     480                0:     PP.CheckEndOfDirective("pragma once");
     481                0:     PP.HandlePragmaOnce(OnceTok);
     482                0:   }
     483                 : };
     484                 : 
     485                 : /// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the
     486                 : /// rest of the line is not lexed.
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     487             2530: struct PragmaMarkHandler : public PragmaHandler {
     488             2533:   PragmaMarkHandler(const IdentifierInfo *MarkID) : PragmaHandler(MarkID) {}
     489                5:   virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) {
     490                5:     PP.HandlePragmaMark();
     491                5:   }
     492                 : };
     493                 : 
     494                 : /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable.
                     5060: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     495             5060: struct PragmaPoisonHandler : public PragmaHandler {
     496             5066:   PragmaPoisonHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     497                5:   virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) {
     498                5:     PP.HandlePragmaPoison(PoisonTok);
     499                5:   }
     500                 : };
     501                 : 
     502                 : /// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file
     503                 : /// as a system header, which silences warnings in it.
                     5060: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     504             5060: struct PragmaSystemHeaderHandler : public PragmaHandler {
     505             5066:   PragmaSystemHeaderHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     506                2:   virtual void HandlePragma(Preprocessor &PP, Token &SHToken) {
     507                2:     PP.HandlePragmaSystemHeader(SHToken);
     508                2:     PP.CheckEndOfDirective("pragma");
     509                2:   }
     510                 : };
                     5060: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     511             5060: struct PragmaDependencyHandler : public PragmaHandler {
     512             5066:   PragmaDependencyHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     513                3:   virtual void HandlePragma(Preprocessor &PP, Token &DepToken) {
     514                3:     PP.HandlePragmaDependency(DepToken);
     515                3:   }
     516                 : };
     517                 : 
     518                 : /// PragmaDiagnosticHandler - e.g. '#pragma GCC diagnostic ignored "-Wformat"'
     519                 : /// Since clang's diagnostic supports extended functionality beyond GCC's
     520                 : /// the constructor takes a clangMode flag to tell it whether or not to allow
     521                 : /// clang's extended functionality, or whether to reject it.
                     5060: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     522             5060: struct PragmaDiagnosticHandler : public PragmaHandler {
     523                 : private:
     524                 :   const bool ClangMode;
     525                 : public:
     526                 :   PragmaDiagnosticHandler(const IdentifierInfo *ID,
     527             5066:                           const bool clangMode) : PragmaHandler(ID),
     528             5066:                                                   ClangMode(clangMode) {}
     529               19:   virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) {
     530               19:     Token Tok;
     531               19:     PP.LexUnexpandedToken(Tok);
                        0: branch 1 not taken
                       19: branch 2 taken
     532               19:     if (Tok.isNot(tok::identifier)) {
     533                 :       unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
                        0: branch 0 not taken
                        0: branch 1 not taken
     534                0:                                  : diag::warn_pragma_diagnostic_gcc_invalid;
     535                0:       PP.Diag(Tok, Diag);
     536                0:       return;
     537                 :     }
     538               19:     IdentifierInfo *II = Tok.getIdentifierInfo();
     539                 : 
     540                 :     diag::Mapping Map;
                        2: branch 1 taken
                       17: branch 2 taken
     541               19:     if (II->isStr("warning"))
     542                2:       Map = diag::MAP_WARNING;
                        6: branch 1 taken
                       11: branch 2 taken
     543               17:     else if (II->isStr("error"))
     544                6:       Map = diag::MAP_ERROR;
                        5: branch 1 taken
                        6: branch 2 taken
     545               11:     else if (II->isStr("ignored"))
     546                5:       Map = diag::MAP_IGNORE;
                        0: branch 1 not taken
                        6: branch 2 taken
     547                6:     else if (II->isStr("fatal"))
     548                0:       Map = diag::MAP_FATAL;
                        5: branch 0 taken
                        1: branch 1 taken
     549                6:     else if (ClangMode) {
                        3: branch 1 taken
                        2: branch 2 taken
     550                5:       if (II->isStr("pop")) {
                        2: branch 2 taken
                        1: branch 3 taken
     551                3:         if (!PP.getDiagnostics().popMappings())
     552                2:           PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_cannot_ppp);
     553                3:         return;
     554                 :       }
     555                 : 
                        1: branch 1 taken
                        1: branch 2 taken
     556                2:       if (II->isStr("push")) {
     557                1:         PP.getDiagnostics().pushMappings();
     558                1:         return;
     559                 :       }
     560                 : 
     561                1:       PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_invalid);
     562                1:       return;
     563                 :     } else {
     564                1:       PP.Diag(Tok, diag::warn_pragma_diagnostic_gcc_invalid);
     565                1:       return;
     566                 :     }
     567                 : 
     568               13:     PP.LexUnexpandedToken(Tok);
     569                 : 
     570                 :     // We need at least one string.
                        1: branch 1 taken
                       12: branch 2 taken
     571               13:     if (Tok.isNot(tok::string_literal)) {
     572                1:       PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
     573                1:       return;
     574                 :     }
     575                 : 
     576                 :     // String concatenation allows multiple strings, which can even come from
     577                 :     // macro expansion.
     578                 :     // "foo " "bar" "Baz"
     579               12:     llvm::SmallVector<Token, 4> StrToks;
                       13: branch 1 taken
                       12: branch 2 taken
     580               37:     while (Tok.is(tok::string_literal)) {
     581               13:       StrToks.push_back(Tok);
     582               13:       PP.LexUnexpandedToken(Tok);
     583                 :     }
     584                 : 
                        1: branch 1 taken
                       11: branch 2 taken
     585               12:     if (Tok.isNot(tok::eom)) {
     586                1:       PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
     587                2:       return;
     588                 :     }
     589                 : 
     590                 :     // Concatenate and parse the strings.
     591               11:     StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP);
                        0: branch 0 not taken
                       11: branch 1 taken
     592               11:     assert(!Literal.AnyWide && "Didn't allow wide strings in");
                        0: branch 0 not taken
                       11: branch 1 taken
     593               11:     if (Literal.hadError)
     594                 :       return;
                        0: branch 0 not taken
                       11: branch 1 taken
     595               11:     if (Literal.Pascal) {
     596                 :       unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
                        0: branch 0 not taken
                        0: branch 1 not taken
     597                0:                                  : diag::warn_pragma_diagnostic_gcc_invalid;
     598                0:       PP.Diag(Tok, Diag);
     599                 :       return;
     600                 :     }
     601                 : 
     602                 :     std::string WarningName(Literal.GetString(),
     603               11:                             Literal.GetString()+Literal.GetStringLength());
     604                 : 
                       11: branch 1 taken
                        0: branch 2 not taken
                       10: branch 4 taken
                        1: branch 5 taken
                        0: branch 7 not taken
                       10: branch 8 taken
                        1: branch 9 taken
                       10: branch 10 taken
     605               11:     if (WarningName.size() < 3 || WarningName[0] != '-' ||
     606                 :         WarningName[1] != 'W') {
     607                 :       PP.Diag(StrToks[0].getLocation(),
     608                1:               diag::warn_pragma_diagnostic_invalid_option);
     609                 :       return;
     610                 :     }
     611                 : 
                        1: branch 3 taken
                        9: branch 4 taken
     612               10:     if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2,
     613                 :                                                       Map))
     614                 :       PP.Diag(StrToks[0].getLocation(),
                       10: branch 7 taken
                        1: branch 8 taken
                       10: branch 10 taken
                        1: branch 11 taken
                       10: branch 13 taken
                        2: branch 14 taken
     615                1:               diag::warn_pragma_diagnostic_unknown_warning) << WarningName;
     616                 :   }
     617                 : };
     618                 : 
     619                 : /// PragmaCommentHandler - "#pragma comment ...".
                       22: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     620               22: struct PragmaCommentHandler : public PragmaHandler {
     621               22:   PragmaCommentHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     622                8:   virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) {
     623                8:     PP.HandlePragmaComment(CommentTok);
     624                8:   }
     625                 : };
     626                 : 
     627                 : // Pragma STDC implementations.
     628                 : 
     629                 : enum STDCSetting {
     630                 :   STDC_ON, STDC_OFF, STDC_DEFAULT, STDC_INVALID
     631                 : };
     632                 : 
     633               30: static STDCSetting LexOnOffSwitch(Preprocessor &PP) {
     634               30:   Token Tok;
     635               30:   PP.LexUnexpandedToken(Tok);
     636                 : 
                        4: branch 1 taken
                       26: branch 2 taken
     637               30:   if (Tok.isNot(tok::identifier)) {
     638                4:     PP.Diag(Tok, diag::ext_stdc_pragma_syntax);
     639                4:     return STDC_INVALID;
     640                 :   }
     641               26:   IdentifierInfo *II = Tok.getIdentifierInfo();
     642                 :   STDCSetting Result;
                        8: branch 1 taken
                       18: branch 2 taken
     643               26:   if (II->isStr("ON"))
     644                8:     Result = STDC_ON;
                        6: branch 1 taken
                       12: branch 2 taken
     645               18:   else if (II->isStr("OFF"))
     646                6:     Result = STDC_OFF;
                        6: branch 1 taken
                        6: branch 2 taken
     647               12:   else if (II->isStr("DEFAULT"))
     648                6:     Result = STDC_DEFAULT;
     649                 :   else {
     650                6:     PP.Diag(Tok, diag::ext_stdc_pragma_syntax);
     651                6:     return STDC_INVALID;
     652                 :   }
     653                 : 
     654                 :   // Verify that this is followed by EOM.
     655               20:   PP.LexUnexpandedToken(Tok);
                        2: branch 1 taken
                       18: branch 2 taken
     656               20:   if (Tok.isNot(tok::eom))
     657                2:     PP.Diag(Tok, diag::ext_stdc_pragma_syntax_eom);
     658               20:   return Result;
     659                 : }
     660                 : 
     661                 : /// PragmaSTDC_FP_CONTRACTHandler - "#pragma STDC FP_CONTRACT ...".
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     662             2530: struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler {
     663             2533:   PragmaSTDC_FP_CONTRACTHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     664                8:   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
     665                 :     // We just ignore the setting of FP_CONTRACT. Since we don't do contractions
     666                 :     // at all, our default is OFF and setting it to ON is an optimization hint
     667                 :     // we can safely ignore.  When we support -ffma or something, we would need
     668                 :     // to diagnose that we are ignoring FMA.
     669                8:     LexOnOffSwitch(PP);
     670                8:   }
     671                 : };
     672                 : 
     673                 : /// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...".
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     674             2530: struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
     675             2533:   PragmaSTDC_FENV_ACCESSHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
     676                8:   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
                        2: branch 1 taken
                        6: branch 2 taken
     677                8:     if (LexOnOffSwitch(PP) == STDC_ON)
     678                2:       PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
     679                8:   }
     680                 : };
     681                 : 
     682                 : /// PragmaSTDC_CX_LIMITED_RANGEHandler - "#pragma STDC CX_LIMITED_RANGE ...".
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     683             2530: struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
     684             2533:   PragmaSTDC_CX_LIMITED_RANGEHandler(const IdentifierInfo *ID)
     685             2533:     : PragmaHandler(ID) {}
     686               14:   virtual void HandlePragma(Preprocessor &PP, Token &Tok) {
     687               14:     LexOnOffSwitch(PP);
     688               14:   }
     689                 : };
     690                 : 
     691                 : /// PragmaSTDC_UnknownHandler - "#pragma STDC ...".
                     2530: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     692             2530: struct PragmaSTDC_UnknownHandler : public PragmaHandler {
     693             2533:   PragmaSTDC_UnknownHandler() : PragmaHandler(0) {}
     694                4:   virtual void HandlePragma(Preprocessor &PP, Token &UnknownTok) {
     695                 :     // C99 6.10.6p2, unknown forms are not allowed.
     696                4:     PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
     697                4:   }
     698                 : };
     699                 : 
     700                 : }  // end anonymous namespace
     701                 : 
     702                 : 
     703                 : /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
     704                 : /// #pragma GCC poison/system_header/dependency and #pragma once.
     705             2533: void Preprocessor::RegisterBuiltinPragmas() {
     706             2533:   AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once")));
     707             2533:   AddPragmaHandler(0, new PragmaMarkHandler(getIdentifierInfo("mark")));
     708                 : 
     709                 :   // #pragma GCC ...
     710             2533:   AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
     711                 :   AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
     712             2533:                                           getIdentifierInfo("system_header")));
     713                 :   AddPragmaHandler("GCC", new PragmaDependencyHandler(
     714             2533:                                           getIdentifierInfo("dependency")));
     715                 :   AddPragmaHandler("GCC", new PragmaDiagnosticHandler(
     716                 :                                               getIdentifierInfo("diagnostic"),
     717             2533:                                               false));
     718                 :   // #pragma clang ...
     719                 :   AddPragmaHandler("clang", new PragmaPoisonHandler(
     720             2533:                                           getIdentifierInfo("poison")));
     721                 :   AddPragmaHandler("clang", new PragmaSystemHeaderHandler(
     722             2533:                                           getIdentifierInfo("system_header")));
     723                 :   AddPragmaHandler("clang", new PragmaDependencyHandler(
     724             2533:                                           getIdentifierInfo("dependency")));
     725                 :   AddPragmaHandler("clang", new PragmaDiagnosticHandler(
     726                 :                                           getIdentifierInfo("diagnostic"),
     727             2533:                                           true));
     728                 : 
     729                 :   AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler(
     730             2533:                                              getIdentifierInfo("FP_CONTRACT")));
     731                 :   AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler(
     732             2533:                                              getIdentifierInfo("FENV_ACCESS")));
     733                 :   AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler(
     734             2533:                                         getIdentifierInfo("CX_LIMITED_RANGE")));
     735             2533:   AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
     736                 : 
     737                 :   // MS extensions.
                       22: branch 0 taken
                     2511: branch 1 taken
     738             2533:   if (Features.Microsoft)
     739               22:     AddPragmaHandler(0, new PragmaCommentHandler(getIdentifierInfo("comment")));
     740             2533: }

Generated: 2010-02-10 01:31 by zcov