Re-arranged some internal functions for coming __has_include changes.

llvm-svn: 85589
This commit is contained in:
John Thompson 2009-10-30 13:49:06 +00:00
parent 305f9f8fed
commit b535352681
4 changed files with 114 additions and 86 deletions

View File

@ -194,7 +194,7 @@ def err_pp_expected_eol : Error<
"expected end of line in preprocessor expression">;
def err_pp_defined_requires_identifier : Error<
"operator 'defined' requires an identifier">;
def err_pp_missing_rparen : Error<"missing ')' after 'defined'">;
def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
def err_pp_colon_without_question : Error<"':' without preceding '?'">;
def err_pp_division_by_zero : Error<
"division by zero in preprocessor expression">;

View File

@ -244,7 +244,12 @@ public:
return CurPPLexer == L;
}
/// getCurrentLexer - Return the current file lexer being lexed from. Note
/// getCurrentLexer - Return the current lexer being lexed from. Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
/// getCurrentFileLexer - 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.
PreprocessorLexer *getCurrentFileLexer() const;
@ -622,6 +627,43 @@ public:
/// SourceLocation.
MacroInfo* AllocateMacroInfo(SourceLocation L);
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
/// checked and spelled filename, e.g. as an operand of #include. This returns
/// true if the input filename was in <>'s or false if it were in ""'s. The
/// caller is expected to provide a buffer that is large enough to hold the
/// spelling of the filename, but is also expected to handle the case when
/// this method decides to use a different buffer.
bool GetIncludeFilenameSpelling(SourceLocation Loc,
const char *&BufStart, const char *&BufEnd);
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir);
/// GetCurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
/// implement #include_next and find directory-specific properties.
const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.
bool isInPrimaryFile() const;
/// ConcatenateIncludeName - Handle cases where the #include name is expanded
/// from a macro as multiple tokens, which need to be glued together. This
/// occurs for code like:
/// #define FOO <a/b.h>
/// #include FOO
/// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
///
/// This code concatenates and consumes tokens up to the '>' token. It returns
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer);
private:
void PushIncludeMacroStack() {
@ -646,10 +688,6 @@ private:
/// be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
/// #include.
bool isInPrimaryFile() const;
/// ReadMacroName - Lex and validate a macro name, which occurs after a
/// #define or #undef. This emits a diagnostic, sets the token kind to eom,
/// and discards the rest of the macro line if the macro name is invalid.
@ -722,24 +760,6 @@ private:
/// start getting tokens from it using the PTH cache.
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
/// checked and spelled filename, e.g. as an operand of #include. This returns
/// true if the input filename was in <>'s or false if it were in ""'s. The
/// caller is expected to provide a buffer that is large enough to hold the
/// spelling of the filename, but is also expected to handle the case when
/// this method decides to use a different buffer.
bool GetIncludeFilenameSpelling(SourceLocation Loc,
const char *&BufStart, const char *&BufEnd);
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir);
/// IsFileLexer - Returns true if we are lexing from a file and not a
/// pragma or a macro.
static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {

View File

@ -974,11 +974,11 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
/// This code concatenates and consumes tokens up to the '>' token. It returns
/// false if the > was found, otherwise it returns true if it finds and consumes
/// the EOM marker.
static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
Preprocessor &PP) {
bool Preprocessor::ConcatenateIncludeName(
llvm::SmallVector<char, 128> &FilenameBuffer) {
Token CurTok;
PP.Lex(CurTok);
Lex(CurTok);
while (CurTok.isNot(tok::eom)) {
// Append the spelling of this token to the buffer. If there was a space
// before it, add it now.
@ -990,7 +990,7 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
const char *BufPtr = &FilenameBuffer[PreAppendSize];
unsigned ActualLen = PP.getSpelling(CurTok, BufPtr);
unsigned ActualLen = getSpelling(CurTok, BufPtr);
// If the token was spelled somewhere else, copy it into FilenameBuffer.
if (BufPtr != &FilenameBuffer[PreAppendSize])
@ -1004,12 +1004,12 @@ static bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer,
if (CurTok.is(tok::greater))
return false;
PP.Lex(CurTok);
Lex(CurTok);
}
// If we hit the eom marker, emit an error and return true so that the caller
// knows the EOM has been read.
PP.Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
return true;
}
@ -1047,7 +1047,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
// This could be a <foo/bar.h> file coming from a macro expansion. In this
// case, glue the tokens together into FilenameBuffer and interpret those.
FilenameBuffer.push_back('<');
if (ConcatenateIncludeName(FilenameBuffer, *this))
if (ConcatenateIncludeName(FilenameBuffer))
return; // Found <eom> but no ">"? Diagnostic already emitted.
FilenameStart = FilenameBuffer.data();
FilenameEnd = FilenameStart + FilenameBuffer.size();

View File

@ -71,6 +71,61 @@ struct DefinedTracker {
IdentifierInfo *TheMacro;
};
/// EvaluateDefined - Process a 'defined(sym)' expression.
static bool EvaluateDefined(PPValue &Result, Token &PeekTok,
DefinedTracker &DT, bool ValueLive, Preprocessor &PP) {
IdentifierInfo *II;
Result.setBegin(PeekTok.getLocation());
// Get the next token, don't expand it.
PP.LexUnexpandedToken(PeekTok);
// Two options, it can either be a pp-identifier or a (.
SourceLocation LParenLoc;
if (PeekTok.is(tok::l_paren)) {
// Found a paren, remember we saw it and skip it.
LParenLoc = PeekTok.getLocation();
PP.LexUnexpandedToken(PeekTok);
}
// If we don't have a pp-identifier now, this is an error.
if ((II = PeekTok.getIdentifierInfo()) == 0) {
PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
return true;
}
// Otherwise, we got an identifier, is it defined to something?
Result.Val = II->hasMacroDefinition();
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive) {
MacroInfo *Macro = PP.getMacroInfo(II);
Macro->setIsUsed(true);
}
// Consume identifier.
Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok);
// If we are in parens, ensure we have a trailing ).
if (LParenLoc.isValid()) {
if (PeekTok.isNot(tok::r_paren)) {
PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
PP.Diag(LParenLoc, diag::note_matching) << "(";
return true;
}
// Consume the ).
Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok);
}
// Success, remember that we saw defined(X).
DT.State = DefinedTracker::DefinedMacro;
DT.TheMacro = II;
return false;
}
/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
/// return the computed value in Result. Return true if there was an error
/// parsing. This function also returns information about the form of the
@ -87,10 +142,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// 'defined' or if it is a macro. Note that we check here because many
// keywords are pp-identifiers, so we can't check the kind.
if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
// If this identifier isn't 'defined' and it wasn't macro expanded, it turns
// into a simple 0, unless it is the C++ keyword "true", in which case it
// turns into "1".
if (!II->isStr("defined")) {
if (II->isStr("defined")) {
// Handle "defined X" and "defined(X)".
return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP));
} else {
// If this identifier isn't 'defined' or one of the special
// preprocessor keywords and it wasn't macro expanded, it turns
// into a simple 0, unless it is the C++ keyword "true", in which case it
// turns into "1".
if (ValueLive)
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
Result.Val = II->getTokenID() == tok::kw_true;
@ -99,57 +158,6 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.LexNonComment(PeekTok);
return false;
}
// Handle "defined X" and "defined(X)".
Result.setBegin(PeekTok.getLocation());
// Get the next token, don't expand it.
PP.LexUnexpandedToken(PeekTok);
// Two options, it can either be a pp-identifier or a (.
SourceLocation LParenLoc;
if (PeekTok.is(tok::l_paren)) {
// Found a paren, remember we saw it and skip it.
LParenLoc = PeekTok.getLocation();
PP.LexUnexpandedToken(PeekTok);
}
// If we don't have a pp-identifier now, this is an error.
if ((II = PeekTok.getIdentifierInfo()) == 0) {
PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
return true;
}
// Otherwise, we got an identifier, is it defined to something?
Result.Val = II->hasMacroDefinition();
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive) {
MacroInfo *Macro = PP.getMacroInfo(II);
Macro->setIsUsed(true);
}
// Consume identifier.
Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok);
// If we are in parens, ensure we have a trailing ).
if (LParenLoc.isValid()) {
if (PeekTok.isNot(tok::r_paren)) {
PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen);
PP.Diag(LParenLoc, diag::note_matching) << "(";
return true;
}
// Consume the ).
Result.setEnd(PeekTok.getLocation());
PP.LexNonComment(PeekTok);
}
// Success, remember that we saw defined(X).
DT.State = DefinedTracker::DefinedMacro;
DT.TheMacro = II;
return false;
}
switch (PeekTok.getKind()) {