Reland "[Clang][PP] Add the __FILE_NAME__ builtin macro"

This relands commit rL360833 which caused issues on Win32
bots due to path handling/normalization differences. Now
this uses `sys::path::filename` which should handle
additional edge cases on Win32.

Original commit:

"[Clang][PP] Add the __FILE_NAME__ builtin macro" 

This patch adds the __FILE_NAME__ macro that expands to the
last component of the path, similar to __FILE__ except with
a guarantee that only the last path component (without the
separator) will be rendered.

I intend to follow through with discussion of this with WG14
as a potential inclusion in the C standard or failing that,
try to discuss this with GCC developers since this extension
is desired by GCC and Clang users/developers alike.

Differential Revision: https://reviews.llvm.org/D61756

llvm-svn: 360938
This commit is contained in:
Kristina Brooks 2019-05-16 21:13:49 +00:00
parent 708afb56c1
commit bd97484241
7 changed files with 71 additions and 2 deletions

View File

@ -147,6 +147,7 @@ class Preprocessor {
IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
IdentifierInfo *Ident__FILE_NAME__; // __FILE_NAME__
IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
IdentifierInfo *Ident__COUNTER__; // __COUNTER__
IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma

View File

@ -43,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>
@ -363,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");
@ -1474,7 +1476,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());
@ -1495,7 +1498,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 << '"';
}

View File

@ -0,0 +1,6 @@
3: __FILE_NAME__
4: "file_name_macro_include.h"
#ifdef MS
// Should be the same even when included with backslash.
5: __FILE_NAME__
#endif

View File

@ -0,0 +1 @@
6: __FILE_NAME__

View File

@ -0,0 +1 @@
7: __FILE_NAME__

View File

@ -0,0 +1 @@
8: __FILE_NAME__

View File

@ -0,0 +1,44 @@
// RUN: %clang_cc1 -E %s -I%S/Inputs | FileCheck -strict-whitespace %s
// RUN: %clang_cc1 -fms-compatibility -DMS -E %s -I%S/Inputs | FileCheck -check-prefix=CHECK-MS -strict-whitespace %s
// RUN: %clang_cc1 -E %s -I%S/Inputs -DBADINC -verify
#ifdef BADINC
// Paranoia.
__FILE_NAME__
#include <include-subdir/> // expected-error {{file not found}}
__FILE_NAME__
#else
// Reference.
1: "file_name_macro.c"
// Ensure it expands correctly for this file.
2: __FILE_NAME__
// CHECK: {{^}}1: "file_name_macro.c"
// CHECK: {{^}}2: "file_name_macro.c"
// Test if inclusion works right.
#ifdef MS
#include <include-subdir\file_name_macro_include.h>
// MS compatibility allows for mixed separators in paths.
#include <include-subdir/subdir1\hdr1.h>
#include <include-subdir\subdir1/hdr2.h>
#else
#include <include-subdir/file_name_macro_include.h>
#endif
#include <include-subdir/h>
// CHECK: {{^}}3: "file_name_macro_include.h"
// CHECK: {{^}}4: "file_name_macro_include.h"
// CHECK-NOT: {{^}}5: "file_name_macro_include.h"
// CHECK-MS: {{^}}5: "file_name_macro_include.h"
// CHECK: {{^}}6: "h"
// CHECK-MS: {{^}}7: "hdr1.h"
// CHECK-MS: {{^}}8: "hdr2.h"
#endif