diff options
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/HeaderMap.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 14 | ||||
-rw-r--r-- | lib/Lex/PPExpressions.cpp | 118 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 131 |
4 files changed, 200 insertions, 65 deletions
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index c9a10dc..df71276 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -15,7 +15,7 @@ #include "clang/Basic/FileManager.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/System/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include <cstdio> diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index e264efa..dc7d95e 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -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(); diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 908385c..a74396c 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -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()) { diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 7ddf215..699b701 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -64,8 +64,10 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__"); // Clang Extensions. - Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); - Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); + Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__has_include = RegisterBuiltinMacro(*this, "__has_include"); + Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next"); } /// isTrivialSingleTokenExpansion - Return true if MI, which has a single token @@ -503,6 +505,117 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { } } +/// EvaluateHasIncludeCommon - Process a '__has_include("path")' +/// or '__has_include_next("path")' expression. +/// Returns true if successful. +static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, + IdentifierInfo *II, Preprocessor &PP, + const DirectoryLookup *LookupFrom) { + SourceLocation LParenLoc; + + // Get '('. + PP.LexNonComment(Tok); + + // Ensure we have a '('. + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName(); + return false; + } + + // Save '(' location for possible missing ')' message. + LParenLoc = Tok.getLocation(); + + // Get the file name. + PP.getCurrentLexer()->LexIncludeFilename(Tok); + + // Reserve a buffer to get the spelling. + llvm::SmallVector<char, 128> FilenameBuffer; + const char *FilenameStart, *FilenameEnd; + + switch (Tok.getKind()) { + case tok::eom: + // If the token kind is EOM, the error has already been diagnosed. + return false; + + case tok::angle_string_literal: + case tok::string_literal: { + FilenameBuffer.resize(Tok.getLength()); + FilenameStart = &FilenameBuffer[0]; + unsigned Len = PP.getSpelling(Tok, FilenameStart); + FilenameEnd = FilenameStart+Len; + break; + } + + case tok::less: + // 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 (PP.ConcatenateIncludeName(FilenameBuffer)) + return false; // Found <eom> but no ">"? Diagnostic already emitted. + FilenameStart = FilenameBuffer.data(); + FilenameEnd = FilenameStart + FilenameBuffer.size(); + break; + default: + PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename); + return false; + } + + bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), + FilenameStart, FilenameEnd); + // If GetIncludeFilenameSpelling set the start ptr to null, there was an + // error. + if (FilenameStart == 0) { + return false; + } + + // Search include directories. + const DirectoryLookup *CurDir; + const FileEntry *File = PP.LookupFile(FilenameStart, FilenameEnd, + isAngled, LookupFrom, CurDir); + + // Get the result value. Result = true means the file exists. + Result = File != 0; + + // Get ')'. + PP.LexNonComment(Tok); + + // Ensure we have a trailing ). + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName(); + PP.Diag(LParenLoc, diag::note_matching) << "("; + return false; + } + + return true; +} + +/// EvaluateHasInclude - Process a '__has_include("path")' expression. +/// Returns true if successful. +static bool EvaluateHasInclude(bool &Result, Token &Tok, IdentifierInfo *II, + Preprocessor &PP) { + return(EvaluateHasIncludeCommon(Result, Tok, II, PP, NULL)); +} + +/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression. +/// Returns true if successful. +static bool EvaluateHasIncludeNext(bool &Result, Token &Tok, + IdentifierInfo *II, Preprocessor &PP) { + // __has_include_next is like __has_include, except that we start + // searching after the current found directory. If we can't do this, + // issue a diagnostic. + const DirectoryLookup *Lookup = PP.GetCurDirLookup(); + if (PP.isInPrimaryFile()) { + Lookup = 0; + PP.Diag(Tok, diag::pp_include_next_in_primary); + } else if (Lookup == 0) { + PP.Diag(Tok, diag::pp_include_next_absolute_path); + } else { + // Start looking up in the next directory. + ++Lookup; + } + + return(EvaluateHasIncludeCommon(Result, Tok, II, PP, Lookup)); +} /// 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'. @@ -671,6 +784,20 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { sprintf(TmpBuffer, "%d", (int)Value); Tok.setKind(tok::numeric_constant); CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation()); + } else if (II == Ident__has_include || + II == Ident__has_include_next) { + // The argument to these two builtins should be a parenthesized + // file name string literal using angle brackets (<>) or + // double-quotes (""). + bool Value = false; + bool IsValid; + if (II == Ident__has_include) + IsValid = EvaluateHasInclude(Value, Tok, II, *this); + else + IsValid = EvaluateHasIncludeNext(Value, Tok, II, *this); + sprintf(TmpBuffer, "%d", (int)Value); + Tok.setKind(tok::numeric_constant); + CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation()); } else { assert(0 && "Unknown identifier!"); } |