[cfe-commits] r38606 - in /cfe/cfe/trunk: Lex/Preprocessor.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Lex/Preprocessor.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:23:08 PDT 2007
Author: sabre
Date: Wed Jul 11 11:23:08 2007
New Revision: 38606
URL: http://llvm.org/viewvc/llvm-project?rev=38606&view=rev
Log:
Implement the _Pragma-style of pragma handling, implementing
test/Preprocessor/_Pragma-poison.c.
This unifies the MacroStack and IncludeStack together into IncludeMacroStack.
Modified:
cfe/cfe/trunk/Lex/Preprocessor.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/cfe/trunk/include/clang/Lex/Preprocessor.h
Modified: cfe/cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Preprocessor.cpp?rev=38606&r1=38605&r2=38606&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:23:08 2007
@@ -31,8 +31,6 @@
//
// TODO: Implement the include guard optimization.
//
-// Predefined Macros: _Pragma, ...
-//
//===----------------------------------------------------------------------===//
#include "clang/Lex/Preprocessor.h"
@@ -59,7 +57,7 @@
NumDirectives = NumIncluded = NumDefined = NumUndefined = NumPragma = 0;
NumIf = NumElse = NumEndif = 0;
NumEnteredSourceFiles = NumMacroExpanded = NumFastMacroExpanded = 0;
- MaxIncludeStackDepth = MaxMacroStackDepth = 0;
+ MaxIncludeStackDepth = 0;
NumSkipped = 0;
// Macro expansion is enabled.
@@ -81,9 +79,10 @@
// Free any active lexers.
delete CurLexer;
- while (!IncludeStack.empty()) {
- delete IncludeStack.back().TheLexer;
- IncludeStack.pop_back();
+ while (!IncludeMacroStack.empty()) {
+ delete IncludeMacroStack.back().TheLexer;
+ delete IncludeMacroStack.back().TheMacroExpander;
+ IncludeMacroStack.pop_back();
}
// Release pragma information.
@@ -206,8 +205,6 @@
std::cerr << NumMacroExpanded << " macros expanded, "
<< NumFastMacroExpanded << " on the fast path.\n";
- if (MaxMacroStackDepth > 1)
- std::cerr << " " << MaxMacroStackDepth << " max macroexpand stack depth\n";
}
//===----------------------------------------------------------------------===//
@@ -356,22 +353,30 @@
/// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID,
const DirectoryLookup *CurDir) {
+ assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles;
- // Add the current lexer to the include stack.
- if (CurLexer) {
- IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
- } else {
- assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
- }
+ if (MaxIncludeStackDepth < IncludeMacroStack.size())
+ MaxIncludeStackDepth = IncludeMacroStack.size();
- if (MaxIncludeStackDepth < IncludeStack.size())
- MaxIncludeStackDepth = IncludeStack.size();
-
const SourceBuffer *Buffer = SourceMgr.getBuffer(FileID);
+ Lexer *TheLexer = new Lexer(Buffer, FileID, *this);
+ EnterSourceFileWithLexer(TheLexer, CurDir);
+}
+
+/// EnterSourceFile - Add a source file to the top of the include stack and
+/// start lexing tokens from it instead of the current buffer.
+void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
+ const DirectoryLookup *CurDir) {
+
+ // Add the current lexer to the include stack.
+ if (CurLexer || CurMacroExpander)
+ IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
+ CurMacroExpander));
- CurLexer = new Lexer(Buffer, FileID, *this);
+ CurLexer = TheLexer;
CurDirLookup = CurDir;
+ CurMacroExpander = 0;
// Notify the client, if desired, that we are in a new source file.
if (FileChangeHandler) {
@@ -387,21 +392,17 @@
}
}
+
+
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer.
void Preprocessor::EnterMacro(LexerToken &Tok) {
IdentifierTokenInfo *Identifier = Tok.getIdentifierInfo();
MacroInfo &MI = *Identifier->getMacroInfo();
- if (CurLexer) {
- IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
- CurLexer = 0;
- CurDirLookup = 0;
- } else if (CurMacroExpander) {
- MacroStack.push_back(CurMacroExpander);
- }
-
- if (MaxMacroStackDepth < MacroStack.size())
- MaxMacroStackDepth = MacroStack.size();
+ IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
+ CurMacroExpander));
+ CurLexer = 0;
+ CurDirLookup = 0;
// TODO: Figure out arguments.
@@ -432,18 +433,18 @@
/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void Preprocessor::RegisterBuiltinMacros() {
- // FIXME: implement them all, including _Pragma.
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
Ident__FILE__ = RegisterBuiltinMacro("__FILE__");
Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
+ Ident_Pragma = RegisterBuiltinMacro("_Pragma");
// GCC Extensions.
Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__");
- // _Pragma
+ // FIXME: implement them all:
//Pseudo #defines.
// __STDC__ 1 if !stdc_0_in_system_headers and "std"
// __STDC_VERSION__
@@ -457,12 +458,14 @@
void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
MacroInfo *MI) {
++NumMacroExpanded;
- // If we started lexing a macro, enter the macro expansion body.
- // FIXME: Read/Validate the argument list here!
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
if (MI->isBuiltinMacro())
- return ExpandBuiltinMacro(Identifier, MI);
+ return ExpandBuiltinMacro(Identifier);
+
+ // If we started lexing a macro, enter the macro expansion body.
+ // FIXME: Read/Validate the argument list here!
+
// If this macro expands to no tokens, don't bother to push it onto the
// expansion stack, only to take it right back off.
@@ -553,13 +556,19 @@
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
-void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
+void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok) {
// Figure out which token this is.
IdentifierTokenInfo *ITI = Tok.getIdentifierInfo();
assert(ITI && "Can't be a macro without id info!");
- char TmpBuffer[100];
+ // If this is an _Pragma directive, expand it, invoke the pragma handler, then
+ // lex the token after it.
+ if (ITI == Ident_Pragma)
+ return Handle_Pragma(Tok);
+ char TmpBuffer[100];
+
+ // Set up the return result.
Tok.SetIdentifierInfo(0);
Tok.ClearFlag(LexerToken::NeedsCleaning);
@@ -621,9 +630,7 @@
// Get the file that we are lexing out of. If we're currently lexing from
// a macro, dig into the include stack.
const FileEntry *CurFile = 0;
- Lexer *TheLexer = CurLexer;
- if (TheLexer == 0 && !IncludeStack.empty())
- TheLexer = IncludeStack.back().TheLexer;
+ Lexer *TheLexer = getCurrentLexer();
if (TheLexer)
CurFile = SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
@@ -703,15 +710,16 @@
// If this is a #include'd file, pop it off the include stack and continue
// lexing the #includer file.
- if (!IncludeStack.empty()) {
+ if (!IncludeMacroStack.empty()) {
// We're done with the #included file.
delete CurLexer;
- CurLexer = IncludeStack.back().TheLexer;
- CurDirLookup = IncludeStack.back().TheDirLookup;
- IncludeStack.pop_back();
+ CurLexer = IncludeMacroStack.back().TheLexer;
+ CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ CurMacroExpander = IncludeMacroStack.back().TheMacroExpander;
+ IncludeMacroStack.pop_back();
// Notify the client, if desired, that we are in a new source file.
- if (FileChangeHandler && !isEndOfMacro) {
+ if (FileChangeHandler && !isEndOfMacro && CurLexer) {
DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir;
// Get the file entry for the current file.
@@ -746,16 +754,9 @@
CurMacroExpander->getMacro().EnableMacro();
delete CurMacroExpander;
- if (!MacroStack.empty()) {
- // In a nested macro invocation, continue lexing from the macro.
- CurMacroExpander = MacroStack.back();
- MacroStack.pop_back();
- return Lex(Result);
- } else {
- CurMacroExpander = 0;
- // Handle this like a #include file being popped off the stack.
- return HandleEndOfFile(Result, true);
- }
+ // Handle this like a #include file being popped off the stack.
+ CurMacroExpander = 0;
+ return HandleEndOfFile(Result, true);
}
@@ -831,7 +832,7 @@
bool FoundNonSkipPortion,
bool FoundElse) {
++NumSkipped;
- assert(MacroStack.empty() && CurMacroExpander == 0 && CurLexer &&
+ assert(CurMacroExpander == 0 && CurLexer &&
"Lexing a macro, not a file?");
CurLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
@@ -1059,7 +1060,7 @@
if (Directive[0] == 'i' && !strcmp(Directive, "import"))
return HandleImportDirective(Result);
if (Directive[0] == 'p' && !strcmp(Directive, "pragma"))
- return HandlePragmaDirective(Result);
+ return HandlePragmaDirective();
if (Directive[0] == 'a' && !strcmp(Directive, "assert"))
isExtension = true; // FIXME: implement #assert
break;
@@ -1132,7 +1133,7 @@
CheckEndOfDirective("#include");
// Check that we don't have infinite #include recursion.
- if (IncludeStack.size() == MaxAllowedIncludeStackDepth-1)
+ if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1)
return Diag(FilenameTok, diag::err_pp_include_too_deep);
// Find out whether the filename is <x> or "x".
@@ -1187,7 +1188,7 @@
// the current found directory. If we can't do this, issue a
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
- if (IncludeStack.empty()) {
+ if (isInPrimaryFile()) {
Lookup = 0;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
} else if (Lookup == 0) {
@@ -1425,10 +1426,9 @@
// Preprocessor Pragma Directive Handling.
//===----------------------------------------------------------------------===//
-/// HandlePragmaDirective - The "#pragma" directive has been parsed with
-/// PragmaTok containing the "pragma" identifier. Lex the rest of the pragma,
-/// passing it to the registered pragma handlers.
-void Preprocessor::HandlePragmaDirective(LexerToken &PragmaTok) {
+/// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the
+/// rest of the pragma, passing it to the registered pragma handlers.
+void Preprocessor::HandlePragmaDirective() {
++NumPragma;
// Invoke the first level of pragma handlers which reads the namespace id.
@@ -1440,10 +1440,89 @@
DiscardUntilEndOfDirective();
}
+/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+/// return the first token after the directive. The _Pragma token has just
+/// been read into 'Tok'.
+void Preprocessor::Handle_Pragma(LexerToken &Tok) {
+ // Remember the pragma token location.
+ SourceLocation PragmaLoc = Tok.getLocation();
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.getKind() != tok::l_paren)
+ return Diag(PragmaLoc, diag::err__Pragma_malformed);
+
+ // Read the '"..."'.
+ Lex(Tok);
+ if (Tok.getKind() != tok::string_literal)
+ return Diag(PragmaLoc, diag::err__Pragma_malformed);
+
+ // Remember the string.
+ std::string StrVal = getSpelling(Tok);
+ SourceLocation StrLoc = Tok.getLocation();
+
+ // Read the ')'.
+ Lex(Tok);
+ if (Tok.getKind() != tok::r_paren)
+ return Diag(PragmaLoc, diag::err__Pragma_malformed);
+
+ // The _Pragma is lexically sound. Destringize according to C99 6.10.9.1.
+ if (StrVal[0] == 'L') // Remove L prefix.
+ StrVal.erase(StrVal.begin());
+ assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
+ "Invalid string token!");
+
+ // Remove the front quote, replacing it with a space, so that the pragma
+ // contents appear to have a space before them.
+ StrVal[0] = ' ';
+
+ // Replace the terminating quote with a \n\0.
+ StrVal[StrVal.size()-1] = '\n';
+ StrVal += '\0';
+
+ // Remove escaped quotes and escapes.
+ for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
+ if (StrVal[i] == '\\' &&
+ (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
+ // \\ -> '\' and \" -> '"'.
+ StrVal.erase(StrVal.begin()+i);
+ --e;
+ }
+ }
+
+ // Plop the string (including the trailing null) into a buffer where we can
+ // lex it.
+ SourceLocation TokLoc = ScratchBuf->getToken(&StrVal[0], StrVal.size());
+ const char *StrData = SourceMgr.getCharacterData(TokLoc);
+
+ // FIXME: Create appropriate mapping info for this FileID, so that we know the
+ // tokens are coming out of the input string (StrLoc).
+ unsigned FileID = TokLoc.getFileID();
+ assert(FileID && "Could not create FileID for predefines?");
+
+ // Make and enter a lexer object so that we lex and expand the tokens just
+ // like any others.
+ Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, *this,
+ StrData, StrData+StrVal.size()-1 /* no null */);
+ EnterSourceFileWithLexer(TL, 0);
+
+ // Ensure that the lexer thinks it is inside a directive, so that end \n will
+ // return an EOM token.
+ TL->ParsingPreprocessorDirective = true;
+
+ // With everything set up, lex this as a #pragma directive.
+ HandlePragmaDirective();
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
+
+
+
/// HandlePragmaOnce - Handle #pragma once. OnceTok is the 'once'.
///
void Preprocessor::HandlePragmaOnce(LexerToken &OnceTok) {
- if (IncludeStack.empty()) {
+ if (isInPrimaryFile()) {
Diag(OnceTok, diag::pp_pragma_once_in_main_file);
return;
}
@@ -1501,7 +1580,7 @@
/// HandlePragmaSystemHeader - Implement #pragma GCC system_header. We know
/// that the whole directive has been parsed.
void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) {
- if (IncludeStack.empty()) {
+ if (isInPrimaryFile()) {
Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
return;
}
@@ -1540,11 +1619,7 @@
if (File == 0)
return Diag(FilenameTok, diag::err_pp_file_not_found);
- Lexer *TheLexer = CurLexer;
- if (TheLexer == 0) {
- assert(!IncludeStack.empty() && "No current lexer?");
- TheLexer = IncludeStack.back().TheLexer;
- }
+ Lexer *TheLexer = getCurrentLexer();
const FileEntry *CurFile =
SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38606&r1=38605&r2=38606&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:08 2007
@@ -171,6 +171,8 @@
"can only poison identifier tokens")
DIAG(err_pp_used_poisoned_id, ERROR,
"attempt to use a poisoned identifier")
+DIAG(err__Pragma_malformed, ERROR,
+ "_Pragma takes a parenthesized string literal")
// Should be a sorry?
DIAG(err_pp_I_dash_not_supported, ERROR,
Modified: cfe/cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=38606&r1=38605&r2=38606&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:23:08 2007
@@ -98,6 +98,7 @@
IdentifierTokenInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
IdentifierTokenInfo *Ident__BASE_FILE__; // __BASE_FILE__
IdentifierTokenInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
+ IdentifierTokenInfo *Ident_Pragma; // _Pragma
SourceLocation DATELoc, TIMELoc;
public:
@@ -138,25 +139,23 @@
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
/// implement #include_next and find directory-specific properties.
const DirectoryLookup *CurDirLookup;
+
+ /// CurMacroExpander - This is the current macro we are expanding, if we are
+ /// expanding a macro. One of CurLexer and CurMacroExpander must be null.
+ MacroExpander *CurMacroExpander;
- /// IncludeStack - This keeps track of the stack of files currently #included,
- /// not counting CurLexer.
+ /// IncludeMacroStack - This keeps track of the stack of files currently
+ /// #included, and macros currently being expanded from, not counting
+ /// CurLexer/CurMacroExpander.
struct IncludeStackInfo {
Lexer *TheLexer;
const DirectoryLookup *TheDirLookup;
- IncludeStackInfo(Lexer *L, const DirectoryLookup *D)
- : TheLexer(L), TheDirLookup(D) {
+ MacroExpander *TheMacroExpander;
+ IncludeStackInfo(Lexer *L, const DirectoryLookup *D, MacroExpander *M)
+ : TheLexer(L), TheDirLookup(D), TheMacroExpander(M) {
}
};
- std::vector<IncludeStackInfo> IncludeStack;
-
- /// CurMacroExpander - This is the current macro we are expanding, if we are
- /// expanding a macro. One of CurLexer and CurMacroExpander must be null.
- MacroExpander *CurMacroExpander;
-
- /// MacroStack - This keeps track of the macros that are recursively being
- /// expanded.
- std::vector<MacroExpander*> MacroStack;
+ std::vector<IncludeStackInfo> IncludeMacroStack;
/// PreFileInfo - The preprocessor keeps track of this information for each
@@ -187,7 +186,7 @@
unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
unsigned NumIf, NumElse, NumEndif;
unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
- unsigned NumMacroExpanded, NumFastMacroExpanded, MaxMacroStackDepth;
+ unsigned NumMacroExpanded, NumFastMacroExpanded;
unsigned NumSkipped;
public:
Preprocessor(Diagnostic &diags, const LangOptions &opts, FileManager &FM,
@@ -211,6 +210,29 @@
return CurLexer == L;
}
+ /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+ /// #include.
+ ///
+ bool isInPrimaryFile() const {
+ /// If there are any stacked lexers, we're in a #include.
+ for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i)
+ if (IncludeMacroStack[i].TheLexer)
+ return false;
+ return true;
+ }
+
+ /// getCurrentLexer - Return the current lexer being lexed from. Note that
+ /// this ignores any potentially active macro expansions going on at the time.
+ Lexer *getCurrentLexer() const {
+ if (CurLexer) return CurLexer;
+
+ // Look for a stacked lexer.
+ for (unsigned i = IncludeMacroStack.size(); i != 0; --i)
+ if (IncludeMacroStack[i].TheLexer) // Ignore macro expansions.
+ return IncludeMacroStack[i].TheLexer;
+ return 0;
+ }
+
/// SetSearchPaths - Interface for setting the file search paths.
///
void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
@@ -423,7 +445,17 @@
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
- void ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI);
+ void ExpandBuiltinMacro(LexerToken &Tok);
+
+ /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+ /// return the first token after the directive. The _Pragma token has just
+ /// been read into 'Tok'.
+ void Handle_Pragma(LexerToken &Tok);
+
+
+ /// EnterSourceFile - Add a source file to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
//===--------------------------------------------------------------------===//
/// Handle*Directive - implement the various preprocessor directives. These
@@ -453,7 +485,7 @@
void HandleElifDirective(LexerToken &Tok);
// Pragmas.
- void HandlePragmaDirective(LexerToken &Result);
+ void HandlePragmaDirective();
public:
void HandlePragmaOnce(LexerToken &OnceTok);
void HandlePragmaPoison(LexerToken &PoisonTok);
More information about the cfe-commits
mailing list