From: Kristina Brooks Date: Thu, 16 May 2019 21:13:49 +0000 (+0000) Subject: Reland "[Clang][PP] Add the __FILE_NAME__ builtin macro" X-Git-Tag: llvmorg-9.0.0-rc1~5384 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bd9748424165c24280ec1b2ddbe4e7522b15dc96;p=platform%2Fupstream%2Fllvm.git 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 --- diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 293fbafdab0d..57c557d6a9cf 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -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 diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index d698f0e6578c..d576f331d1b5 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -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 #include @@ -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 << '"'; } diff --git a/clang/test/Preprocessor/Inputs/include-subdir/file_name_macro_include.h b/clang/test/Preprocessor/Inputs/include-subdir/file_name_macro_include.h new file mode 100644 index 000000000000..e974799b1f66 --- /dev/null +++ b/clang/test/Preprocessor/Inputs/include-subdir/file_name_macro_include.h @@ -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 diff --git a/clang/test/Preprocessor/Inputs/include-subdir/h b/clang/test/Preprocessor/Inputs/include-subdir/h new file mode 100644 index 000000000000..b9839684e897 --- /dev/null +++ b/clang/test/Preprocessor/Inputs/include-subdir/h @@ -0,0 +1 @@ +6: __FILE_NAME__ diff --git a/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr1.h b/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr1.h new file mode 100644 index 000000000000..f793be596c74 --- /dev/null +++ b/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr1.h @@ -0,0 +1 @@ +7: __FILE_NAME__ diff --git a/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr2.h b/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr2.h new file mode 100644 index 000000000000..66860acc64d4 --- /dev/null +++ b/clang/test/Preprocessor/Inputs/include-subdir/subdir1/hdr2.h @@ -0,0 +1 @@ +8: __FILE_NAME__ diff --git a/clang/test/Preprocessor/file_name_macro.c b/clang/test/Preprocessor/file_name_macro.c new file mode 100644 index 000000000000..9dc9dc5684c5 --- /dev/null +++ b/clang/test/Preprocessor/file_name_macro.c @@ -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 // 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 +// MS compatibility allows for mixed separators in paths. +#include +#include +#else +#include +#endif + +#include + +// 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