Make a significant change to invert the control flow handling

predefined macros.  Previously, these were handled by the driver,
now they are handled by the preprocessor.

Some fallout of this:

1. Instead of preprocessing two buffers (the predefines, then the 
   main source file)  we now start preprocessing the main source 
   file and inject the predefines as a "psuedo #include" from the
   main source file.
2. #1 allows us to nuke the Lexer::IsMainFile flag and simplify
   Preprocessor::isInPrimaryFile.
3. The driver doesn't have to know about standard #defines, the
   preprocessor knows, which is nice for people wanting to define
   their own drivers.
4. This allows us to put normal tokens in the predefine buffer,
   for example a definition for __builtin_va_list that is 
   target-specific, and a typedef for id in objc.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42818 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2007-10-09 22:10:18 +00:00
Родитель b216c8861c
Коммит 53b0dabbe5
8 изменённых файлов: 197 добавлений и 162 удалений

Просмотреть файл

@ -91,7 +91,7 @@ static void FindExpectedDiags(Preprocessor &PP, unsigned MainFileID,
PP.SetCommentRetentionState(true, true);
// Enter the cave.
PP.EnterSourceFile(MainFileID, 0, true);
PP.EnterMainSourceFile(MainFileID);
// Turn off all warnings from relexing or preprocessing.
PP.getDiagnostics().setWarnOnExtensions(false);

Просмотреть файл

@ -534,7 +534,7 @@ void clang::DoPrintPreprocessedInput(unsigned MainFileID, Preprocessor &PP,
// After we have configured the preprocessor, enter the main file.
// Start parsing the specified input file.
PP.EnterSourceFile(MainFileID, 0, true);
PP.EnterMainSourceFile(MainFileID);
do {
PrevTok = Tok;

Просмотреть файл

@ -394,76 +394,56 @@ static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro,
Buf.push_back('\n');
}
static void InitializePredefinedMacros(Preprocessor &PP,
std::vector<char> &Buf) {
// FIXME: Implement magic like cpp_init_builtins for things like __STDC__
// and __DATE__ etc.
#if 0
/* __STDC__ has the value 1 under normal circumstances.
However, if (a) we are in a system header, (b) the option
stdc_0_in_system_headers is true (set by target config), and
(c) we are not in strictly conforming mode, then it has the
value 0. (b) and (c) are already checked in cpp_init_builtins. */
//case BT_STDC:
if (cpp_in_system_header (pfile))
number = 0;
else
number = 1;
break;
#endif
// These should all be defined in the preprocessor according to the
// current language configuration.
DefineBuiltinMacro(Buf, "__STDC__=1");
//DefineBuiltinMacro(Buf, "__ASSEMBLER__=1");
if (PP.getLangOptions().C99 && !PP.getLangOptions().CPlusPlus)
DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L");
else if (0) // STDC94 ?
DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L");
DefineBuiltinMacro(Buf, "__STDC_HOSTED__=1");
if (PP.getLangOptions().ObjC1)
DefineBuiltinMacro(Buf, "__OBJC__=1");
if (PP.getLangOptions().ObjC2)
DefineBuiltinMacro(Buf, "__OBJC2__=1");
// Get the target #defines.
PP.getTargetInfo().getTargetDefines(Buf);
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns the file ID for the
/// input file. If a failure happens, it returns 0.
///
static unsigned InitializePreprocessor(Preprocessor &PP,
const std::string &InFile,
SourceManager &SourceMgr,
HeaderSearch &HeaderInfo,
const LangOptions &LangInfo,
std::vector<char> &PredefineBuffer) {
// Compiler set macros.
DefineBuiltinMacro(Buf, "__APPLE_CC__=5250");
DefineBuiltinMacro(Buf, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=1030");
DefineBuiltinMacro(Buf, "__GNUC_MINOR__=0");
DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1");
DefineBuiltinMacro(Buf, "__GNUC__=4");
DefineBuiltinMacro(Buf, "__GXX_ABI_VERSION=1002");
DefineBuiltinMacro(Buf, "__VERSION__=\"4.0.1 (Apple Computer, Inc. "
"build 5250)\"");
// Build configuration options.
DefineBuiltinMacro(Buf, "__DYNAMIC__=1");
DefineBuiltinMacro(Buf, "__FINITE_MATH_ONLY__=0");
DefineBuiltinMacro(Buf, "__NO_INLINE__=1");
DefineBuiltinMacro(Buf, "__PIC__=1");
FileManager &FileMgr = HeaderInfo.getFileMgr();
if (PP.getLangOptions().CPlusPlus) {
DefineBuiltinMacro(Buf, "__DEPRECATED=1");
DefineBuiltinMacro(Buf, "__EXCEPTIONS=1");
DefineBuiltinMacro(Buf, "__GNUG__=4");
DefineBuiltinMacro(Buf, "__GXX_WEAK__=1");
DefineBuiltinMacro(Buf, "__cplusplus=1");
DefineBuiltinMacro(Buf, "__private_extern__=extern");
// Figure out where to get and map in the main file.
unsigned MainFileID = 0;
if (InFile != "-") {
const FileEntry *File = FileMgr.getFile(InFile);
if (File) MainFileID = SourceMgr.createFileID(File, SourceLocation());
if (MainFileID == 0) {
fprintf(stderr, "Error reading '%s'!\n",InFile.c_str());
return 0;
}
} else {
llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
if (SB) MainFileID = SourceMgr.createFileIDForMemBuffer(SB);
if (MainFileID == 0) {
fprintf(stderr, "Error reading standard input! Empty?\n");
return 0;
}
}
// FIXME: Should emit a #line directive here.
// Add macros from the command line.
// FIXME: Should traverse the #define/#undef lists in parallel.
for (unsigned i = 0, e = D_macros.size(); i != e; ++i)
DefineBuiltinMacro(Buf, D_macros[i].c_str());
DefineBuiltinMacro(PredefineBuffer, D_macros[i].c_str());
for (unsigned i = 0, e = U_macros.size(); i != e; ++i)
DefineBuiltinMacro(Buf, U_macros[i].c_str(), "#undef ");
DefineBuiltinMacro(PredefineBuffer, U_macros[i].c_str(), "#undef ");
// FIXME: Read any files specified by -imacros or -include.
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
// Once we've read this, we're done.
return MainFileID;
}
//===----------------------------------------------------------------------===//
// Preprocessor include path information.
@ -712,18 +692,13 @@ static void InitializeIncludePaths(HeaderSearch &Headers, FileManager &FM,
}
// Read any files specified by -imacros or -include.
static void ReadPrologFiles(Preprocessor &PP, std::vector<char> &Buf) {
// FIXME: IMPLEMENT
}
//===----------------------------------------------------------------------===//
// Basic Parser driver
//===----------------------------------------------------------------------===//
static void ParseFile(Preprocessor &PP, MinimalAction *PA, unsigned MainFileID){
Parser P(PP, *PA);
PP.EnterSourceFile(MainFileID, 0, true);
PP.EnterMainSourceFile(MainFileID);
// Parsing the specified input file.
P.ParseTranslationUnit();
@ -734,69 +709,6 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA, unsigned MainFileID){
// Main driver
//===----------------------------------------------------------------------===//
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns the file ID for the
/// input file. If a failure happens, it returns 0.
///
static unsigned InitializePreprocessor(Preprocessor &PP,
const std::string &InFile,
SourceManager &SourceMgr,
HeaderSearch &HeaderInfo,
const LangOptions &LangInfo,
std::vector<char> &PrologMacros) {
PrologMacros.reserve(4080);
FileManager &FileMgr = HeaderInfo.getFileMgr();
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
InitializePredefinedMacros(PP, PrologMacros);
// Read any files specified by -imacros or -include.
ReadPrologFiles(PP, PrologMacros);
// Figure out where to get and map in the main file.
unsigned MainFileID = 0;
if (InFile != "-") {
const FileEntry *File = FileMgr.getFile(InFile);
if (File) MainFileID = SourceMgr.createFileID(File, SourceLocation());
if (MainFileID == 0) {
fprintf(stderr, "Error reading '%s'!\n",InFile.c_str());
return 0;
}
} else {
llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
if (SB) MainFileID = SourceMgr.createFileIDForMemBuffer(SB);
if (MainFileID == 0) {
fprintf(stderr, "Error reading standard input! Empty?\n");
return 0;
}
}
// Now that we have emitted the predefined macros, #includes, etc into
// PrologMacros, preprocess it to populate the initial preprocessor state.
// Memory buffer must end with a null byte!
PrologMacros.push_back(0);
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBuffer(&PrologMacros.front(),&PrologMacros.back(),
"<predefines>");
assert(SB && "Cannot fail to create predefined source buffer");
unsigned FileID = SourceMgr.createFileIDForMemBuffer(SB);
assert(FileID && "Could not create FileID for predefines?");
// Start parsing the predefines.
PP.EnterSourceFile(FileID, 0);
// Lex the file, which will read all the macros.
Token Tok;
PP.Lex(Tok);
assert(Tok.is(tok::eof) && "Didn't read entire file!");
// Once we've read this, we're done.
return MainFileID;
}
/// ProcessInputFile - Process a single input file with the specified state.
///
static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
@ -816,7 +728,7 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
case DumpTokens: { // Token dump mode.
Token Tok;
// Start parsing the specified input file.
PP.EnterSourceFile(MainFileID, 0, true);
PP.EnterMainSourceFile(MainFileID);
do {
PP.Lex(Tok);
PP.DumpToken(Tok, true);
@ -828,7 +740,7 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
Token Tok;
// Start parsing the specified input file.
PP.EnterSourceFile(MainFileID, 0, true);
PP.EnterMainSourceFile(MainFileID);
do {
PP.Lex(Tok);
} while (Tok.isNot(tok::eof));
@ -982,10 +894,10 @@ int main(int argc, char **argv) {
Preprocessor PP(Diags, LangInfo, *Target, SourceMgr, HeaderInfo);
DiagClient->setPreprocessor(PP);
const std::string &InFile = InputFilenames[i];
std::vector<char> PrologMacros;
std::vector<char> PredefineBuffer;
unsigned MainFileID = InitializePreprocessor(PP, InFile, SourceMgr,
HeaderInfo, LangInfo,
PrologMacros);
PredefineBuffer);
if (!MainFileID) continue;

Просмотреть файл

@ -65,7 +65,6 @@ Lexer::Lexer(SourceLocation fileloc, Preprocessor &pp,
const llvm::MemoryBuffer *InputFile = SourceMgr.getBuffer(InputFileID);
Is_PragmaLexer = false;
IsMainFile = false;
InitCharacterInfo();
// BufferStart must always be InputFile->getBufferStart().

Просмотреть файл

@ -73,6 +73,8 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
// This gets unpoisoned where it is allowed.
(Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
Predefines = 0;
// Initialize the pragma handlers.
PragmaHandlers = new PragmaNamespace(0);
RegisterBuiltinPragmas();
@ -311,6 +313,127 @@ SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart,
}
//===----------------------------------------------------------------------===//
// Preprocessor Initialization Methods
//===----------------------------------------------------------------------===//
// Append a #define line to Buf for Macro. Macro should be of the form XXX,
// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
// "#define XXX Y z W". To get a #define with no value, use "XXX=".
static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro,
const char *Command = "#define ") {
Buf.insert(Buf.end(), Command, Command+strlen(Command));
if (const char *Equal = strchr(Macro, '=')) {
// Turn the = into ' '.
Buf.insert(Buf.end(), Macro, Equal);
Buf.push_back(' ');
Buf.insert(Buf.end(), Equal+1, Equal+strlen(Equal));
} else {
// Push "macroname 1".
Buf.insert(Buf.end(), Macro, Macro+strlen(Macro));
Buf.push_back(' ');
Buf.push_back('1');
}
Buf.push_back('\n');
}
static void InitializePredefinedMacros(Preprocessor &PP,
std::vector<char> &Buf) {
// FIXME: Implement magic like cpp_init_builtins for things like __STDC__
// and __DATE__ etc.
#if 0
/* __STDC__ has the value 1 under normal circumstances.
However, if (a) we are in a system header, (b) the option
stdc_0_in_system_headers is true (set by target config), and
(c) we are not in strictly conforming mode, then it has the
value 0. (b) and (c) are already checked in cpp_init_builtins. */
//case BT_STDC:
if (cpp_in_system_header (pfile))
number = 0;
else
number = 1;
break;
#endif
// These should all be defined in the preprocessor according to the
// current language configuration.
DefineBuiltinMacro(Buf, "__STDC__=1");
//DefineBuiltinMacro(Buf, "__ASSEMBLER__=1");
if (PP.getLangOptions().C99 && !PP.getLangOptions().CPlusPlus)
DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L");
else if (0) // STDC94 ?
DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L");
DefineBuiltinMacro(Buf, "__STDC_HOSTED__=1");
if (PP.getLangOptions().ObjC1)
DefineBuiltinMacro(Buf, "__OBJC__=1");
if (PP.getLangOptions().ObjC2)
DefineBuiltinMacro(Buf, "__OBJC2__=1");
// Get the target #defines.
PP.getTargetInfo().getTargetDefines(Buf);
// Compiler set macros.
DefineBuiltinMacro(Buf, "__APPLE_CC__=5250");
DefineBuiltinMacro(Buf, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=1030");
DefineBuiltinMacro(Buf, "__GNUC_MINOR__=0");
DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1");
DefineBuiltinMacro(Buf, "__GNUC__=4");
DefineBuiltinMacro(Buf, "__GXX_ABI_VERSION=1002");
DefineBuiltinMacro(Buf, "__VERSION__=\"4.0.1 (Apple Computer, Inc. "
"build 5250)\"");
// Build configuration options.
DefineBuiltinMacro(Buf, "__DYNAMIC__=1");
DefineBuiltinMacro(Buf, "__FINITE_MATH_ONLY__=0");
DefineBuiltinMacro(Buf, "__NO_INLINE__=1");
DefineBuiltinMacro(Buf, "__PIC__=1");
if (PP.getLangOptions().CPlusPlus) {
DefineBuiltinMacro(Buf, "__DEPRECATED=1");
DefineBuiltinMacro(Buf, "__EXCEPTIONS=1");
DefineBuiltinMacro(Buf, "__GNUG__=4");
DefineBuiltinMacro(Buf, "__GXX_WEAK__=1");
DefineBuiltinMacro(Buf, "__cplusplus=1");
DefineBuiltinMacro(Buf, "__private_extern__=extern");
}
// FIXME: Should emit a #line directive here.
}
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
/// which implicitly adds the builting defines etc.
void Preprocessor::EnterMainSourceFile(unsigned MainFileID) {
// Enter the main file source buffer.
EnterSourceFile(MainFileID, 0);
std::vector<char> PrologFile;
PrologFile.reserve(4080);
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
InitializePredefinedMacros(*this, PrologFile);
// Add on the predefines from the driver.
PrologFile.insert(PrologFile.end(), Predefines,Predefines+strlen(Predefines));
// Memory buffer must end with a null byte!
PrologFile.push_back(0);
// Now that we have emitted the predefined macros, #includes, etc into
// PrologFile, preprocess it to populate the initial preprocessor state.
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBufferCopy(&PrologFile.front(),&PrologFile.back(),
"<predefines>");
assert(SB && "Cannot fail to create predefined source buffer");
unsigned FileID = SourceMgr.createFileIDForMemBuffer(SB);
assert(FileID && "Could not create FileID for predefines?");
// Start parsing the predefines.
EnterSourceFile(FileID, 0);
}
//===----------------------------------------------------------------------===//
// Source File Location Methods.
@ -367,14 +490,17 @@ const FileEntry *Preprocessor::LookupFile(const char *FilenameStart,
/// #include.
bool Preprocessor::isInPrimaryFile() const {
if (CurLexer && !CurLexer->Is_PragmaLexer)
return CurLexer->isMainFile();
return IncludeMacroStack.empty();
// If there are any stacked lexers, we're in a #include.
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i)
assert(IncludeMacroStack[0].TheLexer &&
!IncludeMacroStack[0].TheLexer->Is_PragmaLexer &&
"Top level include stack isn't our primary lexer?");
for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i)
if (IncludeMacroStack[i].TheLexer &&
!IncludeMacroStack[i].TheLexer->Is_PragmaLexer)
return IncludeMacroStack[i].TheLexer->isMainFile();
return false;
return false;
return true;
}
/// getCurrentLexer - Return the current file lexer being lexed from. Note
@ -397,8 +523,7 @@ Lexer *Preprocessor::getCurrentFileLexer() const {
/// start lexing tokens from it instead of the current buffer. Return true
/// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID,
const DirectoryLookup *CurDir,
bool isMainFile) {
const DirectoryLookup *CurDir) {
assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles;
@ -406,7 +531,6 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
MaxIncludeStackDepth = IncludeMacroStack.size();
Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
if (isMainFile) TheLexer->setIsMainFile();
EnterSourceFileWithLexer(TheLexer, CurDir);
}

Просмотреть файл

@ -28,7 +28,7 @@ namespace {
public:
ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID)
: P(pp, *new Sema(pp, ctxt, LastInGroupList)) {
pp.EnterSourceFile(MainFileID, 0, true);
pp.EnterMainSourceFile(MainFileID);
// Initialize the parser.
P.Initialize();

Просмотреть файл

@ -39,7 +39,6 @@ class Lexer {
Preprocessor &PP; // Preprocessor object controlling lexing.
LangOptions Features; // Features enabled by this language (cache).
bool Is_PragmaLexer; // True if lexer for _Pragma handling.
bool IsMainFile; // True if top-level file.
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
@ -112,16 +111,6 @@ public:
/// from. Currently this is only used by _Pragma handling.
SourceLocation getFileLoc() const { return FileLoc; }
/// setIsMainFile - Mark this lexer as being the lexer for the top-level
/// source file.
void setIsMainFile() {
IsMainFile = true;
}
/// isMainFile - Return true if this is the top-level file.
///
bool isMainFile() const { return IsMainFile; }
/// Lex - Return the next token in the file. If this is the end of file, it
/// return the tok::eof token. Return true if an error occurred and
/// compilation should terminate, false if normal. This implicitly involves

Просмотреть файл

@ -129,6 +129,10 @@ class Preprocessor {
unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
unsigned NumSkipped;
/// Predefines - This pointer, if non-null, are the predefined macros that
/// preprocessor should use from the command line etc.
const char *Predefines;
/// MacroExpanderCache - Cache macro expanders to reduce malloc traffic.
enum { MacroExpanderCacheSize = 8 };
unsigned NumCachedMacroExpanders;
@ -163,10 +167,6 @@ public:
return CurLexer == L;
}
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.
bool isInPrimaryFile() const;
/// getCurrentLexer - Return the current file lexer being lexed from. Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
@ -189,6 +189,10 @@ public:
///
void setMacroInfo(IdentifierInfo *II, MacroInfo *MI);
void setPredefines(const char *P) {
Predefines = P;
}
/// getIdentifierInfo - Return information about the specified preprocessor
/// identifier token. The version of this method that takes two character
/// pointers is preferred unless the identifier is already available as a
@ -207,11 +211,15 @@ public:
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
void AddPragmaHandler(const char *Namespace, PragmaHandler *Handler);
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
/// which implicitly adds the builting defines etc.
void EnterMainSourceFile(unsigned CurFileID);
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. If isMainFile
/// is true, this is the main file for the translation unit.
void EnterSourceFile(unsigned CurFileID, const DirectoryLookup *Dir,
bool isMainFile = false);
void EnterSourceFile(unsigned CurFileID, const DirectoryLookup *Dir);
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer. Args specifies the
@ -358,7 +366,10 @@ public:
/// not, emit a diagnostic and consume up until the eom.
void CheckEndOfDirective(const char *Directive);
private:
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.
bool isInPrimaryFile() const;
/// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
/// current line until the tok::eom token is found.
void DiscardUntilEndOfDirective();