aboutsummaryrefslogtreecommitdiff
path: root/lib/Lex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex')
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/PPDirectives.cpp14
-rw-r--r--lib/Lex/PPExpressions.cpp118
-rw-r--r--lib/Lex/PPMacroExpansion.cpp131
4 files changed, 200 insertions, 65 deletions
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index c9a10dc02707..df712760bb25 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 e264efab9d7b..dc7d95e70118 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 908385c5d392..a74396c3146c 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 7ddf215020d0..699b701ea870 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!");
}