diff options
Diffstat (limited to 'lib/Lex/PPMacroExpansion.cpp')
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 112 |
1 files changed, 57 insertions, 55 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index c70ff46ec904..687b9a9d3b7b 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1,9 +1,8 @@ -//===--- MacroExpansion.cpp - Top level Macro Expansion -------------------===// +//===--- PPMacroExpansion.cpp - Top level Macro Expansion -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -44,6 +43,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -364,6 +364,7 @@ void Preprocessor::RegisterBuiltinMacros() { } // Clang Extensions. + Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__"); Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension"); Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); @@ -493,10 +494,13 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // Preprocessor directives used inside macro arguments are not portable, and // this enables the warning. InMacroArgs = true; + ArgMacro = &Identifier; + Args = ReadMacroCallArgumentList(Identifier, MI, ExpansionEnd); // Finished parsing args. InMacroArgs = false; + ArgMacro = nullptr; // If there was an error parsing the arguments, bail out. if (!Args) return true; @@ -802,7 +806,7 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, // Do not lose the EOF/EOD. auto Toks = llvm::make_unique<Token[]>(1); Toks[0] = Tok; - EnterTokenStream(std::move(Toks), 1, true); + EnterTokenStream(std::move(Toks), 1, true, /*IsReinject*/ false); break; } else if (Tok.is(tok::r_paren)) { // If we found the ) token, the macro arg list is done. @@ -1151,8 +1155,11 @@ static bool EvaluateHasIncludeCommon(Token &Tok, return false; } - // Get '('. - PP.LexNonComment(Tok); + // Get '('. If we don't have a '(', try to form a header-name token. + do { + if (PP.LexHeaderName(Tok)) + return false; + } while (Tok.getKind() == tok::comment); // Ensure we have a '('. if (Tok.isNot(tok::l_paren)) { @@ -1161,58 +1168,27 @@ static bool EvaluateHasIncludeCommon(Token &Tok, PP.Diag(LParenLoc, diag::err_pp_expected_after) << II << tok::l_paren; // If the next token looks like a filename or the start of one, // assume it is and process it as such. - if (!Tok.is(tok::angle_string_literal) && !Tok.is(tok::string_literal) && - !Tok.is(tok::less)) + if (Tok.isNot(tok::header_name)) return false; } else { // Save '(' location for possible missing ')' message. LParenLoc = Tok.getLocation(); - - if (PP.getCurrentLexer()) { - // Get the file name. - PP.getCurrentLexer()->LexIncludeFilename(Tok); - } else { - // We're in a macro, so we can't use LexIncludeFilename; just - // grab the next token. - PP.Lex(Tok); - } - } - - // Reserve a buffer to get the spelling. - SmallString<128> FilenameBuffer; - StringRef Filename; - SourceLocation EndLoc; - - switch (Tok.getKind()) { - case tok::eod: - // If the token kind is EOD, the error has already been diagnosed. - return false; - - case tok::angle_string_literal: - case tok::string_literal: { - bool Invalid = false; - Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid); - if (Invalid) + if (PP.LexHeaderName(Tok)) return false; - 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, EndLoc)) { - // Let the caller know a <eod> was found by changing the Token kind. - Tok.setKind(tok::eod); - return false; // Found <eod> but no ">"? Diagnostic already emitted. - } - Filename = FilenameBuffer; - break; - default: + if (Tok.isNot(tok::header_name)) { PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename); return false; } + // Reserve a buffer to get the spelling. + SmallString<128> FilenameBuffer; + bool Invalid = false; + StringRef Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid); + if (Invalid) + return false; + SourceLocation FilenameLoc = Tok.getLocation(); // Get ')'. @@ -1236,7 +1212,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, const DirectoryLookup *CurDir; const FileEntry *File = PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile, - CurDir, nullptr, nullptr, nullptr, nullptr); + CurDir, nullptr, nullptr, nullptr, nullptr, nullptr); if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { SrcMgr::CharacteristicKind FileType = SrcMgr::C_User; @@ -1354,9 +1330,13 @@ already_lexed: // The last ')' has been reached; return the value if one found or // a diagnostic and a dummy value. - if (Result.hasValue()) + if (Result.hasValue()) { OS << Result.getValue(); - else { + // For strict conformance to __has_cpp_attribute rules, use 'L' + // suffix for dated literals. + if (Result.getValue() > 1) + OS << 'L'; + } else { OS << 0; if (!SuppressDiagnostic) PP.Diag(Tok.getLocation(), diag::err_too_few_args_in_macro_invoc); @@ -1478,6 +1458,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // Set up the return result. Tok.setIdentifierInfo(nullptr); Tok.clearFlag(Token::NeedsCleaning); + bool IsAtStartOfLine = Tok.isAtStartOfLine(); + bool HasLeadingSpace = Tok.hasLeadingSpace(); if (II == Ident__LINE__) { // C99 6.10.8: "__LINE__: The presumed line number (within the current @@ -1500,7 +1482,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // __LINE__ expands to a simple numeric value. OS << (PLoc.isValid()? PLoc.getLine() : 1); Tok.setKind(tok::numeric_constant); - } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { + } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__ || + II == Ident__FILE_NAME__) { // C99 6.10.8: "__FILE__: The presumed name of the current source file (a // character string literal)". This can be affected by #line. PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); @@ -1521,7 +1504,19 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // Escape this filename. Turn '\' -> '\\' '"' -> '\"' SmallString<128> FN; if (PLoc.isValid()) { - FN += PLoc.getFilename(); + // __FILE_NAME__ is a Clang-specific extension that expands to the + // the last part of __FILE__. + if (II == Ident__FILE_NAME__) { + // Try to get the last path component, failing that return the original + // presumed location. + StringRef PLFileName = llvm::sys::path::filename(PLoc.getFilename()); + if (PLFileName != "") + FN += PLFileName; + else + FN += PLoc.getFilename(); + } else { + FN += PLoc.getFilename(); + } Lexer::Stringify(FN); OS << '"' << FN << '"'; } @@ -1631,6 +1626,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { .Case("__is_target_vendor", true) .Case("__is_target_os", true) .Case("__is_target_environment", true) + .Case("__builtin_LINE", true) + .Case("__builtin_FILE", true) + .Case("__builtin_FUNCTION", true) + .Case("__builtin_COLUMN", true) + .Case("__builtin_bit_cast", true) .Default(false); } }); @@ -1707,7 +1707,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { HasLexedNextToken = Tok.is(tok::string_literal); if (!FinishLexStringLiteral(Tok, WarningName, "'__has_warning'", - /*MacroExpansion=*/false)) + /*AllowMacroExpansion=*/false)) return false; // FIXME: Should we accept "-R..." flags here, or should that be @@ -1814,6 +1814,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { llvm_unreachable("Unknown identifier!"); } CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation()); + Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine); + Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace); } void Preprocessor::markMacroAsUsed(MacroInfo *MI) { |