forked from OSchip/llvm-project
[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: 360833
This commit is contained in:
parent
e7ab59eda9
commit
3acc1d1be3
|
@ -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
|
||||
|
|
|
@ -363,6 +363,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 +1475,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 +1497,21 @@ 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.
|
||||
StringRef PLFileName = PLoc.getFilename();
|
||||
size_t LastSep = PLFileName.find_last_of('/');
|
||||
// Skip the separator and get the last part, otherwise fall back on
|
||||
// returning the original full filename.
|
||||
if (LastSep != StringRef::npos)
|
||||
FN += PLFileName.substr(LastSep+1);
|
||||
else
|
||||
FN += PLFileName;
|
||||
} else {
|
||||
FN += PLoc.getFilename();
|
||||
}
|
||||
Lexer::Stringify(FN);
|
||||
OS << '"' << FN << '"';
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
6: __FILE_NAME__
|
|
@ -0,0 +1 @@
|
|||
7: __FILE_NAME__
|
|
@ -0,0 +1 @@
|
|||
8: __FILE_NAME__
|
|
@ -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
|
Loading…
Reference in New Issue